Merge changes from topic "saved-state-kmp" into androidx-main
* changes:
Rename `androidTest` to `androidInstrumentedTest` on `savedstate`
Convert `ErrorInStaticBlock` to Kotlin
Rename `main` to `androidMain` on `savedstate`
Configure multiplatform plugin on `savedstate`
Use `kmpDocs` on `savedstate`
Add `KMP` as a build type on `savedstate`
diff --git a/appactions/builtintypes/OWNERS b/appactions/builtintypes/OWNERS
deleted file mode 100644
index 671da19..0000000
--- a/appactions/builtintypes/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 1292315
[email protected]
[email protected]
diff --git a/appactions/builtintypes/builtintypes/api/current.txt b/appactions/builtintypes/builtintypes/api/current.txt
deleted file mode 100644
index ca92db8..0000000
--- a/appactions/builtintypes/builtintypes/api/current.txt
+++ /dev/null
@@ -1,868 +0,0 @@
-// Signature format: 4.0
-package androidx.appactions.builtintypes.properties {
-
- @androidx.appsearch.annotation.Document(name="bitprop:ByDay") public final class ByDay {
- ctor public ByDay(androidx.appactions.builtintypes.types.DayOfWeek dayOfWeek);
- method @androidx.appsearch.annotation.Document.StringProperty(serializer=DayOfWeekAsCanonicalUrlSerializer::class) public androidx.appactions.builtintypes.types.DayOfWeek? asDayOfWeek();
- property @androidx.appsearch.annotation.Document.StringProperty(serializer=DayOfWeekAsCanonicalUrlSerializer::class) public final androidx.appactions.builtintypes.types.DayOfWeek? asDayOfWeek;
- }
-
- @androidx.appsearch.annotation.Document(name="bitprop:EndDate") public final class EndDate {
- ctor public EndDate(java.time.LocalDate date);
- method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public java.time.LocalDate? asDate();
- property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public final java.time.LocalDate? asDate;
- }
-
- @androidx.appsearch.annotation.Document(name="bitprop:EndTime") public final class EndTime {
- ctor public EndTime(java.time.LocalTime time);
- method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalTimeAsNanoOfDaySerializer::class) public java.time.LocalTime? asTime();
- property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalTimeAsNanoOfDaySerializer::class) public final java.time.LocalTime? asTime;
- }
-
- @androidx.appsearch.annotation.Document(name="bitprop:ExceptDate") public final class ExceptDate {
- ctor public ExceptDate(java.time.Instant instant);
- ctor public ExceptDate(java.time.LocalDate date);
- ctor public ExceptDate(java.time.LocalDateTime localDateTime);
- method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public java.time.LocalDate? asDate();
- method @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public java.time.Instant? asInstant();
- method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public java.time.LocalDateTime? asLocalDateTime();
- method public <R> R mapWhen(androidx.appactions.builtintypes.properties.ExceptDate.Mapper<R> mapper);
- property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public final java.time.LocalDate? asDate;
- property @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public final java.time.Instant? asInstant;
- property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public final java.time.LocalDateTime? asLocalDateTime;
- }
-
- public static interface ExceptDate.Mapper<R> {
- method public default R date(java.time.LocalDate instance);
- method public default R instant(java.time.Instant instance);
- method public default R localDateTime(java.time.LocalDateTime instance);
- method public R orElse();
- }
-
- @androidx.appsearch.annotation.Document(name="bitprop:Name") public final class Name {
- ctor public Name(String text);
- method @androidx.appsearch.annotation.Document.StringProperty public String? asText();
- property @androidx.appsearch.annotation.Document.StringProperty public final String? asText;
- }
-
- @androidx.appsearch.annotation.Document(name="bitprop:RepeatFrequency") public final class RepeatFrequency {
- ctor public RepeatFrequency(java.time.Duration duration);
- method @androidx.appsearch.annotation.Document.LongProperty(serializer=DurationAsNanosSerializer::class) public java.time.Duration? asDuration();
- property @androidx.appsearch.annotation.Document.LongProperty(serializer=DurationAsNanosSerializer::class) public final java.time.Duration? asDuration;
- }
-
- @androidx.appsearch.annotation.Document(name="bitprop:StartDate") public final class StartDate {
- ctor public StartDate(java.time.LocalDate date);
- method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public java.time.LocalDate? asDate();
- property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public final java.time.LocalDate? asDate;
- }
-
- @androidx.appsearch.annotation.Document(name="bitprop:StartTime") public final class StartTime {
- ctor public StartTime(java.time.LocalTime time);
- method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalTimeAsNanoOfDaySerializer::class) public java.time.LocalTime? asTime();
- property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalTimeAsNanoOfDaySerializer::class) public final java.time.LocalTime? asTime;
- }
-
-}
-
-package androidx.appactions.builtintypes.serializers {
-
- public final class DayOfWeekAsCanonicalUrlSerializer implements androidx.appsearch.app.StringSerializer<androidx.appactions.builtintypes.types.DayOfWeek> {
- ctor public DayOfWeekAsCanonicalUrlSerializer();
- method public androidx.appactions.builtintypes.types.DayOfWeek? deserialize(String value);
- method public String serialize(androidx.appactions.builtintypes.types.DayOfWeek instance);
- }
-
- public final class DurationAsNanosSerializer implements androidx.appsearch.app.LongSerializer<java.time.Duration> {
- ctor public DurationAsNanosSerializer();
- method public java.time.Duration deserialize(long value);
- method public long serialize(java.time.Duration instance);
- }
-
- public final class InstantAsEpochMilliSerializer implements androidx.appsearch.app.LongSerializer<java.time.Instant> {
- ctor public InstantAsEpochMilliSerializer();
- method public java.time.Instant deserialize(long value);
- method public long serialize(java.time.Instant instance);
- }
-
- public final class LocalDateAsEpochDaySerializer implements androidx.appsearch.app.LongSerializer<java.time.LocalDate> {
- ctor public LocalDateAsEpochDaySerializer();
- method public java.time.LocalDate deserialize(long value);
- method public long serialize(java.time.LocalDate instance);
- }
-
- public final class LocalDateTimeAsUtcEpochSecondSerializer implements androidx.appsearch.app.LongSerializer<java.time.LocalDateTime> {
- ctor public LocalDateTimeAsUtcEpochSecondSerializer();
- method public java.time.LocalDateTime deserialize(long value);
- method public long serialize(java.time.LocalDateTime instance);
- }
-
- public final class LocalTimeAsNanoOfDaySerializer implements androidx.appsearch.app.LongSerializer<java.time.LocalTime> {
- ctor public LocalTimeAsNanoOfDaySerializer();
- method public java.time.LocalTime deserialize(long value);
- method public long serialize(java.time.LocalTime instance);
- }
-
-}
-
-package androidx.appactions.builtintypes.types {
-
- public abstract class AbstractAlarm<Self extends androidx.appactions.builtintypes.types.AbstractAlarm<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractAlarm.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.Alarm {
- ctor public AbstractAlarm(androidx.appactions.builtintypes.types.Alarm alarm);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final androidx.appactions.builtintypes.types.Schedule? getAlarmSchedule();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Boolean? isAlarmEnabled();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final androidx.appactions.builtintypes.types.Schedule? alarmSchedule;
- property public final String identifier;
- property public final Boolean? isAlarmEnabled;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- }
-
- public abstract static class AbstractAlarm.Builder<Self extends androidx.appactions.builtintypes.types.AbstractAlarm.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractAlarm<Built, Self>> implements androidx.appactions.builtintypes.types.Alarm.Builder<Self> {
- ctor public AbstractAlarm.Builder();
- method public final Built build();
- method protected abstract Built buildFromAlarm(androidx.appactions.builtintypes.types.Alarm alarm);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setAlarmEnabled(Boolean? boolean);
- method public final Self setAlarmSchedule(androidx.appactions.builtintypes.types.Schedule? schedule);
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractCommonExecutionStatus<Self extends androidx.appactions.builtintypes.types.AbstractCommonExecutionStatus<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractCommonExecutionStatus.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.CommonExecutionStatus {
- ctor public AbstractCommonExecutionStatus(androidx.appactions.builtintypes.types.CommonExecutionStatus commonExecutionStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- }
-
- public abstract static class AbstractCommonExecutionStatus.Builder<Self extends androidx.appactions.builtintypes.types.AbstractCommonExecutionStatus.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractCommonExecutionStatus<Built, Self>> implements androidx.appactions.builtintypes.types.CommonExecutionStatus.Builder<Self> {
- ctor public AbstractCommonExecutionStatus.Builder();
- method public final Built build();
- method protected abstract Built buildFromCommonExecutionStatus(androidx.appactions.builtintypes.types.CommonExecutionStatus commonExecutionStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractExecutionStatus<Self extends androidx.appactions.builtintypes.types.AbstractExecutionStatus<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractExecutionStatus.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.ExecutionStatus {
- ctor public AbstractExecutionStatus(androidx.appactions.builtintypes.types.ExecutionStatus executionStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- }
-
- public abstract static class AbstractExecutionStatus.Builder<Self extends androidx.appactions.builtintypes.types.AbstractExecutionStatus.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractExecutionStatus<Built, Self>> implements androidx.appactions.builtintypes.types.ExecutionStatus.Builder<Self> {
- ctor public AbstractExecutionStatus.Builder();
- method public final Built build();
- method protected abstract Built buildFromExecutionStatus(androidx.appactions.builtintypes.types.ExecutionStatus executionStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractGenericErrorStatus<Self extends androidx.appactions.builtintypes.types.AbstractGenericErrorStatus<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractGenericErrorStatus.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.GenericErrorStatus {
- ctor public AbstractGenericErrorStatus(androidx.appactions.builtintypes.types.GenericErrorStatus genericErrorStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- }
-
- public abstract static class AbstractGenericErrorStatus.Builder<Self extends androidx.appactions.builtintypes.types.AbstractGenericErrorStatus.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractGenericErrorStatus<Built, Self>> implements androidx.appactions.builtintypes.types.GenericErrorStatus.Builder<Self> {
- ctor public AbstractGenericErrorStatus.Builder();
- method public final Built build();
- method protected abstract Built buildFromGenericErrorStatus(androidx.appactions.builtintypes.types.GenericErrorStatus genericErrorStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractIntangible<Self extends androidx.appactions.builtintypes.types.AbstractIntangible<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractIntangible.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.Intangible {
- ctor public AbstractIntangible(androidx.appactions.builtintypes.types.Intangible intangible);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- }
-
- public abstract static class AbstractIntangible.Builder<Self extends androidx.appactions.builtintypes.types.AbstractIntangible.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractIntangible<Built, Self>> implements androidx.appactions.builtintypes.types.Intangible.Builder<Self> {
- ctor public AbstractIntangible.Builder();
- method public final Built build();
- method protected abstract Built buildFromIntangible(androidx.appactions.builtintypes.types.Intangible intangible);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractObjectCreationLimitReachedStatus<Self extends androidx.appactions.builtintypes.types.AbstractObjectCreationLimitReachedStatus<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractObjectCreationLimitReachedStatus.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus {
- ctor public AbstractObjectCreationLimitReachedStatus(androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus objectCreationLimitReachedStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- }
-
- public abstract static class AbstractObjectCreationLimitReachedStatus.Builder<Self extends androidx.appactions.builtintypes.types.AbstractObjectCreationLimitReachedStatus.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractObjectCreationLimitReachedStatus<Built, Self>> implements androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus.Builder<Self> {
- ctor public AbstractObjectCreationLimitReachedStatus.Builder();
- method public final Built build();
- method protected abstract Built buildFromObjectCreationLimitReachedStatus(androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus objectCreationLimitReachedStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractPerson<Self extends androidx.appactions.builtintypes.types.AbstractPerson<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractPerson.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.Person {
- ctor public AbstractPerson(androidx.appactions.builtintypes.types.Person person);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final String? getEmail();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final String? getTelephoneNumber();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final String? email;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- property public final String? telephoneNumber;
- }
-
- public abstract static class AbstractPerson.Builder<Self extends androidx.appactions.builtintypes.types.AbstractPerson.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractPerson<Built, Self>> implements androidx.appactions.builtintypes.types.Person.Builder<Self> {
- ctor public AbstractPerson.Builder();
- method public final Built build();
- method protected abstract Built buildFromPerson(androidx.appactions.builtintypes.types.Person person);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setEmail(String? text);
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final Self setTelephoneNumber(String? text);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractSchedule<Self extends androidx.appactions.builtintypes.types.AbstractSchedule<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractSchedule.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.Schedule {
- ctor public AbstractSchedule(androidx.appactions.builtintypes.types.Schedule schedule);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final java.util.List<androidx.appactions.builtintypes.properties.ByDay> getByDays();
- method public final java.util.List<java.lang.Long> getByMonthDays();
- method public final java.util.List<java.lang.Long> getByMonthWeeks();
- method public final java.util.List<java.lang.Long> getByMonths();
- method public final androidx.appactions.builtintypes.properties.EndDate? getEndDate();
- method public final androidx.appactions.builtintypes.properties.EndTime? getEndTime();
- method public final androidx.appactions.builtintypes.properties.ExceptDate? getExceptDate();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method public final Long? getRepeatCount();
- method public final androidx.appactions.builtintypes.properties.RepeatFrequency? getRepeatFrequency();
- method public final String? getScheduleTimezone();
- method protected abstract String getSelfTypeName();
- method public final androidx.appactions.builtintypes.properties.StartDate? getStartDate();
- method public final androidx.appactions.builtintypes.properties.StartTime? getStartTime();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final java.util.List<androidx.appactions.builtintypes.properties.ByDay> byDays;
- property public final java.util.List<java.lang.Long> byMonthDays;
- property public final java.util.List<java.lang.Long> byMonthWeeks;
- property public final java.util.List<java.lang.Long> byMonths;
- property public final androidx.appactions.builtintypes.properties.EndDate? endDate;
- property public final androidx.appactions.builtintypes.properties.EndTime? endTime;
- property public final androidx.appactions.builtintypes.properties.ExceptDate? exceptDate;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property public final Long? repeatCount;
- property public final androidx.appactions.builtintypes.properties.RepeatFrequency? repeatFrequency;
- property public final String? scheduleTimezone;
- property protected abstract String selfTypeName;
- property public final androidx.appactions.builtintypes.properties.StartDate? startDate;
- property public final androidx.appactions.builtintypes.properties.StartTime? startTime;
- }
-
- public abstract static class AbstractSchedule.Builder<Self extends androidx.appactions.builtintypes.types.AbstractSchedule.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractSchedule<Built, Self>> implements androidx.appactions.builtintypes.types.Schedule.Builder<Self> {
- ctor public AbstractSchedule.Builder();
- method public final Self addByDay(androidx.appactions.builtintypes.properties.ByDay byDay);
- method public final Self addByDays(Iterable<androidx.appactions.builtintypes.properties.ByDay> values);
- method public final Self addByMonth(long integer);
- method public final Self addByMonthDay(long integer);
- method public final Self addByMonthDays(Iterable<java.lang.Long> values);
- method public final Self addByMonthWeek(long integer);
- method public final Self addByMonthWeeks(Iterable<java.lang.Long> values);
- method public final Self addByMonths(Iterable<java.lang.Long> values);
- method public final Built build();
- method protected abstract Built buildFromSchedule(androidx.appactions.builtintypes.types.Schedule schedule);
- method public final Self clearByDays();
- method public final Self clearByMonthDays();
- method public final Self clearByMonthWeeks();
- method public final Self clearByMonths();
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setEndDate(androidx.appactions.builtintypes.properties.EndDate? endDate);
- method public final Self setEndTime(androidx.appactions.builtintypes.properties.EndTime? endTime);
- method public final Self setExceptDate(androidx.appactions.builtintypes.properties.ExceptDate? exceptDate);
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final Self setRepeatCount(Long? integer);
- method public final Self setRepeatFrequency(androidx.appactions.builtintypes.properties.RepeatFrequency? repeatFrequency);
- method public final Self setScheduleTimezone(String? text);
- method public final Self setStartDate(androidx.appactions.builtintypes.properties.StartDate? startDate);
- method public final Self setStartTime(androidx.appactions.builtintypes.properties.StartTime? startTime);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractSuccessStatus<Self extends androidx.appactions.builtintypes.types.AbstractSuccessStatus<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractSuccessStatus.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.SuccessStatus {
- ctor public AbstractSuccessStatus(androidx.appactions.builtintypes.types.SuccessStatus successStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- }
-
- public abstract static class AbstractSuccessStatus.Builder<Self extends androidx.appactions.builtintypes.types.AbstractSuccessStatus.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractSuccessStatus<Built, Self>> implements androidx.appactions.builtintypes.types.SuccessStatus.Builder<Self> {
- ctor public AbstractSuccessStatus.Builder();
- method public final Built build();
- method protected abstract Built buildFromSuccessStatus(androidx.appactions.builtintypes.types.SuccessStatus successStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractThing<Self extends androidx.appactions.builtintypes.types.AbstractThing<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractThing.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.Thing {
- ctor public AbstractThing(androidx.appactions.builtintypes.types.Thing thing);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- }
-
- public abstract static class AbstractThing.Builder<Self extends androidx.appactions.builtintypes.types.AbstractThing.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractThing<Built, Self>> implements androidx.appactions.builtintypes.types.Thing.Builder<Self> {
- ctor public AbstractThing.Builder();
- method public final Built build();
- method protected abstract Built buildFromThing(androidx.appactions.builtintypes.types.Thing thing);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractTimer<Self extends androidx.appactions.builtintypes.types.AbstractTimer<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractTimer.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.Timer {
- ctor public AbstractTimer(androidx.appactions.builtintypes.types.Timer timer);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final java.time.Duration? getDuration();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final java.time.Duration? duration;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- }
-
- public abstract static class AbstractTimer.Builder<Self extends androidx.appactions.builtintypes.types.AbstractTimer.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractTimer<Built, Self>> implements androidx.appactions.builtintypes.types.Timer.Builder<Self> {
- ctor public AbstractTimer.Builder();
- method public final Built build();
- method protected abstract Built buildFromTimer(androidx.appactions.builtintypes.types.Timer timer);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setDuration(java.time.Duration? duration);
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractUnsupportedOperationStatus<Self extends androidx.appactions.builtintypes.types.AbstractUnsupportedOperationStatus<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractUnsupportedOperationStatus.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.UnsupportedOperationStatus {
- ctor public AbstractUnsupportedOperationStatus(androidx.appactions.builtintypes.types.UnsupportedOperationStatus unsupportedOperationStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- }
-
- public abstract static class AbstractUnsupportedOperationStatus.Builder<Self extends androidx.appactions.builtintypes.types.AbstractUnsupportedOperationStatus.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractUnsupportedOperationStatus<Built, Self>> implements androidx.appactions.builtintypes.types.UnsupportedOperationStatus.Builder<Self> {
- ctor public AbstractUnsupportedOperationStatus.Builder();
- method public final Built build();
- method protected abstract Built buildFromUnsupportedOperationStatus(androidx.appactions.builtintypes.types.UnsupportedOperationStatus unsupportedOperationStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- @androidx.appsearch.annotation.Document(name="bit:Alarm", parent={Thing::class}) public interface Alarm extends androidx.appactions.builtintypes.types.Thing {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.Alarm.Builder<?> Builder();
- method @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.types.Schedule? getAlarmSchedule();
- method @androidx.appsearch.annotation.Document.BooleanProperty public default Boolean? isAlarmEnabled();
- method public androidx.appactions.builtintypes.types.Alarm.Builder<?> toBuilder();
- property @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.types.Schedule? alarmSchedule;
- property @androidx.appsearch.annotation.Document.BooleanProperty public default Boolean? isAlarmEnabled;
- field public static final androidx.appactions.builtintypes.types.Alarm.Companion Companion;
- }
-
- public static interface Alarm.Builder<Self extends androidx.appactions.builtintypes.types.Alarm.Builder<Self>> extends androidx.appactions.builtintypes.types.Thing.Builder<Self> {
- method public androidx.appactions.builtintypes.types.Alarm build();
- method public default Self setAlarmEnabled(Boolean? boolean);
- method public default Self setAlarmSchedule(androidx.appactions.builtintypes.types.Schedule? schedule);
- }
-
- public static final class Alarm.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.Alarm.Builder<?> Builder();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:CommonExecutionStatus", parent={ExecutionStatus::class}) public interface CommonExecutionStatus extends androidx.appactions.builtintypes.types.ExecutionStatus {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.CommonExecutionStatus.Builder<?> Builder();
- method public androidx.appactions.builtintypes.types.CommonExecutionStatus.Builder<?> toBuilder();
- field public static final androidx.appactions.builtintypes.types.CommonExecutionStatus.Companion Companion;
- }
-
- public static interface CommonExecutionStatus.Builder<Self extends androidx.appactions.builtintypes.types.CommonExecutionStatus.Builder<Self>> extends androidx.appactions.builtintypes.types.ExecutionStatus.Builder<Self> {
- method public androidx.appactions.builtintypes.types.CommonExecutionStatus build();
- }
-
- public static final class CommonExecutionStatus.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.CommonExecutionStatus.Builder<?> Builder();
- }
-
- public final class DayOfWeek {
- method public String getCanonicalUrl();
- method public <R> R mapWhen(androidx.appactions.builtintypes.types.DayOfWeek.Mapper<R> mapper);
- method public static java.util.List<androidx.appactions.builtintypes.types.DayOfWeek> values();
- property public final String canonicalUrl;
- field public static final androidx.appactions.builtintypes.types.DayOfWeek.Companion Companion;
- field public static final androidx.appactions.builtintypes.types.DayOfWeek FRIDAY;
- field public static final androidx.appactions.builtintypes.types.DayOfWeek MONDAY;
- field public static final androidx.appactions.builtintypes.types.DayOfWeek PUBLIC_HOLIDAYS;
- field public static final androidx.appactions.builtintypes.types.DayOfWeek SATURDAY;
- field public static final androidx.appactions.builtintypes.types.DayOfWeek SUNDAY;
- field public static final androidx.appactions.builtintypes.types.DayOfWeek THURSDAY;
- field public static final androidx.appactions.builtintypes.types.DayOfWeek TUESDAY;
- field public static final androidx.appactions.builtintypes.types.DayOfWeek WEDNESDAY;
- }
-
- public static final class DayOfWeek.Companion {
- method public java.util.List<androidx.appactions.builtintypes.types.DayOfWeek> values();
- }
-
- public static interface DayOfWeek.Mapper<R> {
- method public default R friday();
- method public default R monday();
- method public R orElse();
- method public default R publicHolidays();
- method public default R saturday();
- method public default R sunday();
- method public default R thursday();
- method public default R tuesday();
- method public default R wednesday();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:ExecutionStatus", parent={Intangible::class}) public interface ExecutionStatus extends androidx.appactions.builtintypes.types.Intangible {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.ExecutionStatus.Builder<?> Builder();
- method public androidx.appactions.builtintypes.types.ExecutionStatus.Builder<?> toBuilder();
- field public static final androidx.appactions.builtintypes.types.ExecutionStatus.Companion Companion;
- }
-
- public static interface ExecutionStatus.Builder<Self extends androidx.appactions.builtintypes.types.ExecutionStatus.Builder<Self>> extends androidx.appactions.builtintypes.types.Intangible.Builder<Self> {
- method public androidx.appactions.builtintypes.types.ExecutionStatus build();
- }
-
- public static final class ExecutionStatus.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.ExecutionStatus.Builder<?> Builder();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:GenericErrorStatus", parent={CommonExecutionStatus::class}) public interface GenericErrorStatus extends androidx.appactions.builtintypes.types.CommonExecutionStatus {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.GenericErrorStatus.Builder<?> Builder();
- method public androidx.appactions.builtintypes.types.GenericErrorStatus.Builder<?> toBuilder();
- field public static final androidx.appactions.builtintypes.types.GenericErrorStatus.Companion Companion;
- }
-
- public static interface GenericErrorStatus.Builder<Self extends androidx.appactions.builtintypes.types.GenericErrorStatus.Builder<Self>> extends androidx.appactions.builtintypes.types.CommonExecutionStatus.Builder<Self> {
- method public androidx.appactions.builtintypes.types.GenericErrorStatus build();
- }
-
- public static final class GenericErrorStatus.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.GenericErrorStatus.Builder<?> Builder();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:Intangible", parent={Thing::class}) public interface Intangible extends androidx.appactions.builtintypes.types.Thing {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.Intangible.Builder<?> Builder();
- method public androidx.appactions.builtintypes.types.Intangible.Builder<?> toBuilder();
- field public static final androidx.appactions.builtintypes.types.Intangible.Companion Companion;
- }
-
- public static interface Intangible.Builder<Self extends androidx.appactions.builtintypes.types.Intangible.Builder<Self>> extends androidx.appactions.builtintypes.types.Thing.Builder<Self> {
- method public androidx.appactions.builtintypes.types.Intangible build();
- }
-
- public static final class Intangible.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.Intangible.Builder<?> Builder();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:ObjectCreationLimitReachedStatus", parent={ExecutionStatus::class}) public interface ObjectCreationLimitReachedStatus extends androidx.appactions.builtintypes.types.ExecutionStatus {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus.Builder<?> Builder();
- method public androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus.Builder<?> toBuilder();
- field public static final androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus.Companion Companion;
- }
-
- public static interface ObjectCreationLimitReachedStatus.Builder<Self extends androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus.Builder<Self>> extends androidx.appactions.builtintypes.types.ExecutionStatus.Builder<Self> {
- method public androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus build();
- }
-
- public static final class ObjectCreationLimitReachedStatus.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus.Builder<?> Builder();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:Person", parent={Thing::class}) public interface Person extends androidx.appactions.builtintypes.types.Thing {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.Person.Builder<?> Builder();
- method @androidx.appsearch.annotation.Document.StringProperty public default String? getEmail();
- method @androidx.appsearch.annotation.Document.StringProperty public default String? getTelephoneNumber();
- method public androidx.appactions.builtintypes.types.Person.Builder<?> toBuilder();
- property @androidx.appsearch.annotation.Document.StringProperty public default String? email;
- property @androidx.appsearch.annotation.Document.StringProperty public default String? telephoneNumber;
- field public static final androidx.appactions.builtintypes.types.Person.Companion Companion;
- }
-
- public static interface Person.Builder<Self extends androidx.appactions.builtintypes.types.Person.Builder<Self>> extends androidx.appactions.builtintypes.types.Thing.Builder<Self> {
- method public androidx.appactions.builtintypes.types.Person build();
- method public default Self setEmail(String? text);
- method public default Self setTelephoneNumber(String? text);
- }
-
- public static final class Person.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.Person.Builder<?> Builder();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:Schedule", parent={Intangible::class}) public interface Schedule extends androidx.appactions.builtintypes.types.Intangible {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.Schedule.Builder<?> Builder();
- method @androidx.appsearch.annotation.Document.DocumentProperty public default java.util.List<androidx.appactions.builtintypes.properties.ByDay> getByDays();
- method @androidx.appsearch.annotation.Document.LongProperty public default java.util.List<java.lang.Long> getByMonthDays();
- method @androidx.appsearch.annotation.Document.LongProperty public default java.util.List<java.lang.Long> getByMonthWeeks();
- method @androidx.appsearch.annotation.Document.LongProperty public default java.util.List<java.lang.Long> getByMonths();
- method @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.EndDate? getEndDate();
- method @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.EndTime? getEndTime();
- method @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.ExceptDate? getExceptDate();
- method @androidx.appsearch.annotation.Document.LongProperty public default Long? getRepeatCount();
- method @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.RepeatFrequency? getRepeatFrequency();
- method @androidx.appsearch.annotation.Document.StringProperty public default String? getScheduleTimezone();
- method @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.StartDate? getStartDate();
- method @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.StartTime? getStartTime();
- method public androidx.appactions.builtintypes.types.Schedule.Builder<?> toBuilder();
- property @androidx.appsearch.annotation.Document.DocumentProperty public default java.util.List<androidx.appactions.builtintypes.properties.ByDay> byDays;
- property @androidx.appsearch.annotation.Document.LongProperty public default java.util.List<java.lang.Long> byMonthDays;
- property @androidx.appsearch.annotation.Document.LongProperty public default java.util.List<java.lang.Long> byMonthWeeks;
- property @androidx.appsearch.annotation.Document.LongProperty public default java.util.List<java.lang.Long> byMonths;
- property @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.EndDate? endDate;
- property @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.EndTime? endTime;
- property @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.ExceptDate? exceptDate;
- property @androidx.appsearch.annotation.Document.LongProperty public default Long? repeatCount;
- property @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.RepeatFrequency? repeatFrequency;
- property @androidx.appsearch.annotation.Document.StringProperty public default String? scheduleTimezone;
- property @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.StartDate? startDate;
- property @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.StartTime? startTime;
- field public static final androidx.appactions.builtintypes.types.Schedule.Companion Companion;
- }
-
- public static interface Schedule.Builder<Self extends androidx.appactions.builtintypes.types.Schedule.Builder<Self>> extends androidx.appactions.builtintypes.types.Intangible.Builder<Self> {
- method public default Self addByDay(androidx.appactions.builtintypes.properties.ByDay byDay);
- method public default Self addByDay(androidx.appactions.builtintypes.types.DayOfWeek dayOfWeek);
- method public default Self addByDays(Iterable<androidx.appactions.builtintypes.properties.ByDay> values);
- method public default Self addByMonth(long integer);
- method public default Self addByMonthDay(long integer);
- method public default Self addByMonthDays(Iterable<java.lang.Long> values);
- method public default Self addByMonthWeek(long integer);
- method public default Self addByMonthWeeks(Iterable<java.lang.Long> values);
- method public default Self addByMonths(Iterable<java.lang.Long> values);
- method public androidx.appactions.builtintypes.types.Schedule build();
- method public default Self clearByDays();
- method public default Self clearByMonthDays();
- method public default Self clearByMonthWeeks();
- method public default Self clearByMonths();
- method public default Self setEndDate(androidx.appactions.builtintypes.properties.EndDate? endDate);
- method public default Self setEndDate(java.time.LocalDate date);
- method public default Self setEndTime(androidx.appactions.builtintypes.properties.EndTime? endTime);
- method public default Self setEndTime(java.time.LocalTime time);
- method public default Self setExceptDate(androidx.appactions.builtintypes.properties.ExceptDate? exceptDate);
- method public default Self setExceptDate(java.time.Instant instant);
- method public default Self setExceptDate(java.time.LocalDate date);
- method public default Self setExceptDate(java.time.LocalDateTime localDateTime);
- method public default Self setRepeatCount(Long? integer);
- method public default Self setRepeatFrequency(androidx.appactions.builtintypes.properties.RepeatFrequency? repeatFrequency);
- method public default Self setRepeatFrequency(java.time.Duration duration);
- method public default Self setScheduleTimezone(String? text);
- method public default Self setStartDate(androidx.appactions.builtintypes.properties.StartDate? startDate);
- method public default Self setStartDate(java.time.LocalDate date);
- method public default Self setStartTime(androidx.appactions.builtintypes.properties.StartTime? startTime);
- method public default Self setStartTime(java.time.LocalTime time);
- }
-
- public static final class Schedule.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.Schedule.Builder<?> Builder();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:SuccessStatus", parent={CommonExecutionStatus::class}) public interface SuccessStatus extends androidx.appactions.builtintypes.types.CommonExecutionStatus {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.SuccessStatus.Builder<?> Builder();
- method public androidx.appactions.builtintypes.types.SuccessStatus.Builder<?> toBuilder();
- field public static final androidx.appactions.builtintypes.types.SuccessStatus.Companion Companion;
- }
-
- public static interface SuccessStatus.Builder<Self extends androidx.appactions.builtintypes.types.SuccessStatus.Builder<Self>> extends androidx.appactions.builtintypes.types.CommonExecutionStatus.Builder<Self> {
- method public androidx.appactions.builtintypes.types.SuccessStatus build();
- }
-
- public static final class SuccessStatus.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.SuccessStatus.Builder<?> Builder();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:Thing") public interface Thing {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.Thing.Builder<?> Builder();
- method @androidx.appsearch.annotation.Document.Id public default String getIdentifier();
- method @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.Name? getName();
- method @androidx.appsearch.annotation.Document.Namespace public default String getNamespace();
- method public androidx.appactions.builtintypes.types.Thing.Builder<?> toBuilder();
- property @androidx.appsearch.annotation.Document.Id public default String identifier;
- property @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.Name? name;
- property @androidx.appsearch.annotation.Document.Namespace public default String namespace;
- field public static final androidx.appactions.builtintypes.types.Thing.Companion Companion;
- }
-
- public static interface Thing.Builder<Self extends androidx.appactions.builtintypes.types.Thing.Builder<Self>> {
- method public androidx.appactions.builtintypes.types.Thing build();
- method public default Self setIdentifier(String text);
- method public default Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public default Self setName(String text);
- method public default Self setNamespace(String namespace);
- }
-
- public static final class Thing.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.Thing.Builder<?> Builder();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:Timer", parent={Thing::class}) public interface Timer extends androidx.appactions.builtintypes.types.Thing {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.Timer.Builder<?> Builder();
- method @androidx.appsearch.annotation.Document.LongProperty(serializer=DurationAsNanosSerializer::class) public default java.time.Duration? getDuration();
- method public androidx.appactions.builtintypes.types.Timer.Builder<?> toBuilder();
- property @androidx.appsearch.annotation.Document.LongProperty(serializer=DurationAsNanosSerializer::class) public default java.time.Duration? duration;
- field public static final androidx.appactions.builtintypes.types.Timer.Companion Companion;
- }
-
- public static interface Timer.Builder<Self extends androidx.appactions.builtintypes.types.Timer.Builder<Self>> extends androidx.appactions.builtintypes.types.Thing.Builder<Self> {
- method public androidx.appactions.builtintypes.types.Timer build();
- method public default Self setDuration(java.time.Duration? duration);
- }
-
- public static final class Timer.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.Timer.Builder<?> Builder();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:UnsupportedOperationStatus", parent={ExecutionStatus::class}) public interface UnsupportedOperationStatus extends androidx.appactions.builtintypes.types.ExecutionStatus {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.UnsupportedOperationStatus.Builder<?> Builder();
- method public androidx.appactions.builtintypes.types.UnsupportedOperationStatus.Builder<?> toBuilder();
- field public static final androidx.appactions.builtintypes.types.UnsupportedOperationStatus.Companion Companion;
- }
-
- public static interface UnsupportedOperationStatus.Builder<Self extends androidx.appactions.builtintypes.types.UnsupportedOperationStatus.Builder<Self>> extends androidx.appactions.builtintypes.types.ExecutionStatus.Builder<Self> {
- method public androidx.appactions.builtintypes.types.UnsupportedOperationStatus build();
- }
-
- public static final class UnsupportedOperationStatus.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.UnsupportedOperationStatus.Builder<?> Builder();
- }
-
-}
-
diff --git a/appactions/builtintypes/builtintypes/api/restricted_current.txt b/appactions/builtintypes/builtintypes/api/restricted_current.txt
deleted file mode 100644
index ca92db8..0000000
--- a/appactions/builtintypes/builtintypes/api/restricted_current.txt
+++ /dev/null
@@ -1,868 +0,0 @@
-// Signature format: 4.0
-package androidx.appactions.builtintypes.properties {
-
- @androidx.appsearch.annotation.Document(name="bitprop:ByDay") public final class ByDay {
- ctor public ByDay(androidx.appactions.builtintypes.types.DayOfWeek dayOfWeek);
- method @androidx.appsearch.annotation.Document.StringProperty(serializer=DayOfWeekAsCanonicalUrlSerializer::class) public androidx.appactions.builtintypes.types.DayOfWeek? asDayOfWeek();
- property @androidx.appsearch.annotation.Document.StringProperty(serializer=DayOfWeekAsCanonicalUrlSerializer::class) public final androidx.appactions.builtintypes.types.DayOfWeek? asDayOfWeek;
- }
-
- @androidx.appsearch.annotation.Document(name="bitprop:EndDate") public final class EndDate {
- ctor public EndDate(java.time.LocalDate date);
- method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public java.time.LocalDate? asDate();
- property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public final java.time.LocalDate? asDate;
- }
-
- @androidx.appsearch.annotation.Document(name="bitprop:EndTime") public final class EndTime {
- ctor public EndTime(java.time.LocalTime time);
- method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalTimeAsNanoOfDaySerializer::class) public java.time.LocalTime? asTime();
- property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalTimeAsNanoOfDaySerializer::class) public final java.time.LocalTime? asTime;
- }
-
- @androidx.appsearch.annotation.Document(name="bitprop:ExceptDate") public final class ExceptDate {
- ctor public ExceptDate(java.time.Instant instant);
- ctor public ExceptDate(java.time.LocalDate date);
- ctor public ExceptDate(java.time.LocalDateTime localDateTime);
- method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public java.time.LocalDate? asDate();
- method @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public java.time.Instant? asInstant();
- method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public java.time.LocalDateTime? asLocalDateTime();
- method public <R> R mapWhen(androidx.appactions.builtintypes.properties.ExceptDate.Mapper<R> mapper);
- property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public final java.time.LocalDate? asDate;
- property @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public final java.time.Instant? asInstant;
- property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public final java.time.LocalDateTime? asLocalDateTime;
- }
-
- public static interface ExceptDate.Mapper<R> {
- method public default R date(java.time.LocalDate instance);
- method public default R instant(java.time.Instant instance);
- method public default R localDateTime(java.time.LocalDateTime instance);
- method public R orElse();
- }
-
- @androidx.appsearch.annotation.Document(name="bitprop:Name") public final class Name {
- ctor public Name(String text);
- method @androidx.appsearch.annotation.Document.StringProperty public String? asText();
- property @androidx.appsearch.annotation.Document.StringProperty public final String? asText;
- }
-
- @androidx.appsearch.annotation.Document(name="bitprop:RepeatFrequency") public final class RepeatFrequency {
- ctor public RepeatFrequency(java.time.Duration duration);
- method @androidx.appsearch.annotation.Document.LongProperty(serializer=DurationAsNanosSerializer::class) public java.time.Duration? asDuration();
- property @androidx.appsearch.annotation.Document.LongProperty(serializer=DurationAsNanosSerializer::class) public final java.time.Duration? asDuration;
- }
-
- @androidx.appsearch.annotation.Document(name="bitprop:StartDate") public final class StartDate {
- ctor public StartDate(java.time.LocalDate date);
- method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public java.time.LocalDate? asDate();
- property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public final java.time.LocalDate? asDate;
- }
-
- @androidx.appsearch.annotation.Document(name="bitprop:StartTime") public final class StartTime {
- ctor public StartTime(java.time.LocalTime time);
- method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalTimeAsNanoOfDaySerializer::class) public java.time.LocalTime? asTime();
- property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalTimeAsNanoOfDaySerializer::class) public final java.time.LocalTime? asTime;
- }
-
-}
-
-package androidx.appactions.builtintypes.serializers {
-
- public final class DayOfWeekAsCanonicalUrlSerializer implements androidx.appsearch.app.StringSerializer<androidx.appactions.builtintypes.types.DayOfWeek> {
- ctor public DayOfWeekAsCanonicalUrlSerializer();
- method public androidx.appactions.builtintypes.types.DayOfWeek? deserialize(String value);
- method public String serialize(androidx.appactions.builtintypes.types.DayOfWeek instance);
- }
-
- public final class DurationAsNanosSerializer implements androidx.appsearch.app.LongSerializer<java.time.Duration> {
- ctor public DurationAsNanosSerializer();
- method public java.time.Duration deserialize(long value);
- method public long serialize(java.time.Duration instance);
- }
-
- public final class InstantAsEpochMilliSerializer implements androidx.appsearch.app.LongSerializer<java.time.Instant> {
- ctor public InstantAsEpochMilliSerializer();
- method public java.time.Instant deserialize(long value);
- method public long serialize(java.time.Instant instance);
- }
-
- public final class LocalDateAsEpochDaySerializer implements androidx.appsearch.app.LongSerializer<java.time.LocalDate> {
- ctor public LocalDateAsEpochDaySerializer();
- method public java.time.LocalDate deserialize(long value);
- method public long serialize(java.time.LocalDate instance);
- }
-
- public final class LocalDateTimeAsUtcEpochSecondSerializer implements androidx.appsearch.app.LongSerializer<java.time.LocalDateTime> {
- ctor public LocalDateTimeAsUtcEpochSecondSerializer();
- method public java.time.LocalDateTime deserialize(long value);
- method public long serialize(java.time.LocalDateTime instance);
- }
-
- public final class LocalTimeAsNanoOfDaySerializer implements androidx.appsearch.app.LongSerializer<java.time.LocalTime> {
- ctor public LocalTimeAsNanoOfDaySerializer();
- method public java.time.LocalTime deserialize(long value);
- method public long serialize(java.time.LocalTime instance);
- }
-
-}
-
-package androidx.appactions.builtintypes.types {
-
- public abstract class AbstractAlarm<Self extends androidx.appactions.builtintypes.types.AbstractAlarm<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractAlarm.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.Alarm {
- ctor public AbstractAlarm(androidx.appactions.builtintypes.types.Alarm alarm);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final androidx.appactions.builtintypes.types.Schedule? getAlarmSchedule();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Boolean? isAlarmEnabled();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final androidx.appactions.builtintypes.types.Schedule? alarmSchedule;
- property public final String identifier;
- property public final Boolean? isAlarmEnabled;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- }
-
- public abstract static class AbstractAlarm.Builder<Self extends androidx.appactions.builtintypes.types.AbstractAlarm.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractAlarm<Built, Self>> implements androidx.appactions.builtintypes.types.Alarm.Builder<Self> {
- ctor public AbstractAlarm.Builder();
- method public final Built build();
- method protected abstract Built buildFromAlarm(androidx.appactions.builtintypes.types.Alarm alarm);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setAlarmEnabled(Boolean? boolean);
- method public final Self setAlarmSchedule(androidx.appactions.builtintypes.types.Schedule? schedule);
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractCommonExecutionStatus<Self extends androidx.appactions.builtintypes.types.AbstractCommonExecutionStatus<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractCommonExecutionStatus.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.CommonExecutionStatus {
- ctor public AbstractCommonExecutionStatus(androidx.appactions.builtintypes.types.CommonExecutionStatus commonExecutionStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- }
-
- public abstract static class AbstractCommonExecutionStatus.Builder<Self extends androidx.appactions.builtintypes.types.AbstractCommonExecutionStatus.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractCommonExecutionStatus<Built, Self>> implements androidx.appactions.builtintypes.types.CommonExecutionStatus.Builder<Self> {
- ctor public AbstractCommonExecutionStatus.Builder();
- method public final Built build();
- method protected abstract Built buildFromCommonExecutionStatus(androidx.appactions.builtintypes.types.CommonExecutionStatus commonExecutionStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractExecutionStatus<Self extends androidx.appactions.builtintypes.types.AbstractExecutionStatus<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractExecutionStatus.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.ExecutionStatus {
- ctor public AbstractExecutionStatus(androidx.appactions.builtintypes.types.ExecutionStatus executionStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- }
-
- public abstract static class AbstractExecutionStatus.Builder<Self extends androidx.appactions.builtintypes.types.AbstractExecutionStatus.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractExecutionStatus<Built, Self>> implements androidx.appactions.builtintypes.types.ExecutionStatus.Builder<Self> {
- ctor public AbstractExecutionStatus.Builder();
- method public final Built build();
- method protected abstract Built buildFromExecutionStatus(androidx.appactions.builtintypes.types.ExecutionStatus executionStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractGenericErrorStatus<Self extends androidx.appactions.builtintypes.types.AbstractGenericErrorStatus<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractGenericErrorStatus.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.GenericErrorStatus {
- ctor public AbstractGenericErrorStatus(androidx.appactions.builtintypes.types.GenericErrorStatus genericErrorStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- }
-
- public abstract static class AbstractGenericErrorStatus.Builder<Self extends androidx.appactions.builtintypes.types.AbstractGenericErrorStatus.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractGenericErrorStatus<Built, Self>> implements androidx.appactions.builtintypes.types.GenericErrorStatus.Builder<Self> {
- ctor public AbstractGenericErrorStatus.Builder();
- method public final Built build();
- method protected abstract Built buildFromGenericErrorStatus(androidx.appactions.builtintypes.types.GenericErrorStatus genericErrorStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractIntangible<Self extends androidx.appactions.builtintypes.types.AbstractIntangible<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractIntangible.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.Intangible {
- ctor public AbstractIntangible(androidx.appactions.builtintypes.types.Intangible intangible);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- }
-
- public abstract static class AbstractIntangible.Builder<Self extends androidx.appactions.builtintypes.types.AbstractIntangible.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractIntangible<Built, Self>> implements androidx.appactions.builtintypes.types.Intangible.Builder<Self> {
- ctor public AbstractIntangible.Builder();
- method public final Built build();
- method protected abstract Built buildFromIntangible(androidx.appactions.builtintypes.types.Intangible intangible);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractObjectCreationLimitReachedStatus<Self extends androidx.appactions.builtintypes.types.AbstractObjectCreationLimitReachedStatus<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractObjectCreationLimitReachedStatus.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus {
- ctor public AbstractObjectCreationLimitReachedStatus(androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus objectCreationLimitReachedStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- }
-
- public abstract static class AbstractObjectCreationLimitReachedStatus.Builder<Self extends androidx.appactions.builtintypes.types.AbstractObjectCreationLimitReachedStatus.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractObjectCreationLimitReachedStatus<Built, Self>> implements androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus.Builder<Self> {
- ctor public AbstractObjectCreationLimitReachedStatus.Builder();
- method public final Built build();
- method protected abstract Built buildFromObjectCreationLimitReachedStatus(androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus objectCreationLimitReachedStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractPerson<Self extends androidx.appactions.builtintypes.types.AbstractPerson<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractPerson.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.Person {
- ctor public AbstractPerson(androidx.appactions.builtintypes.types.Person person);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final String? getEmail();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final String? getTelephoneNumber();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final String? email;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- property public final String? telephoneNumber;
- }
-
- public abstract static class AbstractPerson.Builder<Self extends androidx.appactions.builtintypes.types.AbstractPerson.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractPerson<Built, Self>> implements androidx.appactions.builtintypes.types.Person.Builder<Self> {
- ctor public AbstractPerson.Builder();
- method public final Built build();
- method protected abstract Built buildFromPerson(androidx.appactions.builtintypes.types.Person person);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setEmail(String? text);
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final Self setTelephoneNumber(String? text);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractSchedule<Self extends androidx.appactions.builtintypes.types.AbstractSchedule<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractSchedule.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.Schedule {
- ctor public AbstractSchedule(androidx.appactions.builtintypes.types.Schedule schedule);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final java.util.List<androidx.appactions.builtintypes.properties.ByDay> getByDays();
- method public final java.util.List<java.lang.Long> getByMonthDays();
- method public final java.util.List<java.lang.Long> getByMonthWeeks();
- method public final java.util.List<java.lang.Long> getByMonths();
- method public final androidx.appactions.builtintypes.properties.EndDate? getEndDate();
- method public final androidx.appactions.builtintypes.properties.EndTime? getEndTime();
- method public final androidx.appactions.builtintypes.properties.ExceptDate? getExceptDate();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method public final Long? getRepeatCount();
- method public final androidx.appactions.builtintypes.properties.RepeatFrequency? getRepeatFrequency();
- method public final String? getScheduleTimezone();
- method protected abstract String getSelfTypeName();
- method public final androidx.appactions.builtintypes.properties.StartDate? getStartDate();
- method public final androidx.appactions.builtintypes.properties.StartTime? getStartTime();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final java.util.List<androidx.appactions.builtintypes.properties.ByDay> byDays;
- property public final java.util.List<java.lang.Long> byMonthDays;
- property public final java.util.List<java.lang.Long> byMonthWeeks;
- property public final java.util.List<java.lang.Long> byMonths;
- property public final androidx.appactions.builtintypes.properties.EndDate? endDate;
- property public final androidx.appactions.builtintypes.properties.EndTime? endTime;
- property public final androidx.appactions.builtintypes.properties.ExceptDate? exceptDate;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property public final Long? repeatCount;
- property public final androidx.appactions.builtintypes.properties.RepeatFrequency? repeatFrequency;
- property public final String? scheduleTimezone;
- property protected abstract String selfTypeName;
- property public final androidx.appactions.builtintypes.properties.StartDate? startDate;
- property public final androidx.appactions.builtintypes.properties.StartTime? startTime;
- }
-
- public abstract static class AbstractSchedule.Builder<Self extends androidx.appactions.builtintypes.types.AbstractSchedule.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractSchedule<Built, Self>> implements androidx.appactions.builtintypes.types.Schedule.Builder<Self> {
- ctor public AbstractSchedule.Builder();
- method public final Self addByDay(androidx.appactions.builtintypes.properties.ByDay byDay);
- method public final Self addByDays(Iterable<androidx.appactions.builtintypes.properties.ByDay> values);
- method public final Self addByMonth(long integer);
- method public final Self addByMonthDay(long integer);
- method public final Self addByMonthDays(Iterable<java.lang.Long> values);
- method public final Self addByMonthWeek(long integer);
- method public final Self addByMonthWeeks(Iterable<java.lang.Long> values);
- method public final Self addByMonths(Iterable<java.lang.Long> values);
- method public final Built build();
- method protected abstract Built buildFromSchedule(androidx.appactions.builtintypes.types.Schedule schedule);
- method public final Self clearByDays();
- method public final Self clearByMonthDays();
- method public final Self clearByMonthWeeks();
- method public final Self clearByMonths();
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setEndDate(androidx.appactions.builtintypes.properties.EndDate? endDate);
- method public final Self setEndTime(androidx.appactions.builtintypes.properties.EndTime? endTime);
- method public final Self setExceptDate(androidx.appactions.builtintypes.properties.ExceptDate? exceptDate);
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final Self setRepeatCount(Long? integer);
- method public final Self setRepeatFrequency(androidx.appactions.builtintypes.properties.RepeatFrequency? repeatFrequency);
- method public final Self setScheduleTimezone(String? text);
- method public final Self setStartDate(androidx.appactions.builtintypes.properties.StartDate? startDate);
- method public final Self setStartTime(androidx.appactions.builtintypes.properties.StartTime? startTime);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractSuccessStatus<Self extends androidx.appactions.builtintypes.types.AbstractSuccessStatus<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractSuccessStatus.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.SuccessStatus {
- ctor public AbstractSuccessStatus(androidx.appactions.builtintypes.types.SuccessStatus successStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- }
-
- public abstract static class AbstractSuccessStatus.Builder<Self extends androidx.appactions.builtintypes.types.AbstractSuccessStatus.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractSuccessStatus<Built, Self>> implements androidx.appactions.builtintypes.types.SuccessStatus.Builder<Self> {
- ctor public AbstractSuccessStatus.Builder();
- method public final Built build();
- method protected abstract Built buildFromSuccessStatus(androidx.appactions.builtintypes.types.SuccessStatus successStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractThing<Self extends androidx.appactions.builtintypes.types.AbstractThing<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractThing.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.Thing {
- ctor public AbstractThing(androidx.appactions.builtintypes.types.Thing thing);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- }
-
- public abstract static class AbstractThing.Builder<Self extends androidx.appactions.builtintypes.types.AbstractThing.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractThing<Built, Self>> implements androidx.appactions.builtintypes.types.Thing.Builder<Self> {
- ctor public AbstractThing.Builder();
- method public final Built build();
- method protected abstract Built buildFromThing(androidx.appactions.builtintypes.types.Thing thing);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractTimer<Self extends androidx.appactions.builtintypes.types.AbstractTimer<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractTimer.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.Timer {
- ctor public AbstractTimer(androidx.appactions.builtintypes.types.Timer timer);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final java.time.Duration? getDuration();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final java.time.Duration? duration;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- }
-
- public abstract static class AbstractTimer.Builder<Self extends androidx.appactions.builtintypes.types.AbstractTimer.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractTimer<Built, Self>> implements androidx.appactions.builtintypes.types.Timer.Builder<Self> {
- ctor public AbstractTimer.Builder();
- method public final Built build();
- method protected abstract Built buildFromTimer(androidx.appactions.builtintypes.types.Timer timer);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setDuration(java.time.Duration? duration);
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- public abstract class AbstractUnsupportedOperationStatus<Self extends androidx.appactions.builtintypes.types.AbstractUnsupportedOperationStatus<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractUnsupportedOperationStatus.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.UnsupportedOperationStatus {
- ctor public AbstractUnsupportedOperationStatus(androidx.appactions.builtintypes.types.UnsupportedOperationStatus unsupportedOperationStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method public final String getIdentifier();
- method public final androidx.appactions.builtintypes.properties.Name? getName();
- method public final String getNamespace();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Builder toBuilder();
- method protected abstract Builder toBuilderWithAdditionalPropertiesOnly();
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property public final String identifier;
- property public final androidx.appactions.builtintypes.properties.Name? name;
- property public final String namespace;
- property protected abstract String selfTypeName;
- }
-
- public abstract static class AbstractUnsupportedOperationStatus.Builder<Self extends androidx.appactions.builtintypes.types.AbstractUnsupportedOperationStatus.Builder<Self, Built>, Built extends androidx.appactions.builtintypes.types.AbstractUnsupportedOperationStatus<Built, Self>> implements androidx.appactions.builtintypes.types.UnsupportedOperationStatus.Builder<Self> {
- ctor public AbstractUnsupportedOperationStatus.Builder();
- method public final Built build();
- method protected abstract Built buildFromUnsupportedOperationStatus(androidx.appactions.builtintypes.types.UnsupportedOperationStatus unsupportedOperationStatus);
- method public final boolean equals(Object? other);
- method protected abstract java.util.Map<java.lang.String,java.lang.Object?> getAdditionalProperties();
- method protected abstract String getSelfTypeName();
- method public final int hashCode();
- method public final Self setIdentifier(String text);
- method public final Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public final Self setNamespace(String namespace);
- method public final String toString();
- property protected abstract java.util.Map<java.lang.String,java.lang.Object?> additionalProperties;
- property protected abstract String selfTypeName;
- }
-
- @androidx.appsearch.annotation.Document(name="bit:Alarm", parent={Thing::class}) public interface Alarm extends androidx.appactions.builtintypes.types.Thing {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.Alarm.Builder<?> Builder();
- method @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.types.Schedule? getAlarmSchedule();
- method @androidx.appsearch.annotation.Document.BooleanProperty public default Boolean? isAlarmEnabled();
- method public androidx.appactions.builtintypes.types.Alarm.Builder<?> toBuilder();
- property @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.types.Schedule? alarmSchedule;
- property @androidx.appsearch.annotation.Document.BooleanProperty public default Boolean? isAlarmEnabled;
- field public static final androidx.appactions.builtintypes.types.Alarm.Companion Companion;
- }
-
- public static interface Alarm.Builder<Self extends androidx.appactions.builtintypes.types.Alarm.Builder<Self>> extends androidx.appactions.builtintypes.types.Thing.Builder<Self> {
- method public androidx.appactions.builtintypes.types.Alarm build();
- method public default Self setAlarmEnabled(Boolean? boolean);
- method public default Self setAlarmSchedule(androidx.appactions.builtintypes.types.Schedule? schedule);
- }
-
- public static final class Alarm.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.Alarm.Builder<?> Builder();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:CommonExecutionStatus", parent={ExecutionStatus::class}) public interface CommonExecutionStatus extends androidx.appactions.builtintypes.types.ExecutionStatus {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.CommonExecutionStatus.Builder<?> Builder();
- method public androidx.appactions.builtintypes.types.CommonExecutionStatus.Builder<?> toBuilder();
- field public static final androidx.appactions.builtintypes.types.CommonExecutionStatus.Companion Companion;
- }
-
- public static interface CommonExecutionStatus.Builder<Self extends androidx.appactions.builtintypes.types.CommonExecutionStatus.Builder<Self>> extends androidx.appactions.builtintypes.types.ExecutionStatus.Builder<Self> {
- method public androidx.appactions.builtintypes.types.CommonExecutionStatus build();
- }
-
- public static final class CommonExecutionStatus.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.CommonExecutionStatus.Builder<?> Builder();
- }
-
- public final class DayOfWeek {
- method public String getCanonicalUrl();
- method public <R> R mapWhen(androidx.appactions.builtintypes.types.DayOfWeek.Mapper<R> mapper);
- method public static java.util.List<androidx.appactions.builtintypes.types.DayOfWeek> values();
- property public final String canonicalUrl;
- field public static final androidx.appactions.builtintypes.types.DayOfWeek.Companion Companion;
- field public static final androidx.appactions.builtintypes.types.DayOfWeek FRIDAY;
- field public static final androidx.appactions.builtintypes.types.DayOfWeek MONDAY;
- field public static final androidx.appactions.builtintypes.types.DayOfWeek PUBLIC_HOLIDAYS;
- field public static final androidx.appactions.builtintypes.types.DayOfWeek SATURDAY;
- field public static final androidx.appactions.builtintypes.types.DayOfWeek SUNDAY;
- field public static final androidx.appactions.builtintypes.types.DayOfWeek THURSDAY;
- field public static final androidx.appactions.builtintypes.types.DayOfWeek TUESDAY;
- field public static final androidx.appactions.builtintypes.types.DayOfWeek WEDNESDAY;
- }
-
- public static final class DayOfWeek.Companion {
- method public java.util.List<androidx.appactions.builtintypes.types.DayOfWeek> values();
- }
-
- public static interface DayOfWeek.Mapper<R> {
- method public default R friday();
- method public default R monday();
- method public R orElse();
- method public default R publicHolidays();
- method public default R saturday();
- method public default R sunday();
- method public default R thursday();
- method public default R tuesday();
- method public default R wednesday();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:ExecutionStatus", parent={Intangible::class}) public interface ExecutionStatus extends androidx.appactions.builtintypes.types.Intangible {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.ExecutionStatus.Builder<?> Builder();
- method public androidx.appactions.builtintypes.types.ExecutionStatus.Builder<?> toBuilder();
- field public static final androidx.appactions.builtintypes.types.ExecutionStatus.Companion Companion;
- }
-
- public static interface ExecutionStatus.Builder<Self extends androidx.appactions.builtintypes.types.ExecutionStatus.Builder<Self>> extends androidx.appactions.builtintypes.types.Intangible.Builder<Self> {
- method public androidx.appactions.builtintypes.types.ExecutionStatus build();
- }
-
- public static final class ExecutionStatus.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.ExecutionStatus.Builder<?> Builder();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:GenericErrorStatus", parent={CommonExecutionStatus::class}) public interface GenericErrorStatus extends androidx.appactions.builtintypes.types.CommonExecutionStatus {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.GenericErrorStatus.Builder<?> Builder();
- method public androidx.appactions.builtintypes.types.GenericErrorStatus.Builder<?> toBuilder();
- field public static final androidx.appactions.builtintypes.types.GenericErrorStatus.Companion Companion;
- }
-
- public static interface GenericErrorStatus.Builder<Self extends androidx.appactions.builtintypes.types.GenericErrorStatus.Builder<Self>> extends androidx.appactions.builtintypes.types.CommonExecutionStatus.Builder<Self> {
- method public androidx.appactions.builtintypes.types.GenericErrorStatus build();
- }
-
- public static final class GenericErrorStatus.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.GenericErrorStatus.Builder<?> Builder();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:Intangible", parent={Thing::class}) public interface Intangible extends androidx.appactions.builtintypes.types.Thing {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.Intangible.Builder<?> Builder();
- method public androidx.appactions.builtintypes.types.Intangible.Builder<?> toBuilder();
- field public static final androidx.appactions.builtintypes.types.Intangible.Companion Companion;
- }
-
- public static interface Intangible.Builder<Self extends androidx.appactions.builtintypes.types.Intangible.Builder<Self>> extends androidx.appactions.builtintypes.types.Thing.Builder<Self> {
- method public androidx.appactions.builtintypes.types.Intangible build();
- }
-
- public static final class Intangible.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.Intangible.Builder<?> Builder();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:ObjectCreationLimitReachedStatus", parent={ExecutionStatus::class}) public interface ObjectCreationLimitReachedStatus extends androidx.appactions.builtintypes.types.ExecutionStatus {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus.Builder<?> Builder();
- method public androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus.Builder<?> toBuilder();
- field public static final androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus.Companion Companion;
- }
-
- public static interface ObjectCreationLimitReachedStatus.Builder<Self extends androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus.Builder<Self>> extends androidx.appactions.builtintypes.types.ExecutionStatus.Builder<Self> {
- method public androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus build();
- }
-
- public static final class ObjectCreationLimitReachedStatus.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus.Builder<?> Builder();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:Person", parent={Thing::class}) public interface Person extends androidx.appactions.builtintypes.types.Thing {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.Person.Builder<?> Builder();
- method @androidx.appsearch.annotation.Document.StringProperty public default String? getEmail();
- method @androidx.appsearch.annotation.Document.StringProperty public default String? getTelephoneNumber();
- method public androidx.appactions.builtintypes.types.Person.Builder<?> toBuilder();
- property @androidx.appsearch.annotation.Document.StringProperty public default String? email;
- property @androidx.appsearch.annotation.Document.StringProperty public default String? telephoneNumber;
- field public static final androidx.appactions.builtintypes.types.Person.Companion Companion;
- }
-
- public static interface Person.Builder<Self extends androidx.appactions.builtintypes.types.Person.Builder<Self>> extends androidx.appactions.builtintypes.types.Thing.Builder<Self> {
- method public androidx.appactions.builtintypes.types.Person build();
- method public default Self setEmail(String? text);
- method public default Self setTelephoneNumber(String? text);
- }
-
- public static final class Person.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.Person.Builder<?> Builder();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:Schedule", parent={Intangible::class}) public interface Schedule extends androidx.appactions.builtintypes.types.Intangible {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.Schedule.Builder<?> Builder();
- method @androidx.appsearch.annotation.Document.DocumentProperty public default java.util.List<androidx.appactions.builtintypes.properties.ByDay> getByDays();
- method @androidx.appsearch.annotation.Document.LongProperty public default java.util.List<java.lang.Long> getByMonthDays();
- method @androidx.appsearch.annotation.Document.LongProperty public default java.util.List<java.lang.Long> getByMonthWeeks();
- method @androidx.appsearch.annotation.Document.LongProperty public default java.util.List<java.lang.Long> getByMonths();
- method @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.EndDate? getEndDate();
- method @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.EndTime? getEndTime();
- method @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.ExceptDate? getExceptDate();
- method @androidx.appsearch.annotation.Document.LongProperty public default Long? getRepeatCount();
- method @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.RepeatFrequency? getRepeatFrequency();
- method @androidx.appsearch.annotation.Document.StringProperty public default String? getScheduleTimezone();
- method @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.StartDate? getStartDate();
- method @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.StartTime? getStartTime();
- method public androidx.appactions.builtintypes.types.Schedule.Builder<?> toBuilder();
- property @androidx.appsearch.annotation.Document.DocumentProperty public default java.util.List<androidx.appactions.builtintypes.properties.ByDay> byDays;
- property @androidx.appsearch.annotation.Document.LongProperty public default java.util.List<java.lang.Long> byMonthDays;
- property @androidx.appsearch.annotation.Document.LongProperty public default java.util.List<java.lang.Long> byMonthWeeks;
- property @androidx.appsearch.annotation.Document.LongProperty public default java.util.List<java.lang.Long> byMonths;
- property @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.EndDate? endDate;
- property @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.EndTime? endTime;
- property @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.ExceptDate? exceptDate;
- property @androidx.appsearch.annotation.Document.LongProperty public default Long? repeatCount;
- property @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.RepeatFrequency? repeatFrequency;
- property @androidx.appsearch.annotation.Document.StringProperty public default String? scheduleTimezone;
- property @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.StartDate? startDate;
- property @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.StartTime? startTime;
- field public static final androidx.appactions.builtintypes.types.Schedule.Companion Companion;
- }
-
- public static interface Schedule.Builder<Self extends androidx.appactions.builtintypes.types.Schedule.Builder<Self>> extends androidx.appactions.builtintypes.types.Intangible.Builder<Self> {
- method public default Self addByDay(androidx.appactions.builtintypes.properties.ByDay byDay);
- method public default Self addByDay(androidx.appactions.builtintypes.types.DayOfWeek dayOfWeek);
- method public default Self addByDays(Iterable<androidx.appactions.builtintypes.properties.ByDay> values);
- method public default Self addByMonth(long integer);
- method public default Self addByMonthDay(long integer);
- method public default Self addByMonthDays(Iterable<java.lang.Long> values);
- method public default Self addByMonthWeek(long integer);
- method public default Self addByMonthWeeks(Iterable<java.lang.Long> values);
- method public default Self addByMonths(Iterable<java.lang.Long> values);
- method public androidx.appactions.builtintypes.types.Schedule build();
- method public default Self clearByDays();
- method public default Self clearByMonthDays();
- method public default Self clearByMonthWeeks();
- method public default Self clearByMonths();
- method public default Self setEndDate(androidx.appactions.builtintypes.properties.EndDate? endDate);
- method public default Self setEndDate(java.time.LocalDate date);
- method public default Self setEndTime(androidx.appactions.builtintypes.properties.EndTime? endTime);
- method public default Self setEndTime(java.time.LocalTime time);
- method public default Self setExceptDate(androidx.appactions.builtintypes.properties.ExceptDate? exceptDate);
- method public default Self setExceptDate(java.time.Instant instant);
- method public default Self setExceptDate(java.time.LocalDate date);
- method public default Self setExceptDate(java.time.LocalDateTime localDateTime);
- method public default Self setRepeatCount(Long? integer);
- method public default Self setRepeatFrequency(androidx.appactions.builtintypes.properties.RepeatFrequency? repeatFrequency);
- method public default Self setRepeatFrequency(java.time.Duration duration);
- method public default Self setScheduleTimezone(String? text);
- method public default Self setStartDate(androidx.appactions.builtintypes.properties.StartDate? startDate);
- method public default Self setStartDate(java.time.LocalDate date);
- method public default Self setStartTime(androidx.appactions.builtintypes.properties.StartTime? startTime);
- method public default Self setStartTime(java.time.LocalTime time);
- }
-
- public static final class Schedule.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.Schedule.Builder<?> Builder();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:SuccessStatus", parent={CommonExecutionStatus::class}) public interface SuccessStatus extends androidx.appactions.builtintypes.types.CommonExecutionStatus {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.SuccessStatus.Builder<?> Builder();
- method public androidx.appactions.builtintypes.types.SuccessStatus.Builder<?> toBuilder();
- field public static final androidx.appactions.builtintypes.types.SuccessStatus.Companion Companion;
- }
-
- public static interface SuccessStatus.Builder<Self extends androidx.appactions.builtintypes.types.SuccessStatus.Builder<Self>> extends androidx.appactions.builtintypes.types.CommonExecutionStatus.Builder<Self> {
- method public androidx.appactions.builtintypes.types.SuccessStatus build();
- }
-
- public static final class SuccessStatus.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.SuccessStatus.Builder<?> Builder();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:Thing") public interface Thing {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.Thing.Builder<?> Builder();
- method @androidx.appsearch.annotation.Document.Id public default String getIdentifier();
- method @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.Name? getName();
- method @androidx.appsearch.annotation.Document.Namespace public default String getNamespace();
- method public androidx.appactions.builtintypes.types.Thing.Builder<?> toBuilder();
- property @androidx.appsearch.annotation.Document.Id public default String identifier;
- property @androidx.appsearch.annotation.Document.DocumentProperty public default androidx.appactions.builtintypes.properties.Name? name;
- property @androidx.appsearch.annotation.Document.Namespace public default String namespace;
- field public static final androidx.appactions.builtintypes.types.Thing.Companion Companion;
- }
-
- public static interface Thing.Builder<Self extends androidx.appactions.builtintypes.types.Thing.Builder<Self>> {
- method public androidx.appactions.builtintypes.types.Thing build();
- method public default Self setIdentifier(String text);
- method public default Self setName(androidx.appactions.builtintypes.properties.Name? name);
- method public default Self setName(String text);
- method public default Self setNamespace(String namespace);
- }
-
- public static final class Thing.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.Thing.Builder<?> Builder();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:Timer", parent={Thing::class}) public interface Timer extends androidx.appactions.builtintypes.types.Thing {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.Timer.Builder<?> Builder();
- method @androidx.appsearch.annotation.Document.LongProperty(serializer=DurationAsNanosSerializer::class) public default java.time.Duration? getDuration();
- method public androidx.appactions.builtintypes.types.Timer.Builder<?> toBuilder();
- property @androidx.appsearch.annotation.Document.LongProperty(serializer=DurationAsNanosSerializer::class) public default java.time.Duration? duration;
- field public static final androidx.appactions.builtintypes.types.Timer.Companion Companion;
- }
-
- public static interface Timer.Builder<Self extends androidx.appactions.builtintypes.types.Timer.Builder<Self>> extends androidx.appactions.builtintypes.types.Thing.Builder<Self> {
- method public androidx.appactions.builtintypes.types.Timer build();
- method public default Self setDuration(java.time.Duration? duration);
- }
-
- public static final class Timer.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.Timer.Builder<?> Builder();
- }
-
- @androidx.appsearch.annotation.Document(name="bit:UnsupportedOperationStatus", parent={ExecutionStatus::class}) public interface UnsupportedOperationStatus extends androidx.appactions.builtintypes.types.ExecutionStatus {
- method @androidx.appsearch.annotation.Document.BuilderProducer public static androidx.appactions.builtintypes.types.UnsupportedOperationStatus.Builder<?> Builder();
- method public androidx.appactions.builtintypes.types.UnsupportedOperationStatus.Builder<?> toBuilder();
- field public static final androidx.appactions.builtintypes.types.UnsupportedOperationStatus.Companion Companion;
- }
-
- public static interface UnsupportedOperationStatus.Builder<Self extends androidx.appactions.builtintypes.types.UnsupportedOperationStatus.Builder<Self>> extends androidx.appactions.builtintypes.types.ExecutionStatus.Builder<Self> {
- method public androidx.appactions.builtintypes.types.UnsupportedOperationStatus build();
- }
-
- public static final class UnsupportedOperationStatus.Companion {
- method @androidx.appsearch.annotation.Document.BuilderProducer public androidx.appactions.builtintypes.types.UnsupportedOperationStatus.Builder<?> Builder();
- }
-
-}
-
diff --git a/appactions/builtintypes/builtintypes/build.gradle b/appactions/builtintypes/builtintypes/build.gradle
deleted file mode 100644
index 04d7a42..0000000
--- a/appactions/builtintypes/builtintypes/build.gradle
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-/**
- * This file was created using the `create_project.py` script located in the
- * `<AndroidX root>/development/project-creator` directory.
- *
- * Please use that script when creating a new project, rather than copying an existing project and
- * modifying its settings.
- */
-import androidx.build.LibraryType
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-
-plugins {
- id("AndroidXPlugin")
- id("com.android.library")
- id("org.jetbrains.kotlin.android")
- id("kotlin-kapt")
-}
-
-dependencies {
- api(libs.kotlinStdlib)
- api(project(":appsearch:appsearch"))
-
- kapt(project(":appsearch:appsearch-compiler"))
-
- testImplementation(libs.junit)
- testImplementation(libs.truth)
-}
-
-kapt {
- arguments {
- arg("AppSearchCompiler.RestrictGeneratedCodeToLib", "true")
- }
-}
-
-android {
- namespace "androidx.appactions.builtintypes"
- defaultConfig {
- minSdkVersion 26
- }
-}
-
-tasks.withType(KotlinCompile).configureEach {
- compilerOptions {
- freeCompilerArgs.add("-Xjvm-default=all")
- }
-}
-
-androidx {
- name = "AppActions Built-in Types"
- type = LibraryType.PUBLISHED_LIBRARY
- inceptionYear = "2023"
- description = "This library exposes a core set of data types based on schema.org definitions."
- metalavaK2UastEnabled = true
- samples(project(":appactions:builtintypes:builtintypes:builtintypes-samples"))
-}
diff --git a/appactions/builtintypes/builtintypes/samples/build.gradle b/appactions/builtintypes/builtintypes/samples/build.gradle
deleted file mode 100644
index 561d5cb..0000000
--- a/appactions/builtintypes/builtintypes/samples/build.gradle
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * This file was created using the `create_project.py` script located in the
- * `<AndroidX root>/development/project-creator` directory.
- *
- * Please use that script when creating a new project, rather than copying an existing project and
- * modifying its settings.
- */
-import androidx.build.LibraryType
-
-plugins {
- id("AndroidXPlugin")
- id("com.android.library")
- id("org.jetbrains.kotlin.android")
-}
-
-dependencies {
- api(libs.kotlinStdlib)
-
- compileOnly(project(":annotation:annotation-sampled"))
- implementation(project(":appactions:builtintypes:builtintypes"))
-}
-
-android {
- namespace "androidx.appactions.builtintypes.samples"
- defaultConfig {
- minSdkVersion 26
- }
-}
-
-androidx {
- name = "Built-in Types Samples"
- type = LibraryType.SAMPLES
- inceptionYear = "2023"
- description = "Samples for AndroidX Built-in Types Library"
-}
diff --git a/appactions/builtintypes/builtintypes/samples/src/main/java/androidx/appactions/builtintypes/samples/properties/ExceptDateSamples.kt b/appactions/builtintypes/builtintypes/samples/src/main/java/androidx/appactions/builtintypes/samples/properties/ExceptDateSamples.kt
deleted file mode 100644
index 56c43e7..0000000
--- a/appactions/builtintypes/builtintypes/samples/src/main/java/androidx/appactions/builtintypes/samples/properties/ExceptDateSamples.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.appactions.builtintypes.samples.properties
-
-import androidx.`annotation`.Sampled
-import androidx.appactions.builtintypes.properties.ExceptDate
-import java.time.Instant
-import java.time.LocalDate
-import java.time.LocalDateTime
-import kotlin.String
-
-@Sampled
-public fun exceptDateMapWhenUsage(exceptDate: ExceptDate) =
- exceptDate.mapWhen(
- object : ExceptDate.Mapper<String> {
- override fun date(instance: LocalDate): String = """Got LocalDate: $instance"""
-
- override fun localDateTime(instance: LocalDateTime): String =
- """Got a local DateTime: $instance"""
-
- override fun instant(instance: Instant): String = """Got an absolute DateTime: $instance"""
-
- override fun orElse(): String = """Got some unrecognized variant: $exceptDate"""
- }
- )
diff --git a/appactions/builtintypes/builtintypes/samples/src/main/java/androidx/appactions/builtintypes/samples/types/DayOfWeekSamples.kt b/appactions/builtintypes/builtintypes/samples/src/main/java/androidx/appactions/builtintypes/samples/types/DayOfWeekSamples.kt
deleted file mode 100644
index 1bdc8b2..0000000
--- a/appactions/builtintypes/builtintypes/samples/src/main/java/androidx/appactions/builtintypes/samples/types/DayOfWeekSamples.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.appactions.builtintypes.samples.types
-
-import androidx.`annotation`.Sampled
-import androidx.appactions.builtintypes.types.DayOfWeek
-import kotlin.String
-
-@Sampled
-public fun dayOfWeekMapWhenUsage(dayOfWeek: DayOfWeek) =
- dayOfWeek.mapWhen(
- object : DayOfWeek.Mapper<String> {
- override fun friday(): String = "Got Friday"
-
- override fun monday(): String = "Got Monday"
-
- override fun publicHolidays(): String = "Got PublicHolidays"
-
- override fun saturday(): String = "Got Saturday"
-
- override fun sunday(): String = "Got Sunday"
-
- override fun thursday(): String = "Got Thursday"
-
- override fun tuesday(): String = "Got Tuesday"
-
- override fun wednesday(): String = "Got Wednesday"
-
- override fun orElse(): String = """Got some unrecognized DayOfWeek: $dayOfWeek"""
- }
- )
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/androidx-appactions-builtintypes-builtintypes-documentation.md b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/androidx-appactions-builtintypes-builtintypes-documentation.md
deleted file mode 100644
index c899946e..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/androidx-appactions-builtintypes-builtintypes-documentation.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Module root
-
-androidx.appactions.builtintypes builtintypes
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/ByDay.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/ByDay.kt
deleted file mode 100644
index 1f085e1..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/ByDay.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.appactions.builtintypes.properties
-
-import androidx.appactions.builtintypes.serializers.DayOfWeekAsCanonicalUrlSerializer
-import androidx.appactions.builtintypes.types.DayOfWeek
-import androidx.appsearch.`annotation`.Document
-import java.util.Objects
-import kotlin.Any
-import kotlin.Boolean
-import kotlin.Int
-import kotlin.String
-import kotlin.error
-import kotlin.jvm.JvmName
-
-/**
- * Defines the day(s) of the week on which a recurring Event takes place.
- *
- * See https://schema.org/byDay for context.
- *
- * Holds one of:
- * * [DayOfWeek]
- *
- * May hold more types over time.
- */
-@Document(name = "bitprop:ByDay")
-public class ByDay
-internal constructor(
- /** The [DayOfWeek] variant, or null if constructed using a different variant. */
- @get:JvmName("asDayOfWeek")
- @get:Document.StringProperty(serializer = DayOfWeekAsCanonicalUrlSerializer::class)
- public val asDayOfWeek: DayOfWeek? = null,
- /** Required ctor param for the AppSearch compiler. */
- @get:Document.Id @get:JvmName("getIdentifier") internal val identifier: String = "",
- /** Required ctor param for the AppSearch compiler. */
- @get:Document.Namespace @get:JvmName("getNamespace") internal val namespace: String = "",
-) {
- /** Constructor for the [DayOfWeek] variant. */
- public constructor(dayOfWeek: DayOfWeek) : this(asDayOfWeek = dayOfWeek)
-
- override fun toString(): String = toString(includeWrapperName = true)
-
- internal fun toString(includeWrapperName: Boolean): String =
- when {
- asDayOfWeek != null ->
- if (includeWrapperName) {
- """ByDay($asDayOfWeek)"""
- } else {
- asDayOfWeek.toString()
- }
- else -> error("No variant present in ByDay")
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is ByDay) return false
- if (asDayOfWeek != other.asDayOfWeek) return false
- return true
- }
-
- override fun hashCode(): Int = Objects.hash(asDayOfWeek)
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/EndDate.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/EndDate.kt
deleted file mode 100644
index 18964fb..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/EndDate.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.appactions.builtintypes.properties
-
-import androidx.appactions.builtintypes.serializers.LocalDateAsEpochDaySerializer
-import androidx.appsearch.`annotation`.Document
-import java.time.LocalDate
-import java.util.Objects
-import kotlin.Any
-import kotlin.Boolean
-import kotlin.Int
-import kotlin.String
-import kotlin.error
-import kotlin.jvm.JvmName
-
-/**
- * The end date and time of the item.
- *
- * See https://schema.org/endDate for context.
- *
- * Holds one of:
- * * Date i.e. [LocalDate]
- *
- * May hold more types over time.
- */
-@Document(name = "bitprop:EndDate")
-public class EndDate
-internal constructor(
- /** The [LocalDate] variant, or null if constructed using a different variant. */
- @get:JvmName("asDate")
- @get:Document.LongProperty(serializer = LocalDateAsEpochDaySerializer::class)
- public val asDate: LocalDate? = null,
- /** Required ctor param for the AppSearch compiler. */
- @get:Document.Id @get:JvmName("getIdentifier") internal val identifier: String = "",
- /** Required ctor param for the AppSearch compiler. */
- @get:Document.Namespace @get:JvmName("getNamespace") internal val namespace: String = "",
-) {
- /** Constructor for the [LocalDate] variant. */
- public constructor(date: LocalDate) : this(asDate = date)
-
- override fun toString(): String = toString(includeWrapperName = true)
-
- internal fun toString(includeWrapperName: Boolean): String =
- when {
- asDate != null ->
- if (includeWrapperName) {
- """EndDate($asDate)"""
- } else {
- asDate.toString()
- }
- else -> error("No variant present in EndDate")
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is EndDate) return false
- if (asDate != other.asDate) return false
- return true
- }
-
- override fun hashCode(): Int = Objects.hash(asDate)
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/EndTime.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/EndTime.kt
deleted file mode 100644
index 58d1b00..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/EndTime.kt
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.appactions.builtintypes.properties
-
-import androidx.appactions.builtintypes.serializers.LocalTimeAsNanoOfDaySerializer
-import androidx.appsearch.`annotation`.Document
-import java.time.LocalTime
-import java.util.Objects
-import kotlin.Any
-import kotlin.Boolean
-import kotlin.Int
-import kotlin.String
-import kotlin.error
-import kotlin.jvm.JvmName
-
-/**
- * The endTime of something.
- *
- * For a reserved event or service (e.g. `FoodEstablishmentReservation`), the time that it is
- * expected to end. For actions that span a period of time, when the action was performed. E.g. John
- * wrote a book from January to *December*. For media, including audio and video, it's the time
- * offset of the end of a clip within a larger file.
- *
- * See https://schema.org/endTime for context.
- *
- * Holds one of:
- * * Time i.e. [LocalTime]
- *
- * May hold more types over time.
- */
-@Document(name = "bitprop:EndTime")
-public class EndTime
-internal constructor(
- /** The [LocalTime] variant, or null if constructed using a different variant. */
- @get:JvmName("asTime")
- @get:Document.LongProperty(serializer = LocalTimeAsNanoOfDaySerializer::class)
- public val asTime: LocalTime? = null,
- /** Required ctor param for the AppSearch compiler. */
- @get:Document.Id @get:JvmName("getIdentifier") internal val identifier: String = "",
- /** Required ctor param for the AppSearch compiler. */
- @get:Document.Namespace @get:JvmName("getNamespace") internal val namespace: String = "",
-) {
- /** Constructor for the [LocalTime] variant. */
- public constructor(time: LocalTime) : this(asTime = time)
-
- override fun toString(): String = toString(includeWrapperName = true)
-
- internal fun toString(includeWrapperName: Boolean): String =
- when {
- asTime != null ->
- if (includeWrapperName) {
- """EndTime($asTime)"""
- } else {
- asTime.toString()
- }
- else -> error("No variant present in EndTime")
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is EndTime) return false
- if (asTime != other.asTime) return false
- return true
- }
-
- override fun hashCode(): Int = Objects.hash(asTime)
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/ExceptDate.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/ExceptDate.kt
deleted file mode 100644
index 4e15b62..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/ExceptDate.kt
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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.appactions.builtintypes.properties
-
-import androidx.appactions.builtintypes.serializers.InstantAsEpochMilliSerializer
-import androidx.appactions.builtintypes.serializers.LocalDateAsEpochDaySerializer
-import androidx.appactions.builtintypes.serializers.LocalDateTimeAsUtcEpochSecondSerializer
-import androidx.appsearch.`annotation`.Document
-import java.time.Instant
-import java.time.LocalDate
-import java.time.LocalDateTime
-import java.util.Objects
-import kotlin.Any
-import kotlin.Boolean
-import kotlin.Int
-import kotlin.String
-import kotlin.error
-import kotlin.jvm.JvmName
-
-/**
- * Defines a `Date` or `DateTime` during which a scheduled `Event` will not take place. The property
- * allows exceptions to a `Schedule` to be specified. If an exception is specified as a `DateTime`
- * then only the event that would have started at that specific date and time should be excluded
- * from the schedule. If an exception is specified as a `Date` then any event that is scheduled for
- * that 24 hour period should be excluded from the schedule. This allows a whole day to be excluded
- * from the schedule without having to itemise every scheduled event.
- *
- * See https://schema.org/exceptDate for context.
- *
- * Holds one of:
- * * Date i.e. [LocalDate]
- * * [LocalDateTime]
- * * [Instant]
- *
- * May hold more types over time.
- */
-@Document(name = "bitprop:ExceptDate")
-public class ExceptDate
-internal constructor(
- /** The [LocalDate] variant, or null if constructed using a different variant. */
- @get:JvmName("asDate")
- @get:Document.LongProperty(serializer = LocalDateAsEpochDaySerializer::class)
- public val asDate: LocalDate? = null,
- /** The [LocalDateTime] variant, or null if constructed using a different variant. */
- @get:JvmName("asLocalDateTime")
- @get:Document.LongProperty(serializer = LocalDateTimeAsUtcEpochSecondSerializer::class)
- public val asLocalDateTime: LocalDateTime? = null,
- /** The [Instant] variant, or null if constructed using a different variant. */
- @get:JvmName("asInstant")
- @get:Document.LongProperty(serializer = InstantAsEpochMilliSerializer::class)
- public val asInstant: Instant? = null,
- /** Required ctor param for the AppSearch compiler. */
- @get:Document.Id @get:JvmName("getIdentifier") internal val identifier: String = "",
- /** Required ctor param for the AppSearch compiler. */
- @get:Document.Namespace @get:JvmName("getNamespace") internal val namespace: String = "",
-) {
- /** Constructor for the [LocalDate] variant. */
- public constructor(date: LocalDate) : this(asDate = date)
-
- /** Constructor for the [LocalDateTime] variant. */
- public constructor(localDateTime: LocalDateTime) : this(asLocalDateTime = localDateTime)
-
- /** Constructor for the [Instant] variant. */
- public constructor(instant: Instant) : this(asInstant = instant)
-
- /**
- * Maps each of the possible underlying variants to some [R].
- *
- * A visitor can be provided to handle the possible variants. A catch-all default case must be
- * provided in case a new type is added in a future release of this library.
- *
- * @sample [androidx.appactions.builtintypes.samples.properties.exceptDateMapWhenUsage]
- */
- public fun <R> mapWhen(mapper: Mapper<R>): R =
- when {
- asDate != null -> mapper.date(asDate)
- asLocalDateTime != null -> mapper.localDateTime(asLocalDateTime)
- asInstant != null -> mapper.instant(asInstant)
- else -> error("No variant present in ExceptDate")
- }
-
- override fun toString(): String = toString(includeWrapperName = true)
-
- internal fun toString(includeWrapperName: Boolean): String =
- when {
- asDate != null ->
- if (includeWrapperName) {
- """ExceptDate($asDate)"""
- } else {
- asDate.toString()
- }
- asLocalDateTime != null ->
- if (includeWrapperName) {
- """ExceptDate($asLocalDateTime)"""
- } else {
- asLocalDateTime.toString()
- }
- asInstant != null ->
- if (includeWrapperName) {
- """ExceptDate($asInstant)"""
- } else {
- asInstant.toString()
- }
- else -> error("No variant present in ExceptDate")
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is ExceptDate) return false
- if (asDate != other.asDate) return false
- if (asLocalDateTime != other.asLocalDateTime) return false
- if (asInstant != other.asInstant) return false
- return true
- }
-
- override fun hashCode(): Int = Objects.hash(asDate, asLocalDateTime, asInstant)
-
- /** Maps each of the possible variants of [ExceptDate] to some [R]. */
- public interface Mapper<R> {
- /** Returns some [R] when the [ExceptDate] holds some [LocalDate] instance. */
- public fun date(instance: LocalDate): R = orElse()
-
- /** Returns some [R] when the [ExceptDate] holds some [LocalDateTime] instance. */
- public fun localDateTime(instance: LocalDateTime): R = orElse()
-
- /** Returns some [R] when the [ExceptDate] holds some [Instant] instance. */
- public fun instant(instance: Instant): R = orElse()
-
- /** The catch-all handler that is invoked when a particular variant isn't explicitly handled. */
- public fun orElse(): R
- }
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/Name.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/Name.kt
deleted file mode 100644
index a2d3f08..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/Name.kt
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.appactions.builtintypes.properties
-
-import androidx.appsearch.`annotation`.Document
-import java.util.Objects
-import kotlin.Any
-import kotlin.Boolean
-import kotlin.Int
-import kotlin.String
-import kotlin.error
-import kotlin.jvm.JvmName
-
-/**
- * The name of the item.
- *
- * See https://schema.org/name for context.
- *
- * Holds one of:
- * * Text i.e. [String]
- *
- * May hold more types over time.
- */
-@Document(name = "bitprop:Name")
-public class Name
-internal constructor(
- /** The [String] variant, or null if constructed using a different variant. */
- @get:JvmName("asText") @get:Document.StringProperty public val asText: String? = null,
- /** Required ctor param for the AppSearch compiler. */
- @get:Document.Id @get:JvmName("getIdentifier") internal val identifier: String = "",
- /** Required ctor param for the AppSearch compiler. */
- @get:Document.Namespace @get:JvmName("getNamespace") internal val namespace: String = "",
-) {
- /** Constructor for the [String] variant. */
- public constructor(text: String) : this(asText = text)
-
- override fun toString(): String = toString(includeWrapperName = true)
-
- internal fun toString(includeWrapperName: Boolean): String =
- when {
- asText != null ->
- if (includeWrapperName) {
- """Name($asText)"""
- } else {
- asText
- }
- else -> error("No variant present in Name")
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is Name) return false
- if (asText != other.asText) return false
- return true
- }
-
- override fun hashCode(): Int = Objects.hash(asText)
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/PropertyValidationUtils.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/PropertyValidationUtils.kt
deleted file mode 100644
index ed87915..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/PropertyValidationUtils.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.appactions.builtintypes.properties
-
-import androidx.annotation.RestrictTo
-import androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP
-
-/**
- * Requires that exactly one of the [variants] is non-null.
- *
- * @throws IllegalArgumentException otherwise
- */
-@RestrictTo(LIBRARY_GROUP)
-fun requireExactlyOneOf(vararg variants: Any?) {
- val nonNullCount = variants.count { it != null }
- require(nonNullCount == 1) {
- "Exactly one variant must be set but got $nonNullCount non-null values"
- }
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/RepeatFrequency.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/RepeatFrequency.kt
deleted file mode 100644
index 861e71d..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/RepeatFrequency.kt
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.appactions.builtintypes.properties
-
-import androidx.appactions.builtintypes.serializers.DurationAsNanosSerializer
-import androidx.appsearch.`annotation`.Document
-import java.time.Duration
-import java.util.Objects
-import kotlin.Any
-import kotlin.Boolean
-import kotlin.Int
-import kotlin.String
-import kotlin.error
-import kotlin.jvm.JvmName
-
-/**
- * Defines the frequency at which `Event`s will occur according to a schedule `Schedule`. The
- * intervals between events should be defined as a `Duration` of time.
- *
- * See https://schema.org/repeatFrequency for context.
- *
- * Holds one of:
- * * [Duration]
- *
- * May hold more types over time.
- */
-@Document(name = "bitprop:RepeatFrequency")
-public class RepeatFrequency
-internal constructor(
- /** The [Duration] variant, or null if constructed using a different variant. */
- @get:JvmName("asDuration")
- @get:Document.LongProperty(serializer = DurationAsNanosSerializer::class)
- public val asDuration: Duration? = null,
- /** Required ctor param for the AppSearch compiler. */
- @get:Document.Id @get:JvmName("getIdentifier") internal val identifier: String = "",
- /** Required ctor param for the AppSearch compiler. */
- @get:Document.Namespace @get:JvmName("getNamespace") internal val namespace: String = "",
-) {
- /** Constructor for the [Duration] variant. */
- public constructor(duration: Duration) : this(asDuration = duration)
-
- override fun toString(): String = toString(includeWrapperName = true)
-
- internal fun toString(includeWrapperName: Boolean): String =
- when {
- asDuration != null ->
- if (includeWrapperName) {
- """RepeatFrequency($asDuration)"""
- } else {
- asDuration.toString()
- }
- else -> error("No variant present in RepeatFrequency")
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is RepeatFrequency) return false
- if (asDuration != other.asDuration) return false
- return true
- }
-
- override fun hashCode(): Int = Objects.hash(asDuration)
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/StartDate.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/StartDate.kt
deleted file mode 100644
index 431b420..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/StartDate.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.appactions.builtintypes.properties
-
-import androidx.appactions.builtintypes.serializers.LocalDateAsEpochDaySerializer
-import androidx.appsearch.`annotation`.Document
-import java.time.LocalDate
-import java.util.Objects
-import kotlin.Any
-import kotlin.Boolean
-import kotlin.Int
-import kotlin.String
-import kotlin.error
-import kotlin.jvm.JvmName
-
-/**
- * The start date and time of the item.
- *
- * See https://schema.org/startDate for context.
- *
- * Holds one of:
- * * Date i.e. [LocalDate]
- *
- * May hold more types over time.
- */
-@Document(name = "bitprop:StartDate")
-public class StartDate
-internal constructor(
- /** The [LocalDate] variant, or null if constructed using a different variant. */
- @get:JvmName("asDate")
- @get:Document.LongProperty(serializer = LocalDateAsEpochDaySerializer::class)
- public val asDate: LocalDate? = null,
- /** Required ctor param for the AppSearch compiler. */
- @get:Document.Id @get:JvmName("getIdentifier") internal val identifier: String = "",
- /** Required ctor param for the AppSearch compiler. */
- @get:Document.Namespace @get:JvmName("getNamespace") internal val namespace: String = "",
-) {
- /** Constructor for the [LocalDate] variant. */
- public constructor(date: LocalDate) : this(asDate = date)
-
- override fun toString(): String = toString(includeWrapperName = true)
-
- internal fun toString(includeWrapperName: Boolean): String =
- when {
- asDate != null ->
- if (includeWrapperName) {
- """StartDate($asDate)"""
- } else {
- asDate.toString()
- }
- else -> error("No variant present in StartDate")
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is StartDate) return false
- if (asDate != other.asDate) return false
- return true
- }
-
- override fun hashCode(): Int = Objects.hash(asDate)
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/StartTime.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/StartTime.kt
deleted file mode 100644
index ea72193..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/StartTime.kt
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.appactions.builtintypes.properties
-
-import androidx.appactions.builtintypes.serializers.LocalTimeAsNanoOfDaySerializer
-import androidx.appsearch.`annotation`.Document
-import java.time.LocalTime
-import java.util.Objects
-import kotlin.Any
-import kotlin.Boolean
-import kotlin.Int
-import kotlin.String
-import kotlin.error
-import kotlin.jvm.JvmName
-
-/**
- * The startTime of something.
- *
- * For a reserved event or service (e.g. `FoodEstablishmentReservation`), the time that it is
- * expected to start. For actions that span a period of time, when the action was performed. E.g.
- * John wrote a book from *January* to December. For media, including audio and video, it's the time
- * offset of the start of a clip within a larger file.
- *
- * See https://schema.org/startTime for context.
- *
- * Holds one of:
- * * Time i.e. [LocalTime]
- *
- * May hold more types over time.
- */
-@Document(name = "bitprop:StartTime")
-public class StartTime
-internal constructor(
- /** The [LocalTime] variant, or null if constructed using a different variant. */
- @get:JvmName("asTime")
- @get:Document.LongProperty(serializer = LocalTimeAsNanoOfDaySerializer::class)
- public val asTime: LocalTime? = null,
- /** Required ctor param for the AppSearch compiler. */
- @get:Document.Id @get:JvmName("getIdentifier") internal val identifier: String = "",
- /** Required ctor param for the AppSearch compiler. */
- @get:Document.Namespace @get:JvmName("getNamespace") internal val namespace: String = "",
-) {
- /** Constructor for the [LocalTime] variant. */
- public constructor(time: LocalTime) : this(asTime = time)
-
- override fun toString(): String = toString(includeWrapperName = true)
-
- internal fun toString(includeWrapperName: Boolean): String =
- when {
- asTime != null ->
- if (includeWrapperName) {
- """StartTime($asTime)"""
- } else {
- asTime.toString()
- }
- else -> error("No variant present in StartTime")
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is StartTime) return false
- if (asTime != other.asTime) return false
- return true
- }
-
- override fun hashCode(): Int = Objects.hash(asTime)
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/DayOfWeekAsCanonicalUrlSerializer.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/DayOfWeekAsCanonicalUrlSerializer.kt
deleted file mode 100644
index 0579bf4..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/DayOfWeekAsCanonicalUrlSerializer.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.appactions.builtintypes.serializers
-
-import androidx.appactions.builtintypes.types.DayOfWeek
-import androidx.appsearch.app.StringSerializer
-import kotlin.String
-import kotlin.collections.firstOrNull
-
-/**
- * Serializes [DayOfWeek] as its canonical url String so it may be stored as a
- * `@Document.StringProperty`.
- *
- * @see DayOfWeek.canonicalUrl
- */
-public class DayOfWeekAsCanonicalUrlSerializer : StringSerializer<DayOfWeek> {
- override fun serialize(instance: DayOfWeek): String = instance.canonicalUrl
-
- override fun deserialize(`value`: String): DayOfWeek? =
- DayOfWeek.values().firstOrNull { it.canonicalUrl == value }
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/DurationAsNanosSerializer.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/DurationAsNanosSerializer.kt
deleted file mode 100644
index 8645db9..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/DurationAsNanosSerializer.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.appactions.builtintypes.serializers
-
-import androidx.appsearch.app.LongSerializer
-import java.time.Duration
-
-/**
- * Serializes a [Duration] to nanos so it may be stored as a `@Document.LongProperty`.
- *
- * @see Duration.toNanos
- */
-class DurationAsNanosSerializer : LongSerializer<Duration> {
- override fun serialize(instance: Duration): Long = instance.toNanos()
-
- override fun deserialize(value: Long): Duration = Duration.ofNanos(value)
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/InstantAsEpochMilliSerializer.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/InstantAsEpochMilliSerializer.kt
deleted file mode 100644
index 72c3fec..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/InstantAsEpochMilliSerializer.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.appactions.builtintypes.serializers
-
-import androidx.appsearch.app.LongSerializer
-import java.time.Instant
-
-/**
- * Serializes an [Instant] to epoch millis so it may be stored as a `@Document.LongProperty`.
- *
- * @see Instant.toEpochMilli
- */
-class InstantAsEpochMilliSerializer : LongSerializer<Instant> {
- override fun serialize(instance: Instant): Long = instance.toEpochMilli()
-
- override fun deserialize(value: Long): Instant = Instant.ofEpochMilli(value)
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/LocalDateAsEpochDaySerializer.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/LocalDateAsEpochDaySerializer.kt
deleted file mode 100644
index 765cfba..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/LocalDateAsEpochDaySerializer.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.appactions.builtintypes.serializers
-
-import androidx.appsearch.app.LongSerializer
-import java.time.LocalDate
-
-/**
- * Serializes a [LocalDate] to an epoch day so it may be stored as a `@Document.LongProperty`.
- *
- * @see LocalDate.toEpochDay
- */
-class LocalDateAsEpochDaySerializer : LongSerializer<LocalDate> {
- override fun serialize(instance: LocalDate): Long = instance.toEpochDay()
-
- override fun deserialize(value: Long): LocalDate = LocalDate.ofEpochDay(value)
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/LocalDateTimeAsUtcEpochSecondSerializer.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/LocalDateTimeAsUtcEpochSecondSerializer.kt
deleted file mode 100644
index 14eb7e31..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/LocalDateTimeAsUtcEpochSecondSerializer.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.appactions.builtintypes.serializers
-
-import androidx.appsearch.app.LongSerializer
-import java.time.LocalDateTime
-import java.time.ZoneOffset
-
-/**
- * Serializes a [LocalDateTime] as epoch seconds assuming the UTC timezone so it may be stored as a
- * `@Document.LongProperty`.
- *
- * For example, 2023-08-14T18:30 is serialized as seconds(2023-08-14T18:30+00:00).
- *
- * @see LocalDateTime.toEpochSecond
- * @see ZoneOffset.UTC
- */
-class LocalDateTimeAsUtcEpochSecondSerializer : LongSerializer<LocalDateTime> {
- override fun serialize(instance: LocalDateTime): Long = instance.toEpochSecond(ZoneOffset.UTC)
-
- override fun deserialize(value: Long): LocalDateTime =
- LocalDateTime.ofEpochSecond(value, /* nanoOfSecond= */ 0, ZoneOffset.UTC)
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/LocalTimeAsNanoOfDaySerializer.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/LocalTimeAsNanoOfDaySerializer.kt
deleted file mode 100644
index 1394afb..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/LocalTimeAsNanoOfDaySerializer.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.appactions.builtintypes.serializers
-
-import androidx.appsearch.app.LongSerializer
-import java.time.LocalTime
-
-/**
- * Serializes a [LocalTime] to nanos so it may be stored as a `@Document.LongProperty`.
- *
- * @see LocalTime.toNanoOfDay
- */
-class LocalTimeAsNanoOfDaySerializer : LongSerializer<LocalTime> {
- override fun serialize(instance: LocalTime): Long = instance.toNanoOfDay()
-
- override fun deserialize(value: Long): LocalTime = LocalTime.ofNanoOfDay(value)
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/Alarm.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/Alarm.kt
deleted file mode 100644
index 4ed329e..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/Alarm.kt
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * 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.appactions.builtintypes.types
-
-import androidx.appactions.builtintypes.properties.Name
-import androidx.appsearch.`annotation`.Document
-import java.util.Objects
-import kotlin.Any
-import kotlin.Boolean
-import kotlin.Int
-import kotlin.NotImplementedError
-import kotlin.String
-import kotlin.Suppress
-import kotlin.collections.Map
-import kotlin.collections.emptyMap
-import kotlin.collections.joinToString
-import kotlin.collections.map
-import kotlin.collections.mutableMapOf
-import kotlin.collections.plusAssign
-import kotlin.jvm.JvmStatic
-
-/**
- * An alarm set to go off at a specified schedule.
- *
- * See https://schema.googleapis.com/Alarm for context.
- *
- * Should not be directly implemented. More properties may be added over time. Instead consider
- * using [Companion.Builder] or see [AbstractAlarm] if you need to extend this type.
- */
-@Document(
- name = "bit:Alarm",
- parent = [Thing::class],
-)
-public interface Alarm : Thing {
- /**
- * Associates an Alarm with a Schedule.
- *
- * See https://schema.googleapis.com/alarmSchedule for more context.
- */
- @get:Document.DocumentProperty
- public val alarmSchedule: Schedule?
- get() = null
-
- /**
- * Specifies if the alarm enabled or disabled.
- *
- * Should be left unset in contexts where there is no notion of enabled/disabled alarms.
- *
- * See https://schema.googleapis.com/isAlarmEnabled for more context.
- */
- @get:Document.BooleanProperty
- @get:Suppress("AutoBoxing")
- public val isAlarmEnabled: Boolean?
- get() = null
-
- /** Converts this [Alarm] to its builder with all the properties copied over. */
- override fun toBuilder(): Builder<*>
-
- public companion object {
- /** Returns a default implementation of [Builder]. */
- @JvmStatic @Document.BuilderProducer public fun Builder(): Builder<*> = AlarmImpl.Builder()
- }
-
- /**
- * Builder for [Alarm].
- *
- * Should not be directly implemented. More methods may be added over time. See
- * [AbstractAlarm.Builder] if you need to extend this builder.
- */
- public interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
- /** Returns a built [Alarm]. */
- override fun build(): Alarm
-
- /** Sets the `alarmSchedule`. */
- @Suppress("DocumentExceptions")
- public fun setAlarmSchedule(schedule: Schedule?): Self = throw NotImplementedError()
-
- /** Sets the `isAlarmEnabled`. */
- @Suppress("DocumentExceptions")
- public fun setAlarmEnabled(@Suppress("AutoBoxing") boolean: Boolean?): Self =
- throw NotImplementedError()
- }
-}
-
-/**
- * An abstract implementation of [Alarm].
- *
- * Allows for extension like:
- * ```kt
- * @Document(
- * name = "MyAlarm",
- * parent = [Alarm::class],
- * )
- * class MyAlarm internal constructor(
- * alarm: Alarm,
- * @Document.StringProperty val foo: String,
- * @Document.LongProperty val bars: List<Int>,
- * ) : AbstractAlarm<
- * MyAlarm,
- * MyAlarm.Builder
- * >(alarm) {
- *
- * // No need to implement equals(), hashCode(), toString() or toBuilder()
- *
- * override val selfTypeName =
- * "MyAlarm"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun toBuilderWithAdditionalPropertiesOnly(): Builder {
- * return Builder()
- * .setFoo(foo)
- * .addBars(bars)
- * }
- *
- * @Document.BuilderProducer
- * class Builder :
- * AbstractAlarm.Builder<
- * Builder,
- * MyAlarm> {...}
- * }
- * ```
- *
- * Also see [AbstractAlarm.Builder].
- */
-@Suppress("UNCHECKED_CAST")
-public abstract class AbstractAlarm<
- Self : AbstractAlarm<Self, Builder>,
- Builder : AbstractAlarm.Builder<Builder, Self>
->
-internal constructor(
- final override val namespace: String,
- final override val alarmSchedule: Schedule?,
- @get:Suppress("AutoBoxing") final override val isAlarmEnabled: Boolean?,
- final override val identifier: String,
- final override val name: Name?,
-) : Alarm {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- protected abstract val additionalProperties: Map<String, Any?>
-
- /** A copy-constructor that copies over properties from another [Alarm] instance. */
- public constructor(
- alarm: Alarm
- ) : this(alarm.namespace, alarm.alarmSchedule, alarm.isAlarmEnabled, alarm.identifier, alarm.name)
-
- /** Returns a concrete [Builder] with the additional, non-[Alarm] properties copied over. */
- protected abstract fun toBuilderWithAdditionalPropertiesOnly(): Builder
-
- final override fun toBuilder(): Builder =
- toBuilderWithAdditionalPropertiesOnly()
- .setNamespace(namespace)
- .setAlarmSchedule(alarmSchedule)
- .setAlarmEnabled(isAlarmEnabled)
- .setIdentifier(identifier)
- .setName(name)
-
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (alarmSchedule != other.alarmSchedule) return false
- if (isAlarmEnabled != other.isAlarmEnabled) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- final override fun hashCode(): Int =
- Objects.hash(namespace, alarmSchedule, isAlarmEnabled, identifier, name, additionalProperties)
-
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (alarmSchedule != null) {
- attributes["alarmSchedule"] = alarmSchedule.toString()
- }
- if (isAlarmEnabled != null) {
- attributes["isAlarmEnabled"] = isAlarmEnabled.toString()
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated = attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
-
- /**
- * An abstract implementation of [Alarm.Builder].
- *
- * Allows for extension like:
- * ```kt
- * @Document(...)
- * class MyAlarm :
- * : AbstractAlarm<
- * MyAlarm,
- * MyAlarm.Builder>(...) {
- *
- * @Document.BuilderProducer
- * class Builder
- * : AbstractAlarm.Builder<
- * Builder,
- * MyAlarm
- * >() {
- *
- * // No need to implement equals(), hashCode(), toString() or build()
- *
- * private var foo: String? = null
- * private val bars = mutableListOf<Int>()
- *
- * override val selfTypeName =
- * "MyAlarm.Builder"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun buildFromAlarm(
- * alarm: Alarm
- * ): MyAlarm {
- * return MyAlarm(
- * alarm,
- * foo,
- * bars.toList()
- * )
- * }
- *
- * fun setFoo(string: String): Builder {
- * return apply { foo = string }
- * }
- *
- * fun addBar(int: Int): Builder {
- * return apply { bars += int }
- * }
- *
- * fun addBars(values: Iterable<Int>): Builder {
- * return apply { bars += values }
- * }
- * }
- * }
- * ```
- *
- * Also see [AbstractAlarm].
- */
- @Suppress("StaticFinalBuilder")
- public abstract class Builder<Self : Builder<Self, Built>, Built : AbstractAlarm<Built, Self>> :
- Alarm.Builder<Self> {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val additionalProperties: Map<String, Any?>
-
- private var namespace: String = ""
-
- private var alarmSchedule: Schedule? = null
-
- @get:Suppress("AutoBoxing") private var isAlarmEnabled: Boolean? = null
-
- private var identifier: String = ""
-
- private var name: Name? = null
-
- /**
- * Builds a concrete [Built] instance, given a built [Alarm].
- *
- * Subclasses should override this method to build a concrete [Built] instance that holds both
- * the [Alarm]-specific properties and the subclass specific [additionalProperties].
- *
- * See the sample code in the documentation of this class for more context.
- */
- @Suppress("BuilderSetStyle") protected abstract fun buildFromAlarm(alarm: Alarm): Built
-
- final override fun build(): Built =
- buildFromAlarm(AlarmImpl(namespace, alarmSchedule, isAlarmEnabled, identifier, name))
-
- final override fun setNamespace(namespace: String): Self {
- this.namespace = namespace
- return this as Self
- }
-
- final override fun setAlarmSchedule(schedule: Schedule?): Self {
- this.alarmSchedule = schedule
- return this as Self
- }
-
- final override fun setAlarmEnabled(@Suppress("AutoBoxing") boolean: Boolean?): Self {
- this.isAlarmEnabled = boolean
- return this as Self
- }
-
- final override fun setIdentifier(text: String): Self {
- this.identifier = text
- return this as Self
- }
-
- final override fun setName(name: Name?): Self {
- this.name = name
- return this as Self
- }
-
- @Suppress("BuilderSetStyle")
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (alarmSchedule != other.alarmSchedule) return false
- if (isAlarmEnabled != other.isAlarmEnabled) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- @Suppress("BuilderSetStyle")
- final override fun hashCode(): Int =
- Objects.hash(namespace, alarmSchedule, isAlarmEnabled, identifier, name, additionalProperties)
-
- @Suppress("BuilderSetStyle")
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (alarmSchedule != null) {
- attributes["alarmSchedule"] = alarmSchedule!!.toString()
- }
- if (isAlarmEnabled != null) {
- attributes["isAlarmEnabled"] = isAlarmEnabled!!.toString()
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name!!.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated =
- attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
- }
-}
-
-private class AlarmImpl : AbstractAlarm<AlarmImpl, AlarmImpl.Builder> {
- protected override val selfTypeName: String
- get() = "Alarm"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- public constructor(
- namespace: String,
- alarmSchedule: Schedule?,
- isAlarmEnabled: Boolean?,
- identifier: String,
- name: Name?,
- ) : super(namespace, alarmSchedule, isAlarmEnabled, identifier, name)
-
- public constructor(alarm: Alarm) : super(alarm)
-
- protected override fun toBuilderWithAdditionalPropertiesOnly(): Builder = Builder()
-
- public class Builder : AbstractAlarm.Builder<Builder, AlarmImpl>() {
- protected override val selfTypeName: String
- get() = "Alarm.Builder"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- protected override fun buildFromAlarm(alarm: Alarm): AlarmImpl =
- alarm as? AlarmImpl ?: AlarmImpl(alarm)
- }
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/CommonExecutionStatus.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/CommonExecutionStatus.kt
deleted file mode 100644
index 9bf51a9..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/CommonExecutionStatus.kt
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * 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.appactions.builtintypes.types
-
-import androidx.appactions.builtintypes.properties.Name
-import androidx.appsearch.`annotation`.Document
-import java.util.Objects
-import kotlin.Any
-import kotlin.Boolean
-import kotlin.Int
-import kotlin.String
-import kotlin.Suppress
-import kotlin.collections.Map
-import kotlin.collections.emptyMap
-import kotlin.collections.joinToString
-import kotlin.collections.map
-import kotlin.collections.mutableMapOf
-import kotlin.collections.plusAssign
-import kotlin.jvm.JvmStatic
-
-/**
- * A parent type that serves as the umbrella for a number of canonical execution statuses that apply
- * to the vast majority of tasks.
- *
- * Prefer one of the subtypes in most contexts to represent a specific type of common status e.g.
- * `SuccessStatus`.
- *
- * See https://schema.googleapis.com/CommonExecutionStatus for context.
- *
- * Should not be directly implemented. More properties may be added over time. Instead consider
- * using [Companion.Builder] or see [AbstractCommonExecutionStatus] if you need to extend this type.
- */
-@Document(
- name = "bit:CommonExecutionStatus",
- parent = [ExecutionStatus::class],
-)
-public interface CommonExecutionStatus : ExecutionStatus {
- /** Converts this [CommonExecutionStatus] to its builder with all the properties copied over. */
- override fun toBuilder(): Builder<*>
-
- public companion object {
- /** Returns a default implementation of [Builder]. */
- @JvmStatic
- @Document.BuilderProducer
- public fun Builder(): Builder<*> = CommonExecutionStatusImpl.Builder()
- }
-
- /**
- * Builder for [CommonExecutionStatus].
- *
- * Should not be directly implemented. More methods may be added over time. See
- * [AbstractCommonExecutionStatus.Builder] if you need to extend this builder.
- */
- public interface Builder<Self : Builder<Self>> : ExecutionStatus.Builder<Self> {
- /** Returns a built [CommonExecutionStatus]. */
- override fun build(): CommonExecutionStatus
- }
-}
-
-/**
- * An abstract implementation of [CommonExecutionStatus].
- *
- * Allows for extension like:
- * ```kt
- * @Document(
- * name = "MyCommonExecutionStatus",
- * parent = [CommonExecutionStatus::class],
- * )
- * class MyCommonExecutionStatus internal constructor(
- * commonExecutionStatus: CommonExecutionStatus,
- * @Document.StringProperty val foo: String,
- * @Document.LongProperty val bars: List<Int>,
- * ) : AbstractCommonExecutionStatus<
- * MyCommonExecutionStatus,
- * MyCommonExecutionStatus.Builder
- * >(commonExecutionStatus) {
- *
- * // No need to implement equals(), hashCode(), toString() or toBuilder()
- *
- * override val selfTypeName =
- * "MyCommonExecutionStatus"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun toBuilderWithAdditionalPropertiesOnly(): Builder {
- * return Builder()
- * .setFoo(foo)
- * .addBars(bars)
- * }
- *
- * @Document.BuilderProducer
- * class Builder :
- * AbstractCommonExecutionStatus.Builder<
- * Builder,
- * MyCommonExecutionStatus> {...}
- * }
- * ```
- *
- * Also see [AbstractCommonExecutionStatus.Builder].
- */
-@Suppress("UNCHECKED_CAST")
-public abstract class AbstractCommonExecutionStatus<
- Self : AbstractCommonExecutionStatus<Self, Builder>,
- Builder : AbstractCommonExecutionStatus.Builder<Builder, Self>
->
-internal constructor(
- final override val namespace: String,
- final override val identifier: String,
- final override val name: Name?,
-) : CommonExecutionStatus {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- protected abstract val additionalProperties: Map<String, Any?>
-
- /**
- * A copy-constructor that copies over properties from another [CommonExecutionStatus] instance.
- */
- public constructor(
- commonExecutionStatus: CommonExecutionStatus
- ) : this(
- commonExecutionStatus.namespace,
- commonExecutionStatus.identifier,
- commonExecutionStatus.name
- )
-
- /**
- * Returns a concrete [Builder] with the additional, non-[CommonExecutionStatus] properties copied
- * over.
- */
- protected abstract fun toBuilderWithAdditionalPropertiesOnly(): Builder
-
- final override fun toBuilder(): Builder =
- toBuilderWithAdditionalPropertiesOnly()
- .setNamespace(namespace)
- .setIdentifier(identifier)
- .setName(name)
-
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- final override fun hashCode(): Int =
- Objects.hash(namespace, identifier, name, additionalProperties)
-
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated = attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
-
- /**
- * An abstract implementation of [CommonExecutionStatus.Builder].
- *
- * Allows for extension like:
- * ```kt
- * @Document(...)
- * class MyCommonExecutionStatus :
- * : AbstractCommonExecutionStatus<
- * MyCommonExecutionStatus,
- * MyCommonExecutionStatus.Builder>(...) {
- *
- * @Document.BuilderProducer
- * class Builder
- * : AbstractCommonExecutionStatus.Builder<
- * Builder,
- * MyCommonExecutionStatus
- * >() {
- *
- * // No need to implement equals(), hashCode(), toString() or build()
- *
- * private var foo: String? = null
- * private val bars = mutableListOf<Int>()
- *
- * override val selfTypeName =
- * "MyCommonExecutionStatus.Builder"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun buildFromCommonExecutionStatus(
- * commonExecutionStatus: CommonExecutionStatus
- * ): MyCommonExecutionStatus {
- * return MyCommonExecutionStatus(
- * commonExecutionStatus,
- * foo,
- * bars.toList()
- * )
- * }
- *
- * fun setFoo(string: String): Builder {
- * return apply { foo = string }
- * }
- *
- * fun addBar(int: Int): Builder {
- * return apply { bars += int }
- * }
- *
- * fun addBars(values: Iterable<Int>): Builder {
- * return apply { bars += values }
- * }
- * }
- * }
- * ```
- *
- * Also see [AbstractCommonExecutionStatus].
- */
- @Suppress("StaticFinalBuilder")
- public abstract class Builder<
- Self : Builder<Self, Built>,
- Built : AbstractCommonExecutionStatus<Built, Self>
- > : CommonExecutionStatus.Builder<Self> {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val additionalProperties: Map<String, Any?>
-
- private var namespace: String = ""
-
- private var identifier: String = ""
-
- private var name: Name? = null
-
- /**
- * Builds a concrete [Built] instance, given a built [CommonExecutionStatus].
- *
- * Subclasses should override this method to build a concrete [Built] instance that holds both
- * the [CommonExecutionStatus]-specific properties and the subclass specific
- * [additionalProperties].
- *
- * See the sample code in the documentation of this class for more context.
- */
- @Suppress("BuilderSetStyle")
- protected abstract fun buildFromCommonExecutionStatus(
- commonExecutionStatus: CommonExecutionStatus
- ): Built
-
- final override fun build(): Built =
- buildFromCommonExecutionStatus(CommonExecutionStatusImpl(namespace, identifier, name))
-
- final override fun setNamespace(namespace: String): Self {
- this.namespace = namespace
- return this as Self
- }
-
- final override fun setIdentifier(text: String): Self {
- this.identifier = text
- return this as Self
- }
-
- final override fun setName(name: Name?): Self {
- this.name = name
- return this as Self
- }
-
- @Suppress("BuilderSetStyle")
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- @Suppress("BuilderSetStyle")
- final override fun hashCode(): Int =
- Objects.hash(namespace, identifier, name, additionalProperties)
-
- @Suppress("BuilderSetStyle")
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name!!.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated =
- attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
- }
-}
-
-private class CommonExecutionStatusImpl :
- AbstractCommonExecutionStatus<CommonExecutionStatusImpl, CommonExecutionStatusImpl.Builder> {
- protected override val selfTypeName: String
- get() = "CommonExecutionStatus"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- public constructor(
- namespace: String,
- identifier: String,
- name: Name?,
- ) : super(namespace, identifier, name)
-
- public constructor(commonExecutionStatus: CommonExecutionStatus) : super(commonExecutionStatus)
-
- protected override fun toBuilderWithAdditionalPropertiesOnly(): Builder = Builder()
-
- public class Builder :
- AbstractCommonExecutionStatus.Builder<Builder, CommonExecutionStatusImpl>() {
- protected override val selfTypeName: String
- get() = "CommonExecutionStatus.Builder"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- protected override fun buildFromCommonExecutionStatus(
- commonExecutionStatus: CommonExecutionStatus
- ): CommonExecutionStatusImpl =
- commonExecutionStatus as? CommonExecutionStatusImpl
- ?: CommonExecutionStatusImpl(commonExecutionStatus)
- }
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/DayOfWeek.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/DayOfWeek.kt
deleted file mode 100644
index 450fdc3..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/DayOfWeek.kt
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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.appactions.builtintypes.types
-
-import kotlin.String
-import kotlin.collections.List
-import kotlin.collections.listOf
-import kotlin.jvm.JvmField
-import kotlin.jvm.JvmStatic
-
-/**
- * The day of the week.
- *
- * See https://schema.org/DayOfWeek for context.
- *
- * Represents an open enum. See [Companion] for the different possible variants. More variants may
- * be added over time.
- */
-public class DayOfWeek
-private constructor(
- public val canonicalUrl: String,
-) {
- /**
- * Maps each of the possible variants to some [R].
- *
- * A visitor can be provided to handle the possible variants. A catch-all default case must be
- * provided in case a new variant is added in a future release of this library.
- *
- * @sample [androidx.appactions.builtintypes.samples.types.dayOfWeekMapWhenUsage]
- */
- public fun <R> mapWhen(mapper: Mapper<R>): R =
- when (this) {
- FRIDAY -> mapper.friday()
- MONDAY -> mapper.monday()
- PUBLIC_HOLIDAYS -> mapper.publicHolidays()
- SATURDAY -> mapper.saturday()
- SUNDAY -> mapper.sunday()
- THURSDAY -> mapper.thursday()
- TUESDAY -> mapper.tuesday()
- WEDNESDAY -> mapper.wednesday()
- else -> mapper.orElse()
- }
-
- override fun toString(): String = """DayOfWeek($canonicalUrl)"""
-
- public companion object {
- /** The day of the week between Thursday and Saturday. */
- @JvmField public val FRIDAY: DayOfWeek = DayOfWeek(canonicalUrl = "http://schema.org/Friday")
-
- /** The day of the week between Sunday and Tuesday. */
- @JvmField public val MONDAY: DayOfWeek = DayOfWeek(canonicalUrl = "http://schema.org/Monday")
-
- /**
- * This stands for any day that is a public holiday; it is a placeholder for all official public
- * holidays in some particular location. While not technically a "day of the week", it can be
- * used with `OpeningHoursSpecification`. In the context of an opening hours specification it
- * can be used to indicate opening hours on public holidays, overriding general opening hours
- * for the day of the week on which a public holiday occurs.
- */
- @JvmField
- public val PUBLIC_HOLIDAYS: DayOfWeek =
- DayOfWeek(canonicalUrl = "http://schema.org/PublicHolidays")
-
- /** The day of the week between Friday and Sunday. */
- @JvmField
- public val SATURDAY: DayOfWeek = DayOfWeek(canonicalUrl = "http://schema.org/Saturday")
-
- /** The day of the week between Saturday and Monday. */
- @JvmField public val SUNDAY: DayOfWeek = DayOfWeek(canonicalUrl = "http://schema.org/Sunday")
-
- /** The day of the week between Wednesday and Friday. */
- @JvmField
- public val THURSDAY: DayOfWeek = DayOfWeek(canonicalUrl = "http://schema.org/Thursday")
-
- /** The day of the week between Monday and Wednesday. */
- @JvmField public val TUESDAY: DayOfWeek = DayOfWeek(canonicalUrl = "http://schema.org/Tuesday")
-
- /** The day of the week between Tuesday and Thursday. */
- @JvmField
- public val WEDNESDAY: DayOfWeek = DayOfWeek(canonicalUrl = "http://schema.org/Wednesday")
-
- @JvmStatic
- public fun values(): List<DayOfWeek> =
- listOf(FRIDAY, MONDAY, PUBLIC_HOLIDAYS, SATURDAY, SUNDAY, THURSDAY, TUESDAY, WEDNESDAY)
- }
-
- /** Maps each of the possible variants of [DayOfWeek] to some [R]. */
- public interface Mapper<R> {
- /** Returns some [R] when the [DayOfWeek] is [FRIDAY]. */
- public fun friday(): R = orElse()
-
- /** Returns some [R] when the [DayOfWeek] is [MONDAY]. */
- public fun monday(): R = orElse()
-
- /** Returns some [R] when the [DayOfWeek] is [PUBLIC_HOLIDAYS]. */
- public fun publicHolidays(): R = orElse()
-
- /** Returns some [R] when the [DayOfWeek] is [SATURDAY]. */
- public fun saturday(): R = orElse()
-
- /** Returns some [R] when the [DayOfWeek] is [SUNDAY]. */
- public fun sunday(): R = orElse()
-
- /** Returns some [R] when the [DayOfWeek] is [THURSDAY]. */
- public fun thursday(): R = orElse()
-
- /** Returns some [R] when the [DayOfWeek] is [TUESDAY]. */
- public fun tuesday(): R = orElse()
-
- /** Returns some [R] when the [DayOfWeek] is [WEDNESDAY]. */
- public fun wednesday(): R = orElse()
-
- /** The catch-all handler that is invoked when a particular variant isn't explicitly handled. */
- public fun orElse(): R
- }
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/ExecutionStatus.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/ExecutionStatus.kt
deleted file mode 100644
index 52faa64..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/ExecutionStatus.kt
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * 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.appactions.builtintypes.types
-
-import androidx.appactions.builtintypes.properties.Name
-import androidx.appsearch.`annotation`.Document
-import java.util.Objects
-import kotlin.Any
-import kotlin.Boolean
-import kotlin.Int
-import kotlin.String
-import kotlin.Suppress
-import kotlin.collections.Map
-import kotlin.collections.emptyMap
-import kotlin.collections.joinToString
-import kotlin.collections.map
-import kotlin.collections.mutableMapOf
-import kotlin.collections.plusAssign
-import kotlin.jvm.JvmStatic
-
-/**
- * A parent type that serves as the umbrella for a number of types that represent the status of a
- * pending task.
- *
- * Prefer one of the subtypes in most contexts to represent a specific type of status e.g.
- * `UnsupportedOperationStatus`.
- *
- * See https://schema.googleapis.com/ExecutionStatus for context.
- *
- * Should not be directly implemented. More properties may be added over time. Instead consider
- * using [Companion.Builder] or see [AbstractExecutionStatus] if you need to extend this type.
- */
-@Document(
- name = "bit:ExecutionStatus",
- parent = [Intangible::class],
-)
-public interface ExecutionStatus : Intangible {
- /** Converts this [ExecutionStatus] to its builder with all the properties copied over. */
- override fun toBuilder(): Builder<*>
-
- public companion object {
- /** Returns a default implementation of [Builder]. */
- @JvmStatic
- @Document.BuilderProducer
- public fun Builder(): Builder<*> = ExecutionStatusImpl.Builder()
- }
-
- /**
- * Builder for [ExecutionStatus].
- *
- * Should not be directly implemented. More methods may be added over time. See
- * [AbstractExecutionStatus.Builder] if you need to extend this builder.
- */
- public interface Builder<Self : Builder<Self>> : Intangible.Builder<Self> {
- /** Returns a built [ExecutionStatus]. */
- override fun build(): ExecutionStatus
- }
-}
-
-/**
- * An abstract implementation of [ExecutionStatus].
- *
- * Allows for extension like:
- * ```kt
- * @Document(
- * name = "MyExecutionStatus",
- * parent = [ExecutionStatus::class],
- * )
- * class MyExecutionStatus internal constructor(
- * executionStatus: ExecutionStatus,
- * @Document.StringProperty val foo: String,
- * @Document.LongProperty val bars: List<Int>,
- * ) : AbstractExecutionStatus<
- * MyExecutionStatus,
- * MyExecutionStatus.Builder
- * >(executionStatus) {
- *
- * // No need to implement equals(), hashCode(), toString() or toBuilder()
- *
- * override val selfTypeName =
- * "MyExecutionStatus"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun toBuilderWithAdditionalPropertiesOnly(): Builder {
- * return Builder()
- * .setFoo(foo)
- * .addBars(bars)
- * }
- *
- * @Document.BuilderProducer
- * class Builder :
- * AbstractExecutionStatus.Builder<
- * Builder,
- * MyExecutionStatus> {...}
- * }
- * ```
- *
- * Also see [AbstractExecutionStatus.Builder].
- */
-@Suppress("UNCHECKED_CAST")
-public abstract class AbstractExecutionStatus<
- Self : AbstractExecutionStatus<Self, Builder>,
- Builder : AbstractExecutionStatus.Builder<Builder, Self>
->
-internal constructor(
- final override val namespace: String,
- final override val identifier: String,
- final override val name: Name?,
-) : ExecutionStatus {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- protected abstract val additionalProperties: Map<String, Any?>
-
- /** A copy-constructor that copies over properties from another [ExecutionStatus] instance. */
- public constructor(
- executionStatus: ExecutionStatus
- ) : this(executionStatus.namespace, executionStatus.identifier, executionStatus.name)
-
- /**
- * Returns a concrete [Builder] with the additional, non-[ExecutionStatus] properties copied over.
- */
- protected abstract fun toBuilderWithAdditionalPropertiesOnly(): Builder
-
- final override fun toBuilder(): Builder =
- toBuilderWithAdditionalPropertiesOnly()
- .setNamespace(namespace)
- .setIdentifier(identifier)
- .setName(name)
-
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- final override fun hashCode(): Int =
- Objects.hash(namespace, identifier, name, additionalProperties)
-
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated = attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
-
- /**
- * An abstract implementation of [ExecutionStatus.Builder].
- *
- * Allows for extension like:
- * ```kt
- * @Document(...)
- * class MyExecutionStatus :
- * : AbstractExecutionStatus<
- * MyExecutionStatus,
- * MyExecutionStatus.Builder>(...) {
- *
- * @Document.BuilderProducer
- * class Builder
- * : AbstractExecutionStatus.Builder<
- * Builder,
- * MyExecutionStatus
- * >() {
- *
- * // No need to implement equals(), hashCode(), toString() or build()
- *
- * private var foo: String? = null
- * private val bars = mutableListOf<Int>()
- *
- * override val selfTypeName =
- * "MyExecutionStatus.Builder"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun buildFromExecutionStatus(
- * executionStatus: ExecutionStatus
- * ): MyExecutionStatus {
- * return MyExecutionStatus(
- * executionStatus,
- * foo,
- * bars.toList()
- * )
- * }
- *
- * fun setFoo(string: String): Builder {
- * return apply { foo = string }
- * }
- *
- * fun addBar(int: Int): Builder {
- * return apply { bars += int }
- * }
- *
- * fun addBars(values: Iterable<Int>): Builder {
- * return apply { bars += values }
- * }
- * }
- * }
- * ```
- *
- * Also see [AbstractExecutionStatus].
- */
- @Suppress("StaticFinalBuilder")
- public abstract class Builder<
- Self : Builder<Self, Built>,
- Built : AbstractExecutionStatus<Built, Self>
- > : ExecutionStatus.Builder<Self> {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val additionalProperties: Map<String, Any?>
-
- private var namespace: String = ""
-
- private var identifier: String = ""
-
- private var name: Name? = null
-
- /**
- * Builds a concrete [Built] instance, given a built [ExecutionStatus].
- *
- * Subclasses should override this method to build a concrete [Built] instance that holds both
- * the [ExecutionStatus]-specific properties and the subclass specific [additionalProperties].
- *
- * See the sample code in the documentation of this class for more context.
- */
- @Suppress("BuilderSetStyle")
- protected abstract fun buildFromExecutionStatus(executionStatus: ExecutionStatus): Built
-
- final override fun build(): Built =
- buildFromExecutionStatus(ExecutionStatusImpl(namespace, identifier, name))
-
- final override fun setNamespace(namespace: String): Self {
- this.namespace = namespace
- return this as Self
- }
-
- final override fun setIdentifier(text: String): Self {
- this.identifier = text
- return this as Self
- }
-
- final override fun setName(name: Name?): Self {
- this.name = name
- return this as Self
- }
-
- @Suppress("BuilderSetStyle")
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- @Suppress("BuilderSetStyle")
- final override fun hashCode(): Int =
- Objects.hash(namespace, identifier, name, additionalProperties)
-
- @Suppress("BuilderSetStyle")
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name!!.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated =
- attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
- }
-}
-
-private class ExecutionStatusImpl :
- AbstractExecutionStatus<ExecutionStatusImpl, ExecutionStatusImpl.Builder> {
- protected override val selfTypeName: String
- get() = "ExecutionStatus"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- public constructor(
- namespace: String,
- identifier: String,
- name: Name?,
- ) : super(namespace, identifier, name)
-
- public constructor(executionStatus: ExecutionStatus) : super(executionStatus)
-
- protected override fun toBuilderWithAdditionalPropertiesOnly(): Builder = Builder()
-
- public class Builder : AbstractExecutionStatus.Builder<Builder, ExecutionStatusImpl>() {
- protected override val selfTypeName: String
- get() = "ExecutionStatus.Builder"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- protected override fun buildFromExecutionStatus(
- executionStatus: ExecutionStatus
- ): ExecutionStatusImpl =
- executionStatus as? ExecutionStatusImpl ?: ExecutionStatusImpl(executionStatus)
- }
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/GenericErrorStatus.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/GenericErrorStatus.kt
deleted file mode 100644
index 9b05a4a..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/GenericErrorStatus.kt
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * 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.appactions.builtintypes.types
-
-import androidx.appactions.builtintypes.properties.Name
-import androidx.appsearch.`annotation`.Document
-import java.util.Objects
-import kotlin.Any
-import kotlin.Boolean
-import kotlin.Int
-import kotlin.String
-import kotlin.Suppress
-import kotlin.collections.Map
-import kotlin.collections.emptyMap
-import kotlin.collections.joinToString
-import kotlin.collections.map
-import kotlin.collections.mutableMapOf
-import kotlin.collections.plusAssign
-import kotlin.jvm.JvmStatic
-
-/**
- * Status indicating that the task was not executed successfully.
- *
- * See https://schema.googleapis.com/GenericErrorStatus for context.
- *
- * Should not be directly implemented. More properties may be added over time. Instead consider
- * using [Companion.Builder] or see [AbstractGenericErrorStatus] if you need to extend this type.
- */
-@Document(
- name = "bit:GenericErrorStatus",
- parent = [CommonExecutionStatus::class],
-)
-public interface GenericErrorStatus : CommonExecutionStatus {
- /** Converts this [GenericErrorStatus] to its builder with all the properties copied over. */
- override fun toBuilder(): Builder<*>
-
- public companion object {
- /** Returns a default implementation of [Builder]. */
- @JvmStatic
- @Document.BuilderProducer
- public fun Builder(): Builder<*> = GenericErrorStatusImpl.Builder()
- }
-
- /**
- * Builder for [GenericErrorStatus].
- *
- * Should not be directly implemented. More methods may be added over time. See
- * [AbstractGenericErrorStatus.Builder] if you need to extend this builder.
- */
- public interface Builder<Self : Builder<Self>> : CommonExecutionStatus.Builder<Self> {
- /** Returns a built [GenericErrorStatus]. */
- override fun build(): GenericErrorStatus
- }
-}
-
-/**
- * An abstract implementation of [GenericErrorStatus].
- *
- * Allows for extension like:
- * ```kt
- * @Document(
- * name = "MyGenericErrorStatus",
- * parent = [GenericErrorStatus::class],
- * )
- * class MyGenericErrorStatus internal constructor(
- * genericErrorStatus: GenericErrorStatus,
- * @Document.StringProperty val foo: String,
- * @Document.LongProperty val bars: List<Int>,
- * ) : AbstractGenericErrorStatus<
- * MyGenericErrorStatus,
- * MyGenericErrorStatus.Builder
- * >(genericErrorStatus) {
- *
- * // No need to implement equals(), hashCode(), toString() or toBuilder()
- *
- * override val selfTypeName =
- * "MyGenericErrorStatus"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun toBuilderWithAdditionalPropertiesOnly(): Builder {
- * return Builder()
- * .setFoo(foo)
- * .addBars(bars)
- * }
- *
- * @Document.BuilderProducer
- * class Builder :
- * AbstractGenericErrorStatus.Builder<
- * Builder,
- * MyGenericErrorStatus> {...}
- * }
- * ```
- *
- * Also see [AbstractGenericErrorStatus.Builder].
- */
-@Suppress("UNCHECKED_CAST")
-public abstract class AbstractGenericErrorStatus<
- Self : AbstractGenericErrorStatus<Self, Builder>,
- Builder : AbstractGenericErrorStatus.Builder<Builder, Self>
->
-internal constructor(
- final override val namespace: String,
- final override val identifier: String,
- final override val name: Name?,
-) : GenericErrorStatus {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- protected abstract val additionalProperties: Map<String, Any?>
-
- /** A copy-constructor that copies over properties from another [GenericErrorStatus] instance. */
- public constructor(
- genericErrorStatus: GenericErrorStatus
- ) : this(genericErrorStatus.namespace, genericErrorStatus.identifier, genericErrorStatus.name)
-
- /**
- * Returns a concrete [Builder] with the additional, non-[GenericErrorStatus] properties copied
- * over.
- */
- protected abstract fun toBuilderWithAdditionalPropertiesOnly(): Builder
-
- final override fun toBuilder(): Builder =
- toBuilderWithAdditionalPropertiesOnly()
- .setNamespace(namespace)
- .setIdentifier(identifier)
- .setName(name)
-
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- final override fun hashCode(): Int =
- Objects.hash(namespace, identifier, name, additionalProperties)
-
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated = attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
-
- /**
- * An abstract implementation of [GenericErrorStatus.Builder].
- *
- * Allows for extension like:
- * ```kt
- * @Document(...)
- * class MyGenericErrorStatus :
- * : AbstractGenericErrorStatus<
- * MyGenericErrorStatus,
- * MyGenericErrorStatus.Builder>(...) {
- *
- * @Document.BuilderProducer
- * class Builder
- * : AbstractGenericErrorStatus.Builder<
- * Builder,
- * MyGenericErrorStatus
- * >() {
- *
- * // No need to implement equals(), hashCode(), toString() or build()
- *
- * private var foo: String? = null
- * private val bars = mutableListOf<Int>()
- *
- * override val selfTypeName =
- * "MyGenericErrorStatus.Builder"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun buildFromGenericErrorStatus(
- * genericErrorStatus: GenericErrorStatus
- * ): MyGenericErrorStatus {
- * return MyGenericErrorStatus(
- * genericErrorStatus,
- * foo,
- * bars.toList()
- * )
- * }
- *
- * fun setFoo(string: String): Builder {
- * return apply { foo = string }
- * }
- *
- * fun addBar(int: Int): Builder {
- * return apply { bars += int }
- * }
- *
- * fun addBars(values: Iterable<Int>): Builder {
- * return apply { bars += values }
- * }
- * }
- * }
- * ```
- *
- * Also see [AbstractGenericErrorStatus].
- */
- @Suppress("StaticFinalBuilder")
- public abstract class Builder<
- Self : Builder<Self, Built>,
- Built : AbstractGenericErrorStatus<Built, Self>
- > : GenericErrorStatus.Builder<Self> {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val additionalProperties: Map<String, Any?>
-
- private var namespace: String = ""
-
- private var identifier: String = ""
-
- private var name: Name? = null
-
- /**
- * Builds a concrete [Built] instance, given a built [GenericErrorStatus].
- *
- * Subclasses should override this method to build a concrete [Built] instance that holds both
- * the [GenericErrorStatus]-specific properties and the subclass specific
- * [additionalProperties].
- *
- * See the sample code in the documentation of this class for more context.
- */
- @Suppress("BuilderSetStyle")
- protected abstract fun buildFromGenericErrorStatus(
- genericErrorStatus: GenericErrorStatus
- ): Built
-
- final override fun build(): Built =
- buildFromGenericErrorStatus(GenericErrorStatusImpl(namespace, identifier, name))
-
- final override fun setNamespace(namespace: String): Self {
- this.namespace = namespace
- return this as Self
- }
-
- final override fun setIdentifier(text: String): Self {
- this.identifier = text
- return this as Self
- }
-
- final override fun setName(name: Name?): Self {
- this.name = name
- return this as Self
- }
-
- @Suppress("BuilderSetStyle")
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- @Suppress("BuilderSetStyle")
- final override fun hashCode(): Int =
- Objects.hash(namespace, identifier, name, additionalProperties)
-
- @Suppress("BuilderSetStyle")
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name!!.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated =
- attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
- }
-}
-
-private class GenericErrorStatusImpl :
- AbstractGenericErrorStatus<GenericErrorStatusImpl, GenericErrorStatusImpl.Builder> {
- protected override val selfTypeName: String
- get() = "GenericErrorStatus"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- public constructor(
- namespace: String,
- identifier: String,
- name: Name?,
- ) : super(namespace, identifier, name)
-
- public constructor(genericErrorStatus: GenericErrorStatus) : super(genericErrorStatus)
-
- protected override fun toBuilderWithAdditionalPropertiesOnly(): Builder = Builder()
-
- public class Builder : AbstractGenericErrorStatus.Builder<Builder, GenericErrorStatusImpl>() {
- protected override val selfTypeName: String
- get() = "GenericErrorStatus.Builder"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- protected override fun buildFromGenericErrorStatus(
- genericErrorStatus: GenericErrorStatus
- ): GenericErrorStatusImpl =
- genericErrorStatus as? GenericErrorStatusImpl ?: GenericErrorStatusImpl(genericErrorStatus)
- }
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/Intangible.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/Intangible.kt
deleted file mode 100644
index 09aaac6..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/Intangible.kt
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * 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.appactions.builtintypes.types
-
-import androidx.appactions.builtintypes.properties.Name
-import androidx.appsearch.`annotation`.Document
-import java.util.Objects
-import kotlin.Any
-import kotlin.Boolean
-import kotlin.Int
-import kotlin.String
-import kotlin.Suppress
-import kotlin.collections.Map
-import kotlin.collections.emptyMap
-import kotlin.collections.joinToString
-import kotlin.collections.map
-import kotlin.collections.mutableMapOf
-import kotlin.collections.plusAssign
-import kotlin.jvm.JvmStatic
-
-/**
- * A utility class that serves as the umbrella for a number of 'intangible' things such as
- * quantities, structured values, etc.
- *
- * See https://schema.org/Intangible for context.
- *
- * Should not be directly implemented. More properties may be added over time. Instead consider
- * using [Companion.Builder] or see [AbstractIntangible] if you need to extend this type.
- */
-@Document(
- name = "bit:Intangible",
- parent = [Thing::class],
-)
-public interface Intangible : Thing {
- /** Converts this [Intangible] to its builder with all the properties copied over. */
- override fun toBuilder(): Builder<*>
-
- public companion object {
- /** Returns a default implementation of [Builder]. */
- @JvmStatic @Document.BuilderProducer public fun Builder(): Builder<*> = IntangibleImpl.Builder()
- }
-
- /**
- * Builder for [Intangible].
- *
- * Should not be directly implemented. More methods may be added over time. See
- * [AbstractIntangible.Builder] if you need to extend this builder.
- */
- public interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
- /** Returns a built [Intangible]. */
- override fun build(): Intangible
- }
-}
-
-/**
- * An abstract implementation of [Intangible].
- *
- * Allows for extension like:
- * ```kt
- * @Document(
- * name = "MyIntangible",
- * parent = [Intangible::class],
- * )
- * class MyIntangible internal constructor(
- * intangible: Intangible,
- * @Document.StringProperty val foo: String,
- * @Document.LongProperty val bars: List<Int>,
- * ) : AbstractIntangible<
- * MyIntangible,
- * MyIntangible.Builder
- * >(intangible) {
- *
- * // No need to implement equals(), hashCode(), toString() or toBuilder()
- *
- * override val selfTypeName =
- * "MyIntangible"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun toBuilderWithAdditionalPropertiesOnly(): Builder {
- * return Builder()
- * .setFoo(foo)
- * .addBars(bars)
- * }
- *
- * @Document.BuilderProducer
- * class Builder :
- * AbstractIntangible.Builder<
- * Builder,
- * MyIntangible> {...}
- * }
- * ```
- *
- * Also see [AbstractIntangible.Builder].
- */
-@Suppress("UNCHECKED_CAST")
-public abstract class AbstractIntangible<
- Self : AbstractIntangible<Self, Builder>,
- Builder : AbstractIntangible.Builder<Builder, Self>
->
-internal constructor(
- final override val namespace: String,
- final override val identifier: String,
- final override val name: Name?,
-) : Intangible {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- protected abstract val additionalProperties: Map<String, Any?>
-
- /** A copy-constructor that copies over properties from another [Intangible] instance. */
- public constructor(
- intangible: Intangible
- ) : this(intangible.namespace, intangible.identifier, intangible.name)
-
- /** Returns a concrete [Builder] with the additional, non-[Intangible] properties copied over. */
- protected abstract fun toBuilderWithAdditionalPropertiesOnly(): Builder
-
- final override fun toBuilder(): Builder =
- toBuilderWithAdditionalPropertiesOnly()
- .setNamespace(namespace)
- .setIdentifier(identifier)
- .setName(name)
-
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- final override fun hashCode(): Int =
- Objects.hash(namespace, identifier, name, additionalProperties)
-
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated = attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
-
- /**
- * An abstract implementation of [Intangible.Builder].
- *
- * Allows for extension like:
- * ```kt
- * @Document(...)
- * class MyIntangible :
- * : AbstractIntangible<
- * MyIntangible,
- * MyIntangible.Builder>(...) {
- *
- * @Document.BuilderProducer
- * class Builder
- * : AbstractIntangible.Builder<
- * Builder,
- * MyIntangible
- * >() {
- *
- * // No need to implement equals(), hashCode(), toString() or build()
- *
- * private var foo: String? = null
- * private val bars = mutableListOf<Int>()
- *
- * override val selfTypeName =
- * "MyIntangible.Builder"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun buildFromIntangible(
- * intangible: Intangible
- * ): MyIntangible {
- * return MyIntangible(
- * intangible,
- * foo,
- * bars.toList()
- * )
- * }
- *
- * fun setFoo(string: String): Builder {
- * return apply { foo = string }
- * }
- *
- * fun addBar(int: Int): Builder {
- * return apply { bars += int }
- * }
- *
- * fun addBars(values: Iterable<Int>): Builder {
- * return apply { bars += values }
- * }
- * }
- * }
- * ```
- *
- * Also see [AbstractIntangible].
- */
- @Suppress("StaticFinalBuilder")
- public abstract class Builder<
- Self : Builder<Self, Built>,
- Built : AbstractIntangible<Built, Self>
- > : Intangible.Builder<Self> {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val additionalProperties: Map<String, Any?>
-
- private var namespace: String = ""
-
- private var identifier: String = ""
-
- private var name: Name? = null
-
- /**
- * Builds a concrete [Built] instance, given a built [Intangible].
- *
- * Subclasses should override this method to build a concrete [Built] instance that holds both
- * the [Intangible]-specific properties and the subclass specific [additionalProperties].
- *
- * See the sample code in the documentation of this class for more context.
- */
- @Suppress("BuilderSetStyle")
- protected abstract fun buildFromIntangible(intangible: Intangible): Built
-
- final override fun build(): Built =
- buildFromIntangible(IntangibleImpl(namespace, identifier, name))
-
- final override fun setNamespace(namespace: String): Self {
- this.namespace = namespace
- return this as Self
- }
-
- final override fun setIdentifier(text: String): Self {
- this.identifier = text
- return this as Self
- }
-
- final override fun setName(name: Name?): Self {
- this.name = name
- return this as Self
- }
-
- @Suppress("BuilderSetStyle")
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- @Suppress("BuilderSetStyle")
- final override fun hashCode(): Int =
- Objects.hash(namespace, identifier, name, additionalProperties)
-
- @Suppress("BuilderSetStyle")
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name!!.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated =
- attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
- }
-}
-
-private class IntangibleImpl : AbstractIntangible<IntangibleImpl, IntangibleImpl.Builder> {
- protected override val selfTypeName: String
- get() = "Intangible"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- public constructor(
- namespace: String,
- identifier: String,
- name: Name?,
- ) : super(namespace, identifier, name)
-
- public constructor(intangible: Intangible) : super(intangible)
-
- protected override fun toBuilderWithAdditionalPropertiesOnly(): Builder = Builder()
-
- public class Builder : AbstractIntangible.Builder<Builder, IntangibleImpl>() {
- protected override val selfTypeName: String
- get() = "Intangible.Builder"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- protected override fun buildFromIntangible(intangible: Intangible): IntangibleImpl =
- intangible as? IntangibleImpl ?: IntangibleImpl(intangible)
- }
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/ObjectCreationLimitReachedStatus.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/ObjectCreationLimitReachedStatus.kt
deleted file mode 100644
index bb7888c..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/ObjectCreationLimitReachedStatus.kt
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * 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.appactions.builtintypes.types
-
-import androidx.appactions.builtintypes.properties.Name
-import androidx.appsearch.`annotation`.Document
-import java.util.Objects
-import kotlin.Any
-import kotlin.Boolean
-import kotlin.Int
-import kotlin.String
-import kotlin.Suppress
-import kotlin.collections.Map
-import kotlin.collections.emptyMap
-import kotlin.collections.joinToString
-import kotlin.collections.map
-import kotlin.collections.mutableMapOf
-import kotlin.collections.plusAssign
-import kotlin.jvm.JvmStatic
-
-/**
- * Status indicating that the number of objects have reached the limit and more objects cannot be
- * created.
- *
- * See https://schema.googleapis.com/ObjectCreationLimitReachedStatus for context.
- *
- * Should not be directly implemented. More properties may be added over time. Instead consider
- * using [Companion.Builder] or see [AbstractObjectCreationLimitReachedStatus] if you need to extend
- * this type.
- */
-@Document(
- name = "bit:ObjectCreationLimitReachedStatus",
- parent = [ExecutionStatus::class],
-)
-public interface ObjectCreationLimitReachedStatus : ExecutionStatus {
- /**
- * Converts this [ObjectCreationLimitReachedStatus] to its builder with all the properties copied
- * over.
- */
- override fun toBuilder(): Builder<*>
-
- public companion object {
- /** Returns a default implementation of [Builder]. */
- @JvmStatic
- @Document.BuilderProducer
- public fun Builder(): Builder<*> = ObjectCreationLimitReachedStatusImpl.Builder()
- }
-
- /**
- * Builder for [ObjectCreationLimitReachedStatus].
- *
- * Should not be directly implemented. More methods may be added over time. See
- * [AbstractObjectCreationLimitReachedStatus.Builder] if you need to extend this builder.
- */
- public interface Builder<Self : Builder<Self>> : ExecutionStatus.Builder<Self> {
- /** Returns a built [ObjectCreationLimitReachedStatus]. */
- override fun build(): ObjectCreationLimitReachedStatus
- }
-}
-
-/**
- * An abstract implementation of [ObjectCreationLimitReachedStatus].
- *
- * Allows for extension like:
- * ```kt
- * @Document(
- * name = "MyObjectCreationLimitReachedStatus",
- * parent = [ObjectCreationLimitReachedStatus::class],
- * )
- * class MyObjectCreationLimitReachedStatus internal constructor(
- * objectCreationLimitReachedStatus: ObjectCreationLimitReachedStatus,
- * @Document.StringProperty val foo: String,
- * @Document.LongProperty val bars: List<Int>,
- * ) : AbstractObjectCreationLimitReachedStatus<
- * MyObjectCreationLimitReachedStatus,
- * MyObjectCreationLimitReachedStatus.Builder
- * >(objectCreationLimitReachedStatus) {
- *
- * // No need to implement equals(), hashCode(), toString() or toBuilder()
- *
- * override val selfTypeName =
- * "MyObjectCreationLimitReachedStatus"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun toBuilderWithAdditionalPropertiesOnly(): Builder {
- * return Builder()
- * .setFoo(foo)
- * .addBars(bars)
- * }
- *
- * @Document.BuilderProducer
- * class Builder :
- * AbstractObjectCreationLimitReachedStatus.Builder<
- * Builder,
- * MyObjectCreationLimitReachedStatus> {...}
- * }
- * ```
- *
- * Also see [AbstractObjectCreationLimitReachedStatus.Builder].
- */
-@Suppress("UNCHECKED_CAST")
-public abstract class AbstractObjectCreationLimitReachedStatus<
- Self : AbstractObjectCreationLimitReachedStatus<Self, Builder>,
- Builder : AbstractObjectCreationLimitReachedStatus.Builder<Builder, Self>
->
-internal constructor(
- final override val namespace: String,
- final override val identifier: String,
- final override val name: Name?,
-) : ObjectCreationLimitReachedStatus {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- protected abstract val additionalProperties: Map<String, Any?>
-
- /**
- * A copy-constructor that copies over properties from another [ObjectCreationLimitReachedStatus]
- * instance.
- */
- public constructor(
- objectCreationLimitReachedStatus: ObjectCreationLimitReachedStatus
- ) : this(
- objectCreationLimitReachedStatus.namespace,
- objectCreationLimitReachedStatus.identifier,
- objectCreationLimitReachedStatus.name
- )
-
- /**
- * Returns a concrete [Builder] with the additional, non-[ObjectCreationLimitReachedStatus]
- * properties copied over.
- */
- protected abstract fun toBuilderWithAdditionalPropertiesOnly(): Builder
-
- final override fun toBuilder(): Builder =
- toBuilderWithAdditionalPropertiesOnly()
- .setNamespace(namespace)
- .setIdentifier(identifier)
- .setName(name)
-
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- final override fun hashCode(): Int =
- Objects.hash(namespace, identifier, name, additionalProperties)
-
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated = attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
-
- /**
- * An abstract implementation of [ObjectCreationLimitReachedStatus.Builder].
- *
- * Allows for extension like:
- * ```kt
- * @Document(...)
- * class MyObjectCreationLimitReachedStatus :
- * : AbstractObjectCreationLimitReachedStatus<
- * MyObjectCreationLimitReachedStatus,
- * MyObjectCreationLimitReachedStatus.Builder>(...) {
- *
- * @Document.BuilderProducer
- * class Builder
- * : AbstractObjectCreationLimitReachedStatus.Builder<
- * Builder,
- * MyObjectCreationLimitReachedStatus
- * >() {
- *
- * // No need to implement equals(), hashCode(), toString() or build()
- *
- * private var foo: String? = null
- * private val bars = mutableListOf<Int>()
- *
- * override val selfTypeName =
- * "MyObjectCreationLimitReachedStatus.Builder"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun buildFromObjectCreationLimitReachedStatus(
- * objectCreationLimitReachedStatus: ObjectCreationLimitReachedStatus
- * ): MyObjectCreationLimitReachedStatus {
- * return MyObjectCreationLimitReachedStatus(
- * objectCreationLimitReachedStatus,
- * foo,
- * bars.toList()
- * )
- * }
- *
- * fun setFoo(string: String): Builder {
- * return apply { foo = string }
- * }
- *
- * fun addBar(int: Int): Builder {
- * return apply { bars += int }
- * }
- *
- * fun addBars(values: Iterable<Int>): Builder {
- * return apply { bars += values }
- * }
- * }
- * }
- * ```
- *
- * Also see [AbstractObjectCreationLimitReachedStatus].
- */
- @Suppress("StaticFinalBuilder")
- public abstract class Builder<
- Self : Builder<Self, Built>,
- Built : AbstractObjectCreationLimitReachedStatus<Built, Self>
- > : ObjectCreationLimitReachedStatus.Builder<Self> {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val additionalProperties: Map<String, Any?>
-
- private var namespace: String = ""
-
- private var identifier: String = ""
-
- private var name: Name? = null
-
- /**
- * Builds a concrete [Built] instance, given a built [ObjectCreationLimitReachedStatus].
- *
- * Subclasses should override this method to build a concrete [Built] instance that holds both
- * the [ObjectCreationLimitReachedStatus]-specific properties and the subclass specific
- * [additionalProperties].
- *
- * See the sample code in the documentation of this class for more context.
- */
- @Suppress("BuilderSetStyle")
- protected abstract fun buildFromObjectCreationLimitReachedStatus(
- objectCreationLimitReachedStatus: ObjectCreationLimitReachedStatus
- ): Built
-
- final override fun build(): Built =
- buildFromObjectCreationLimitReachedStatus(
- ObjectCreationLimitReachedStatusImpl(namespace, identifier, name)
- )
-
- final override fun setNamespace(namespace: String): Self {
- this.namespace = namespace
- return this as Self
- }
-
- final override fun setIdentifier(text: String): Self {
- this.identifier = text
- return this as Self
- }
-
- final override fun setName(name: Name?): Self {
- this.name = name
- return this as Self
- }
-
- @Suppress("BuilderSetStyle")
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- @Suppress("BuilderSetStyle")
- final override fun hashCode(): Int =
- Objects.hash(namespace, identifier, name, additionalProperties)
-
- @Suppress("BuilderSetStyle")
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name!!.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated =
- attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
- }
-}
-
-private class ObjectCreationLimitReachedStatusImpl :
- AbstractObjectCreationLimitReachedStatus<
- ObjectCreationLimitReachedStatusImpl, ObjectCreationLimitReachedStatusImpl.Builder
- > {
- protected override val selfTypeName: String
- get() = "ObjectCreationLimitReachedStatus"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- public constructor(
- namespace: String,
- identifier: String,
- name: Name?,
- ) : super(namespace, identifier, name)
-
- public constructor(
- objectCreationLimitReachedStatus: ObjectCreationLimitReachedStatus
- ) : super(objectCreationLimitReachedStatus)
-
- protected override fun toBuilderWithAdditionalPropertiesOnly(): Builder = Builder()
-
- public class Builder :
- AbstractObjectCreationLimitReachedStatus.Builder<
- Builder, ObjectCreationLimitReachedStatusImpl
- >() {
- protected override val selfTypeName: String
- get() = "ObjectCreationLimitReachedStatus.Builder"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- protected override fun buildFromObjectCreationLimitReachedStatus(
- objectCreationLimitReachedStatus: ObjectCreationLimitReachedStatus
- ): ObjectCreationLimitReachedStatusImpl =
- objectCreationLimitReachedStatus as? ObjectCreationLimitReachedStatusImpl
- ?: ObjectCreationLimitReachedStatusImpl(objectCreationLimitReachedStatus)
- }
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/Person.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/Person.kt
deleted file mode 100644
index 5e33c05..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/Person.kt
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * 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.appactions.builtintypes.types
-
-import androidx.appactions.builtintypes.properties.Name
-import androidx.appsearch.`annotation`.Document
-import java.util.Objects
-import kotlin.Any
-import kotlin.Boolean
-import kotlin.Int
-import kotlin.NotImplementedError
-import kotlin.String
-import kotlin.Suppress
-import kotlin.collections.Map
-import kotlin.collections.emptyMap
-import kotlin.collections.joinToString
-import kotlin.collections.map
-import kotlin.collections.mutableMapOf
-import kotlin.collections.plusAssign
-import kotlin.jvm.JvmStatic
-
-/**
- * A person (alive, dead, undead, or fictional).
- *
- * See https://schema.org/Person for context.
- *
- * Should not be directly implemented. More properties may be added over time. Instead consider
- * using [Companion.Builder] or see [AbstractPerson] if you need to extend this type.
- */
-@Document(
- name = "bit:Person",
- parent = [Thing::class],
-)
-public interface Person : Thing {
- /**
- * Email address.
- *
- * See https://schema.org/email for more context.
- */
- @get:Document.StringProperty
- public val email: String?
- get() = null
-
- /**
- * The telephone number.
- *
- * See https://schema.org/telephone for more context.
- */
- @get:Document.StringProperty
- public val telephoneNumber: String?
- get() = null
-
- /** Converts this [Person] to its builder with all the properties copied over. */
- override fun toBuilder(): Builder<*>
-
- public companion object {
- /** Returns a default implementation of [Builder]. */
- @JvmStatic @Document.BuilderProducer public fun Builder(): Builder<*> = PersonImpl.Builder()
- }
-
- /**
- * Builder for [Person].
- *
- * Should not be directly implemented. More methods may be added over time. See
- * [AbstractPerson.Builder] if you need to extend this builder.
- */
- public interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
- /** Returns a built [Person]. */
- override fun build(): Person
-
- /** Sets the `email`. */
- @Suppress("DocumentExceptions")
- public fun setEmail(text: String?): Self = throw NotImplementedError()
-
- /** Sets the `telephoneNumber`. */
- @Suppress("DocumentExceptions")
- public fun setTelephoneNumber(text: String?): Self = throw NotImplementedError()
- }
-}
-
-/**
- * An abstract implementation of [Person].
- *
- * Allows for extension like:
- * ```kt
- * @Document(
- * name = "MyPerson",
- * parent = [Person::class],
- * )
- * class MyPerson internal constructor(
- * person: Person,
- * @Document.StringProperty val foo: String,
- * @Document.LongProperty val bars: List<Int>,
- * ) : AbstractPerson<
- * MyPerson,
- * MyPerson.Builder
- * >(person) {
- *
- * // No need to implement equals(), hashCode(), toString() or toBuilder()
- *
- * override val selfTypeName =
- * "MyPerson"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun toBuilderWithAdditionalPropertiesOnly(): Builder {
- * return Builder()
- * .setFoo(foo)
- * .addBars(bars)
- * }
- *
- * @Document.BuilderProducer
- * class Builder :
- * AbstractPerson.Builder<
- * Builder,
- * MyPerson> {...}
- * }
- * ```
- *
- * Also see [AbstractPerson.Builder].
- */
-@Suppress("UNCHECKED_CAST")
-public abstract class AbstractPerson<
- Self : AbstractPerson<Self, Builder>,
- Builder : AbstractPerson.Builder<Builder, Self>
->
-internal constructor(
- final override val namespace: String,
- final override val email: String?,
- final override val telephoneNumber: String?,
- final override val identifier: String,
- final override val name: Name?,
-) : Person {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- protected abstract val additionalProperties: Map<String, Any?>
-
- /** A copy-constructor that copies over properties from another [Person] instance. */
- public constructor(
- person: Person
- ) : this(person.namespace, person.email, person.telephoneNumber, person.identifier, person.name)
-
- /** Returns a concrete [Builder] with the additional, non-[Person] properties copied over. */
- protected abstract fun toBuilderWithAdditionalPropertiesOnly(): Builder
-
- final override fun toBuilder(): Builder =
- toBuilderWithAdditionalPropertiesOnly()
- .setNamespace(namespace)
- .setEmail(email)
- .setTelephoneNumber(telephoneNumber)
- .setIdentifier(identifier)
- .setName(name)
-
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (email != other.email) return false
- if (telephoneNumber != other.telephoneNumber) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- final override fun hashCode(): Int =
- Objects.hash(namespace, email, telephoneNumber, identifier, name, additionalProperties)
-
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (email != null) {
- attributes["email"] = email
- }
- if (telephoneNumber != null) {
- attributes["telephoneNumber"] = telephoneNumber
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated = attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
-
- /**
- * An abstract implementation of [Person.Builder].
- *
- * Allows for extension like:
- * ```kt
- * @Document(...)
- * class MyPerson :
- * : AbstractPerson<
- * MyPerson,
- * MyPerson.Builder>(...) {
- *
- * @Document.BuilderProducer
- * class Builder
- * : AbstractPerson.Builder<
- * Builder,
- * MyPerson
- * >() {
- *
- * // No need to implement equals(), hashCode(), toString() or build()
- *
- * private var foo: String? = null
- * private val bars = mutableListOf<Int>()
- *
- * override val selfTypeName =
- * "MyPerson.Builder"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun buildFromPerson(
- * person: Person
- * ): MyPerson {
- * return MyPerson(
- * person,
- * foo,
- * bars.toList()
- * )
- * }
- *
- * fun setFoo(string: String): Builder {
- * return apply { foo = string }
- * }
- *
- * fun addBar(int: Int): Builder {
- * return apply { bars += int }
- * }
- *
- * fun addBars(values: Iterable<Int>): Builder {
- * return apply { bars += values }
- * }
- * }
- * }
- * ```
- *
- * Also see [AbstractPerson].
- */
- @Suppress("StaticFinalBuilder")
- public abstract class Builder<Self : Builder<Self, Built>, Built : AbstractPerson<Built, Self>> :
- Person.Builder<Self> {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val additionalProperties: Map<String, Any?>
-
- private var namespace: String = ""
-
- private var email: String? = null
-
- private var telephoneNumber: String? = null
-
- private var identifier: String = ""
-
- private var name: Name? = null
-
- /**
- * Builds a concrete [Built] instance, given a built [Person].
- *
- * Subclasses should override this method to build a concrete [Built] instance that holds both
- * the [Person]-specific properties and the subclass specific [additionalProperties].
- *
- * See the sample code in the documentation of this class for more context.
- */
- @Suppress("BuilderSetStyle") protected abstract fun buildFromPerson(person: Person): Built
-
- final override fun build(): Built =
- buildFromPerson(PersonImpl(namespace, email, telephoneNumber, identifier, name))
-
- final override fun setNamespace(namespace: String): Self {
- this.namespace = namespace
- return this as Self
- }
-
- final override fun setEmail(text: String?): Self {
- this.email = text
- return this as Self
- }
-
- final override fun setTelephoneNumber(text: String?): Self {
- this.telephoneNumber = text
- return this as Self
- }
-
- final override fun setIdentifier(text: String): Self {
- this.identifier = text
- return this as Self
- }
-
- final override fun setName(name: Name?): Self {
- this.name = name
- return this as Self
- }
-
- @Suppress("BuilderSetStyle")
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (email != other.email) return false
- if (telephoneNumber != other.telephoneNumber) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- @Suppress("BuilderSetStyle")
- final override fun hashCode(): Int =
- Objects.hash(namespace, email, telephoneNumber, identifier, name, additionalProperties)
-
- @Suppress("BuilderSetStyle")
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (email != null) {
- attributes["email"] = email!!
- }
- if (telephoneNumber != null) {
- attributes["telephoneNumber"] = telephoneNumber!!
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name!!.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated =
- attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
- }
-}
-
-private class PersonImpl : AbstractPerson<PersonImpl, PersonImpl.Builder> {
- protected override val selfTypeName: String
- get() = "Person"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- public constructor(
- namespace: String,
- email: String?,
- telephoneNumber: String?,
- identifier: String,
- name: Name?,
- ) : super(namespace, email, telephoneNumber, identifier, name)
-
- public constructor(person: Person) : super(person)
-
- protected override fun toBuilderWithAdditionalPropertiesOnly(): Builder = Builder()
-
- public class Builder : AbstractPerson.Builder<Builder, PersonImpl>() {
- protected override val selfTypeName: String
- get() = "Person.Builder"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- protected override fun buildFromPerson(person: Person): PersonImpl =
- person as? PersonImpl ?: PersonImpl(person)
- }
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/Schedule.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/Schedule.kt
deleted file mode 100644
index 0eae687..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/Schedule.kt
+++ /dev/null
@@ -1,954 +0,0 @@
-/*
- * 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.appactions.builtintypes.types
-
-import androidx.appactions.builtintypes.properties.ByDay
-import androidx.appactions.builtintypes.properties.EndDate
-import androidx.appactions.builtintypes.properties.EndTime
-import androidx.appactions.builtintypes.properties.ExceptDate
-import androidx.appactions.builtintypes.properties.Name
-import androidx.appactions.builtintypes.properties.RepeatFrequency
-import androidx.appactions.builtintypes.properties.StartDate
-import androidx.appactions.builtintypes.properties.StartTime
-import androidx.appsearch.`annotation`.Document
-import java.time.Duration
-import java.time.Instant
-import java.time.LocalDate
-import java.time.LocalDateTime
-import java.time.LocalTime
-import java.util.Objects
-import kotlin.Any
-import kotlin.Boolean
-import kotlin.Int
-import kotlin.Long
-import kotlin.NotImplementedError
-import kotlin.String
-import kotlin.Suppress
-import kotlin.collections.Iterable
-import kotlin.collections.List
-import kotlin.collections.Map
-import kotlin.collections.MutableList
-import kotlin.collections.emptyList
-import kotlin.collections.emptyMap
-import kotlin.collections.isNotEmpty
-import kotlin.collections.joinToString
-import kotlin.collections.map
-import kotlin.collections.mutableListOf
-import kotlin.collections.mutableMapOf
-import kotlin.collections.plusAssign
-import kotlin.collections.toList
-import kotlin.jvm.JvmStatic
-
-/**
- * A schedule defines a repeating time period used to describe a regularly occurring `Event`. At a
- * minimum a schedule will specify `repeatFrequency` which describes the interval between
- * occurrences of the event. Additional information can be provided to specify the schedule more
- * precisely. This includes identifying the day(s) of the week or month when the recurring event
- * will take place, in addition to its start and end time. Schedules may also have start and end
- * dates to indicate when they are active, e.g. to define a limited calendar of events.
- *
- * See https://schema.org/Schedule for context.
- *
- * Should not be directly implemented. More properties may be added over time. Instead consider
- * using [Companion.Builder] or see [AbstractSchedule] if you need to extend this type.
- */
-@Document(
- name = "bit:Schedule",
- parent = [Intangible::class],
-)
-public interface Schedule : Intangible {
- /**
- * Defines the day(s) of the week on which a recurring Event takes place.
- *
- * See https://schema.org/byDay for more context.
- */
- @get:Document.DocumentProperty
- public val byDays: List<ByDay>
- get() = emptyList()
-
- /**
- * Defines the month(s) of the year on which a recurring Event takes place. Specified as an
- * Integer between 1-12. January is 1.
- *
- * See https://schema.org/byMonth for more context.
- */
- @get:Document.LongProperty
- public val byMonths: List<Long>
- get() = emptyList()
-
- /**
- * Defines the day(s) of the month on which a recurring Event takes place. Specified as an Integer
- * between 1-31.
- *
- * See https://schema.org/byMonthDay for more context.
- */
- @get:Document.LongProperty
- public val byMonthDays: List<Long>
- get() = emptyList()
-
- /**
- * Defines the week(s) of the month on which a recurring Event takes place. Specified as an
- * Integer between 1-5. For clarity, byMonthWeek is best used in conjunction with byDay to
- * indicate concepts like the first and third Mondays of a month.
- *
- * See https://schema.org/byMonthWeek for more context.
- */
- @get:Document.LongProperty
- public val byMonthWeeks: List<Long>
- get() = emptyList()
-
- /**
- * The end date and time of the item.
- *
- * See https://schema.org/endDate for more context.
- */
- @get:Document.DocumentProperty
- public val endDate: EndDate?
- get() = null
-
- /**
- * The endTime of something.
- *
- * For a reserved event or service (e.g. `FoodEstablishmentReservation`), the time that it is
- * expected to end. For actions that span a period of time, when the action was performed. E.g.
- * John wrote a book from January to *December*. For media, including audio and video, it's the
- * time offset of the end of a clip within a larger file.
- *
- * See https://schema.org/endTime for more context.
- */
- @get:Document.DocumentProperty
- public val endTime: EndTime?
- get() = null
-
- /**
- * Defines a `Date` or `DateTime` during which a scheduled `Event` will not take place. The
- * property allows exceptions to a `Schedule` to be specified. If an exception is specified as a
- * `DateTime` then only the event that would have started at that specific date and time should be
- * excluded from the schedule. If an exception is specified as a `Date` then any event that is
- * scheduled for that 24 hour period should be excluded from the schedule. This allows a whole day
- * to be excluded from the schedule without having to itemise every scheduled event.
- *
- * See https://schema.org/exceptDate for more context.
- */
- @get:Document.DocumentProperty
- public val exceptDate: ExceptDate?
- get() = null
-
- /**
- * Defines the number of times a recurring `Event` will take place.
- *
- * See https://schema.org/repeatCount for more context.
- */
- @get:Document.LongProperty
- @get:Suppress("AutoBoxing")
- public val repeatCount: Long?
- get() = null
-
- /**
- * Defines the frequency at which `Event`s will occur according to a schedule `Schedule`. The
- * intervals between events should be defined as a `Duration` of time.
- *
- * See https://schema.org/repeatFrequency for more context.
- */
- @get:Document.DocumentProperty
- public val repeatFrequency: RepeatFrequency?
- get() = null
-
- /**
- * Indicates the timezone for which the time(s) indicated in the `Schedule` are given. The value
- * provided should be among those listed in the IANA Time Zone Database.
- *
- * See https://schema.org/scheduleTimezone for more context.
- */
- @get:Document.StringProperty
- public val scheduleTimezone: String?
- get() = null
-
- /**
- * The start date and time of the item.
- *
- * See https://schema.org/startDate for more context.
- */
- @get:Document.DocumentProperty
- public val startDate: StartDate?
- get() = null
-
- /**
- * The startTime of something.
- *
- * For a reserved event or service (e.g. `FoodEstablishmentReservation`), the time that it is
- * expected to start. For actions that span a period of time, when the action was performed. E.g.
- * John wrote a book from *January* to December. For media, including audio and video, it's the
- * time offset of the start of a clip within a larger file.
- *
- * See https://schema.org/startTime for more context.
- */
- @get:Document.DocumentProperty
- public val startTime: StartTime?
- get() = null
-
- /** Converts this [Schedule] to its builder with all the properties copied over. */
- override fun toBuilder(): Builder<*>
-
- public companion object {
- /** Returns a default implementation of [Builder]. */
- @JvmStatic @Document.BuilderProducer public fun Builder(): Builder<*> = ScheduleImpl.Builder()
- }
-
- /**
- * Builder for [Schedule].
- *
- * Should not be directly implemented. More methods may be added over time. See
- * [AbstractSchedule.Builder] if you need to extend this builder.
- */
- public interface Builder<Self : Builder<Self>> : Intangible.Builder<Self> {
- /** Returns a built [Schedule]. */
- override fun build(): Schedule
-
- /** Appends [DayOfWeek] as a value to `byDays`. */
- public fun addByDay(dayOfWeek: DayOfWeek): Self = addByDay(ByDay(dayOfWeek))
-
- /** Appends a value to `byDays`. */
- @Suppress("DocumentExceptions")
- public fun addByDay(byDay: ByDay): Self = throw NotImplementedError()
-
- /** Appends multiple values to `byDays`. */
- @Suppress("DocumentExceptions")
- public fun addByDays(values: Iterable<ByDay>): Self = throw NotImplementedError()
-
- /** Clears `byDays`. */
- @Suppress("DocumentExceptions") public fun clearByDays(): Self = throw NotImplementedError()
-
- /** Appends a value to `byMonths`. */
- @Suppress("DocumentExceptions")
- public fun addByMonth(integer: Long): Self = throw NotImplementedError()
-
- /** Appends multiple values to `byMonths`. */
- @Suppress("DocumentExceptions")
- public fun addByMonths(values: Iterable<Long>): Self = throw NotImplementedError()
-
- /** Clears `byMonths`. */
- @Suppress("DocumentExceptions") public fun clearByMonths(): Self = throw NotImplementedError()
-
- /** Appends a value to `byMonthDays`. */
- @Suppress("DocumentExceptions")
- public fun addByMonthDay(integer: Long): Self = throw NotImplementedError()
-
- /** Appends multiple values to `byMonthDays`. */
- @Suppress("DocumentExceptions")
- public fun addByMonthDays(values: Iterable<Long>): Self = throw NotImplementedError()
-
- /** Clears `byMonthDays`. */
- @Suppress("DocumentExceptions")
- public fun clearByMonthDays(): Self = throw NotImplementedError()
-
- /** Appends a value to `byMonthWeeks`. */
- @Suppress("DocumentExceptions")
- public fun addByMonthWeek(integer: Long): Self = throw NotImplementedError()
-
- /** Appends multiple values to `byMonthWeeks`. */
- @Suppress("DocumentExceptions")
- public fun addByMonthWeeks(values: Iterable<Long>): Self = throw NotImplementedError()
-
- /** Clears `byMonthWeeks`. */
- @Suppress("DocumentExceptions")
- public fun clearByMonthWeeks(): Self = throw NotImplementedError()
-
- /** Sets the `endDate` to [LocalDate]. */
- public fun setEndDate(date: LocalDate): Self = setEndDate(EndDate(date))
-
- /** Sets the `endDate`. */
- @Suppress("DocumentExceptions")
- public fun setEndDate(endDate: EndDate?): Self = throw NotImplementedError()
-
- /** Sets the `endTime` to [LocalTime]. */
- public fun setEndTime(time: LocalTime): Self = setEndTime(EndTime(time))
-
- /** Sets the `endTime`. */
- @Suppress("DocumentExceptions")
- public fun setEndTime(endTime: EndTime?): Self = throw NotImplementedError()
-
- /** Sets the `exceptDate` to [LocalDate]. */
- public fun setExceptDate(date: LocalDate): Self = setExceptDate(ExceptDate(date))
-
- /** Sets the `exceptDate` to [LocalDateTime]. */
- public fun setExceptDate(localDateTime: LocalDateTime): Self =
- setExceptDate(ExceptDate(localDateTime))
-
- /** Sets the `exceptDate` to [Instant]. */
- public fun setExceptDate(instant: Instant): Self = setExceptDate(ExceptDate(instant))
-
- /** Sets the `exceptDate`. */
- @Suppress("DocumentExceptions")
- public fun setExceptDate(exceptDate: ExceptDate?): Self = throw NotImplementedError()
-
- /** Sets the `repeatCount`. */
- @Suppress("DocumentExceptions")
- public fun setRepeatCount(@Suppress("AutoBoxing") integer: Long?): Self =
- throw NotImplementedError()
-
- /** Sets the `repeatFrequency` to [Duration]. */
- public fun setRepeatFrequency(duration: Duration): Self =
- setRepeatFrequency(RepeatFrequency(duration))
-
- /** Sets the `repeatFrequency`. */
- @Suppress("DocumentExceptions")
- public fun setRepeatFrequency(repeatFrequency: RepeatFrequency?): Self =
- throw NotImplementedError()
-
- /** Sets the `scheduleTimezone`. */
- @Suppress("DocumentExceptions")
- public fun setScheduleTimezone(text: String?): Self = throw NotImplementedError()
-
- /** Sets the `startDate` to [LocalDate]. */
- public fun setStartDate(date: LocalDate): Self = setStartDate(StartDate(date))
-
- /** Sets the `startDate`. */
- @Suppress("DocumentExceptions")
- public fun setStartDate(startDate: StartDate?): Self = throw NotImplementedError()
-
- /** Sets the `startTime` to [LocalTime]. */
- public fun setStartTime(time: LocalTime): Self = setStartTime(StartTime(time))
-
- /** Sets the `startTime`. */
- @Suppress("DocumentExceptions")
- public fun setStartTime(startTime: StartTime?): Self = throw NotImplementedError()
- }
-}
-
-/**
- * An abstract implementation of [Schedule].
- *
- * Allows for extension like:
- * ```kt
- * @Document(
- * name = "MySchedule",
- * parent = [Schedule::class],
- * )
- * class MySchedule internal constructor(
- * schedule: Schedule,
- * @Document.StringProperty val foo: String,
- * @Document.LongProperty val bars: List<Int>,
- * ) : AbstractSchedule<
- * MySchedule,
- * MySchedule.Builder
- * >(schedule) {
- *
- * // No need to implement equals(), hashCode(), toString() or toBuilder()
- *
- * override val selfTypeName =
- * "MySchedule"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun toBuilderWithAdditionalPropertiesOnly(): Builder {
- * return Builder()
- * .setFoo(foo)
- * .addBars(bars)
- * }
- *
- * @Document.BuilderProducer
- * class Builder :
- * AbstractSchedule.Builder<
- * Builder,
- * MySchedule> {...}
- * }
- * ```
- *
- * Also see [AbstractSchedule.Builder].
- */
-@Suppress("UNCHECKED_CAST")
-public abstract class AbstractSchedule<
- Self : AbstractSchedule<Self, Builder>,
- Builder : AbstractSchedule.Builder<Builder, Self>
->
-internal constructor(
- final override val namespace: String,
- final override val byDays: List<ByDay>,
- final override val byMonths: List<Long>,
- final override val byMonthDays: List<Long>,
- final override val byMonthWeeks: List<Long>,
- final override val endDate: EndDate?,
- final override val endTime: EndTime?,
- final override val exceptDate: ExceptDate?,
- @get:Suppress("AutoBoxing") final override val repeatCount: Long?,
- final override val repeatFrequency: RepeatFrequency?,
- final override val scheduleTimezone: String?,
- final override val startDate: StartDate?,
- final override val startTime: StartTime?,
- final override val identifier: String,
- final override val name: Name?,
-) : Schedule {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- protected abstract val additionalProperties: Map<String, Any?>
-
- /** A copy-constructor that copies over properties from another [Schedule] instance. */
- public constructor(
- schedule: Schedule
- ) : this(
- schedule.namespace,
- schedule.byDays,
- schedule.byMonths,
- schedule.byMonthDays,
- schedule.byMonthWeeks,
- schedule.endDate,
- schedule.endTime,
- schedule.exceptDate,
- schedule.repeatCount,
- schedule.repeatFrequency,
- schedule.scheduleTimezone,
- schedule.startDate,
- schedule.startTime,
- schedule.identifier,
- schedule.name
- )
-
- /** Returns a concrete [Builder] with the additional, non-[Schedule] properties copied over. */
- protected abstract fun toBuilderWithAdditionalPropertiesOnly(): Builder
-
- final override fun toBuilder(): Builder =
- toBuilderWithAdditionalPropertiesOnly()
- .setNamespace(namespace)
- .addByDays(byDays)
- .addByMonths(byMonths)
- .addByMonthDays(byMonthDays)
- .addByMonthWeeks(byMonthWeeks)
- .setEndDate(endDate)
- .setEndTime(endTime)
- .setExceptDate(exceptDate)
- .setRepeatCount(repeatCount)
- .setRepeatFrequency(repeatFrequency)
- .setScheduleTimezone(scheduleTimezone)
- .setStartDate(startDate)
- .setStartTime(startTime)
- .setIdentifier(identifier)
- .setName(name)
-
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (byDays != other.byDays) return false
- if (byMonths != other.byMonths) return false
- if (byMonthDays != other.byMonthDays) return false
- if (byMonthWeeks != other.byMonthWeeks) return false
- if (endDate != other.endDate) return false
- if (endTime != other.endTime) return false
- if (exceptDate != other.exceptDate) return false
- if (repeatCount != other.repeatCount) return false
- if (repeatFrequency != other.repeatFrequency) return false
- if (scheduleTimezone != other.scheduleTimezone) return false
- if (startDate != other.startDate) return false
- if (startTime != other.startTime) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- final override fun hashCode(): Int =
- Objects.hash(
- namespace,
- byDays,
- byMonths,
- byMonthDays,
- byMonthWeeks,
- endDate,
- endTime,
- exceptDate,
- repeatCount,
- repeatFrequency,
- scheduleTimezone,
- startDate,
- startTime,
- identifier,
- name,
- additionalProperties
- )
-
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (byDays.isNotEmpty()) {
- attributes["byDays"] = byDays.map { it.toString(includeWrapperName = false) }.toString()
- }
- if (byMonths.isNotEmpty()) {
- attributes["byMonths"] = byMonths.toString()
- }
- if (byMonthDays.isNotEmpty()) {
- attributes["byMonthDays"] = byMonthDays.toString()
- }
- if (byMonthWeeks.isNotEmpty()) {
- attributes["byMonthWeeks"] = byMonthWeeks.toString()
- }
- if (endDate != null) {
- attributes["endDate"] = endDate.toString(includeWrapperName = false)
- }
- if (endTime != null) {
- attributes["endTime"] = endTime.toString(includeWrapperName = false)
- }
- if (exceptDate != null) {
- attributes["exceptDate"] = exceptDate.toString(includeWrapperName = false)
- }
- if (repeatCount != null) {
- attributes["repeatCount"] = repeatCount.toString()
- }
- if (repeatFrequency != null) {
- attributes["repeatFrequency"] = repeatFrequency.toString(includeWrapperName = false)
- }
- if (scheduleTimezone != null) {
- attributes["scheduleTimezone"] = scheduleTimezone
- }
- if (startDate != null) {
- attributes["startDate"] = startDate.toString(includeWrapperName = false)
- }
- if (startTime != null) {
- attributes["startTime"] = startTime.toString(includeWrapperName = false)
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated = attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
-
- /**
- * An abstract implementation of [Schedule.Builder].
- *
- * Allows for extension like:
- * ```kt
- * @Document(...)
- * class MySchedule :
- * : AbstractSchedule<
- * MySchedule,
- * MySchedule.Builder>(...) {
- *
- * @Document.BuilderProducer
- * class Builder
- * : AbstractSchedule.Builder<
- * Builder,
- * MySchedule
- * >() {
- *
- * // No need to implement equals(), hashCode(), toString() or build()
- *
- * private var foo: String? = null
- * private val bars = mutableListOf<Int>()
- *
- * override val selfTypeName =
- * "MySchedule.Builder"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun buildFromSchedule(
- * schedule: Schedule
- * ): MySchedule {
- * return MySchedule(
- * schedule,
- * foo,
- * bars.toList()
- * )
- * }
- *
- * fun setFoo(string: String): Builder {
- * return apply { foo = string }
- * }
- *
- * fun addBar(int: Int): Builder {
- * return apply { bars += int }
- * }
- *
- * fun addBars(values: Iterable<Int>): Builder {
- * return apply { bars += values }
- * }
- * }
- * }
- * ```
- *
- * Also see [AbstractSchedule].
- */
- @Suppress("StaticFinalBuilder")
- public abstract class Builder<
- Self : Builder<Self, Built>,
- Built : AbstractSchedule<Built, Self>
- > : Schedule.Builder<Self> {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val additionalProperties: Map<String, Any?>
-
- private var namespace: String = ""
-
- private val byDays: MutableList<ByDay> = mutableListOf()
-
- private val byMonths: MutableList<Long> = mutableListOf()
-
- private val byMonthDays: MutableList<Long> = mutableListOf()
-
- private val byMonthWeeks: MutableList<Long> = mutableListOf()
-
- private var endDate: EndDate? = null
-
- private var endTime: EndTime? = null
-
- private var exceptDate: ExceptDate? = null
-
- @get:Suppress("AutoBoxing") private var repeatCount: Long? = null
-
- private var repeatFrequency: RepeatFrequency? = null
-
- private var scheduleTimezone: String? = null
-
- private var startDate: StartDate? = null
-
- private var startTime: StartTime? = null
-
- private var identifier: String = ""
-
- private var name: Name? = null
-
- /**
- * Builds a concrete [Built] instance, given a built [Schedule].
- *
- * Subclasses should override this method to build a concrete [Built] instance that holds both
- * the [Schedule]-specific properties and the subclass specific [additionalProperties].
- *
- * See the sample code in the documentation of this class for more context.
- */
- @Suppress("BuilderSetStyle") protected abstract fun buildFromSchedule(schedule: Schedule): Built
-
- final override fun build(): Built =
- buildFromSchedule(
- ScheduleImpl(
- namespace,
- byDays.toList(),
- byMonths.toList(),
- byMonthDays.toList(),
- byMonthWeeks.toList(),
- endDate,
- endTime,
- exceptDate,
- repeatCount,
- repeatFrequency,
- scheduleTimezone,
- startDate,
- startTime,
- identifier,
- name
- )
- )
-
- final override fun setNamespace(namespace: String): Self {
- this.namespace = namespace
- return this as Self
- }
-
- final override fun addByDay(byDay: ByDay): Self {
- byDays += byDay
- return this as Self
- }
-
- final override fun addByDays(values: Iterable<ByDay>): Self {
- byDays += values
- return this as Self
- }
-
- final override fun clearByDays(): Self {
- byDays.clear()
- return this as Self
- }
-
- final override fun addByMonth(integer: Long): Self {
- byMonths += integer
- return this as Self
- }
-
- final override fun addByMonths(values: Iterable<Long>): Self {
- byMonths += values
- return this as Self
- }
-
- final override fun clearByMonths(): Self {
- byMonths.clear()
- return this as Self
- }
-
- final override fun addByMonthDay(integer: Long): Self {
- byMonthDays += integer
- return this as Self
- }
-
- final override fun addByMonthDays(values: Iterable<Long>): Self {
- byMonthDays += values
- return this as Self
- }
-
- final override fun clearByMonthDays(): Self {
- byMonthDays.clear()
- return this as Self
- }
-
- final override fun addByMonthWeek(integer: Long): Self {
- byMonthWeeks += integer
- return this as Self
- }
-
- final override fun addByMonthWeeks(values: Iterable<Long>): Self {
- byMonthWeeks += values
- return this as Self
- }
-
- final override fun clearByMonthWeeks(): Self {
- byMonthWeeks.clear()
- return this as Self
- }
-
- final override fun setEndDate(endDate: EndDate?): Self {
- this.endDate = endDate
- return this as Self
- }
-
- final override fun setEndTime(endTime: EndTime?): Self {
- this.endTime = endTime
- return this as Self
- }
-
- final override fun setExceptDate(exceptDate: ExceptDate?): Self {
- this.exceptDate = exceptDate
- return this as Self
- }
-
- final override fun setRepeatCount(@Suppress("AutoBoxing") integer: Long?): Self {
- this.repeatCount = integer
- return this as Self
- }
-
- final override fun setRepeatFrequency(repeatFrequency: RepeatFrequency?): Self {
- this.repeatFrequency = repeatFrequency
- return this as Self
- }
-
- final override fun setScheduleTimezone(text: String?): Self {
- this.scheduleTimezone = text
- return this as Self
- }
-
- final override fun setStartDate(startDate: StartDate?): Self {
- this.startDate = startDate
- return this as Self
- }
-
- final override fun setStartTime(startTime: StartTime?): Self {
- this.startTime = startTime
- return this as Self
- }
-
- final override fun setIdentifier(text: String): Self {
- this.identifier = text
- return this as Self
- }
-
- final override fun setName(name: Name?): Self {
- this.name = name
- return this as Self
- }
-
- @Suppress("BuilderSetStyle")
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (byDays != other.byDays) return false
- if (byMonths != other.byMonths) return false
- if (byMonthDays != other.byMonthDays) return false
- if (byMonthWeeks != other.byMonthWeeks) return false
- if (endDate != other.endDate) return false
- if (endTime != other.endTime) return false
- if (exceptDate != other.exceptDate) return false
- if (repeatCount != other.repeatCount) return false
- if (repeatFrequency != other.repeatFrequency) return false
- if (scheduleTimezone != other.scheduleTimezone) return false
- if (startDate != other.startDate) return false
- if (startTime != other.startTime) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- @Suppress("BuilderSetStyle")
- final override fun hashCode(): Int =
- Objects.hash(
- namespace,
- byDays,
- byMonths,
- byMonthDays,
- byMonthWeeks,
- endDate,
- endTime,
- exceptDate,
- repeatCount,
- repeatFrequency,
- scheduleTimezone,
- startDate,
- startTime,
- identifier,
- name,
- additionalProperties
- )
-
- @Suppress("BuilderSetStyle")
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (byDays.isNotEmpty()) {
- attributes["byDays"] = byDays.map { it.toString(includeWrapperName = false) }.toString()
- }
- if (byMonths.isNotEmpty()) {
- attributes["byMonths"] = byMonths.toString()
- }
- if (byMonthDays.isNotEmpty()) {
- attributes["byMonthDays"] = byMonthDays.toString()
- }
- if (byMonthWeeks.isNotEmpty()) {
- attributes["byMonthWeeks"] = byMonthWeeks.toString()
- }
- if (endDate != null) {
- attributes["endDate"] = endDate!!.toString(includeWrapperName = false)
- }
- if (endTime != null) {
- attributes["endTime"] = endTime!!.toString(includeWrapperName = false)
- }
- if (exceptDate != null) {
- attributes["exceptDate"] = exceptDate!!.toString(includeWrapperName = false)
- }
- if (repeatCount != null) {
- attributes["repeatCount"] = repeatCount!!.toString()
- }
- if (repeatFrequency != null) {
- attributes["repeatFrequency"] = repeatFrequency!!.toString(includeWrapperName = false)
- }
- if (scheduleTimezone != null) {
- attributes["scheduleTimezone"] = scheduleTimezone!!
- }
- if (startDate != null) {
- attributes["startDate"] = startDate!!.toString(includeWrapperName = false)
- }
- if (startTime != null) {
- attributes["startTime"] = startTime!!.toString(includeWrapperName = false)
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name!!.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated =
- attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
- }
-}
-
-private class ScheduleImpl : AbstractSchedule<ScheduleImpl, ScheduleImpl.Builder> {
- protected override val selfTypeName: String
- get() = "Schedule"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- public constructor(
- namespace: String,
- byDays: List<ByDay>,
- byMonths: List<Long>,
- byMonthDays: List<Long>,
- byMonthWeeks: List<Long>,
- endDate: EndDate?,
- endTime: EndTime?,
- exceptDate: ExceptDate?,
- repeatCount: Long?,
- repeatFrequency: RepeatFrequency?,
- scheduleTimezone: String?,
- startDate: StartDate?,
- startTime: StartTime?,
- identifier: String,
- name: Name?,
- ) : super(
- namespace,
- byDays,
- byMonths,
- byMonthDays,
- byMonthWeeks,
- endDate,
- endTime,
- exceptDate,
- repeatCount,
- repeatFrequency,
- scheduleTimezone,
- startDate,
- startTime,
- identifier,
- name
- )
-
- public constructor(schedule: Schedule) : super(schedule)
-
- protected override fun toBuilderWithAdditionalPropertiesOnly(): Builder = Builder()
-
- public class Builder : AbstractSchedule.Builder<Builder, ScheduleImpl>() {
- protected override val selfTypeName: String
- get() = "Schedule.Builder"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- protected override fun buildFromSchedule(schedule: Schedule): ScheduleImpl =
- schedule as? ScheduleImpl ?: ScheduleImpl(schedule)
- }
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/SuccessStatus.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/SuccessStatus.kt
deleted file mode 100644
index 65ac499..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/SuccessStatus.kt
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * 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.appactions.builtintypes.types
-
-import androidx.appactions.builtintypes.properties.Name
-import androidx.appsearch.`annotation`.Document
-import java.util.Objects
-import kotlin.Any
-import kotlin.Boolean
-import kotlin.Int
-import kotlin.String
-import kotlin.Suppress
-import kotlin.collections.Map
-import kotlin.collections.emptyMap
-import kotlin.collections.joinToString
-import kotlin.collections.map
-import kotlin.collections.mutableMapOf
-import kotlin.collections.plusAssign
-import kotlin.jvm.JvmStatic
-
-/**
- * Status indicating that the task was executed successfully.
- *
- * See https://schema.googleapis.com/SuccessStatus for context.
- *
- * Should not be directly implemented. More properties may be added over time. Instead consider
- * using [Companion.Builder] or see [AbstractSuccessStatus] if you need to extend this type.
- */
-@Document(
- name = "bit:SuccessStatus",
- parent = [CommonExecutionStatus::class],
-)
-public interface SuccessStatus : CommonExecutionStatus {
- /** Converts this [SuccessStatus] to its builder with all the properties copied over. */
- override fun toBuilder(): Builder<*>
-
- public companion object {
- /** Returns a default implementation of [Builder]. */
- @JvmStatic
- @Document.BuilderProducer
- public fun Builder(): Builder<*> = SuccessStatusImpl.Builder()
- }
-
- /**
- * Builder for [SuccessStatus].
- *
- * Should not be directly implemented. More methods may be added over time. See
- * [AbstractSuccessStatus.Builder] if you need to extend this builder.
- */
- public interface Builder<Self : Builder<Self>> : CommonExecutionStatus.Builder<Self> {
- /** Returns a built [SuccessStatus]. */
- override fun build(): SuccessStatus
- }
-}
-
-/**
- * An abstract implementation of [SuccessStatus].
- *
- * Allows for extension like:
- * ```kt
- * @Document(
- * name = "MySuccessStatus",
- * parent = [SuccessStatus::class],
- * )
- * class MySuccessStatus internal constructor(
- * successStatus: SuccessStatus,
- * @Document.StringProperty val foo: String,
- * @Document.LongProperty val bars: List<Int>,
- * ) : AbstractSuccessStatus<
- * MySuccessStatus,
- * MySuccessStatus.Builder
- * >(successStatus) {
- *
- * // No need to implement equals(), hashCode(), toString() or toBuilder()
- *
- * override val selfTypeName =
- * "MySuccessStatus"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun toBuilderWithAdditionalPropertiesOnly(): Builder {
- * return Builder()
- * .setFoo(foo)
- * .addBars(bars)
- * }
- *
- * @Document.BuilderProducer
- * class Builder :
- * AbstractSuccessStatus.Builder<
- * Builder,
- * MySuccessStatus> {...}
- * }
- * ```
- *
- * Also see [AbstractSuccessStatus.Builder].
- */
-@Suppress("UNCHECKED_CAST")
-public abstract class AbstractSuccessStatus<
- Self : AbstractSuccessStatus<Self, Builder>,
- Builder : AbstractSuccessStatus.Builder<Builder, Self>
->
-internal constructor(
- final override val namespace: String,
- final override val identifier: String,
- final override val name: Name?,
-) : SuccessStatus {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- protected abstract val additionalProperties: Map<String, Any?>
-
- /** A copy-constructor that copies over properties from another [SuccessStatus] instance. */
- public constructor(
- successStatus: SuccessStatus
- ) : this(successStatus.namespace, successStatus.identifier, successStatus.name)
-
- /**
- * Returns a concrete [Builder] with the additional, non-[SuccessStatus] properties copied over.
- */
- protected abstract fun toBuilderWithAdditionalPropertiesOnly(): Builder
-
- final override fun toBuilder(): Builder =
- toBuilderWithAdditionalPropertiesOnly()
- .setNamespace(namespace)
- .setIdentifier(identifier)
- .setName(name)
-
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- final override fun hashCode(): Int =
- Objects.hash(namespace, identifier, name, additionalProperties)
-
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated = attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
-
- /**
- * An abstract implementation of [SuccessStatus.Builder].
- *
- * Allows for extension like:
- * ```kt
- * @Document(...)
- * class MySuccessStatus :
- * : AbstractSuccessStatus<
- * MySuccessStatus,
- * MySuccessStatus.Builder>(...) {
- *
- * @Document.BuilderProducer
- * class Builder
- * : AbstractSuccessStatus.Builder<
- * Builder,
- * MySuccessStatus
- * >() {
- *
- * // No need to implement equals(), hashCode(), toString() or build()
- *
- * private var foo: String? = null
- * private val bars = mutableListOf<Int>()
- *
- * override val selfTypeName =
- * "MySuccessStatus.Builder"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun buildFromSuccessStatus(
- * successStatus: SuccessStatus
- * ): MySuccessStatus {
- * return MySuccessStatus(
- * successStatus,
- * foo,
- * bars.toList()
- * )
- * }
- *
- * fun setFoo(string: String): Builder {
- * return apply { foo = string }
- * }
- *
- * fun addBar(int: Int): Builder {
- * return apply { bars += int }
- * }
- *
- * fun addBars(values: Iterable<Int>): Builder {
- * return apply { bars += values }
- * }
- * }
- * }
- * ```
- *
- * Also see [AbstractSuccessStatus].
- */
- @Suppress("StaticFinalBuilder")
- public abstract class Builder<
- Self : Builder<Self, Built>,
- Built : AbstractSuccessStatus<Built, Self>
- > : SuccessStatus.Builder<Self> {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val additionalProperties: Map<String, Any?>
-
- private var namespace: String = ""
-
- private var identifier: String = ""
-
- private var name: Name? = null
-
- /**
- * Builds a concrete [Built] instance, given a built [SuccessStatus].
- *
- * Subclasses should override this method to build a concrete [Built] instance that holds both
- * the [SuccessStatus]-specific properties and the subclass specific [additionalProperties].
- *
- * See the sample code in the documentation of this class for more context.
- */
- @Suppress("BuilderSetStyle")
- protected abstract fun buildFromSuccessStatus(successStatus: SuccessStatus): Built
-
- final override fun build(): Built =
- buildFromSuccessStatus(SuccessStatusImpl(namespace, identifier, name))
-
- final override fun setNamespace(namespace: String): Self {
- this.namespace = namespace
- return this as Self
- }
-
- final override fun setIdentifier(text: String): Self {
- this.identifier = text
- return this as Self
- }
-
- final override fun setName(name: Name?): Self {
- this.name = name
- return this as Self
- }
-
- @Suppress("BuilderSetStyle")
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- @Suppress("BuilderSetStyle")
- final override fun hashCode(): Int =
- Objects.hash(namespace, identifier, name, additionalProperties)
-
- @Suppress("BuilderSetStyle")
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name!!.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated =
- attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
- }
-}
-
-private class SuccessStatusImpl :
- AbstractSuccessStatus<SuccessStatusImpl, SuccessStatusImpl.Builder> {
- protected override val selfTypeName: String
- get() = "SuccessStatus"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- public constructor(
- namespace: String,
- identifier: String,
- name: Name?,
- ) : super(namespace, identifier, name)
-
- public constructor(successStatus: SuccessStatus) : super(successStatus)
-
- protected override fun toBuilderWithAdditionalPropertiesOnly(): Builder = Builder()
-
- public class Builder : AbstractSuccessStatus.Builder<Builder, SuccessStatusImpl>() {
- protected override val selfTypeName: String
- get() = "SuccessStatus.Builder"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- protected override fun buildFromSuccessStatus(successStatus: SuccessStatus): SuccessStatusImpl =
- successStatus as? SuccessStatusImpl ?: SuccessStatusImpl(successStatus)
- }
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/Thing.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/Thing.kt
deleted file mode 100644
index f86de3b..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/Thing.kt
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * 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.appactions.builtintypes.types
-
-import androidx.appactions.builtintypes.properties.Name
-import androidx.appsearch.`annotation`.Document
-import java.util.Objects
-import kotlin.Any
-import kotlin.Boolean
-import kotlin.Int
-import kotlin.NotImplementedError
-import kotlin.String
-import kotlin.Suppress
-import kotlin.collections.Map
-import kotlin.collections.emptyMap
-import kotlin.collections.joinToString
-import kotlin.collections.map
-import kotlin.collections.mutableMapOf
-import kotlin.collections.plusAssign
-import kotlin.jvm.JvmStatic
-
-/**
- * The most generic type of item.
- *
- * See https://schema.org/Thing for context.
- *
- * Should not be directly implemented. More properties may be added over time. Instead consider
- * using [Companion.Builder] or see [AbstractThing] if you need to extend this type.
- */
-@Document(name = "bit:Thing")
-public interface Thing {
- /** Represents the AppSearch document's namespace. */
- @get:Document.Namespace
- public val namespace: String
- get() = ""
-
- /**
- * The identifier property represents any kind of identifier for any kind of Thing, such as ISBNs,
- * GTIN codes, UUIDs etc.
- *
- * See https://schema.org/identifier for more context.
- */
- @get:Document.Id
- public val identifier: String
- get() = ""
-
- /**
- * The name of the item.
- *
- * See https://schema.org/name for more context.
- */
- @get:Document.DocumentProperty
- public val name: Name?
- get() = null
-
- /** Converts this [Thing] to its builder with all the properties copied over. */
- public fun toBuilder(): Builder<*>
-
- public companion object {
- /** Returns a default implementation of [Builder]. */
- @JvmStatic @Document.BuilderProducer public fun Builder(): Builder<*> = ThingImpl.Builder()
- }
-
- /**
- * Builder for [Thing].
- *
- * Should not be directly implemented. More methods may be added over time. See
- * [AbstractThing.Builder] if you need to extend this builder.
- */
- @Suppress("StaticFinalBuilder")
- public interface Builder<Self : Builder<Self>> {
- /** Returns a built [Thing]. */
- public fun build(): Thing
-
- /** Sets the `namespace`. */
- @Suppress("DocumentExceptions")
- public fun setNamespace(namespace: String): Self = throw NotImplementedError()
-
- /** Sets the `identifier`. */
- @Suppress("DocumentExceptions")
- public fun setIdentifier(text: String): Self = throw NotImplementedError()
-
- /** Sets the `name` to [String]. */
- public fun setName(text: String): Self = setName(Name(text))
-
- /** Sets the `name`. */
- @Suppress("DocumentExceptions")
- public fun setName(name: Name?): Self = throw NotImplementedError()
- }
-}
-
-/**
- * An abstract implementation of [Thing].
- *
- * Allows for extension like:
- * ```kt
- * @Document(
- * name = "MyThing",
- * parent = [Thing::class],
- * )
- * class MyThing internal constructor(
- * thing: Thing,
- * @Document.StringProperty val foo: String,
- * @Document.LongProperty val bars: List<Int>,
- * ) : AbstractThing<
- * MyThing,
- * MyThing.Builder
- * >(thing) {
- *
- * // No need to implement equals(), hashCode(), toString() or toBuilder()
- *
- * override val selfTypeName =
- * "MyThing"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun toBuilderWithAdditionalPropertiesOnly(): Builder {
- * return Builder()
- * .setFoo(foo)
- * .addBars(bars)
- * }
- *
- * @Document.BuilderProducer
- * class Builder :
- * AbstractThing.Builder<
- * Builder,
- * MyThing> {...}
- * }
- * ```
- *
- * Also see [AbstractThing.Builder].
- */
-@Suppress("UNCHECKED_CAST")
-public abstract class AbstractThing<
- Self : AbstractThing<Self, Builder>,
- Builder : AbstractThing.Builder<Builder, Self>
->
-internal constructor(
- final override val namespace: String,
- final override val identifier: String,
- final override val name: Name?,
-) : Thing {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- protected abstract val additionalProperties: Map<String, Any?>
-
- /** A copy-constructor that copies over properties from another [Thing] instance. */
- public constructor(thing: Thing) : this(thing.namespace, thing.identifier, thing.name)
-
- /** Returns a concrete [Builder] with the additional, non-[Thing] properties copied over. */
- protected abstract fun toBuilderWithAdditionalPropertiesOnly(): Builder
-
- final override fun toBuilder(): Builder =
- toBuilderWithAdditionalPropertiesOnly()
- .setNamespace(namespace)
- .setIdentifier(identifier)
- .setName(name)
-
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- final override fun hashCode(): Int =
- Objects.hash(namespace, identifier, name, additionalProperties)
-
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated = attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
-
- /**
- * An abstract implementation of [Thing.Builder].
- *
- * Allows for extension like:
- * ```kt
- * @Document(...)
- * class MyThing :
- * : AbstractThing<
- * MyThing,
- * MyThing.Builder>(...) {
- *
- * @Document.BuilderProducer
- * class Builder
- * : AbstractThing.Builder<
- * Builder,
- * MyThing
- * >() {
- *
- * // No need to implement equals(), hashCode(), toString() or build()
- *
- * private var foo: String? = null
- * private val bars = mutableListOf<Int>()
- *
- * override val selfTypeName =
- * "MyThing.Builder"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun buildFromThing(
- * thing: Thing
- * ): MyThing {
- * return MyThing(
- * thing,
- * foo,
- * bars.toList()
- * )
- * }
- *
- * fun setFoo(string: String): Builder {
- * return apply { foo = string }
- * }
- *
- * fun addBar(int: Int): Builder {
- * return apply { bars += int }
- * }
- *
- * fun addBars(values: Iterable<Int>): Builder {
- * return apply { bars += values }
- * }
- * }
- * }
- * ```
- *
- * Also see [AbstractThing].
- */
- @Suppress("StaticFinalBuilder")
- public abstract class Builder<Self : Builder<Self, Built>, Built : AbstractThing<Built, Self>> :
- Thing.Builder<Self> {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val additionalProperties: Map<String, Any?>
-
- private var namespace: String = ""
-
- private var identifier: String = ""
-
- private var name: Name? = null
-
- /**
- * Builds a concrete [Built] instance, given a built [Thing].
- *
- * Subclasses should override this method to build a concrete [Built] instance that holds both
- * the [Thing]-specific properties and the subclass specific [additionalProperties].
- *
- * See the sample code in the documentation of this class for more context.
- */
- @Suppress("BuilderSetStyle") protected abstract fun buildFromThing(thing: Thing): Built
-
- final override fun build(): Built = buildFromThing(ThingImpl(namespace, identifier, name))
-
- final override fun setNamespace(namespace: String): Self {
- this.namespace = namespace
- return this as Self
- }
-
- final override fun setIdentifier(text: String): Self {
- this.identifier = text
- return this as Self
- }
-
- final override fun setName(name: Name?): Self {
- this.name = name
- return this as Self
- }
-
- @Suppress("BuilderSetStyle")
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- @Suppress("BuilderSetStyle")
- final override fun hashCode(): Int =
- Objects.hash(namespace, identifier, name, additionalProperties)
-
- @Suppress("BuilderSetStyle")
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name!!.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated =
- attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
- }
-}
-
-private class ThingImpl : AbstractThing<ThingImpl, ThingImpl.Builder> {
- protected override val selfTypeName: String
- get() = "Thing"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- public constructor(
- namespace: String,
- identifier: String,
- name: Name?,
- ) : super(namespace, identifier, name)
-
- public constructor(thing: Thing) : super(thing)
-
- protected override fun toBuilderWithAdditionalPropertiesOnly(): Builder = Builder()
-
- public class Builder : AbstractThing.Builder<Builder, ThingImpl>() {
- protected override val selfTypeName: String
- get() = "Thing.Builder"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- protected override fun buildFromThing(thing: Thing): ThingImpl =
- thing as? ThingImpl ?: ThingImpl(thing)
- }
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/Timer.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/Timer.kt
deleted file mode 100644
index c34b587..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/Timer.kt
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * 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.appactions.builtintypes.types
-
-import androidx.appactions.builtintypes.properties.Name
-import androidx.appactions.builtintypes.serializers.DurationAsNanosSerializer
-import androidx.appsearch.`annotation`.Document
-import java.time.Duration
-import java.util.Objects
-import kotlin.Any
-import kotlin.Boolean
-import kotlin.Int
-import kotlin.NotImplementedError
-import kotlin.String
-import kotlin.Suppress
-import kotlin.collections.Map
-import kotlin.collections.emptyMap
-import kotlin.collections.joinToString
-import kotlin.collections.map
-import kotlin.collections.mutableMapOf
-import kotlin.collections.plusAssign
-import kotlin.jvm.JvmStatic
-
-/**
- * A timer to go off at a particular time.
- *
- * See https://schema.googleapis.com/Timer for context.
- *
- * Should not be directly implemented. More properties may be added over time. Instead consider
- * using [Companion.Builder] or see [AbstractTimer] if you need to extend this type.
- */
-@Document(
- name = "bit:Timer",
- parent = [Thing::class],
-)
-public interface Timer : Thing {
- /**
- * The duration of the item (movie, audio recording, event, etc.).
- *
- * See https://schema.org/duration for more context.
- */
- @get:Document.LongProperty(serializer = DurationAsNanosSerializer::class)
- public val duration: Duration?
- get() = null
-
- /** Converts this [Timer] to its builder with all the properties copied over. */
- override fun toBuilder(): Builder<*>
-
- public companion object {
- /** Returns a default implementation of [Builder]. */
- @JvmStatic @Document.BuilderProducer public fun Builder(): Builder<*> = TimerImpl.Builder()
- }
-
- /**
- * Builder for [Timer].
- *
- * Should not be directly implemented. More methods may be added over time. See
- * [AbstractTimer.Builder] if you need to extend this builder.
- */
- public interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
- /** Returns a built [Timer]. */
- override fun build(): Timer
-
- /** Sets the `duration`. */
- @Suppress("DocumentExceptions")
- public fun setDuration(duration: Duration?): Self = throw NotImplementedError()
- }
-}
-
-/**
- * An abstract implementation of [Timer].
- *
- * Allows for extension like:
- * ```kt
- * @Document(
- * name = "MyTimer",
- * parent = [Timer::class],
- * )
- * class MyTimer internal constructor(
- * timer: Timer,
- * @Document.StringProperty val foo: String,
- * @Document.LongProperty val bars: List<Int>,
- * ) : AbstractTimer<
- * MyTimer,
- * MyTimer.Builder
- * >(timer) {
- *
- * // No need to implement equals(), hashCode(), toString() or toBuilder()
- *
- * override val selfTypeName =
- * "MyTimer"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun toBuilderWithAdditionalPropertiesOnly(): Builder {
- * return Builder()
- * .setFoo(foo)
- * .addBars(bars)
- * }
- *
- * @Document.BuilderProducer
- * class Builder :
- * AbstractTimer.Builder<
- * Builder,
- * MyTimer> {...}
- * }
- * ```
- *
- * Also see [AbstractTimer.Builder].
- */
-@Suppress("UNCHECKED_CAST")
-public abstract class AbstractTimer<
- Self : AbstractTimer<Self, Builder>,
- Builder : AbstractTimer.Builder<Builder, Self>
->
-internal constructor(
- final override val namespace: String,
- final override val duration: Duration?,
- final override val identifier: String,
- final override val name: Name?,
-) : Timer {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- protected abstract val additionalProperties: Map<String, Any?>
-
- /** A copy-constructor that copies over properties from another [Timer] instance. */
- public constructor(
- timer: Timer
- ) : this(timer.namespace, timer.duration, timer.identifier, timer.name)
-
- /** Returns a concrete [Builder] with the additional, non-[Timer] properties copied over. */
- protected abstract fun toBuilderWithAdditionalPropertiesOnly(): Builder
-
- final override fun toBuilder(): Builder =
- toBuilderWithAdditionalPropertiesOnly()
- .setNamespace(namespace)
- .setDuration(duration)
- .setIdentifier(identifier)
- .setName(name)
-
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (duration != other.duration) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- final override fun hashCode(): Int =
- Objects.hash(namespace, duration, identifier, name, additionalProperties)
-
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (duration != null) {
- attributes["duration"] = duration.toString()
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated = attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
-
- /**
- * An abstract implementation of [Timer.Builder].
- *
- * Allows for extension like:
- * ```kt
- * @Document(...)
- * class MyTimer :
- * : AbstractTimer<
- * MyTimer,
- * MyTimer.Builder>(...) {
- *
- * @Document.BuilderProducer
- * class Builder
- * : AbstractTimer.Builder<
- * Builder,
- * MyTimer
- * >() {
- *
- * // No need to implement equals(), hashCode(), toString() or build()
- *
- * private var foo: String? = null
- * private val bars = mutableListOf<Int>()
- *
- * override val selfTypeName =
- * "MyTimer.Builder"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun buildFromTimer(
- * timer: Timer
- * ): MyTimer {
- * return MyTimer(
- * timer,
- * foo,
- * bars.toList()
- * )
- * }
- *
- * fun setFoo(string: String): Builder {
- * return apply { foo = string }
- * }
- *
- * fun addBar(int: Int): Builder {
- * return apply { bars += int }
- * }
- *
- * fun addBars(values: Iterable<Int>): Builder {
- * return apply { bars += values }
- * }
- * }
- * }
- * ```
- *
- * Also see [AbstractTimer].
- */
- @Suppress("StaticFinalBuilder")
- public abstract class Builder<Self : Builder<Self, Built>, Built : AbstractTimer<Built, Self>> :
- Timer.Builder<Self> {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val additionalProperties: Map<String, Any?>
-
- private var namespace: String = ""
-
- private var duration: Duration? = null
-
- private var identifier: String = ""
-
- private var name: Name? = null
-
- /**
- * Builds a concrete [Built] instance, given a built [Timer].
- *
- * Subclasses should override this method to build a concrete [Built] instance that holds both
- * the [Timer]-specific properties and the subclass specific [additionalProperties].
- *
- * See the sample code in the documentation of this class for more context.
- */
- @Suppress("BuilderSetStyle") protected abstract fun buildFromTimer(timer: Timer): Built
-
- final override fun build(): Built =
- buildFromTimer(TimerImpl(namespace, duration, identifier, name))
-
- final override fun setNamespace(namespace: String): Self {
- this.namespace = namespace
- return this as Self
- }
-
- final override fun setDuration(duration: Duration?): Self {
- this.duration = duration
- return this as Self
- }
-
- final override fun setIdentifier(text: String): Self {
- this.identifier = text
- return this as Self
- }
-
- final override fun setName(name: Name?): Self {
- this.name = name
- return this as Self
- }
-
- @Suppress("BuilderSetStyle")
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (duration != other.duration) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- @Suppress("BuilderSetStyle")
- final override fun hashCode(): Int =
- Objects.hash(namespace, duration, identifier, name, additionalProperties)
-
- @Suppress("BuilderSetStyle")
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (duration != null) {
- attributes["duration"] = duration!!.toString()
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name!!.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated =
- attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
- }
-}
-
-private class TimerImpl : AbstractTimer<TimerImpl, TimerImpl.Builder> {
- protected override val selfTypeName: String
- get() = "Timer"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- public constructor(
- namespace: String,
- duration: Duration?,
- identifier: String,
- name: Name?,
- ) : super(namespace, duration, identifier, name)
-
- public constructor(timer: Timer) : super(timer)
-
- protected override fun toBuilderWithAdditionalPropertiesOnly(): Builder = Builder()
-
- public class Builder : AbstractTimer.Builder<Builder, TimerImpl>() {
- protected override val selfTypeName: String
- get() = "Timer.Builder"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- protected override fun buildFromTimer(timer: Timer): TimerImpl =
- timer as? TimerImpl ?: TimerImpl(timer)
- }
-}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/UnsupportedOperationStatus.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/UnsupportedOperationStatus.kt
deleted file mode 100644
index 7743764..0000000
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/UnsupportedOperationStatus.kt
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * 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.appactions.builtintypes.types
-
-import androidx.appactions.builtintypes.properties.Name
-import androidx.appsearch.`annotation`.Document
-import java.util.Objects
-import kotlin.Any
-import kotlin.Boolean
-import kotlin.Int
-import kotlin.String
-import kotlin.Suppress
-import kotlin.collections.Map
-import kotlin.collections.emptyMap
-import kotlin.collections.joinToString
-import kotlin.collections.map
-import kotlin.collections.mutableMapOf
-import kotlin.collections.plusAssign
-import kotlin.jvm.JvmStatic
-
-/**
- * Status indicating that the operation is not supported, e.g. updating an unsupported field.
- *
- * See https://schema.googleapis.com/UnsupportedOperationStatus for context.
- *
- * Should not be directly implemented. More properties may be added over time. Instead consider
- * using [Companion.Builder] or see [AbstractUnsupportedOperationStatus] if you need to extend this
- * type.
- */
-@Document(
- name = "bit:UnsupportedOperationStatus",
- parent = [ExecutionStatus::class],
-)
-public interface UnsupportedOperationStatus : ExecutionStatus {
- /**
- * Converts this [UnsupportedOperationStatus] to its builder with all the properties copied over.
- */
- override fun toBuilder(): Builder<*>
-
- public companion object {
- /** Returns a default implementation of [Builder]. */
- @JvmStatic
- @Document.BuilderProducer
- public fun Builder(): Builder<*> = UnsupportedOperationStatusImpl.Builder()
- }
-
- /**
- * Builder for [UnsupportedOperationStatus].
- *
- * Should not be directly implemented. More methods may be added over time. See
- * [AbstractUnsupportedOperationStatus.Builder] if you need to extend this builder.
- */
- public interface Builder<Self : Builder<Self>> : ExecutionStatus.Builder<Self> {
- /** Returns a built [UnsupportedOperationStatus]. */
- override fun build(): UnsupportedOperationStatus
- }
-}
-
-/**
- * An abstract implementation of [UnsupportedOperationStatus].
- *
- * Allows for extension like:
- * ```kt
- * @Document(
- * name = "MyUnsupportedOperationStatus",
- * parent = [UnsupportedOperationStatus::class],
- * )
- * class MyUnsupportedOperationStatus internal constructor(
- * unsupportedOperationStatus: UnsupportedOperationStatus,
- * @Document.StringProperty val foo: String,
- * @Document.LongProperty val bars: List<Int>,
- * ) : AbstractUnsupportedOperationStatus<
- * MyUnsupportedOperationStatus,
- * MyUnsupportedOperationStatus.Builder
- * >(unsupportedOperationStatus) {
- *
- * // No need to implement equals(), hashCode(), toString() or toBuilder()
- *
- * override val selfTypeName =
- * "MyUnsupportedOperationStatus"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun toBuilderWithAdditionalPropertiesOnly(): Builder {
- * return Builder()
- * .setFoo(foo)
- * .addBars(bars)
- * }
- *
- * @Document.BuilderProducer
- * class Builder :
- * AbstractUnsupportedOperationStatus.Builder<
- * Builder,
- * MyUnsupportedOperationStatus> {...}
- * }
- * ```
- *
- * Also see [AbstractUnsupportedOperationStatus.Builder].
- */
-@Suppress("UNCHECKED_CAST")
-public abstract class AbstractUnsupportedOperationStatus<
- Self : AbstractUnsupportedOperationStatus<Self, Builder>,
- Builder : AbstractUnsupportedOperationStatus.Builder<Builder, Self>
->
-internal constructor(
- final override val namespace: String,
- final override val identifier: String,
- final override val name: Name?,
-) : UnsupportedOperationStatus {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- protected abstract val additionalProperties: Map<String, Any?>
-
- /**
- * A copy-constructor that copies over properties from another [UnsupportedOperationStatus]
- * instance.
- */
- public constructor(
- unsupportedOperationStatus: UnsupportedOperationStatus
- ) : this(
- unsupportedOperationStatus.namespace,
- unsupportedOperationStatus.identifier,
- unsupportedOperationStatus.name
- )
-
- /**
- * Returns a concrete [Builder] with the additional, non-[UnsupportedOperationStatus] properties
- * copied over.
- */
- protected abstract fun toBuilderWithAdditionalPropertiesOnly(): Builder
-
- final override fun toBuilder(): Builder =
- toBuilderWithAdditionalPropertiesOnly()
- .setNamespace(namespace)
- .setIdentifier(identifier)
- .setName(name)
-
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- final override fun hashCode(): Int =
- Objects.hash(namespace, identifier, name, additionalProperties)
-
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated = attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
-
- /**
- * An abstract implementation of [UnsupportedOperationStatus.Builder].
- *
- * Allows for extension like:
- * ```kt
- * @Document(...)
- * class MyUnsupportedOperationStatus :
- * : AbstractUnsupportedOperationStatus<
- * MyUnsupportedOperationStatus,
- * MyUnsupportedOperationStatus.Builder>(...) {
- *
- * @Document.BuilderProducer
- * class Builder
- * : AbstractUnsupportedOperationStatus.Builder<
- * Builder,
- * MyUnsupportedOperationStatus
- * >() {
- *
- * // No need to implement equals(), hashCode(), toString() or build()
- *
- * private var foo: String? = null
- * private val bars = mutableListOf<Int>()
- *
- * override val selfTypeName =
- * "MyUnsupportedOperationStatus.Builder"
- *
- * override val additionalProperties: Map<String, Any?>
- * get() = mapOf("foo" to foo, "bars" to bars)
- *
- * override fun buildFromUnsupportedOperationStatus(
- * unsupportedOperationStatus: UnsupportedOperationStatus
- * ): MyUnsupportedOperationStatus {
- * return MyUnsupportedOperationStatus(
- * unsupportedOperationStatus,
- * foo,
- * bars.toList()
- * )
- * }
- *
- * fun setFoo(string: String): Builder {
- * return apply { foo = string }
- * }
- *
- * fun addBar(int: Int): Builder {
- * return apply { bars += int }
- * }
- *
- * fun addBars(values: Iterable<Int>): Builder {
- * return apply { bars += values }
- * }
- * }
- * }
- * ```
- *
- * Also see [AbstractUnsupportedOperationStatus].
- */
- @Suppress("StaticFinalBuilder")
- public abstract class Builder<
- Self : Builder<Self, Built>,
- Built : AbstractUnsupportedOperationStatus<Built, Self>
- > : UnsupportedOperationStatus.Builder<Self> {
- /**
- * Human readable name for the concrete [Self] class.
- *
- * Used in the [toString] output.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val selfTypeName: String
-
- /**
- * The additional properties that exist on the concrete [Self] class.
- *
- * Used for equality comparison and computing the hash code.
- */
- @get:Suppress("GetterOnBuilder") protected abstract val additionalProperties: Map<String, Any?>
-
- private var namespace: String = ""
-
- private var identifier: String = ""
-
- private var name: Name? = null
-
- /**
- * Builds a concrete [Built] instance, given a built [UnsupportedOperationStatus].
- *
- * Subclasses should override this method to build a concrete [Built] instance that holds both
- * the [UnsupportedOperationStatus]-specific properties and the subclass specific
- * [additionalProperties].
- *
- * See the sample code in the documentation of this class for more context.
- */
- @Suppress("BuilderSetStyle")
- protected abstract fun buildFromUnsupportedOperationStatus(
- unsupportedOperationStatus: UnsupportedOperationStatus
- ): Built
-
- final override fun build(): Built =
- buildFromUnsupportedOperationStatus(
- UnsupportedOperationStatusImpl(namespace, identifier, name)
- )
-
- final override fun setNamespace(namespace: String): Self {
- this.namespace = namespace
- return this as Self
- }
-
- final override fun setIdentifier(text: String): Self {
- this.identifier = text
- return this as Self
- }
-
- final override fun setName(name: Name?): Self {
- this.name = name
- return this as Self
- }
-
- @Suppress("BuilderSetStyle")
- final override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other == null || this::class.java != other::class.java) return false
- other as Self
- if (namespace != other.namespace) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (additionalProperties != other.additionalProperties) return false
- return true
- }
-
- @Suppress("BuilderSetStyle")
- final override fun hashCode(): Int =
- Objects.hash(namespace, identifier, name, additionalProperties)
-
- @Suppress("BuilderSetStyle")
- final override fun toString(): String {
- val attributes = mutableMapOf<String, String>()
- if (namespace.isNotEmpty()) {
- attributes["namespace"] = namespace
- }
- if (identifier.isNotEmpty()) {
- attributes["identifier"] = identifier
- }
- if (name != null) {
- attributes["name"] = name!!.toString(includeWrapperName = false)
- }
- attributes += additionalProperties.map { (k, v) -> k to v.toString() }
- val commaSeparated =
- attributes.entries.joinToString(separator = ", ") { (k, v) -> """$k=$v""" }
- return """$selfTypeName($commaSeparated)"""
- }
- }
-}
-
-private class UnsupportedOperationStatusImpl :
- AbstractUnsupportedOperationStatus<
- UnsupportedOperationStatusImpl, UnsupportedOperationStatusImpl.Builder
- > {
- protected override val selfTypeName: String
- get() = "UnsupportedOperationStatus"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- public constructor(
- namespace: String,
- identifier: String,
- name: Name?,
- ) : super(namespace, identifier, name)
-
- public constructor(
- unsupportedOperationStatus: UnsupportedOperationStatus
- ) : super(unsupportedOperationStatus)
-
- protected override fun toBuilderWithAdditionalPropertiesOnly(): Builder = Builder()
-
- public class Builder :
- AbstractUnsupportedOperationStatus.Builder<Builder, UnsupportedOperationStatusImpl>() {
- protected override val selfTypeName: String
- get() = "UnsupportedOperationStatus.Builder"
-
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- protected override fun buildFromUnsupportedOperationStatus(
- unsupportedOperationStatus: UnsupportedOperationStatus
- ): UnsupportedOperationStatusImpl =
- unsupportedOperationStatus as? UnsupportedOperationStatusImpl
- ?: UnsupportedOperationStatusImpl(unsupportedOperationStatus)
- }
-}
diff --git a/appactions/builtintypes/builtintypes/src/test/java/androidx/appactions/builtintypes/types/DataTypeTest.kt b/appactions/builtintypes/builtintypes/src/test/java/androidx/appactions/builtintypes/types/DataTypeTest.kt
deleted file mode 100644
index d9c5c92..0000000
--- a/appactions/builtintypes/builtintypes/src/test/java/androidx/appactions/builtintypes/types/DataTypeTest.kt
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.appactions.builtintypes.types
-
-import androidx.appactions.builtintypes.properties.Name
-import com.google.common.truth.Truth.assertThat
-import java.time.LocalDate
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class DataTypeTest {
- @Test
- fun testBuilder() {
- val schedule =
- Schedule.Builder()
- .setName(Name("Some schedule")) // authoritative setter
- .setExceptDate(LocalDate.of(2023, 12, 31)) // convenience setter
- .build()
- assertThat(schedule.name?.asText).isEqualTo("Some schedule")
- assertThat(schedule.exceptDate?.asDate).isEqualTo(LocalDate.of(2023, 12, 31))
- assertThat(schedule.exceptDate?.asInstant).isNull()
- }
-
- @Test
- fun testEquals() {
- val thing1 = Thing.Builder().setName("John Wick 4").build()
- val thing2 = Thing.Builder().setName("John Wick 4").build()
- assertThat(thing1).isEqualTo(thing2)
- }
-
- @Test
- fun testCopying() {
- val thing: Thing =
- Schedule.Builder().setExceptDate(LocalDate.of(2023, 12, 31)).setName("Some schedule").build()
- val copy = thing.toBuilder().setName("Another schedule").build()
- assertThat(copy)
- .isEqualTo(
- Schedule.Builder()
- .setExceptDate(LocalDate.of(2023, 12, 31))
- .setName("Another schedule")
- .build()
- )
- }
-}
diff --git a/appactions/builtintypes/builtintypes/src/test/java/androidx/appactions/builtintypes/types/ExtensionTest.kt b/appactions/builtintypes/builtintypes/src/test/java/androidx/appactions/builtintypes/types/ExtensionTest.kt
deleted file mode 100644
index 56ae906..0000000
--- a/appactions/builtintypes/builtintypes/src/test/java/androidx/appactions/builtintypes/types/ExtensionTest.kt
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.appactions.builtintypes.types
-
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class ExtensionTest {
-
- class MyThing internal constructor(thing: Thing, val foo: String?, val bars: List<Int>) :
- AbstractThing<MyThing, MyThing.Builder>(thing) {
- override val selfTypeName = "MyThing"
- override val additionalProperties: Map<String, Any?>
- get() = mapOf("foo" to foo, "bars" to bars)
-
- override fun toBuilderWithAdditionalPropertiesOnly(): Builder {
- return Builder().setFoo(foo).addBars(bars)
- }
-
- class Builder : AbstractThing.Builder<Builder, MyThing>() {
- private var foo: String? = null
- private val bars: MutableList<Int> = mutableListOf()
-
- override val selfTypeName = "MyThingBuilder"
- override val additionalProperties: Map<String, Any?>
- get() = mapOf("foo" to foo, "bars" to bars)
-
- override fun buildFromThing(thing: Thing): MyThing {
- return MyThing(thing, foo, bars.toList())
- }
-
- fun setFoo(foo: String?) = apply { this.foo = foo }
-
- fun addBar(bar: Int) = apply { bars += bar }
-
- fun addBars(values: Iterable<Int>) = apply { bars += values }
- }
- }
-
- @Test
- fun extendedTypeSupportEquality() {
- val thing1 =
- MyThing.Builder()
- .setName("Jane")
- .setFoo("some string")
- .addBar(1)
- .addBars(listOf(2, 3))
- .build()
- val thing2 =
- MyThing.Builder()
- .setName("Jane")
- .setFoo("some string")
- .addBar(1)
- .addBars(listOf(2, 3))
- .build()
-
- assertThat(thing1).isEqualTo(thing2)
- assertThat(thing1.hashCode()).isEqualTo(thing2.hashCode())
- }
-
- @Test
- fun extendedTypeSupportsCopying() {
- val thing1 =
- MyThing.Builder()
- .setName("Jane")
- .setFoo("some string")
- .addBar(1)
- .addBars(listOf(2, 3))
- .build()
- val thing2 = thing1.toBuilder().setFoo("other string").setName("John").build()
-
- assertThat(thing1).isNotEqualTo(thing2)
- assertThat(thing2.name?.asText).isEqualTo("John")
- assertThat(thing2.foo).isEqualTo("other string")
- assertThat(thing1.bars).isEqualTo(thing2.bars)
- }
-}
diff --git a/appactions/interaction/OWNERS b/appactions/interaction/OWNERS
deleted file mode 100644
index 014a52a..0000000
--- a/appactions/interaction/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-# Bug component: 1292315
[email protected]
[email protected]
[email protected] #{LAST_RESORT_SUGGESTION}
[email protected]
[email protected]
\ No newline at end of file
diff --git a/appactions/interaction/integration-tests/testapp/build.gradle b/appactions/interaction/integration-tests/testapp/build.gradle
deleted file mode 100644
index b5834ae..0000000
--- a/appactions/interaction/integration-tests/testapp/build.gradle
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 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.application")
- id("kotlin-android")
-}
-
-android {
- defaultConfig {
- applicationId "androidx.appactions.interaction.testapp"
- minSdkVersion 26
- }
- namespace "androidx.appactions.interaction.testapp"
-}
-
-dependencies {
- implementation(project(":appactions:interaction:interaction-service"))
- implementation(project(":appactions:interaction:interaction-capabilities-core"))
- implementation(project(":appactions:interaction:interaction-capabilities-productivity"))
- implementation("androidx.core:core-ktx:1.7.0")
- implementation("androidx.appcompat:appcompat:1.6.1")
- implementation("com.google.android.material:material:1.6.0")
- implementation("androidx.constraintlayout:constraintlayout:2.0.1")
-}
\ No newline at end of file
diff --git a/appactions/interaction/integration-tests/testapp/src/main/AndroidManifest.xml b/appactions/interaction/integration-tests/testapp/src/main/AndroidManifest.xml
deleted file mode 100644
index 4a7733f..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools">
-
- <application
- android:allowBackup="true"
- android:dataExtractionRules="@xml/data_extraction_rules"
- android:fullBackupContent="@xml/backup_rules"
- android:icon="@mipmap/ic_launcher"
- android:label="@string/app_name"
- android:roundIcon="@mipmap/ic_launcher_round"
- android:supportsRtl="true"
- android:theme="@style/Theme.AppInteractionTest"
- tools:targetApi="31">
- <activity android:name=".Alarm.AlarmActivity" />
- <activity
- android:name=".MainActivity"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- <!-- Register as Android Service -->
- <service
- android:name=".ClockInteractionService"
- android:exported="true">
- <!-- Link shortcuts.xml to register capabilities -->
- <meta-data
- android:name="android.app.shortcuts"
- android:resource="@xml/shortcuts" />
- <intent-filter>
- <action android:name="grpc.io.action.BIND" />
- </intent-filter>
- </service>
- </application>
- <uses-permission android:name="android.permission.VIBRATE" />
-</manifest>
\ No newline at end of file
diff --git a/appactions/interaction/integration-tests/testapp/src/main/java/androidx/appactions/interaction/testapp/ClockInteractionService.kt b/appactions/interaction/integration-tests/testapp/src/main/java/androidx/appactions/interaction/testapp/ClockInteractionService.kt
deleted file mode 100644
index f3a097a..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/java/androidx/appactions/interaction/testapp/ClockInteractionService.kt
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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.appactions.interaction.testapp
-
-import android.content.Context
-import android.content.SharedPreferences
-import android.os.Handler
-import android.os.Looper
-import android.widget.Toast
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.productivity.PauseTimer
-import androidx.appactions.interaction.capabilities.productivity.ResumeTimer
-import androidx.appactions.interaction.capabilities.productivity.StartTimer
-import androidx.appactions.interaction.capabilities.productivity.StopTimer
-import androidx.appactions.interaction.service.AppInteractionService
-import androidx.appactions.interaction.service.AppVerificationInfo
-import java.time.Duration
-
-const val KEY_TIMER_SHARED_PREFERENCES = "timer_shared_preferences"
-const val KEY_TIMER_STARTED_AT = "timer_started_at"
-const val KEY_TIMER_NAME = "timer_name"
-const val KEY_TIMER_DURATION = "timer_duration"
-const val KEY_TIMER_PAUSED_AT = "timer_paused_at"
-
-class ClockInteractionService : AppInteractionService() {
-
- private lateinit var mHandler: Handler
- private var duration: Long = 0L
- private lateinit var sharedPreferences: SharedPreferences
- override fun onCreate() {
- super.onCreate()
- sharedPreferences = applicationContext
- .getSharedPreferences(KEY_TIMER_SHARED_PREFERENCES, Context.MODE_PRIVATE)
- mHandler = Handler(Looper.myLooper()!!)
- }
-
- private fun showToast(msg: String) {
- mHandler.post(Runnable {
- Toast.makeText(
- this@ClockInteractionService,
- msg,
- Toast.LENGTH_LONG
- ).show()
- })
- }
-
- private val startTimerCapability =
- StartTimer.CapabilityBuilder()
- .setId("start_timer_oneshot")
- .setDurationProperty(Property<Duration>(isRequiredForExecution = true))
- .setExecutionCallback(ExecutionCallback<StartTimer.Arguments, StartTimer.Output> {
- val result = ExecutionResult.Builder<StartTimer.Output>().build()
- val name = it.name ?: "Default title"
- val duration = it.duration!!
- if (sharedPreferences.getBoolean(KEY_IS_TIMER_RUNNING, false)) {
- showToast(msg = "Could not start a timer because one is already running")
- return@ExecutionCallback result
- }
- sharedPreferences.edit().putLong(KEY_TIMER_STARTED_AT, System.currentTimeMillis())
- sharedPreferences.edit().putBoolean(KEY_IS_TIMER_RUNNING, true)
- sharedPreferences.edit().putString(KEY_TIMER_NAME, name)
- sharedPreferences.edit().putLong(KEY_TIMER_DURATION, duration.toMillis())
- showToast(msg = "Timer Name:$name Duration:$duration has been started")
-
- result
- })
- .build()
-
- private val pauseTimerCapability =
- PauseTimer.CapabilityBuilder()
- .setId("pause_timer_oneshot")
- .setExecutionCallback(ExecutionCallback {
- sharedPreferences.edit().putLong(KEY_TIMER_PAUSED_AT, System.currentTimeMillis())
- ExecutionResult.Builder<PauseTimer.Output>().build()
- })
- .build()
-
- private val resumeTimerCapability =
- ResumeTimer.CapabilityBuilder()
- .setId("resume_timer_oneshot")
- .setExecutionCallback(ExecutionCallback {
- val pausedTime = sharedPreferences.getLong(KEY_TIMER_PAUSED_AT, 0L)
- val startedTime = sharedPreferences.getLong(KEY_TIMER_STARTED_AT, 0L)
- val elapsedTime = pausedTime - startedTime
- val duration = duration - elapsedTime
- sharedPreferences.edit().putLong(KEY_TIMER_STARTED_AT, System.currentTimeMillis())
- sharedPreferences.edit().putLong(KEY_TIMER_DURATION, duration)
- ExecutionResult.Builder<ResumeTimer.Output>().build()
- })
- .build()
-
- private val stopTimerCapability =
- StopTimer.CapabilityBuilder()
- .setId("resume_timer_oneshot")
- .setExecutionCallback(ExecutionCallback {
- sharedPreferences.edit().putBoolean(KEY_IS_TIMER_RUNNING, false)
- ExecutionResult.Builder<StopTimer.Output>().build()
- })
- .build()
-
- override val registeredCapabilities: List<Capability> = listOf(
- startTimerCapability,
- pauseTimerCapability,
- resumeTimerCapability,
- stopTimerCapability,
- )
- override val allowedApps: List<AppVerificationInfo> = listOf(
- AppVerificationInfo.Builder()
- .addSignature(hex2Byte(ASSISTANT_SIGNATURE))
- .setPackageName(ASSISTANT_PACKAGE)
- .build()
- )
-}
diff --git a/appactions/interaction/integration-tests/testapp/src/main/java/androidx/appactions/interaction/testapp/MainActivity.kt b/appactions/interaction/integration-tests/testapp/src/main/java/androidx/appactions/interaction/testapp/MainActivity.kt
deleted file mode 100644
index ac9d5a9..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/java/androidx/appactions/interaction/testapp/MainActivity.kt
+++ /dev/null
@@ -1,112 +0,0 @@
-package androidx.appactions.interaction.testapp
-
-import android.content.Context
-import android.content.SharedPreferences
-import android.os.Bundle
-import android.os.CountDownTimer
-import android.widget.TextView
-import androidx.appcompat.app.AppCompatActivity
-import androidx.appcompat.widget.AppCompatButton
-
-const val KEY_IS_TIMER_PAUSED = "timer_paused"
-const val KEY_IS_TIMER_RUNNING = "timer_running"
-const val DEFAULT_DURATION = 120 * 1000L
-
-class MainActivity : AppCompatActivity() {
- private var remainingDuration = 0L
- private var hasRunningTimer = false
- private var startButton: AppCompatButton? = null
- private lateinit var timer: CountDownTimer
- private lateinit var sharedPreferences: SharedPreferences
- private lateinit var remainingTimeLabel: TextView
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
- sharedPreferences = applicationContext
- .getSharedPreferences(KEY_TIMER_SHARED_PREFERENCES, Context.MODE_PRIVATE)
- startButton = findViewById(R.id.startButton)
- remainingTimeLabel = findViewById(R.id.remainingTimeLabel)
- hasRunningTimer = sharedPreferences.getBoolean(KEY_IS_TIMER_RUNNING, false)
-
- if (hasRunningTimer) {
- remainingDuration = sharedPreferences.getLong(KEY_TIMER_DURATION, 0L)
- if (!sharedPreferences.getBoolean(KEY_IS_TIMER_PAUSED, false)) {
- val startedTime = sharedPreferences.getLong(KEY_TIMER_STARTED_AT, 0L)
- val elapsedTime = System.currentTimeMillis() - startedTime
- remainingDuration = remainingDuration - elapsedTime
- }
- startTimer(remainingDuration)
- }
-
- startButton?.apply {
- if (!hasRunningTimer) {
- text = "Start"
- } else if (sharedPreferences.getBoolean(KEY_IS_TIMER_PAUSED, false)) {
- text = "Resume"
- } else {
- text = "Pause"
- }
- setOnClickListener {
- setTimer(DEFAULT_DURATION)
- }
- }
- }
- private fun setTimer(duration: Long) {
- hasRunningTimer = sharedPreferences.getBoolean(KEY_IS_TIMER_RUNNING, false)
- if (!hasRunningTimer) {
- startButton?.text = "Pause"
- startTimer(duration)
- } else if (sharedPreferences.getBoolean(KEY_IS_TIMER_PAUSED, false)) {
- startButton?.text = "Pause"
- resumeTimer()
- } else {
- startButton?.text = "Resume"
- pauseTimer()
- }
- }
- private fun startTimer(duration: Long) {
- sharedPreferences.edit().putBoolean(KEY_IS_TIMER_RUNNING, true).apply()
- timer = object : CountDownTimer(duration, 1000) {
-
- override fun onTick(millisUntilFinished: Long) {
- runOnUiThread {
- [email protected] = millisUntilFinished
- val timeArray = millisecondsToTimeString(millisUntilFinished).split(":")
- remainingTimeLabel.text = "$timeArray[0]:$timeArray[1]:$timeArray[2]"
- }
- }
- override fun onFinish() {
- // Reset timer duration
- [email protected] = 0
- sharedPreferences.edit().putBoolean(KEY_IS_TIMER_RUNNING, false).apply()
- }
- }
- timer.start()
- }
-
- private fun pauseTimer() {
- timer.cancel()
- sharedPreferences.edit().putBoolean(KEY_IS_TIMER_PAUSED, true).apply()
- sharedPreferences.edit().putLong(KEY_TIMER_DURATION, this.remainingDuration).apply()
- }
-
- private fun resumeTimer() {
- val duration = sharedPreferences.getLong(KEY_TIMER_DURATION, DEFAULT_DURATION)
- sharedPreferences.edit().putBoolean(KEY_IS_TIMER_PAUSED, false).apply()
- sharedPreferences.edit().putLong(KEY_TIMER_STARTED_AT, System.currentTimeMillis()).apply()
- startTimer(duration)
- }
-
- private fun stopTimer() {
- sharedPreferences.edit().putBoolean(KEY_IS_TIMER_RUNNING, false).apply()
- sharedPreferences.edit().putBoolean(KEY_IS_TIMER_PAUSED, false).apply()
- }
-
- private fun millisecondsToTimeString(milliseconds: Long): String {
- val hours = milliseconds / 3600000
- val minutes = (milliseconds % 3600000) / 60000
- val seconds = (milliseconds % 60000) / 1000
- return String.format("%02d:%02d:%02d", hours, minutes, seconds)
- }
-}
diff --git a/appactions/interaction/integration-tests/testapp/src/main/java/androidx/appactions/interaction/testapp/Signatures.kt b/appactions/interaction/integration-tests/testapp/src/main/java/androidx/appactions/interaction/testapp/Signatures.kt
deleted file mode 100644
index 2e3fea9..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/java/androidx/appactions/interaction/testapp/Signatures.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.appactions.interaction.testapp
-
-internal const val ASSISTANT_PACKAGE = "com.google.android.googlequicksearchbox"
-internal const val ASSISTANT_SIGNATURE =
- "f0:fd:6c:5b:41:0f:25:cb:25:c3:b5:33:46:c8:97:2f:ae:30:f8:ee:74:11:df:91:04:80:ad:" +
- "6b:2d:60:db:83"
-
-internal fun hex2Byte(s: String): ByteArray {
- val parts = s.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
- val result = ByteArray(parts.size)
- for (i in parts.indices) {
- result[i] = parts[i].toInt(16).toByte()
- }
- return result
-}
diff --git a/appactions/interaction/integration-tests/testapp/src/main/java/androidx/appactions/interaction/testapp/alarm/AlarmActivity.kt b/appactions/interaction/integration-tests/testapp/src/main/java/androidx/appactions/interaction/testapp/alarm/AlarmActivity.kt
deleted file mode 100644
index 974d92f..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/java/androidx/appactions/interaction/testapp/alarm/AlarmActivity.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * 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.appactions.interaction.testapp.Alarm
-
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import android.os.Bundle
-import android.os.VibrationEffect
-import android.os.Vibrator
-import android.util.Log
-import androidx.appactions.interaction.testapp.R
-import androidx.appcompat.app.AppCompatActivity
-
-const val TAG = "AlarmActivity"
-const val DEFAULT_ALARM_AFTER_CURRENT_MILLIS = 20 * 1000L
-const val VIBRATE_MILLIS = 2000L
-
-class AlarmActivity : AppCompatActivity() {
- var alarmAfterCurrentMillis: Long = DEFAULT_ALARM_AFTER_CURRENT_MILLIS
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_alarm)
- }
-
- class AlarmReceiver : BroadcastReceiver() {
- override fun onReceive(context: Context, intent: Intent) {
- Log.e(TAG, "System.currentTimeMillis().toString() in AlarmReceiver onReceive()")
- vibrateDevice(context)
- }
-
- // Vibrates the device for 100 milliseconds.
- fun vibrateDevice(context: Context) {
- val vibrator = context.getSystemService(Vibrator::class.java)
- vibrator.vibrate(VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE))
- }
-
- companion object {
- private const val TAG = "alarmclock.AlarmReceiver"
- }
- }
-}
diff --git a/appactions/interaction/integration-tests/testapp/src/main/java/androidx/appactions/interaction/testapp/alarm/AlarmInteractionService.kt b/appactions/interaction/integration-tests/testapp/src/main/java/androidx/appactions/interaction/testapp/alarm/AlarmInteractionService.kt
deleted file mode 100644
index 7f56057..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/java/androidx/appactions/interaction/testapp/alarm/AlarmInteractionService.kt
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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.appactions.interaction.testapp.alarm
-
-import android.app.AlarmManager
-import android.app.PendingIntent
-import android.content.Context
-import android.content.Intent
-import android.content.SharedPreferences
-import android.os.Handler
-import android.os.Looper
-import android.widget.Toast
-import androidx.appactions.builtintypes.types.Schedule
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.core.properties.StringValue
-import androidx.appactions.interaction.capabilities.productivity.CreateAlarm
-import androidx.appactions.interaction.capabilities.productivity.DismissAlarm
-import androidx.appactions.interaction.capabilities.productivity.SnoozeAlarm
-import androidx.appactions.interaction.capabilities.productivity.UpdateAlarm
-import androidx.appactions.interaction.service.AppInteractionService
-import androidx.appactions.interaction.service.AppVerificationInfo
-import androidx.appactions.interaction.testapp.Alarm.AlarmActivity
-import java.util.Calendar
-
-const val KEY_ALARM_SHARED_PREFERENCES = "alarm_shared_preferences"
-const val KEY_ALARM_SCHEDULE = "alarm_schedule"
-const val KEY_ALARM_IS_SET = "alarm_is_set"
-const val KEY_ALARM_IS_SNOOZED = "alarm_is_snoozed"
-
-class AlarmInteractionService : AppInteractionService() {
-
- private lateinit var mHandler: Handler
- private lateinit var sharedPreferences: SharedPreferences
- private lateinit var context: Context
- private lateinit var intent: Intent
- private lateinit var alarmIntent: PendingIntent
- private var schedule: Schedule? = null
- val alarmManager = getSystemService(ALARM_SERVICE) as AlarmManager
-
- override fun onCreate() {
- super.onCreate()
- sharedPreferences = applicationContext
- .getSharedPreferences(KEY_ALARM_SHARED_PREFERENCES, Context.MODE_PRIVATE)
- mHandler = Handler(Looper.myLooper()!!)
- context = applicationContext
- intent = Intent(context, AlarmActivity.AlarmReceiver::class.java)
- alarmIntent = PendingIntent.getBroadcast(
- context,
- 0,
- intent,
- PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
- )
- }
- private fun showToast(msg: String) {
- mHandler.post(Runnable {
- Toast.makeText(
- this@AlarmInteractionService,
- msg,
- Toast.LENGTH_LONG
- ).show()
- })
- }
-
- private val createAlarmCapability =
- CreateAlarm.CapabilityBuilder()
- .setIdentifierProperty(Property(listOf(StringValue("create_alarm_oneshot"))))
- .setExecutionCallback(
- ExecutionCallback {
- schedule = it.schedule
- sharedPreferences.edit().putString(KEY_ALARM_SCHEDULE, schedule.toString())
- .apply()
- sharedPreferences.edit().putBoolean(KEY_ALARM_IS_SET, true).apply()
- setAlarm()
- ExecutionResult.Builder<CreateAlarm.Output>().build()
- }).build()
-
- fun setAlarm() {
- val calendar: Calendar = Calendar.getInstance().apply {
- timeInMillis = System.currentTimeMillis()
- set(Calendar.HOUR_OF_DAY, schedule?.startTime?.asTime?.hour ?: 12)
- set(Calendar.MINUTE, schedule?.startTime?.asTime?.minute ?: 30)
- }
- alarmManager.setRepeating(
- AlarmManager.RTC_WAKEUP,
- calendar.timeInMillis,
- schedule?.repeatFrequency?.asDuration?.toMillis() ?: -1,
- alarmIntent,
- )
- }
-
- private val dismissAlarmCapability =
- DismissAlarm.CapabilityBuilder()
- .setExecutionCallback(
- ExecutionCallback {
- sharedPreferences.edit().putBoolean(KEY_ALARM_IS_SET, false).apply()
- alarmManager.cancel(alarmIntent)
- ExecutionResult.Builder<DismissAlarm.Output>().build()
- }).build()
-
- private val snoozeAlarmCapability =
- SnoozeAlarm.CapabilityBuilder()
- .setExecutionCallback(
- ExecutionCallback {
- sharedPreferences.edit().putBoolean(KEY_ALARM_IS_SNOOZED, true).apply()
- ExecutionResult.Builder<SnoozeAlarm.Output>().build()
- }).build()
-
- private val updateAlarmCapability =
- UpdateAlarm.OverwriteAlarmSchedule.CapabilityBuilder()
- .setExecutionCallback(
- ExecutionCallback {
- schedule = it.schedule
- sharedPreferences.edit().putString(KEY_ALARM_SCHEDULE, schedule.toString())
- .apply()
- sharedPreferences.edit().putBoolean(KEY_ALARM_IS_SET, true).apply()
- setAlarm()
- ExecutionResult.Builder<UpdateAlarm.OverwriteAlarmSchedule.Output>().build()
- }).build()
-
- override val registeredCapabilities: List<Capability> = listOf(
- createAlarmCapability,
- dismissAlarmCapability,
- snoozeAlarmCapability,
- updateAlarmCapability,
- )
-
- override val allowedApps: List<AppVerificationInfo> = /* TODO */ listOf()
-}
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/drawable/ic_launcher_background.xml b/appactions/interaction/integration-tests/testapp/src/main/res/drawable/ic_launcher_background.xml
deleted file mode 100644
index 2be47c2..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/drawable/ic_launcher_background.xml
+++ /dev/null
@@ -1,74 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="108dp"
- android:height="108dp"
- android:viewportHeight="108"
- android:viewportWidth="108">
- <path android:fillColor="#3DDC84"
- android:pathData="M0,0h108v108h-108z"/>
- <path android:fillColor="#00000000" android:pathData="M9,0L9,108"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M19,0L19,108"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M29,0L29,108"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M39,0L39,108"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M49,0L49,108"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M59,0L59,108"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M69,0L69,108"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M79,0L79,108"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M89,0L89,108"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M99,0L99,108"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M0,9L108,9"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M0,19L108,19"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M0,29L108,29"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M0,39L108,39"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M0,49L108,49"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M0,59L108,59"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M0,69L108,69"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M0,79L108,79"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M0,89L108,89"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M0,99L108,99"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M19,29L89,29"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M19,39L89,39"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M19,49L89,49"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M19,59L89,59"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M19,69L89,69"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M19,79L89,79"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M29,19L29,89"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M39,19L39,89"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M49,19L49,89"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M59,19L59,89"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M69,19L69,89"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
- <path android:fillColor="#00000000" android:pathData="M79,19L79,89"
- android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
-</vector>
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/drawable/round_back_black10_10.xml b/appactions/interaction/integration-tests/testapp/src/main/res/drawable/round_back_black10_10.xml
deleted file mode 100644
index 0d05958..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/drawable/round_back_black10_10.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="@color/cardview_dark_background"/>
- <corners android:radius="10dp"/>
-</shape>
\ No newline at end of file
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/layout/activity_alarm.xml b/appactions/interaction/integration-tests/testapp/src/main/res/layout/activity_alarm.xml
deleted file mode 100644
index f9cff5d..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/layout/activity_alarm.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
- 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.
- -->
-
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/layout/activity_main.xml b/appactions/interaction/integration-tests/testapp/src/main/res/layout/activity_main.xml
deleted file mode 100644
index ff4f005..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/layout/activity_main.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@color/primary"
- tools:context=".MainActivity">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="200dp"
- android:gravity="center"
- android:orientation="horizontal">
- <TextView
- android:id="@+id/remainingTimeLabel"
- android:layout_width="50dp"
- android:layout_height="50dp"
- android:background="@drawable/round_back_black10_10"
- android:text="00"
- android:textColor="#FFFFFF"
- android:textStyle="bold"
- android:textSize="30sp"
- android:gravity="center"/>
- </LinearLayout>
- <androidx.appcompat.widget.AppCompatButton
- android:id="@+id/startButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@color/secondary"
- android:text="Start"
- android:textColor="@color/white"
- android:textAllCaps="true"
- android:layout_alignParentBottom="true"
- android:layout_centerHorizontal="true"
- android:layout_marginBottom="100dp"/>
-</RelativeLayout>
\ No newline at end of file
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-hdpi/ic_launcher.webp b/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-hdpi/ic_launcher.webp
deleted file mode 100644
index c209e78..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-hdpi/ic_launcher.webp
+++ /dev/null
Binary files differ
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-hdpi/ic_launcher_round.webp
deleted file mode 100644
index b2dfe3d..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-hdpi/ic_launcher_round.webp
+++ /dev/null
Binary files differ
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-mdpi/ic_launcher.webp b/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-mdpi/ic_launcher.webp
deleted file mode 100644
index 4f0f1d6..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-mdpi/ic_launcher.webp
+++ /dev/null
Binary files differ
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-mdpi/ic_launcher_round.webp
deleted file mode 100644
index 62b611d..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-mdpi/ic_launcher_round.webp
+++ /dev/null
Binary files differ
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-xhdpi/ic_launcher.webp b/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-xhdpi/ic_launcher.webp
deleted file mode 100644
index 948a307..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-xhdpi/ic_launcher.webp
+++ /dev/null
Binary files differ
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
deleted file mode 100644
index 1b9a695..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
+++ /dev/null
Binary files differ
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-xxhdpi/ic_launcher.webp
deleted file mode 100644
index 28d4b77..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-xxhdpi/ic_launcher.webp
+++ /dev/null
Binary files differ
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
deleted file mode 100644
index 9287f50..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
+++ /dev/null
Binary files differ
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
deleted file mode 100644
index aa7d642..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
+++ /dev/null
Binary files differ
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
deleted file mode 100644
index 9126ae3..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
+++ /dev/null
Binary files differ
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/values-night/themes.xml b/appactions/interaction/integration-tests/testapp/src/main/res/values-night/themes.xml
deleted file mode 100644
index cf79c9e..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/values-night/themes.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<resources xmlns:tools="http://schemas.android.com/tools">
- <!-- Base application theme. -->
- <style name="Theme.AppInteractionTest"
- parent="Theme.MaterialComponents.DayNight.DarkActionBar">
- <!-- Primary brand color. -->
- <item name="colorPrimary">@color/purple_200</item>
- <item name="colorPrimaryVariant">@color/purple_700</item>
- <item name="colorOnPrimary">@color/black</item>
- <!-- Secondary brand color. -->
- <item name="colorSecondary">@color/teal_200</item>
- <item name="colorSecondaryVariant">@color/teal_200</item>
- <item name="colorOnSecondary">@color/black</item>
- <!-- Status bar color. -->
- <item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
- <!-- Customize your theme here. -->
- </style>
-</resources>
\ No newline at end of file
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/values/colors.xml b/appactions/interaction/integration-tests/testapp/src/main/res/values/colors.xml
deleted file mode 100644
index fc67530..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/values/colors.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <color name="purple_200">#FFBB86FC</color>
- <color name="purple_500">#FF6200EE</color>
- <color name="purple_700">#FF3700B3</color>
- <color name="teal_200">#FF03DAC5</color>
- <color name="teal_700">#FF018786</color>
- <color name="black">#FF000000</color>
- <color name="white">#FFFFFFFF</color>
-
- <color name="primary">#1E1B1C</color>
- <color name="secondary">@color/teal_700</color>
-</resources>
\ No newline at end of file
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/values/donottranslate-strings.xml b/appactions/interaction/integration-tests/testapp/src/main/res/values/donottranslate-strings.xml
deleted file mode 100644
index 37ed16e7..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/values/donottranslate-strings.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-<resources>
- <string name="app_name">App Interaction Test</string>
-</resources>
\ No newline at end of file
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/values/themes.xml b/appactions/interaction/integration-tests/testapp/src/main/res/values/themes.xml
deleted file mode 100644
index 22e6872..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/values/themes.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<resources xmlns:tools="http://schemas.android.com/tools">
- <!-- Base application theme. -->
- <style name="Theme.AppInteractionTest"
- parent="Theme.MaterialComponents.DayNight.NoActionBar">
- <!-- Primary brand color. -->
- <item name="colorPrimary">@color/purple_500</item>
- <item name="colorPrimaryVariant">@color/purple_700</item>
- <item name="colorOnPrimary">@color/white</item>
- <!-- Secondary brand color. -->
- <item name="colorSecondary">@color/teal_200</item>
- <item name="colorSecondaryVariant">@color/teal_700</item>
- <item name="colorOnSecondary">@color/black</item>
- <!-- Status bar color. -->
- <item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
- <!-- Customize your theme here. -->
- </style>
-</resources>
\ No newline at end of file
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/xml/backup_rules.xml b/appactions/interaction/integration-tests/testapp/src/main/res/xml/backup_rules.xml
deleted file mode 100644
index 7a180f4..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/xml/backup_rules.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Sample backup rules file; uncomment and customize as necessary.
- See https://developer.android.com/guide/topics/data/autobackup
- for details.
- Note: This file is ignored for devices older that API 31
- See https://developer.android.com/about/versions/12/backup-restore
--->
-<full-backup-content>
- <!--
- <include domain="sharedpref" path="."/>
- <exclude domain="sharedpref" path="device.xml"/>
--->
-</full-backup-content>
\ No newline at end of file
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/xml/data_extraction_rules.xml b/appactions/interaction/integration-tests/testapp/src/main/res/xml/data_extraction_rules.xml
deleted file mode 100644
index 84910a7..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/xml/data_extraction_rules.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Sample data extraction rules file; uncomment and customize as necessary.
- See https://developer.android.com/about/versions/12/backup-restore#xml-changes
- for details.
--->
-<data-extraction-rules>
- <cloud-backup>
- <!-- TODO: Use <include> and <exclude> to control what is backed up.
- <include .../>
- <exclude .../>
- -->
- </cloud-backup>
- <!--
- <device-transfer>
- <include .../>
- <exclude .../>
- </device-transfer>
- -->
-</data-extraction-rules>
\ No newline at end of file
diff --git a/appactions/interaction/integration-tests/testapp/src/main/res/xml/shortcuts.xml b/appactions/interaction/integration-tests/testapp/src/main/res/xml/shortcuts.xml
deleted file mode 100644
index 11327f3..0000000
--- a/appactions/interaction/integration-tests/testapp/src/main/res/xml/shortcuts.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
- 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.
- -->
-
-<!-- file: res/xml/shortcuts.xml -->
-<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
- <capability android:name="actions.intent.START_TIMER">
- <service
- android:name="androidx.appactions.interaction.testapp.ClockInteractionService"
- android:identifier="start_timer_oneshot">
- <parameter
- android:name="timer.identifier"
- android:key="timer.identifier" />
- <parameter
- android:name="timer.name"
- android:key="timer.name" />
- <parameter
- android:name="timer.duration"
- android:key="timer.duration" />
- </service>
- </capability>
- <capability android:name="actions.intent.PAUSE_TIMER">
- <service
- android:name="androidx.appactions.interaction.testapp.ClockInteractionService"
- android:identifier="pause_timer_oneshot">
- <parameter
- android:name="timer.name"
- android:key="timer.name" />
- </service>
- </capability>
- <capability android:name="actions.intent.RESUME_TIMER">
- <service
- android:name="androidx.appactions.interaction.testapp.ClockInteractionService"
- android:identifier="resume_timer_oneshot">
- <parameter
- android:name="timer.name"
- android:key="timer.name" />
- </service>
- </capability>
-</shortcuts>
\ No newline at end of file
diff --git a/appactions/interaction/interaction-capabilities-communication/api/current.txt b/appactions/interaction/interaction-capabilities-communication/api/current.txt
deleted file mode 100644
index e6f50d0..0000000
--- a/appactions/interaction/interaction-capabilities-communication/api/current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 4.0
diff --git a/appactions/interaction/interaction-capabilities-communication/api/res-current.txt b/appactions/interaction/interaction-capabilities-communication/api/res-current.txt
deleted file mode 100644
index e69de29..0000000
--- a/appactions/interaction/interaction-capabilities-communication/api/res-current.txt
+++ /dev/null
diff --git a/appactions/interaction/interaction-capabilities-communication/api/restricted_current.txt b/appactions/interaction/interaction-capabilities-communication/api/restricted_current.txt
deleted file mode 100644
index e6f50d0..0000000
--- a/appactions/interaction/interaction-capabilities-communication/api/restricted_current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 4.0
diff --git a/appactions/interaction/interaction-capabilities-communication/build.gradle b/appactions/interaction/interaction-capabilities-communication/build.gradle
deleted file mode 100644
index 7822365..0000000
--- a/appactions/interaction/interaction-capabilities-communication/build.gradle
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-/**
- * This file was created using the `create_project.py` script located in the
- * `<AndroidX root>/development/project-creator` directory.
- *
- * Please use that script when creating a new project, rather than copying an existing project and
- * modifying its settings.
- */
-import androidx.build.LibraryType
-
-plugins {
- id("AndroidXPlugin")
- id("com.android.library")
- id("org.jetbrains.kotlin.android")
-}
-
-dependencies {
- api(libs.kotlinStdlib)
- implementation("androidx.annotation:annotation:1.1.0")
- implementation(project(":appactions:interaction:interaction-capabilities-core"))
-}
-
-android {
- namespace "androidx.appactions.interaction.capabilities.communication"
- defaultConfig {
- minSdkVersion 26
- }
-}
-
-androidx {
- name = "androidx.appactions.interaction:interaction-capabilities-communication"
- type = LibraryType.PUBLISHED_LIBRARY
- inceptionYear = "2023"
- description = "Capability library for communication apps integrating with virtual assistant."
- metalavaK2UastEnabled = true
-}
diff --git a/appactions/interaction/interaction-capabilities-communication/src/main/java/androidx/appactions/interaction/capabilities/communication/CreateCall.kt b/appactions/interaction/interaction-capabilities-communication/src/main/java/androidx/appactions/interaction/capabilities/communication/CreateCall.kt
deleted file mode 100644
index e787f76..0000000
--- a/appactions/interaction/interaction-capabilities-communication/src/main/java/androidx/appactions/interaction/capabilities/communication/CreateCall.kt
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.communication
-
-import androidx.appactions.builtintypes.experimental.properties.Participant
-import androidx.appactions.builtintypes.experimental.types.Call
-import androidx.appactions.builtintypes.experimental.types.GenericErrorStatus
-import androidx.appactions.builtintypes.experimental.types.SuccessStatus
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters.CALL_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters.PARTICIPANT_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-
-/** A capability corresponding to actions.intent.CREATE_CALL */
-@CapabilityFactory(name = CreateCall.CAPABILITY_NAME)
-class CreateCall private constructor() {
- internal enum class SlotMetadata(val path: String) {
- CALL_FORMAT("call.callFormat"),
- PARTICIPANT("call.participant")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder, Arguments, Output, Confirmation, ExecutionSession
- >(ACTION_SPEC) {
-
- fun setCallFormatProperty(
- callFormat: Property<Call.CanonicalValue.CallFormat>
- ): CapabilityBuilder =
- setProperty(
- SlotMetadata.CALL_FORMAT.path,
- callFormat,
- TypeConverters.CALL_FORMAT_ENTITY_CONVERTER)
-
- fun setParticipantProperty(participant: Property<Participant>): CapabilityBuilder =
- setProperty(
- SlotMetadata.PARTICIPANT.path,
- participant,
- EntityConverter.of(PARTICIPANT_TYPE_SPEC))
- }
-
- class Arguments
- internal constructor(
- val callFormat: Call.CanonicalValue.CallFormat?,
- val participantList: List<ParticipantReference>
- ) {
- override fun toString(): String {
- return "Arguments(callFormat=$callFormat, participantList=$participantList)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Arguments
-
- if (callFormat != other.callFormat) return false
- if (participantList != other.participantList) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = callFormat.hashCode()
- result = 31 * result + participantList.hashCode()
- return result
- }
-
- class Builder {
- private var callFormat: Call.CanonicalValue.CallFormat? = null
- private var participantList: List<ParticipantReference> = mutableListOf()
-
- fun setCallFormat(callFormat: Call.CanonicalValue.CallFormat): Builder = apply {
- this.callFormat = callFormat
- }
-
- fun setParticipantList(participantList: List<ParticipantReference>): Builder = apply {
- this.participantList = participantList
- }
-
- fun build(): Arguments = Arguments(callFormat, participantList)
- }
- }
-
- class Output internal constructor(val call: Call?, val executionStatus: ExecutionStatus?) {
- override fun toString(): String {
- return "Output(call=$call, executionStatus=$executionStatus)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Output
-
- if (call != other.call) return false
- if (executionStatus != other.executionStatus) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = call.hashCode()
- result = 31 * result + executionStatus.hashCode()
- return result
- }
-
- class Builder {
- private var call: Call? = null
- private var executionStatus: ExecutionStatus? = null
-
- fun setCall(call: Call): Builder = apply { this.call = call }
-
- fun setExecutionStatus(executionStatus: ExecutionStatus): Builder = apply {
- this.executionStatus = executionStatus
- }
-
- fun build(): Output = Output(call, executionStatus)
- }
- }
-
- class ExecutionStatus {
- private var successStatus: SuccessStatus? = null
- private var genericErrorStatus: GenericErrorStatus? = null
-
- constructor(successStatus: SuccessStatus) {
- this.successStatus = successStatus
- }
-
- constructor(genericErrorStatus: GenericErrorStatus) {
- this.genericErrorStatus = genericErrorStatus
- }
-
- internal fun toParamValue(): ParamValue {
- var status = ""
- if (successStatus != null) {
- status = successStatus.toString()
- }
- if (genericErrorStatus != null) {
- status = genericErrorStatus.toString()
- }
- val value: Value = Value.newBuilder().setStringValue(status).build()
- return ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder().putFields(TypeConverters.FIELD_NAME_TYPE, value).build()
- )
- .build()
- }
- }
-
- class Confirmation internal constructor()
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
-
- companion object {
- /** Canonical name for [CreateCall] capability. */
- const val CAPABILITY_NAME: String = "actions.intent.CREATE_CALL"
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindParameter(
- SlotMetadata.CALL_FORMAT.path,
- Arguments::callFormat,
- Arguments.Builder::setCallFormat,
- TypeConverters.CALL_FORMAT_PARAM_VALUE_CONVERTER
- )
- .bindRepeatedParameter(
- SlotMetadata.PARTICIPANT.path,
- Arguments::participantList,
- Arguments.Builder::setParticipantList,
- ParticipantReference.PARAM_VALUE_CONVERTER,
- )
- .bindOutput(
- "call",
- Output::call,
- ParamValueConverter.of(CALL_TYPE_SPEC)::toParamValue
- )
- .bindOutput(
- "executionStatus",
- Output::executionStatus,
- ExecutionStatus::toParamValue
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-communication/src/main/java/androidx/appactions/interaction/capabilities/communication/CreateMessage.kt b/appactions/interaction/interaction-capabilities-communication/src/main/java/androidx/appactions/interaction/capabilities/communication/CreateMessage.kt
deleted file mode 100644
index bec43e5..0000000
--- a/appactions/interaction/interaction-capabilities-communication/src/main/java/androidx/appactions/interaction/capabilities/communication/CreateMessage.kt
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.communication
-
-import androidx.appactions.builtintypes.experimental.properties.Recipient
-import androidx.appactions.builtintypes.experimental.types.GenericErrorStatus
-import androidx.appactions.builtintypes.experimental.types.Message
-import androidx.appactions.builtintypes.experimental.types.SuccessStatus
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters.MESSAGE_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters.RECIPIENT_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.core.properties.StringValue
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-
-/** A capability corresponding to actions.intent.CREATE_MESSAGE */
-@CapabilityFactory(name = CreateMessage.CAPABILITY_NAME)
-class CreateMessage private constructor() {
- internal enum class SlotMetadata(val path: String) {
- TEXT("message.text"),
- RECIPIENT("message.recipient")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder, Arguments, Output, Confirmation, ExecutionSession
- >(ACTION_SPEC) {
- fun setMessageTextProperty(
- messageText: Property<StringValue>
- ): CapabilityBuilder = setProperty(
- SlotMetadata.TEXT.path,
- messageText,
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
-
- fun setRecipientProperty(recipient: Property<Recipient>): CapabilityBuilder = setProperty(
- SlotMetadata.RECIPIENT.path,
- recipient,
- EntityConverter.of(TypeConverters.RECIPIENT_TYPE_SPEC)
- )
- }
-
- class Arguments
- internal constructor(val recipientList: List<RecipientReference>, val messageText: String?) {
- override fun toString(): String {
- return "Arguments(recipient=$recipientList, messageTextList=$messageText)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Arguments
-
- if (recipientList != other.recipientList) return false
- if (messageText != other.messageText) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = recipientList.hashCode()
- result = 31 * result + messageText.hashCode()
- return result
- }
-
- class Builder {
- private var recipientList: List<RecipientReference> = mutableListOf()
- private var messageText: String? = null
-
- fun setRecipientList(recipientList: List<RecipientReference>): Builder = apply {
- this.recipientList = recipientList
- }
-
- fun setMessageText(messageText: String): Builder = apply {
- this.messageText = messageText
- }
-
- fun build(): Arguments = Arguments(recipientList, messageText)
- }
- }
-
- class Output
- internal constructor(val message: Message?, val executionStatus: ExecutionStatus?) {
- override fun toString(): String {
- return "Output(call=$message, executionStatus=$executionStatus)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Output
-
- if (message != other.message) return false
- if (executionStatus != other.executionStatus) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = message.hashCode()
- result = 31 * result + executionStatus.hashCode()
- return result
- }
-
- class Builder {
- private var message: Message? = null
- private var executionStatus: ExecutionStatus? = null
-
- fun setMessage(message: Message): Builder = apply { this.message = message }
-
- fun setExecutionStatus(executionStatus: ExecutionStatus): Builder = apply {
- this.executionStatus = executionStatus
- }
-
- fun build(): Output = Output(message, executionStatus)
- }
- }
-
- class ExecutionStatus {
- private var successStatus: SuccessStatus? = null
- private var genericErrorStatus: GenericErrorStatus? = null
-
- constructor(successStatus: SuccessStatus) {
- this.successStatus = successStatus
- }
-
- constructor(genericErrorStatus: GenericErrorStatus) {
- this.genericErrorStatus = genericErrorStatus
- }
-
- internal fun toParamValue(): ParamValue {
- var status = ""
- if (successStatus != null) {
- status = successStatus.toString()
- }
- if (genericErrorStatus != null) {
- status = genericErrorStatus.toString()
- }
- val value: Value = Value.newBuilder().setStringValue(status).build()
- return ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder().putFields(TypeConverters.FIELD_NAME_TYPE, value).build()
- )
- .build()
- }
- }
-
- class Confirmation internal constructor()
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
-
- companion object {
- /** Canonical name for [CreateMessage] capability. */
- const val CAPABILITY_NAME: String = "actions.intent.CREATE_MESSAGE"
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindRepeatedParameter(
- SlotMetadata.RECIPIENT.path,
- Arguments::recipientList,
- Arguments.Builder::setRecipientList,
- RecipientReference.PARAM_VALUE_CONVERTER,
- )
- .bindParameter(
- SlotMetadata.TEXT.path,
- Arguments::messageText,
- Arguments.Builder::setMessageText,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER,
- )
- .bindOutput(
- "message",
- Output::message,
- ParamValueConverter.of(MESSAGE_TYPE_SPEC)::toParamValue
- )
- .bindOutput(
- "executionStatus",
- Output::executionStatus,
- ExecutionStatus::toParamValue
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-communication/src/main/java/androidx/appactions/interaction/capabilities/communication/ParticipantReference.kt b/appactions/interaction/interaction-capabilities-communication/src/main/java/androidx/appactions/interaction/capabilities/communication/ParticipantReference.kt
deleted file mode 100644
index 2d56546..0000000
--- a/appactions/interaction/interaction-capabilities-communication/src/main/java/androidx/appactions/interaction/capabilities/communication/ParticipantReference.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.communication
-
-import androidx.appactions.builtintypes.experimental.properties.Participant
-import androidx.appactions.interaction.capabilities.core.SearchAction
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-
-class ParticipantReference private constructor(
- val asParticipant: Participant?,
- val asSearchAction: SearchAction<Participant>?,
-) {
- constructor(participant: Participant) : this(participant, null)
-
- // TODO(b/268071906) add ParticipantFilter type to SearchAction
- constructor(participantFilter: SearchAction<Participant>) : this(null, participantFilter)
-
- companion object {
- private val TYPE_SPEC = UnionTypeSpec.Builder<ParticipantReference>()
- .bindMemberType(
- memberGetter = ParticipantReference::asParticipant,
- ctor = { ParticipantReference(it) },
- typeSpec = TypeConverters.PARTICIPANT_TYPE_SPEC,
- )
- .bindMemberType(
- memberGetter = ParticipantReference::asSearchAction,
- ctor = { ParticipantReference(it) },
- typeSpec = TypeConverters.createSearchActionTypeSpec(
- TypeConverters.PARTICIPANT_TYPE_SPEC,
- ),
- )
- .build()
-
- internal val PARAM_VALUE_CONVERTER = ParamValueConverter.of(TYPE_SPEC)
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-communication/src/main/java/androidx/appactions/interaction/capabilities/communication/RecipientReference.kt b/appactions/interaction/interaction-capabilities-communication/src/main/java/androidx/appactions/interaction/capabilities/communication/RecipientReference.kt
deleted file mode 100644
index badd6ba..0000000
--- a/appactions/interaction/interaction-capabilities-communication/src/main/java/androidx/appactions/interaction/capabilities/communication/RecipientReference.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.communication
-
-import androidx.appactions.builtintypes.experimental.properties.Recipient
-import androidx.appactions.interaction.capabilities.core.SearchAction
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-
-class RecipientReference private constructor(
- val asRecipient: Recipient?,
- val asSearchAction: SearchAction<Recipient>?,
-) {
- constructor(recipient: Recipient) : this(recipient, null)
-
- // TODO(b/268071906) add RecipientFilter type to SearchAction
- constructor(recipientFilter: SearchAction<Recipient>) : this(null, recipientFilter)
-
- companion object {
- private val TYPE_SPEC = UnionTypeSpec.Builder<RecipientReference>()
- .bindMemberType(
- memberGetter = RecipientReference::asRecipient,
- ctor = { RecipientReference(it) },
- typeSpec = TypeConverters.RECIPIENT_TYPE_SPEC,
- )
- .bindMemberType(
- memberGetter = RecipientReference::asSearchAction,
- ctor = { RecipientReference(it) },
- typeSpec = TypeConverters.createSearchActionTypeSpec(
- TypeConverters.RECIPIENT_TYPE_SPEC,
- ),
- )
- .build()
-
- internal val PARAM_VALUE_CONVERTER = ParamValueConverter.of(TYPE_SPEC)
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-communication/src/main/java/androidx/appactions/interaction/capabilities/communication/package-info.java b/appactions/interaction/interaction-capabilities-communication/src/main/java/androidx/appactions/interaction/capabilities/communication/package-info.java
deleted file mode 100644
index 4c3216d..0000000
--- a/appactions/interaction/interaction-capabilities-communication/src/main/java/androidx/appactions/interaction/capabilities/communication/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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.
- */
-
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-package androidx.appactions.interaction.capabilities.communication;
-
-import androidx.annotation.RestrictTo;
diff --git a/appactions/interaction/interaction-capabilities-core/api/current.txt b/appactions/interaction/interaction-capabilities-core/api/current.txt
deleted file mode 100644
index a2c066f..0000000
--- a/appactions/interaction/interaction-capabilities-core/api/current.txt
+++ /dev/null
@@ -1,88 +0,0 @@
-// Signature format: 4.0
-package androidx.appactions.interaction.capabilities.core {
-
- public interface BaseExecutionSession<ArgumentsT, OutputT> {
- method public default void onCreate(androidx.appactions.interaction.capabilities.core.SessionConfig sessionConfig);
- method public default void onDestroy();
- method public default suspend Object? onExecute(ArgumentsT arguments, kotlin.coroutines.Continuation<? super androidx.appactions.interaction.capabilities.core.ExecutionResult<OutputT>>);
- method public default com.google.common.util.concurrent.ListenableFuture<androidx.appactions.interaction.capabilities.core.ExecutionResult<OutputT>> onExecuteAsync(ArgumentsT arguments);
- }
-
- public abstract class Capability {
- method public String getId();
- property public String id;
- }
-
- public abstract static class Capability.Builder<BuilderT extends androidx.appactions.interaction.capabilities.core.Capability.Builder<BuilderT, ArgumentsT, OutputT, ConfirmationT, ExecutionSessionT>, ArgumentsT, OutputT, ConfirmationT, ExecutionSessionT extends androidx.appactions.interaction.capabilities.core.BaseExecutionSession<ArgumentsT, OutputT>> {
- method public androidx.appactions.interaction.capabilities.core.Capability build();
- method public final BuilderT setExecutionCallback(androidx.appactions.interaction.capabilities.core.ExecutionCallback<ArgumentsT,OutputT> executionCallback);
- method public final BuilderT setExecutionCallback(androidx.appactions.interaction.capabilities.core.ExecutionCallbackAsync<ArgumentsT,OutputT> executionCallbackAsync);
- method protected BuilderT setExecutionSessionFactory(kotlin.jvm.functions.Function1<? super androidx.appactions.interaction.capabilities.core.HostProperties?,? extends ExecutionSessionT> sessionFactory);
- method public final BuilderT setId(String id);
- }
-
- public fun interface ExecutionCallback<ArgumentsT, OutputT> {
- method public suspend Object? onExecute(ArgumentsT arguments, kotlin.coroutines.Continuation<? super androidx.appactions.interaction.capabilities.core.ExecutionResult<OutputT>>);
- }
-
- public fun interface ExecutionCallbackAsync<ArgumentsT, OutputT> {
- method public com.google.common.util.concurrent.ListenableFuture<androidx.appactions.interaction.capabilities.core.ExecutionResult<OutputT>> onExecute(ArgumentsT arguments);
- }
-
- public final class ExecutionResult<OutputT> {
- method public OutputT? getOutput();
- property public final OutputT? output;
- }
-
- public static final class ExecutionResult.Builder<OutputT> {
- ctor public ExecutionResult.Builder();
- method public androidx.appactions.interaction.capabilities.core.ExecutionResult<OutputT> build();
- method public androidx.appactions.interaction.capabilities.core.ExecutionResult.Builder<OutputT> setOutput(OutputT output);
- }
-
- public final class HostProperties {
- method public android.util.SizeF getMaxHostSizeDp();
- property public final android.util.SizeF maxHostSizeDp;
- }
-
- public final class SessionConfig {
- }
-
-}
-
-package androidx.appactions.interaction.capabilities.core.properties {
-
- public final class Property<T> {
- ctor public Property(optional java.util.List<? extends T> possibleValues);
- ctor public Property(optional java.util.List<? extends T> possibleValues, optional boolean isRequiredForExecution);
- ctor public Property(optional java.util.List<? extends T> possibleValues, optional boolean isRequiredForExecution, optional boolean shouldMatchPossibleValues);
- ctor public Property(kotlin.jvm.functions.Function0<? extends java.util.List<? extends T>> possibleValueSupplier);
- ctor public Property(kotlin.jvm.functions.Function0<? extends java.util.List<? extends T>> possibleValueSupplier, optional boolean isRequiredForExecution);
- ctor public Property(kotlin.jvm.functions.Function0<? extends java.util.List<? extends T>> possibleValueSupplier, optional boolean isRequiredForExecution, optional boolean shouldMatchPossibleValues);
- method public java.util.List<T> getPossibleValues();
- method public boolean isRequiredForExecution();
- method public boolean isSupported();
- method public boolean shouldMatchPossibleValues();
- method public static <T> androidx.appactions.interaction.capabilities.core.properties.Property<T> unsupported();
- property public final boolean isRequiredForExecution;
- property public final boolean isSupported;
- property public final java.util.List<T> possibleValues;
- property public final boolean shouldMatchPossibleValues;
- field public static final androidx.appactions.interaction.capabilities.core.properties.Property.Companion Companion;
- }
-
- public static final class Property.Companion {
- method public <T> androidx.appactions.interaction.capabilities.core.properties.Property<T> unsupported();
- }
-
- public final class StringValue {
- ctor public StringValue(String name);
- ctor public StringValue(String name, optional java.util.List<java.lang.String> alternateNames);
- method public java.util.List<java.lang.String> getAlternateNames();
- method public String getName();
- property public final java.util.List<java.lang.String> alternateNames;
- property public final String name;
- }
-
-}
-
diff --git a/appactions/interaction/interaction-capabilities-core/api/res-current.txt b/appactions/interaction/interaction-capabilities-core/api/res-current.txt
deleted file mode 100644
index e69de29..0000000
--- a/appactions/interaction/interaction-capabilities-core/api/res-current.txt
+++ /dev/null
diff --git a/appactions/interaction/interaction-capabilities-core/api/restricted_current.txt b/appactions/interaction/interaction-capabilities-core/api/restricted_current.txt
deleted file mode 100644
index a2c066f..0000000
--- a/appactions/interaction/interaction-capabilities-core/api/restricted_current.txt
+++ /dev/null
@@ -1,88 +0,0 @@
-// Signature format: 4.0
-package androidx.appactions.interaction.capabilities.core {
-
- public interface BaseExecutionSession<ArgumentsT, OutputT> {
- method public default void onCreate(androidx.appactions.interaction.capabilities.core.SessionConfig sessionConfig);
- method public default void onDestroy();
- method public default suspend Object? onExecute(ArgumentsT arguments, kotlin.coroutines.Continuation<? super androidx.appactions.interaction.capabilities.core.ExecutionResult<OutputT>>);
- method public default com.google.common.util.concurrent.ListenableFuture<androidx.appactions.interaction.capabilities.core.ExecutionResult<OutputT>> onExecuteAsync(ArgumentsT arguments);
- }
-
- public abstract class Capability {
- method public String getId();
- property public String id;
- }
-
- public abstract static class Capability.Builder<BuilderT extends androidx.appactions.interaction.capabilities.core.Capability.Builder<BuilderT, ArgumentsT, OutputT, ConfirmationT, ExecutionSessionT>, ArgumentsT, OutputT, ConfirmationT, ExecutionSessionT extends androidx.appactions.interaction.capabilities.core.BaseExecutionSession<ArgumentsT, OutputT>> {
- method public androidx.appactions.interaction.capabilities.core.Capability build();
- method public final BuilderT setExecutionCallback(androidx.appactions.interaction.capabilities.core.ExecutionCallback<ArgumentsT,OutputT> executionCallback);
- method public final BuilderT setExecutionCallback(androidx.appactions.interaction.capabilities.core.ExecutionCallbackAsync<ArgumentsT,OutputT> executionCallbackAsync);
- method protected BuilderT setExecutionSessionFactory(kotlin.jvm.functions.Function1<? super androidx.appactions.interaction.capabilities.core.HostProperties?,? extends ExecutionSessionT> sessionFactory);
- method public final BuilderT setId(String id);
- }
-
- public fun interface ExecutionCallback<ArgumentsT, OutputT> {
- method public suspend Object? onExecute(ArgumentsT arguments, kotlin.coroutines.Continuation<? super androidx.appactions.interaction.capabilities.core.ExecutionResult<OutputT>>);
- }
-
- public fun interface ExecutionCallbackAsync<ArgumentsT, OutputT> {
- method public com.google.common.util.concurrent.ListenableFuture<androidx.appactions.interaction.capabilities.core.ExecutionResult<OutputT>> onExecute(ArgumentsT arguments);
- }
-
- public final class ExecutionResult<OutputT> {
- method public OutputT? getOutput();
- property public final OutputT? output;
- }
-
- public static final class ExecutionResult.Builder<OutputT> {
- ctor public ExecutionResult.Builder();
- method public androidx.appactions.interaction.capabilities.core.ExecutionResult<OutputT> build();
- method public androidx.appactions.interaction.capabilities.core.ExecutionResult.Builder<OutputT> setOutput(OutputT output);
- }
-
- public final class HostProperties {
- method public android.util.SizeF getMaxHostSizeDp();
- property public final android.util.SizeF maxHostSizeDp;
- }
-
- public final class SessionConfig {
- }
-
-}
-
-package androidx.appactions.interaction.capabilities.core.properties {
-
- public final class Property<T> {
- ctor public Property(optional java.util.List<? extends T> possibleValues);
- ctor public Property(optional java.util.List<? extends T> possibleValues, optional boolean isRequiredForExecution);
- ctor public Property(optional java.util.List<? extends T> possibleValues, optional boolean isRequiredForExecution, optional boolean shouldMatchPossibleValues);
- ctor public Property(kotlin.jvm.functions.Function0<? extends java.util.List<? extends T>> possibleValueSupplier);
- ctor public Property(kotlin.jvm.functions.Function0<? extends java.util.List<? extends T>> possibleValueSupplier, optional boolean isRequiredForExecution);
- ctor public Property(kotlin.jvm.functions.Function0<? extends java.util.List<? extends T>> possibleValueSupplier, optional boolean isRequiredForExecution, optional boolean shouldMatchPossibleValues);
- method public java.util.List<T> getPossibleValues();
- method public boolean isRequiredForExecution();
- method public boolean isSupported();
- method public boolean shouldMatchPossibleValues();
- method public static <T> androidx.appactions.interaction.capabilities.core.properties.Property<T> unsupported();
- property public final boolean isRequiredForExecution;
- property public final boolean isSupported;
- property public final java.util.List<T> possibleValues;
- property public final boolean shouldMatchPossibleValues;
- field public static final androidx.appactions.interaction.capabilities.core.properties.Property.Companion Companion;
- }
-
- public static final class Property.Companion {
- method public <T> androidx.appactions.interaction.capabilities.core.properties.Property<T> unsupported();
- }
-
- public final class StringValue {
- ctor public StringValue(String name);
- ctor public StringValue(String name, optional java.util.List<java.lang.String> alternateNames);
- method public java.util.List<java.lang.String> getAlternateNames();
- method public String getName();
- property public final java.util.List<java.lang.String> alternateNames;
- property public final String name;
- }
-
-}
-
diff --git a/appactions/interaction/interaction-capabilities-core/build.gradle b/appactions/interaction/interaction-capabilities-core/build.gradle
deleted file mode 100644
index 90d97c5b..0000000
--- a/appactions/interaction/interaction-capabilities-core/build.gradle
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 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.LibraryType
-import androidx.build.Publish
-
-plugins {
- id("AndroidXPlugin")
- id("com.android.library")
- id("org.jetbrains.kotlin.android")
-}
-
-dependencies {
- api(project(path: ":appactions:interaction:interaction-proto", configuration: "shadowJar"))
- api(project(":appactions:builtintypes:builtintypes"))
-
- api(libs.autoValueAnnotations)
- implementation(libs.guavaListenableFuture)
- implementation(libs.kotlinCoroutinesCore)
- implementation(libs.kotlinStdlib)
- implementation("androidx.concurrent:concurrent-futures:1.1.0")
- implementation("androidx.concurrent:concurrent-futures-ktx:1.1.0")
-
- testImplementation(project(":appactions:interaction:interaction-capabilities-testing"))
- testImplementation(libs.junit)
- testImplementation(libs.truth)
- testImplementation(libs.testCore)
- testImplementation(libs.mockitoCore)
- testImplementation(libs.mockitoKotlin4)
- testImplementation(libs.kotlinCoroutinesTest)
- testImplementation(libs.kotlinStdlib)
- testImplementation(libs.androidLint)
- testImplementation(libs.androidLintTests)
- testImplementation(libs.autoValueAnnotations)
- testImplementation(libs.testRunner)
-}
-
-android {
- buildFeatures {
- resValues = true
- }
- defaultConfig {
- minSdkVersion 26
- resValue "string", "appactions_interaction_library_version", androidx.LibraryVersions.APPACTIONS_INTERACTION.toString()
- }
-
- lintOptions {
- disable("UnknownNullness")
- }
-
- namespace "androidx.appactions.interaction.capabilities.core"
-}
-
-androidx {
- name = "App Actions Interaction Capabiliities Core"
- type = LibraryType.PUBLISHED_LIBRARY
- inceptionYear = "2023"
- description = "App Interaction library core capabilities API and implementation."
- metalavaK2UastEnabled = true
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/package-info.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/package-info.java
deleted file mode 100644
index d6624512..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/package-info.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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.
- */
-
-// TODO(b/271000058): Delete experimental builtintypes package.
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-package androidx.appactions.builtintypes.experimental;
-
-import androidx.annotation.RestrictTo;
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/Attendee.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/Attendee.kt
deleted file mode 100644
index 7616521..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/Attendee.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.properties
-
-import androidx.appactions.builtintypes.experimental.types.Person
-
-/**
- * Represents the value of the union property: http://schema.org/attendee, currently it only can
- * contain {@link Person}.
- */
-class Attendee(person: Person) {
- @get:JvmName("asPerson")
- val asPerson: Person? = person
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is Attendee) return false
- if (asPerson != other.asPerson) return false
- return true
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/CallFormat.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/CallFormat.kt
deleted file mode 100644
index 1615291..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/CallFormat.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.properties
-
-class CallFormat private constructor(
- val asText: String?,
- val asCanonicalValue: CanonicalValue?,
-) {
-
- constructor(text: String) : this(asText = text, asCanonicalValue = null)
-
- constructor(canonicalValue: CanonicalValue) : this(
- asText = null,
- asCanonicalValue = canonicalValue
- )
-
- abstract class CanonicalValue internal constructor(val textValue: String)
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/EndDate.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/EndDate.kt
deleted file mode 100644
index db03a15..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/EndDate.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.properties
-
-import java.time.LocalDate
-import java.time.ZonedDateTime
-
-class EndDate internal constructor(
- @get:JvmName("asDate")
- val asDate: LocalDate? = null,
- @get:JvmName("asZonedDateTime")
- val asZonedDateTime: ZonedDateTime? = null
-) {
- constructor(date: LocalDate) : this(asDate = date, asZonedDateTime = null)
- constructor(zonedDateTime: ZonedDateTime) : this(asDate = null, asZonedDateTime = zonedDateTime)
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is EndDate) return false
- if (asDate != other.asDate) return false
- if (asZonedDateTime != other.asZonedDateTime) return false
- return true
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/ItemListElement.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/ItemListElement.kt
deleted file mode 100644
index baff5d82..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/ItemListElement.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.properties
-
-import androidx.appactions.builtintypes.experimental.types.ListItem
-
-class ItemListElement(asListItem: ListItem) {
- @get:JvmName("asListItem")
- val asListItem: ListItem = asListItem
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is ItemListElement) return false
- if (asListItem != other.asListItem) return false
- return true
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/Name.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/Name.kt
deleted file mode 100644
index bdd5983..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/Name.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.properties
-
-class Name(asText: String) {
- @get:JvmName("asText")
- val asText: String = asText
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is Name) return false
- if (asText != other.asText) return false
- return true
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/Participant.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/Participant.kt
deleted file mode 100644
index 5a46ae2..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/Participant.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.properties
-
-import androidx.appactions.builtintypes.experimental.types.Person
-
-/**
- * Represents the value of the union property: http://schema.org/participant, currently it only can
- * contain {@link Person}.
- */
-class Participant(person: Person) {
- @get:JvmName("asPerson")
- val asPerson: Person? = person
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is Participant) return false
- if (asPerson != other.asPerson) return false
- return true
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/Recipient.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/Recipient.kt
deleted file mode 100644
index 1e7b7e6..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/Recipient.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.properties
-
-import androidx.appactions.builtintypes.experimental.types.Person
-
-/**
- * Represents the value of the union property: http://schema.org/recipient, currently it only can
- * contain {@link Person}.
- */
-class Recipient(person: Person) {
- @get:JvmName("asPerson")
- val asPerson: Person? = person
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is Recipient) return false
- if (asPerson != other.asPerson) return false
- return true
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/StartDate.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/StartDate.kt
deleted file mode 100644
index 5915fee..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/StartDate.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.properties
-
-import java.time.LocalDate
-import java.time.ZonedDateTime
-
-class StartDate internal constructor(
- @get:JvmName("asDate")
- val asDate: LocalDate? = null,
- @get:JvmName("asZonedDateTime")
- val asZonedDateTime: ZonedDateTime? = null
-) {
- constructor(date: LocalDate) : this(asDate = date, asZonedDateTime = null)
- constructor(zonedDateTime: ZonedDateTime) : this(asDate = null, asZonedDateTime = zonedDateTime)
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is StartDate) return false
- if (asDate != other.asDate) return false
- if (asZonedDateTime != other.asZonedDateTime) return false
- return true
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/Text.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/Text.kt
deleted file mode 100644
index c66dc1b..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/properties/Text.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.properties
-
-class Text(asText: String) {
- @get:JvmName("asText")
- val asText: String = asText
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/ActionAlreadyInProgress.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/ActionAlreadyInProgress.kt
deleted file mode 100644
index b88f275..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/ActionAlreadyInProgress.kt
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.types
-
-import androidx.appactions.builtintypes.experimental.properties.Name
-
-interface ActionAlreadyInProgress : Thing {
- override fun toBuilder(): Builder<*>
-
- companion object {
- @JvmStatic
- fun Builder(): Builder<*> = ActionAlreadyInProgressBuilderImpl()
- }
-
- interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
- override fun build(): ActionAlreadyInProgress
- }
-}
-
-private class ActionAlreadyInProgressBuilderImpl :
- ActionAlreadyInProgress.Builder<ActionAlreadyInProgressBuilderImpl> {
-
- private var identifier: String? = null
- private var name: Name? = null
-
- override fun build() = ActionAlreadyInProgressImpl(identifier, name)
-
- override fun setIdentifier(text: String?): ActionAlreadyInProgressBuilderImpl =
- apply { identifier = text }
-
- override fun setName(text: String): ActionAlreadyInProgressBuilderImpl =
- apply { name = Name(text) }
-
- override fun setName(name: Name?): ActionAlreadyInProgressBuilderImpl =
- apply { this.name = name }
-
- override fun clearName(): ActionAlreadyInProgressBuilderImpl = apply { name = null }
-}
-
-private class ActionAlreadyInProgressImpl(
- override val identifier: String?,
- override val name: Name?
-) :
- ActionAlreadyInProgress {
- override fun toBuilder(): ActionAlreadyInProgress.Builder<*> =
- ActionAlreadyInProgressBuilderImpl().setIdentifier(identifier).setName(name)
-
- override fun toString(): String = "ActionAlreadyInProgress"
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/ActionNotInProgress.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/ActionNotInProgress.kt
deleted file mode 100644
index da7822d..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/ActionNotInProgress.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.types
-
-import androidx.appactions.builtintypes.experimental.properties.Name
-
-interface ActionNotInProgress : Thing {
- override fun toBuilder(): Builder<*>
-
- companion object {
- @JvmStatic
- fun Builder(): Builder<*> = ActionNotInProgressBuilderImpl()
- }
-
- interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
- override fun build(): ActionNotInProgress
- }
-}
-
-private class ActionNotInProgressBuilderImpl :
- ActionNotInProgress.Builder<ActionNotInProgressBuilderImpl> {
-
- private var identifier: String? = null
- private var name: Name? = null
-
- override fun build() = ActionNotInProgressImpl(identifier, name)
-
- override fun setIdentifier(text: String?): ActionNotInProgressBuilderImpl =
- apply { identifier = text }
-
- override fun setName(text: String): ActionNotInProgressBuilderImpl = apply { name = Name(text) }
-
- override fun setName(name: Name?): ActionNotInProgressBuilderImpl = apply { this.name = name }
-
- override fun clearName(): ActionNotInProgressBuilderImpl = apply { name = null }
-}
-
-private class ActionNotInProgressImpl(override val identifier: String?, override val name: Name?) :
- ActionNotInProgress {
- override fun toBuilder(): ActionNotInProgress.Builder<*> =
- ActionNotInProgressBuilderImpl().setIdentifier(identifier).setName(name)
-
- override fun toString(): String = "ActionNotInProgress"
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/CalendarEvent.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/CalendarEvent.kt
deleted file mode 100644
index f904e1f..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/CalendarEvent.kt
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.types
-
-import androidx.appactions.builtintypes.experimental.properties.Attendee
-import androidx.appactions.builtintypes.experimental.properties.EndDate
-import androidx.appactions.builtintypes.experimental.properties.Name
-import androidx.appactions.builtintypes.experimental.properties.StartDate
-import java.time.LocalDate
-import java.time.ZonedDateTime
-
-interface CalendarEvent : Thing {
- val startDate: StartDate?
- val endDate: EndDate?
- val attendeeList: List<Attendee>
- override fun toBuilder(): Builder<*>
-
- companion object {
- @JvmStatic
- fun Builder(): Builder<*> = CalendarEventBuilderImpl()
- }
-
- interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
- fun setStartDate(startDate: StartDate?): Self
- fun setStartDate(value: LocalDate): Self
- fun setStartDate(value: ZonedDateTime): Self
- fun setEndDate(endDate: EndDate?): Self
- fun setEndDate(value: LocalDate): Self
- fun setEndDate(value: ZonedDateTime): Self
- fun addAttendee(attendee: Attendee): Self
- fun addAttendees(value: List<Attendee>): Self
-
- override fun build(): CalendarEvent
- }
-}
-
-private class CalendarEventBuilderImpl : CalendarEvent.Builder<CalendarEventBuilderImpl> {
-
- private var identifier: String? = null
- private var name: Name? = null
- private var startDate: StartDate? = null
- private var endDate: EndDate? = null
- private var attendeeList = mutableListOf<Attendee>()
-
- override fun build() =
- CalendarEventImpl(identifier, name, startDate, endDate, attendeeList.toList())
-
- override fun setStartDate(startDate: StartDate?): CalendarEventBuilderImpl = apply {
- this.startDate = startDate
- }
-
- override fun setStartDate(value: LocalDate): CalendarEventBuilderImpl = apply {
- startDate = StartDate(value)
- }
-
- override fun setStartDate(value: ZonedDateTime): CalendarEventBuilderImpl = apply {
- startDate = StartDate(value)
- }
-
- override fun setEndDate(endDate: EndDate?): CalendarEventBuilderImpl = apply {
- this.endDate = endDate
- }
-
- override fun setEndDate(value: LocalDate): CalendarEventBuilderImpl = apply {
- endDate = EndDate(value)
- }
-
- override fun setEndDate(value: ZonedDateTime): CalendarEventBuilderImpl = apply {
- endDate = EndDate(value)
- }
-
- override fun addAttendee(attendee: Attendee): CalendarEventBuilderImpl = apply {
- attendeeList.add(attendee)
- }
-
- override fun addAttendees(value: List<Attendee>): CalendarEventBuilderImpl = apply {
- attendeeList.addAll(value)
- }
-
- override fun setIdentifier(text: String?): CalendarEventBuilderImpl =
- apply { identifier = text }
-
- override fun setName(text: String): CalendarEventBuilderImpl = apply { name = Name(text) }
-
- override fun setName(name: Name?): CalendarEventBuilderImpl = apply { this.name = name }
-
- override fun clearName(): CalendarEventBuilderImpl = apply { name = null }
-}
-
-private class CalendarEventImpl(
- override val identifier: String?,
- override val name: Name?,
- override val startDate: StartDate?,
- override val endDate: EndDate?,
- override val attendeeList: List<Attendee>
-) :
- CalendarEvent {
- override fun toBuilder(): CalendarEvent.Builder<*> =
- CalendarEventBuilderImpl()
- .setIdentifier(identifier)
- .setName(name)
- .setStartDate(startDate)
- .setEndDate(endDate)
- .addAttendees(attendeeList)
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is CalendarEventImpl) return false
- if (attendeeList != other.attendeeList) return false
- if (endDate != other.endDate) return false
- if (startDate != other.startDate) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
-
- return true
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/Call.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/Call.kt
deleted file mode 100644
index 8d690de..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/Call.kt
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.types
-
-import androidx.appactions.builtintypes.experimental.properties.CallFormat
-import androidx.appactions.builtintypes.experimental.properties.Name
-import androidx.appactions.builtintypes.experimental.properties.Participant
-
-interface Call : Thing {
- val callFormat: CallFormat?
- val participantList: List<Participant>
- override fun toBuilder(): Builder<*>
-
- companion object {
- @JvmStatic
- fun Builder(): Builder<*> = CallBuilderImpl()
- }
-
- object CanonicalValue {
- class CallFormat private constructor(textValue: String) :
- androidx.appactions.builtintypes.experimental.properties.CallFormat
- .CanonicalValue(textValue) {
- companion object {
- @JvmField
- val Audio = CallFormat("Audio")
-
- @JvmField
- val Video = CallFormat("Video")
- }
- }
- }
-
- interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
- fun setCallFormat(callFormat: CallFormat?): Self
- fun setCallFormat(canonicalValue: CanonicalValue.CallFormat): Self
- fun setCallFormat(text: String): Self
- fun addParticipant(person: Person): Self
- fun addParticipant(participant: Participant): Self
- fun addAllParticipant(value: Iterable<Participant>): Self
-
- override fun build(): Call
- }
-}
-
-private class CallBuilderImpl : Call.Builder<CallBuilderImpl> {
-
- private var identifier: String? = null
- private var name: Name? = null
- private var callFormat: CallFormat? = null
- private var participantList = mutableListOf<Participant>()
-
- override fun build() = CallImpl(identifier, name, callFormat, participantList.toList())
-
- override fun setCallFormat(callFormat: CallFormat?): CallBuilderImpl =
- apply { this.callFormat = callFormat }
-
- override fun setCallFormat(canonicalValue: Call.CanonicalValue.CallFormat): CallBuilderImpl =
- apply {
- this.callFormat = CallFormat(canonicalValue)
- }
-
- override fun setCallFormat(text: String): CallBuilderImpl = apply {
- this.callFormat = CallFormat(text)
- }
-
- override fun addParticipant(person: Person): CallBuilderImpl = apply {
- participantList.add(Participant(person))
- }
-
- override fun addParticipant(participant: Participant): CallBuilderImpl = apply {
- participantList.add(participant)
- }
-
- override fun addAllParticipant(value: Iterable<Participant>): CallBuilderImpl = apply {
- participantList.addAll(value)
- }
-
- override fun setIdentifier(text: String?): CallBuilderImpl = apply { identifier = text }
-
- override fun setName(text: String): CallBuilderImpl = apply { name = Name(text) }
-
- override fun setName(name: Name?): CallBuilderImpl = apply { this.name = name }
-
- override fun clearName(): CallBuilderImpl = apply { name = null }
-}
-
-private class CallImpl(
- override val identifier: String?,
- override val name: Name?,
- override val callFormat: CallFormat?,
- override val participantList: List<Participant>
-) : Call {
- override fun toBuilder(): Call.Builder<*> =
- CallBuilderImpl()
- .setIdentifier(identifier)
- .setName(name)
- .setCallFormat(callFormat)
- .addAllParticipant(participantList)
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/CreativeWork.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/CreativeWork.kt
deleted file mode 100644
index 136efdd..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/CreativeWork.kt
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.types
-
-import androidx.appactions.builtintypes.experimental.properties.Name
-import androidx.appactions.builtintypes.experimental.properties.Text
-
-interface CreativeWork : Thing {
- val text: Text?
-
- override fun toBuilder(): Thing.Builder<*>
-
- companion object {
- @JvmStatic
- fun Builder(): Thing.Builder<*> = CreativeWorkBuilderImpl()
- }
-
- interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
- fun setText(text: Text?): Self
- fun setText(text: String): Self
-
- override fun build(): CreativeWork
- }
-}
-
-private class CreativeWorkBuilderImpl : CreativeWork.Builder<CreativeWorkBuilderImpl> {
- private var identifier: String? = null
- private var name: Name? = null
- private var text: Text? = null
-
- override fun build() = CreateWorkImpl(text, identifier, name)
-
- override fun setText(text: Text?): CreativeWorkBuilderImpl = apply { this.text = text }
-
- override fun setText(text: String): CreativeWorkBuilderImpl = apply { this.text = Text(text) }
-
- override fun setIdentifier(text: String?): CreativeWorkBuilderImpl = apply {
- identifier = text
- }
-
- override fun setName(text: String): CreativeWorkBuilderImpl = apply { name = Name(text) }
- override fun setName(name: Name?): CreativeWorkBuilderImpl = apply {
- this.name = name
- }
-
- override fun clearName(): CreativeWorkBuilderImpl = apply { name = null }
-}
-
-private class CreateWorkImpl(
- override val text: Text?,
- override val identifier: String?,
- override val name: Name?
-) : CreativeWork {
- override fun toBuilder(): CreativeWork.Builder<*> =
- CreativeWorkBuilderImpl()
- .setIdentifier(identifier)
- .setName(name)
- .setText(text)
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/GenericErrorStatus.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/GenericErrorStatus.kt
deleted file mode 100644
index 6c8b17b..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/GenericErrorStatus.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.types
-
-import androidx.appactions.builtintypes.experimental.properties.Name
-
-interface GenericErrorStatus : Thing {
- override fun toBuilder(): Builder<*>
-
- companion object {
- @JvmStatic
- fun Builder(): Builder<*> = GenericErrorStatusBuilderImpl()
- }
-
- interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
- override fun build(): GenericErrorStatus
- }
-}
-
-private class GenericErrorStatusBuilderImpl :
- GenericErrorStatus.Builder<GenericErrorStatusBuilderImpl> {
-
- private var identifier: String? = null
- private var name: Name? = null
-
- override fun build() = GenericErrorStatusImpl(identifier, name)
-
- override fun setIdentifier(text: String?): GenericErrorStatusBuilderImpl =
- apply { identifier = text }
-
- override fun setName(text: String): GenericErrorStatusBuilderImpl = apply { name = Name(text) }
-
- override fun setName(name: Name?): GenericErrorStatusBuilderImpl = apply { this.name = name }
-
- override fun clearName(): GenericErrorStatusBuilderImpl = apply { name = null }
-}
-
-private class GenericErrorStatusImpl(override val identifier: String?, override val name: Name?) :
- GenericErrorStatus {
- override fun toBuilder(): GenericErrorStatus.Builder<*> =
- GenericErrorStatusBuilderImpl().setIdentifier(identifier).setName(name)
-
- override fun toString(): String = "GenericErrorStatus"
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/ItemList.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/ItemList.kt
deleted file mode 100644
index 58cab34..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/ItemList.kt
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.types
-
-import androidx.appactions.builtintypes.experimental.properties.ItemListElement
-import androidx.appactions.builtintypes.experimental.properties.Name
-
-interface ItemList : Thing {
- val itemListElements: List<ItemListElement>
- override fun toBuilder(): Builder<*>
-
- companion object {
- @JvmStatic
- fun Builder(): Builder<*> = ItemListBuilderImpl()
- }
-
- interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
- fun addItemListElements(itemListElements: List<ItemListElement>): Self
- fun addItemListElement(itemListElement: ItemListElement): Self
- fun addItemListElement(listItem: ListItem): Self
- override fun build(): ItemList
- }
-}
-
-private class ItemListBuilderImpl : ItemList.Builder<ItemListBuilderImpl> {
- private var identifier: String? = null
- private var name: Name? = null
- private var itemListElements = mutableListOf<ItemListElement>()
-
- override fun build() = ItemListImpl(identifier, name, itemListElements.toList())
-
- override fun addItemListElements(itemListElements: List<ItemListElement>): ItemListBuilderImpl =
- apply {
- this.itemListElements.addAll(itemListElements)
- }
-
- override fun addItemListElement(itemListElement: ItemListElement): ItemListBuilderImpl = apply {
- itemListElements.add(itemListElement)
- }
-
- override fun addItemListElement(listItem: ListItem): ItemListBuilderImpl = apply {
- itemListElements.add(ItemListElement(listItem))
- }
-
- override fun setIdentifier(text: String?): ItemListBuilderImpl = apply {
- identifier = text
- }
-
- override fun setName(text: String): ItemListBuilderImpl = apply {
- name = Name(text)
- }
-
- override fun setName(name: Name?): ItemListBuilderImpl = apply {
- this.name = name
- }
-
- override fun clearName(): ItemListBuilderImpl = apply { name = null }
-}
-
-private class ItemListImpl(
- override val identifier: String?,
- override val name: Name?,
- override val itemListElements: List<ItemListElement>
-) : ItemList {
- override fun toBuilder(): ItemList.Builder<*> =
- ItemListBuilderImpl()
- .setIdentifier(identifier)
- .setName(name)
- .addItemListElements(itemListElements)
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is ItemListImpl) return false
- if (this.name != other.name) return false
- if (this.identifier != other.identifier) return false
- if (this.itemListElements != other.itemListElements) return false
- return true
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/ListItem.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/ListItem.kt
deleted file mode 100644
index fba7511..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/ListItem.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.types
-
-import androidx.appactions.builtintypes.experimental.properties.Name
-
-interface ListItem : Thing {
- override fun toBuilder(): Builder<*>
-
- companion object {
- @JvmStatic
- fun Builder(): Builder<*> = ListItemBuilderImpl()
- }
-
- interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
- override fun build(): ListItem
- }
-}
-
-private class ListItemBuilderImpl : ListItem.Builder<ListItemBuilderImpl> {
- private var identifier: String? = null
- private var name: Name? = null
- override fun build() = ListItemImpl(identifier, name)
-
- override fun setIdentifier(text: String?): ListItemBuilderImpl = apply {
- identifier = text
- }
-
- override fun setName(text: String): ListItemBuilderImpl = apply {
- name = Name(text)
- }
-
- override fun setName(name: Name?): ListItemBuilderImpl = apply {
- this.name = name
- }
-
- override fun clearName(): ListItemBuilderImpl = apply { name = null }
-}
-
-private class ListItemImpl(
- override val identifier: String?,
- override val name: Name?
-) : ListItem {
- override fun toBuilder(): ListItem.Builder<*> =
- ListItemBuilderImpl().setIdentifier(identifier).setName(name)
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is ListItemImpl) return false
- if (this.name != other.name) return false
- if (this.identifier != other.identifier) return false
- return true
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/Message.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/Message.kt
deleted file mode 100644
index 3750db9..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/Message.kt
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.types
-
-import androidx.appactions.builtintypes.experimental.properties.Name
-import androidx.appactions.builtintypes.experimental.properties.Recipient
-import androidx.appactions.builtintypes.experimental.properties.Text
-
-interface Message : Thing, CreativeWork {
- val recipientList: List<Recipient>
- override fun toBuilder(): Builder<*>
-
- companion object {
- @JvmStatic
- fun Builder(): Builder<*> = MessageBuilderImpl()
- }
-
- interface Builder<Self : Builder<Self>> : Thing.Builder<Self>, CreativeWork.Builder<Self> {
- fun addRecipient(person: Person): Self
- fun addRecipient(recipient: Recipient): Self
- fun addRecipients(value: List<Recipient>): Self
-
- override fun build(): Message
- }
-}
-
-private class MessageBuilderImpl : Message.Builder<MessageBuilderImpl> {
-
- private var identifier: String? = null
- private var name: Name? = null
- private var text: Text? = null
- private var recipientList = mutableListOf<Recipient>()
-
- override fun build() = MessageImpl(identifier, name, text, recipientList.toList())
-
- override fun addRecipient(person: Person): MessageBuilderImpl = apply {
- recipientList.add(Recipient(person))
- }
-
- override fun addRecipient(recipient: Recipient): MessageBuilderImpl = apply {
- recipientList.add(recipient)
- }
-
- override fun addRecipients(value: List<Recipient>): MessageBuilderImpl = apply {
- recipientList.addAll(value)
- }
-
- override fun setIdentifier(text: String?): MessageBuilderImpl = apply { identifier = text }
-
- override fun setName(text: String): MessageBuilderImpl = apply { name = Name(text) }
-
- override fun setName(name: Name?): MessageBuilderImpl = apply { this.name = name }
-
- override fun clearName(): MessageBuilderImpl = apply { name = null }
-
- override fun setText(text: Text?): MessageBuilderImpl = apply { this.text = text }
-
- override fun setText(text: String): MessageBuilderImpl = apply { this.text = Text(text) }
-}
-
-private class MessageImpl(
- override val identifier: String?,
- override val name: Name?,
- override val text: Text?,
- override val recipientList: List<Recipient>
-) : Message {
- override fun toBuilder(): Message.Builder<*> =
- MessageBuilderImpl()
- .setIdentifier(identifier)
- .setName(name)
- .setText(text)
- .addRecipients(recipientList)
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/NoInternetConnection.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/NoInternetConnection.kt
deleted file mode 100644
index 334b2ce..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/NoInternetConnection.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.types
-
-import androidx.appactions.builtintypes.experimental.properties.Name
-
-interface NoInternetConnection : Thing {
- override fun toBuilder(): Builder<*>
-
- companion object {
- @JvmStatic
- fun Builder(): Builder<*> = NoInternetConnectionBuilderImpl()
- }
-
- interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
- override fun build(): NoInternetConnection
- }
-}
-
-private class NoInternetConnectionBuilderImpl :
- NoInternetConnection.Builder<NoInternetConnectionBuilderImpl> {
-
- private var identifier: String? = null
- private var name: Name? = null
-
- override fun build() = NoInternetConnectionImpl(identifier, name)
-
- override fun setIdentifier(text: String?): NoInternetConnectionBuilderImpl =
- apply { identifier = text }
-
- override fun setName(text: String): NoInternetConnectionBuilderImpl =
- apply { name = Name(text) }
-
- override fun setName(name: Name?): NoInternetConnectionBuilderImpl = apply { this.name = name }
-
- override fun clearName(): NoInternetConnectionBuilderImpl = apply { name = null }
-}
-
-private class NoInternetConnectionImpl(override val identifier: String?, override val name: Name?) :
- NoInternetConnection {
- override fun toBuilder(): NoInternetConnection.Builder<*> =
- NoInternetConnectionBuilderImpl().setIdentifier(identifier).setName(name)
-
- override fun toString(): String = "NoInternetConnection"
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/Person.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/Person.kt
deleted file mode 100644
index 178b06b..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/Person.kt
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.types
-
-import androidx.appactions.builtintypes.experimental.properties.Name
-
-interface Person : Thing {
- val email: String?
- val telephone: String?
-
- override fun toBuilder(): Builder<*>
-
- companion object {
- @JvmStatic
- fun Builder(): Builder<*> = PersonBuilderImpl()
- }
-
- interface Builder<Self : Builder<Self>> : Thing.Builder<Builder<Self>> {
- fun setEmail(email: String?): Self
- fun setTelephone(telephone: String?): Self
-
- override fun build(): Person
- }
-}
-
-private class PersonBuilderImpl : Person.Builder<PersonBuilderImpl> {
-
- private var identifier: String? = null
- private var name: Name? = null
- private var email: String? = null
- private var telephone: String? = null
-
- override fun setEmail(email: String?): PersonBuilderImpl = apply { this.email = email }
-
- override fun setTelephone(telephone: String?): PersonBuilderImpl =
- apply { this.telephone = telephone }
-
- override fun build() = PersonImpl(identifier, name, email, telephone)
-
- override fun setIdentifier(text: String?): PersonBuilderImpl = apply { identifier = text }
-
- override fun setName(text: String): PersonBuilderImpl = apply { name = Name(text) }
-
- override fun setName(name: Name?): PersonBuilderImpl = apply { this.name = name }
-
- override fun clearName(): PersonBuilderImpl = apply { name = null }
-}
-
-private class PersonImpl(
- override val identifier: String?,
- override val name: Name?,
- override val email: String?,
- override val telephone: String?
-) : Person {
- override fun toBuilder(): Person.Builder<*> =
- PersonBuilderImpl()
- .setIdentifier(identifier)
- .setName(name)
- .setEmail(email)
- .setTelephone(telephone)
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is PersonImpl) return false
- if (email != other.email) return false
- if (telephone != other.telephone) return false
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- return true
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/SafetyCheck.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/SafetyCheck.kt
deleted file mode 100644
index 4b4355e..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/SafetyCheck.kt
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.types
-
-import androidx.appactions.builtintypes.experimental.properties.Name
-import java.time.Duration
-import java.time.ZonedDateTime
-
-interface SafetyCheck : Thing {
- val duration: Duration?
- val checkInTime: ZonedDateTime?
-
- override fun toBuilder(): Builder<*>
-
- companion object {
- @JvmStatic
- fun Builder(): Builder<*> = SafetyCheckBuilderImpl()
- }
-
- interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
- fun setDuration(duration: Duration?): Self
- fun setCheckInTime(checkInTime: ZonedDateTime?): Self
- override fun build(): SafetyCheck
- }
-}
-
-private class SafetyCheckBuilderImpl : SafetyCheck.Builder<SafetyCheckBuilderImpl> {
-
- private var identifier: String? = null
- private var name: Name? = null
- private var duration: Duration? = null
- private var checkInTime: ZonedDateTime? = null
-
- override fun build(): SafetyCheck = SafetyCheckImpl(identifier, name, duration, checkInTime)
-
- override fun setDuration(duration: Duration?): SafetyCheckBuilderImpl =
- apply { this.duration = duration }
-
- override fun setCheckInTime(checkInTime: ZonedDateTime?): SafetyCheckBuilderImpl =
- apply { this.checkInTime = checkInTime }
-
- override fun setIdentifier(text: String?): SafetyCheckBuilderImpl = apply { identifier = text }
-
- override fun setName(text: String): SafetyCheckBuilderImpl = apply { name = Name(text) }
-
- override fun setName(name: Name?): SafetyCheckBuilderImpl = apply { this.name = name }
-
- override fun clearName(): SafetyCheckBuilderImpl = apply { name = null }
-}
-
-private class SafetyCheckImpl(
- override val identifier: String?,
- override val name: Name?,
- override val duration: Duration?,
- override val checkInTime: ZonedDateTime?
-) : SafetyCheck {
- override fun toBuilder(): SafetyCheck.Builder<*> =
- SafetyCheckBuilderImpl()
- .setIdentifier(identifier)
- .setName(name)
- .setDuration(duration)
- .setCheckInTime(checkInTime)
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/SuccessStatus.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/SuccessStatus.kt
deleted file mode 100644
index f06badd..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/SuccessStatus.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.types
-
-import androidx.appactions.builtintypes.experimental.properties.Name
-
-interface SuccessStatus : Thing {
- override fun toBuilder(): Builder<*>
-
- companion object {
- @JvmStatic
- fun Builder(): Builder<*> = SuccessStatusBuilderImpl()
- }
-
- interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
- override fun build(): SuccessStatus
- }
-}
-
-private class SuccessStatusBuilderImpl :
- SuccessStatus.Builder<SuccessStatusBuilderImpl> {
-
- private var identifier: String? = null
- private var name: Name? = null
-
- override fun build() = SuccessStatusImpl(identifier, name)
-
- override fun setIdentifier(text: String?): SuccessStatusBuilderImpl =
- apply { identifier = text }
-
- override fun setName(text: String): SuccessStatusBuilderImpl = apply { name = Name(text) }
-
- override fun setName(name: Name?): SuccessStatusBuilderImpl = apply { this.name = name }
-
- override fun clearName(): SuccessStatusBuilderImpl = apply { name = null }
-}
-
-private class SuccessStatusImpl(override val identifier: String?, override val name: Name?) :
- SuccessStatus {
- override fun toBuilder(): SuccessStatus.Builder<*> =
- SuccessStatusBuilderImpl().setIdentifier(identifier).setName(name)
-
- override fun toString(): String = "SuccessStatus"
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/Thing.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/Thing.kt
deleted file mode 100644
index 1fe28c8..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/builtintypes/experimental/types/Thing.kt
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.appactions.builtintypes.experimental.types
-
-import androidx.appactions.builtintypes.experimental.properties.Name
-
-interface Thing {
- val identifier: String?
- val name: Name?
-
- fun toBuilder(): Builder<*>
-
- companion object {
- @JvmStatic
- fun Builder(): Builder<*> = ThingBuilderImpl()
- }
-
- @Suppress("StaticFinalBuilder")
- interface Builder<Self : Builder<Self>> {
- fun build(): Thing
-
- fun setIdentifier(text: String?): Self
- fun setName(text: String): Self
- fun setName(name: Name?): Self
- fun clearName(): Self
- }
-}
-
-private class ThingBuilderImpl : Thing.Builder<ThingBuilderImpl> {
-
- private var identifier: String? = null
- private var name: Name? = null
-
- override fun build(): Thing = ThingImpl(identifier, name)
-
- override fun setIdentifier(text: String?): ThingBuilderImpl =
- apply { identifier = text }
-
- override fun setName(text: String): ThingBuilderImpl = apply { name = Name(text) }
- override fun setName(name: Name?): ThingBuilderImpl = apply { this.name = name }
- override fun clearName(): ThingBuilderImpl = apply { name = null }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
-
- other as ThingBuilderImpl
- if (this.name != other.name) return false
- if (this.identifier != other.identifier) return false
- return true
- }
-}
-
-private class ThingImpl(override val identifier: String?, override val name: Name?) : Thing {
- override fun toBuilder(): Thing.Builder<*> =
- ThingBuilderImpl().setIdentifier(identifier).setName(name)
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is ThingImpl) return false
- if (this.name != other.name) return false
- if (this.identifier != other.identifier) return false
- return true
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/AppEntityListener.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/AppEntityListener.kt
deleted file mode 100644
index 10c014c..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/AppEntityListener.kt
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core
-
-import androidx.annotation.RestrictTo
-import androidx.concurrent.futures.await
-import com.google.common.util.concurrent.ListenableFuture
-
-/**
- * Handle grounding of ungrounded values.
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY)
-interface AppEntityListenerBase<T> {
- /**
- * Given a search criteria, looks up the inventory during runtime, renders the search result
- * within the app's own UI and then returns it to the Assistant so that the task can be kept in
- * sync with the app UI.
- *
- * @return a structured search result represented by [EntitySearchResult] for the given
- * [searchAction]
- */
- suspend fun lookupAndRender(searchAction: SearchAction<T>): EntitySearchResult<T> =
- lookupAndRenderAsync(searchAction).await()
-
- /**
- * Given a search criteria, looks up the inventory during runtime, renders the search result
- * within the app's own UI and then returns it to the Assistant so that the task can be kept in
- * sync with the app UI.
- *
- * @return a [ListenableFuture] of the structured search result represented by
- * [EntitySearchResult] for the given [searchAction]
- */
- fun lookupAndRenderAsync(
- searchAction: SearchAction<T>,
- ): ListenableFuture<EntitySearchResult<T>> {
- throw NotImplementedError()
- }
-}
-
-/**
- * Similar to ValueListener, but also need to handle grounding of ungrounded values.
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY)
-interface AppEntityListener<T> : ValueListener<T>, AppEntityListenerBase<T>
-
-/**
- * Similar to ValueListener, but also need to handle grounding of ungrounded values.
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY)
-interface AppEntityListListener<T> : ValueListener<List<T>>, AppEntityListenerBase<T>
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/BaseExecutionSession.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/BaseExecutionSession.kt
deleted file mode 100644
index e42fe2b..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/BaseExecutionSession.kt
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core
-
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures
-import androidx.concurrent.futures.await
-import com.google.common.util.concurrent.ListenableFuture
-
-/** Base interface for ExecutionSession of all verticals. */
-interface BaseExecutionSession<ArgumentsT, OutputT> {
- /**
- * Implement any initialization logic.
- *
- * This method is called once, before any other listeners are invoked.
- */
- fun onCreate(sessionConfig: SessionConfig) {}
-
- /**
- * Called when all arguments are finalized.
- *
- * @param arguments the [ArgumentsT] instance containing data for fulfillment.
- * @return an [ExecutionResult] instance.
- */
- suspend fun onExecute(arguments: ArgumentsT): ExecutionResult<OutputT> {
- return onExecuteAsync(arguments).await()
- }
-
- /**
- * Called when all arguments are finalized.
- *
- * @param arguments the Argument instance containing data for fulfillment.
- * @return a [ListenableFuture] containing an [ExecutionResult] instance.
- */
- fun onExecuteAsync(arguments: ArgumentsT): ListenableFuture<ExecutionResult<OutputT>> {
- return Futures.immediateFuture(ExecutionResult.Builder<OutputT>().build())
- }
-
- /** Implement any cleanup logic. This method is called some time after the session finishes. */
- fun onDestroy() {}
-}
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
deleted file mode 100644
index 77af3e3..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/Capability.kt
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core
-
-import android.annotation.SuppressLint
-import androidx.annotation.RestrictTo
-import androidx.appactions.interaction.capabilities.core.impl.CapabilitySession
-import androidx.appactions.interaction.capabilities.core.impl.SingleTurnCapabilityImpl
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpec
-import androidx.appactions.interaction.capabilities.core.impl.spec.BoundProperty
-import androidx.appactions.interaction.capabilities.core.impl.task.EmptyTaskUpdater
-import androidx.appactions.interaction.capabilities.core.impl.task.SessionBridge
-import androidx.appactions.interaction.capabilities.core.impl.task.TaskCapabilityImpl
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-
-/**
- * A Capability represents a supported [built-in intent](https://developer.android.com/reference/app-actions/built-in-intents).
- * [Register](https://developer.android.com/guide/app-actions/intents) capabilities within an app to declare support for the capability.
- */
-abstract class Capability internal constructor(
- /** Returns the unique Id of this capability declaration. */
- open val id: String
-) {
-
- /**
- * Returns an app action proto describing how to fulfill this capability.
- */
- @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- abstract val appAction: AppAction
-
- /**
- * Create a new capability session. The capability library doesn't maintain registry of
- * capabilities, so it's not going to assign any session id.
- */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- abstract fun createSession(
- sessionId: String,
- hostProperties: HostProperties
- ): CapabilitySession
-
- /**
- * An abstract Builder class for Capability.
- */
- @SuppressLint("StaticFinalBuilder")
- abstract class Builder<
- BuilderT :
- Builder<
- BuilderT,
- ArgumentsT,
- OutputT,
- ConfirmationT,
- ExecutionSessionT
- >,
- ArgumentsT,
- OutputT,
- ConfirmationT,
- ExecutionSessionT : BaseExecutionSession<ArgumentsT, OutputT>
- > private constructor() {
- private var id: String? = null
- private val boundPropertyMap = mutableMapOf<String, BoundProperty<*>>()
- private var executionCallback: ExecutionCallback<ArgumentsT, OutputT>? = null
- private var sessionFactory:
- ((hostProperties: HostProperties?) -> ExecutionSessionT)? = null
- private var actionSpec: ActionSpec<ArgumentsT, OutputT>? = null
-
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- constructor(actionSpec: ActionSpec<ArgumentsT, OutputT>) : this() {
- this.actionSpec = actionSpec
- }
-
- /**
- * The SessionBridge object, which is used to normalize Session instances to TaskHandler.
- * see SessionBridge documentation for more information.
- */
- @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- protected open val sessionBridge: SessionBridge<
- ExecutionSessionT,
- ArgumentsT,
- ConfirmationT
- >? = null
-
- @Suppress("UNCHECKED_CAST")
- private fun asBuilder(): BuilderT {
- return this as BuilderT
- }
-
- /**
- * Sets the Id of the capability being built. The Id should be a non-null string that is
- * unique among all Capability, and should not change during/across activity lifecycles.
- */
- fun setId(id: String): BuilderT = asBuilder().apply {
- this.id = id
- }
-
- /**
- * Sets a single slot property for this capability, and associated entity converter. */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- protected fun <T> setProperty(
- slotName: String,
- property: Property<T>,
- entityConverter: EntityConverter<T>,
- ) = asBuilder().apply {
- this.boundPropertyMap[slotName] = BoundProperty(slotName, property, entityConverter)
- }
-
- /**
- * Sets the ExecutionCallback for this capability.
- *
- * [setExecutionSessionFactory] and [setExecutionCallback] are mutually exclusive, so
- * calling one will nullify the other.
- *
- * This method accepts a coroutine-based ExecutionCallback instance. There is also an
- * overload which accepts the [ExecutionCallbackAsync] instead.
- */
- @SuppressLint("MissingGetterMatchingBuilder")
- fun setExecutionCallback(executionCallback: ExecutionCallback<ArgumentsT, OutputT>) =
- asBuilder().apply {
- this.executionCallback = executionCallback
- }
-
- /**
- * Sets the [ExecutionCallbackAsync] for this capability.
- *
- * [setExecutionSessionFactory] and [setExecutionCallback] are mutually exclusive, so
- * calling one will nullify the other.
- *
- * This method accepts the [ExecutionCallbackAsync] interface, which is the Future version
- * of [ExecutionCallback]
- */
- @SuppressLint("MissingGetterMatchingBuilder")
- fun setExecutionCallback(
- executionCallbackAsync: ExecutionCallbackAsync<ArgumentsT, OutputT>
- ) = asBuilder().apply {
- this.executionCallback = executionCallbackAsync.toExecutionCallback()
- }
-
- /**
- * Sets the lambda used to create [ExecutionSessionT] instances for this
- * capability.
- *
- * [setExecutionSessionFactory] and [setExecutionCallback] are mutually exclusive, so
- * calling one will nullify the other.
- */
- @SuppressLint("MissingGetterMatchingBuilder")
- protected open fun setExecutionSessionFactory(
- sessionFactory: (hostProperties: HostProperties?) -> ExecutionSessionT
- ): BuilderT = asBuilder().apply {
- this.sessionFactory = sessionFactory
- }
-
- /**
- * Builds and returns this Capability.
- * [setId] must be called before [build].
- * either [setExecutionCabllack] or [setSessionFactory] must be called before [build].
- * child classes may enforce additional required properties to be set before [build].
- * An [IllegalStateException] will be thrown if above requirements are not met.
- */
- open fun build(): Capability {
- val checkedId = id ?: throw IllegalStateException("setId must be called before build")
- val boundProperties = boundPropertyMap.values.toList()
- if (executionCallback != null) {
- return SingleTurnCapabilityImpl(
- checkedId,
- actionSpec!!,
- boundProperties,
- executionCallback!!
- )
- } else if (sessionFactory != null) {
- return TaskCapabilityImpl(
- checkedId,
- actionSpec!!,
- boundProperties,
- sessionFactory!!,
- sessionBridge!!,
- ::EmptyTaskUpdater
- )
- } else {
- throw IllegalStateException(
- """either setExecutionCallback or setExecutionSessionFactory must be called
- before capability '$id' can be built"""
- )
- }
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/CapabilityFactory.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/CapabilityFactory.kt
deleted file mode 100644
index 3c2ec4b..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/CapabilityFactory.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core
-
-import androidx.annotation.RestrictTo
-
-/**
- * Annotates a class for creating some Capability.
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-@Target(AnnotationTarget.CLASS)
-@Retention(AnnotationRetention.RUNTIME)
-annotation class CapabilityFactory(val name: String)
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ConfirmationOutput.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ConfirmationOutput.kt
deleted file mode 100644
index 2093d6d..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ConfirmationOutput.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core
-
-import androidx.annotation.RestrictTo
-import java.util.Objects
-
-/**
- * Class that represents the response after all slots are filled and accepted and the task is ready
- * to enter the confirmation turn.
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-class ConfirmationOutput<ConfirmationT> internal constructor(val confirmation: ConfirmationT?) {
- override fun toString() =
- "ConfirmationOutput(confirmation=$confirmation)"
-
- override fun equals(other: Any?): Boolean {
- return other is ConfirmationOutput<*> && confirmation == other.confirmation
- }
-
- override fun hashCode() = Objects.hash(confirmation)
-
- /**
- * Builder for ConfirmationOutput.
- */
- class Builder<ConfirmationT> {
- private var confirmation: ConfirmationT? = null
-
- /** Sets the confirmation output. */
- fun setConfirmation(confirmation: ConfirmationT) = apply {
- this.confirmation = confirmation
- }
-
- /** Builds and returns the ConfirmationOutput instance. */
- fun build() = ConfirmationOutput(confirmation)
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/EntitySearchResult.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/EntitySearchResult.kt
deleted file mode 100644
index 7ea8dea..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/EntitySearchResult.kt
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core
-
-import androidx.annotation.RestrictTo
-import java.util.Objects
-
-/**
- * Represents results from searching for ungrounded value(s).
- *
- * Returning exactly 1 result means the value will be immediately accepted by the session.
- * Returning multiple values will leave the argument in disambiguation state, and Assistant should
- * ask for clarification from the user.
- *
- * @property possibleValues The possible values for grounding.
- *
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-class EntitySearchResult<V> internal constructor(
- val possibleValues: List<V>,
-) {
- override fun toString() =
- "EntitySearchResult(possibleValues=$possibleValues)"
-
- override fun equals(other: Any?): Boolean {
- return other is EntitySearchResult<*> && possibleValues == other.possibleValues
- }
-
- override fun hashCode() = Objects.hash(possibleValues)
-
- /**
- * Builder for the EntitySearchResult.
- */
- class Builder<V> {
- private val possibleValues = mutableListOf<V>()
-
- /** Sets the search result values. */
- fun setPossibleValues(possibleValues: List<V>) = apply {
- this.possibleValues.clear()
- this.possibleValues.addAll(possibleValues)
- }
-
- /**
- * Add one or more search result values.
- */
- fun addPossibleValue(vararg value: V) = apply {
- possibleValues.addAll(value)
- }
-
- fun build() = EntitySearchResult(possibleValues.toList())
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ExecutionCallback.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ExecutionCallback.kt
deleted file mode 100644
index e003734..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ExecutionCallback.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core
-
-import androidx.annotation.RestrictTo
-import androidx.concurrent.futures.await
-
-/**
- * An interface for executing the action.
- *
- * Actions are executed asynchronously using Kotlin coroutines.
- * For a Future-based solution, see ExecutionCallbackAsync.
- */
-fun interface ExecutionCallback<ArgumentsT, OutputT> {
- @get:RestrictTo(RestrictTo.Scope.LIBRARY)
- val uiHandle: Any
- get() = this
-
- /**
- * Calls to execute the action.
- *
- * @param arguments the argument for this action.
- * @return the ExecutionResult
- */
- suspend fun onExecute(arguments: ArgumentsT): ExecutionResult<OutputT>
-}
-
-internal fun <ArgumentsT, OutputT>
- ExecutionCallbackAsync<ArgumentsT, OutputT>.toExecutionCallback():
- ExecutionCallback<ArgumentsT, OutputT> = object : ExecutionCallback<ArgumentsT, OutputT> {
- override val uiHandle = this@toExecutionCallback
- override suspend fun onExecute(arguments: ArgumentsT): ExecutionResult<OutputT> =
- [email protected](arguments).await()
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ExecutionCallbackAsync.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ExecutionCallbackAsync.kt
deleted file mode 100644
index d53a108..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ExecutionCallbackAsync.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core
-
-import com.google.common.util.concurrent.ListenableFuture
-
-/** An ListenableFuture-based interface to handle executing an action. */
-fun interface ExecutionCallbackAsync<ArgumentsT, OutputT> {
- /**
- * Calls to execute the action.
- *
- * @param arguments the argument for this action.
- * @return A ListenableFuture containing the ExecutionResult
- */
- @Suppress("AsyncSuffixFuture")
- fun onExecute(arguments: ArgumentsT): ListenableFuture<ExecutionResult<OutputT>>
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ExecutionResult.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ExecutionResult.kt
deleted file mode 100644
index 6ed9819..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ExecutionResult.kt
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core
-
-import androidx.annotation.RestrictTo
-import java.util.Objects
-/**
- * A class that represents the response after a [Capability] fulfills an action.
- * An [ExecutionResult] may contain an [output] based on the capability associated
- * with the execution.
- * For example, an execution associated with the CreateCalendarEvent capability would
- * produce an ExecutionResult containing a CreateCalendarEvent.Output, the created event.
- *
- * If [output] is null, the assistant client will know the execution has completed, but
- * may be unable to provide a natural language response or support confirmation from the user.
- *
- * @property output the object created by executing the capability.
- */
-class ExecutionResult<OutputT> internal constructor(
- internal val shouldStartDictation: Boolean,
- val output: OutputT?,
-) {
- override fun toString() =
- "ExecutionResult(shouldStartDictation=$shouldStartDictation,output=$output)"
-
- override fun equals(other: Any?): Boolean {
- return other is ExecutionResult<*> && output == other.output
- }
-
- override fun hashCode() = Objects.hash(shouldStartDictation, output)
-
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- fun shouldStartDictation(): Boolean = shouldStartDictation
-
- /**
- * Builder for ExecutionResult.
- */
- class Builder<OutputT> {
- private var shouldStartDictation: Boolean = false
- private var output: OutputT? = null
-
- /**
- * If true, start dictation after returning the result of executing the [Capability].
- * Defaults to false.
- */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- fun setShouldStartDictation(startDictation: Boolean) = apply {
- this.shouldStartDictation = startDictation
- }
-
- /** Sets the execution output. */
- fun setOutput(output: OutputT) = apply {
- this.output = output
- }
-
- /** Builds and returns the ExecutionResult instance. */
- fun build() = ExecutionResult(shouldStartDictation, output)
- }
-}
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
deleted file mode 100644
index b3cdb06..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/HostProperties.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core
-
-import android.util.SizeF
-import androidx.annotation.RestrictTo
-import java.util.Objects
-
-/**
- * HostProperties contains information about the connected assistant's environment which can be
- * used to customize behaviour for the different assistant contexts.
- *
- * @property maxHostSizeDp the dimensions of the host area where the app content will be displayed.
- */
-class HostProperties internal constructor(val maxHostSizeDp: SizeF) {
- override fun toString() =
- "HostProperties(maxHostSizeDp=$maxHostSizeDp)"
-
- override fun equals(other: Any?): Boolean {
- return other is HostProperties && maxHostSizeDp == other.maxHostSizeDp
- }
-
- override fun hashCode() = Objects.hash(maxHostSizeDp)
-
- /**
- * Builder class for [HostProperties].
- */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- class Builder {
- private var maxHostSizeDp: SizeF? = null
-
- /** Sets the dimensions of the host area where the app content will be displayed in dp. */
- fun setMaxHostSizeDp(maxHostSizeDp: SizeF) = apply {
- this.maxHostSizeDp = maxHostSizeDp
- }
-
- /**
- * Builds and returns the HostProperties instance.
- */
- fun build() = HostProperties(
- requireNotNull(maxHostSizeDp) { "maxHostSizeDp must be set." },
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/InventoryListener.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/InventoryListener.kt
deleted file mode 100644
index 9415c17..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/InventoryListener.kt
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core
-
-import androidx.annotation.RestrictTo
-import androidx.concurrent.futures.await
-import com.google.common.util.concurrent.ListenableFuture
-
-/**
- * Handles entity rendering.
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY)
-interface InventoryListenerBase {
- /**
- * Renders the provided entities in the app UI for disambiguation.
- *
- * The app should not modify the entity contents or their orders during the rendering.
- * Otherwise, the Assistant task will be out of sync with the app UI.
- */
- suspend fun renderChoices(entityIDs: List<String>) {
- renderChoicesAsync(entityIDs).await()
- }
-
- /**
- * Renders the provided entities in the app UI for disambiguation.
- *
- * The app should not modify the entity contents or their orders during the rendering.
- * Otherwise, the Assistant task will be out of sync with the app UI.
- *
- * @return a [ListenableFuture] of nothing, which only indicates when the rendering finishes.
- */
- fun renderChoicesAsync(entityIDs: List<String>): ListenableFuture<Void> {
- throw NotImplementedError()
- }
-}
-
-/**
- * Similar to ValueListener, but also need to handle entity rendering.
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY)
-interface InventoryListener<T> : ValueListener<T>, InventoryListenerBase
-
-/**
- * Similar to ValueListener, but also need to handle entity rendering.
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY)
-interface InventoryListListener<T> : ValueListener<List<T>>, InventoryListenerBase
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/LibInfo.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/LibInfo.kt
deleted file mode 100644
index 52b238a..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/LibInfo.kt
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core
-
-import android.content.Context
-import androidx.annotation.RestrictTo
-import java.util.Objects.requireNonNull
-import java.util.regex.Pattern
-
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-data class LibInfo(val context: Context) {
- fun getVersion(): Version {
- return Version.parse(
- context.resources.getString(R.string.appactions_interaction_library_version)
- )
- }
-
- data class Version(
- val major: Int,
- val minor: Int,
- val patch: Int,
- val preReleaseId: String? = null,
- ) : Comparable<Version> {
-
- override fun compareTo(other: Version) = compareValuesBy(
- this, other,
- { it.major },
- { it.minor },
- { it.patch },
- { it.preReleaseId == null }, // False (no preReleaseId) sorts above true (has preReleaseId)
- { it.preReleaseId } // gradle uses lexicographic ordering
- )
-
- override fun toString(): String {
- return if (preReleaseId != null) {
- "$major.$minor.$patch-$preReleaseId"
- } else "$major.$minor.$patch"
- }
-
- companion object {
- private val VERSION_REGEX = Pattern.compile("^(\\d+)\\.(\\d+)\\.(\\d+)(-.+)?$")
-
- fun parse(versionString: String): Version {
- val matcher = VERSION_REGEX.matcher(versionString)
- if (!matcher.matches()) {
- throw IllegalArgumentException("Can not parse version: $versionString")
- }
- return Version(
- Integer.parseInt(requireNonNull(matcher.group(1))),
- Integer.parseInt(requireNonNull(matcher.group(2))),
- Integer.parseInt(requireNonNull(matcher.group(3))),
- if (matcher.groupCount() == 4) requireNonNull(matcher.group(4)).drop(1) else null
- )
- }
- }
- }
-}
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
deleted file mode 100644
index cd3171d..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/SearchAction.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core
-
-import androidx.annotation.RestrictTo
-
-/**
- * A request to perform a search for in-app entities.
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-class SearchAction<FilterT> internal constructor(
- val query: String?,
- val filter: FilterT?
-) {
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is SearchAction<*>) return false
- if (this.query != other.query) return false
- if (this.filter != other.filter) return false
- 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
- private var filter: FilterT? = null
-
- /** Sets the query keywords to search by. */
- fun setQuery(query: String) = apply {
- this.query = query
- }
-
- /** Sets the entity filter object to search by. */
- fun setFilter(filter: FilterT) = apply {
- this.filter = filter
- }
-
- /** Builds and returns a [SearchAction]. */
- fun build() = SearchAction(query, filter)
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/SessionConfig.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/SessionConfig.kt
deleted file mode 100644
index 904adc5..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/SessionConfig.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core
-
-/**
- * [SessionConfig] contains data passed to [BaseExecutionSession.onCreate].
- */
-class SessionConfig internal constructor() {
- override fun toString() =
- "SessionConfig()"
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ValidationResult.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ValidationResult.kt
deleted file mode 100644
index 0cee27d..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ValidationResult.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core
-
-import androidx.annotation.RestrictTo
-import java.util.Objects
-
-/** Result from validating a single argument value. */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-class ValidationResult internal constructor(
- val kind: Kind,
-) {
- override fun toString() =
- "ValidationResult(kind=$kind)"
-
- override fun equals(other: Any?): Boolean {
- return other is ValidationResult && kind == other.kind
- }
-
- override fun hashCode() = Objects.hash(kind)
-
- /** The state of the argument value after performing validation. */
- enum class Kind {
- ACCEPTED,
- REJECTED,
- }
-
- companion object {
- /** Creates a new ACCEPTED ValidationResult. */
- @JvmStatic
- fun newAccepted() = ValidationResult(Kind.ACCEPTED)
-
- /** Creates a new REJECTED ValidationResult. */
- @JvmStatic
- fun newRejected() = ValidationResult(Kind.REJECTED)
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ValueListener.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ValueListener.kt
deleted file mode 100644
index cfb4269..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/ValueListener.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core
-
-import androidx.annotation.RestrictTo
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures
-import androidx.concurrent.futures.await
-import com.google.common.util.concurrent.ListenableFuture
-
-/** Provides a mechanism for the app to listen to argument updates from Assistant. */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-interface ValueListener<T> {
- /**
- * Invoked when Assistant reports that an argument value has changed. This method should be
- * idempotent, as it may be called multiple times with the same input value, not only on the
- * initial value change.
- *
- * <p>This method should:
- * <ul>
- * <li>1. validate the given argument value(s).
- * <li>2. If the given values are valid, update app UI state if applicable.
- * </ul>
- *
- * @return the [ValidationResult].
- */
- suspend fun onReceived(value: T): ValidationResult = onReceivedAsync(value).await()
-
- /**
- * Invoked when Assistant reports that an argument value has changed. This method should be
- * idempotent, as it may be called multiple times with the same input value, not only on the
- * initial value change.
- *
- * <p>This method should:
- * <ul>
- * <li>1. validate the given argument value(s).
- * <li>2. If the given values are valid, update app UI state if applicable.
- * </ul>
- *
- * @return a [ListenableFuture] containing the [ValidationResult].
- */
- fun onReceivedAsync(value: T): ListenableFuture<ValidationResult> =
- Futures.immediateFuture(ValidationResult.newAccepted())
-}
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
deleted file mode 100644
index d20b4e9..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupCandidate.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.entity
-
-/** The candidate of the lookup results, including the entity object. */
-class EntityLookupCandidate<T> internal constructor(
- val candidate: T
-) {
-
- override fun toString(): String {
- return "EntityLookupCandidate(candidate=$candidate)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as EntityLookupCandidate<*>
-
- if (candidate != other.candidate) return false
- return true
- }
-
- override fun hashCode(): Int {
- return candidate.hashCode()
- }
-
- /** Builder class for [EntityLookupCandidate]. */
- class Builder<T> {
- private var candidate: T? = null
- fun setCandidate(candidate: T): Builder<T> = apply { this.candidate = candidate }
- fun build(): EntityLookupCandidate<T> = EntityLookupCandidate(
- requireNotNull(candidate) { "Entity lookup candidate must be set." })
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupRequest.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupRequest.kt
deleted file mode 100644
index 34c3cc0..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupRequest.kt
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.entity
-
-import androidx.appactions.interaction.capabilities.core.SearchAction
-import androidx.appactions.interaction.protobuf.ByteString
-
-/** The class for the request of the entity lookup. */
-class EntityLookupRequest<T> internal constructor(
- val searchAction: SearchAction<T>,
- val pageSize: Int?,
- val pageToken: ByteString?,
-) {
- override fun toString(): String {
- return "EntityLookupRequest(" +
- "searchAction=$searchAction, " +
- "pageSize=$pageSize, " +
- "pageToken=$pageToken)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as EntityLookupRequest<*>
-
- if (searchAction != other.searchAction) return false
- if (pageSize != other.pageSize) return false
- if (pageToken != other.pageToken) return false
- return true
- }
-
- override fun hashCode(): Int {
- var result = searchAction.hashCode()
- result = 31 * result + pageSize.hashCode()
- result = 31 * result + pageToken.hashCode()
- return result
- }
-
- /** Builder class for EntityLookupRequest. */
- class Builder<T> {
- private var searchAction: SearchAction<T>? = null
- private var pageSize: Int? = null
- private var pageToken: ByteString? = null
-
- fun setSearchAction(searchAction: SearchAction<T>) =
- apply { this.searchAction = searchAction }
-
- fun setPageSize(pageSize: Int) = apply { this.pageSize = pageSize }
-
- fun setPageToken(pageToken: ByteString) = apply { this.pageToken = pageToken }
-
- fun build() = EntityLookupRequest(
- requireNotNull(searchAction) { "Search action must be set." },
- pageSize,
- pageToken
- )
- }
-}
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
deleted file mode 100644
index 1f3f166..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupResponse.kt
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.entity
-
-import androidx.annotation.IntDef
-import androidx.appactions.interaction.protobuf.ByteString
-
-/** The class for the response of the entity lookup. */
-class EntityLookupResponse<T> internal constructor(
- val candidateList: List<EntityLookupCandidate<T>>,
- @property:EntityLookupStatus val status: Int,
- val nextPageToken: ByteString?,
-) {
- override fun toString(): String {
- return "EntityLookupResponse(" +
- "candidateList=$candidateList, " +
- "status=$status, " +
- "nextPageToken=$nextPageToken)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as EntityLookupResponse<*>
-
- if (candidateList != other.candidateList) return false
- if (status != other.status) return false
- if (nextPageToken != other.nextPageToken) return false
- return true
- }
-
- override fun hashCode(): Int {
- var result = candidateList.hashCode()
- result = 31 * result + status.hashCode()
- result = 31 * result + nextPageToken.hashCode()
- return result
- }
-
- /** Builder class for [EntityLookupResponse]. */
- class Builder<T> {
- private var candidateList: List<EntityLookupCandidate<T>> = listOf()
-
- @property:EntityLookupStatus
- private var status: Int = SUCCESS
- private var nextPageToken: ByteString? = null
- fun setCandidateList(candidateList: List<EntityLookupCandidate<T>>): Builder<T> = apply {
- this.candidateList = candidateList
- }
-
- fun setStatus(status: @EntityLookupStatus Int): Builder<T> =
- apply {
- this.status = status
- }
-
- fun setNextPageToken(nextPageToken: ByteString): Builder<T> = apply {
- this.nextPageToken = nextPageToken
- }
-
- fun build() = EntityLookupResponse(candidateList, status, nextPageToken)
- }
-
- companion object {
-
- const val SUCCESS: Int = 0
- const val CANCELED: Int = 1
- const val INVALID_PAGE_TOKEN: Int = 2
- const val TIMEOUT: Int = 3
- const val UNKNOWN_ERROR: Int = 4
- }
-
- // IntDef enum for lookup status.
- @Target(
- AnnotationTarget.PROPERTY,
- AnnotationTarget.LOCAL_VARIABLE,
- AnnotationTarget.VALUE_PARAMETER,
- AnnotationTarget.TYPE
- )
- @Retention(AnnotationRetention.SOURCE)
- @IntDef(
- value = [
- SUCCESS,
- CANCELED,
- INVALID_PAGE_TOKEN,
- TIMEOUT,
- UNKNOWN_ERROR,
- ]
- )
- annotation class EntityLookupStatus
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityProvider.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityProvider.kt
deleted file mode 100644
index 564e051..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityProvider.kt
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.entity
-
-import androidx.annotation.RestrictTo
-import androidx.appactions.builtintypes.types.Thing
-import androidx.appactions.interaction.capabilities.core.SearchAction
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.SearchActionConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException
-import androidx.appactions.interaction.proto.GroundingRequest
-import androidx.appactions.interaction.proto.GroundingResponse
-import androidx.concurrent.futures.await
-import com.google.common.util.concurrent.ListenableFuture
-
-/**
- * EntityProvider could provide candidates for assistant's search actions.
- *
- * <p>Use abstract classes within the library to create instances of the {@link EntityProvider}.
- */
-abstract class EntityProvider<T : Thing>
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-constructor(
- private val typeSpec: TypeSpec<T>
-) {
- private val entityConverter = EntityConverter.of(typeSpec)
-
- /**
- * Unique identifier for this EntityFilter. Must match the shortcuts.xml declaration, which
- * allows different filters to be assigned to types on a per-BII basis.
- */
- abstract val id: String
-
- /**
- * Executes the entity lookup.
- *
- * @param request The request includes e.g. entity, search metadata, etc.
- * @return an [EntityLookupResponse] instance
- * * TODO(dennistwo) lookup request should contain a different generic type (filter type)
- */
- open suspend fun lookup(request: EntityLookupRequest<T>): EntityLookupResponse<T> {
- return lookupAsync(request).await()
- }
-
- /**
- * Executes the entity lookup.
- *
- * @param request The request includes e.g. entity, search metadata, etc.
- * @return a [ListenableFuture] containing a default [EntityLookupResponse] instance
- */
- open fun lookupAsync(request: EntityLookupRequest<T>):
- ListenableFuture<EntityLookupResponse<T>> {
- return Futures.immediateFuture(EntityLookupResponse.Builder<T>().build())
- }
-
- /**
- * Internal method to lookup untyped entity, which will be used by service library to handle
- * {@link GroundingRequest}.
- */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- suspend fun lookupInternal(request: GroundingRequest): GroundingResponse {
- val converter: SearchActionConverter<T> =
- TypeConverters.createSearchActionConverter(this.typeSpec)
- val searchAction: SearchAction<T> =
- try {
- converter.toSearchAction(request.request.searchAction)
- } catch (e: StructConversionException) {
- return createResponse(GroundingResponse.Status.INVALID_ENTITY_ARGUMENT)
- }
- val lookupRequest =
- EntityLookupRequest.Builder<T>()
- .setSearchAction(searchAction)
- .setPageSize(request.request.pageSize)
- .setPageToken(request.request.pageToken)
- .build()
- val response = lookup(lookupRequest)
- return when (response.status) {
- EntityLookupResponse.SUCCESS -> createResponse(response)
- else -> createResponse(convertStatus(response.status))
- }
- }
-
- private fun createResponse(status: GroundingResponse.Status): GroundingResponse {
- return GroundingResponse.newBuilder()
- .setResponse(GroundingResponse.Response.newBuilder().setStatus(status))
- .build()
- }
-
- private fun createResponse(response: EntityLookupResponse<T>): GroundingResponse {
- val builder =
- GroundingResponse.Response.newBuilder().setStatus(GroundingResponse.Status.SUCCESS)
- for (candidate in response.candidateList) {
- builder.addCandidates(
- GroundingResponse.Candidate.newBuilder()
- .setGroundedEntity(
- entityConverter.convert(candidate.candidate)
- )
- .build()
- )
- }
- return GroundingResponse.newBuilder().setResponse(builder.build()).build()
- }
-
- private fun convertStatus(
- @EntityLookupResponse.EntityLookupStatus status: Int
- ): GroundingResponse.Status {
- return when (status) {
- EntityLookupResponse.CANCELED -> GroundingResponse.Status.CANCELED
- EntityLookupResponse.INVALID_PAGE_TOKEN -> GroundingResponse.Status.INVALID_PAGE_TOKEN
- EntityLookupResponse.TIMEOUT -> GroundingResponse.Status.TIMEOUT
- else -> GroundingResponse.Status.DEFAULT_UNKNOWN
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/package-info.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/package-info.java
deleted file mode 100644
index 4f695da..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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.
- */
-
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-package androidx.appactions.interaction.capabilities.core.entity;
-
-import androidx.annotation.RestrictTo;
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/ArgumentsWrapper.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/ArgumentsWrapper.kt
deleted file mode 100644
index ae2bc6e..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/ArgumentsWrapper.kt
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl
-
-import androidx.annotation.RestrictTo
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.FulfillmentValue
-
-/**
- * Represents Fulfillment request sent from assistant, including arguments.
- *
- * @param paramValues A map of BII parameter names to a task param value, where each
- * `FulfillmentValue` can have a value and `DisambigData` sent from Assistant.
- * @param requestMetadata Metadata from the FulfillmentRequest on the current Assistant turn. This
- * field should be null for one-shot capabilities.
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-data class ArgumentsWrapper
-internal constructor(
- val paramValues: Map<String, List<FulfillmentValue>>,
- val requestMetadata: RequestMetadata?,
-) {
- companion object {
- /**
- * Creates an instance of ArgumentsWrapper based on the Fulfillment send from Assistant.
- *
- * @param fulfillment for a single BII sent from Assistant.
- */
- @JvmStatic
- fun create(fulfillment: Fulfillment): ArgumentsWrapper {
- return ArgumentsWrapper(
- convertToArgumentMap(fulfillment),
- createRequestMetadata(fulfillment),
- )
- }
-
- internal fun createRequestMetadata(fulfillment: Fulfillment): RequestMetadata? {
- return if (
- fulfillment.type == Fulfillment.Type.UNKNOWN_TYPE ||
- fulfillment.type == Fulfillment.Type.UNRECOGNIZED
- ) {
- null
- } else {
- RequestMetadata(fulfillment.type, fulfillment.syncStatus)
- }
- }
-
- internal fun convertToArgumentMap(
- fulfillment: Fulfillment,
- ): Map<String, List<FulfillmentValue>> {
- val result = mutableMapOf<String, List<FulfillmentValue>>()
- for (fp in fulfillment.paramsList) {
- result[fp.name] = fp.fulfillmentValuesList
- }
- return result.toMap()
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/CallbackInternal.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/CallbackInternal.kt
deleted file mode 100644
index 3c204d3..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/CallbackInternal.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl
-
-import androidx.annotation.RestrictTo
-import androidx.appactions.interaction.proto.FulfillmentResponse
-
-/** An interface for receiving the result of action. */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-interface CallbackInternal {
- /** Invoke to set an action result upon success. */
- fun onSuccess(fulfillmentResponse: FulfillmentResponse)
-
- /** Invokes to set an error status for the action. */
- fun onError(errorStatus: ErrorStatusInternal)
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/CapabilitySession.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/CapabilitySession.kt
deleted file mode 100644
index 0f9640d..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/CapabilitySession.kt
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl
-
-import androidx.annotation.RestrictTo
-import androidx.appactions.interaction.proto.AppActionsContext.AppDialogState
-
-/**
- * Internal interface for a session, contains developer's Session instance
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-interface CapabilitySession {
- /** The id of this ActionCapabilitySession instance. */
- val sessionId: String
-
- /**
- * Executes the action and returns the result of execution.
- *
- * @param argumentsWrapper The arguments send from assistant to the activity.
- * @param callback The callback to receive app action result.
- */
- fun execute(
- argumentsWrapper: ArgumentsWrapper,
- callback: CallbackInternal
- )
-
- /**
- * Notify this session to stop processing and perform cleanup.
- */
- fun destroy()
-
- /**
- * Support for manual input. This method should be invoked by AppInteraction SDKs
- * (background/foreground), so the developers have a way to report state updates back to
- * Assistant.
- */
- fun setTouchEventCallback(callback: TouchEventCallback)
-
- /**
- * The current state of the multi-turn session including slot values and their statuses.
- */
- val state: AppDialogState?
-
- /** The current status of the CapabilitySession. */
- val isActive: Boolean
-
- /**
- * The developer-provided external object (either a BaseExecutionSession instance or an
- * ExecutionCallback instance).
- */
- val uiHandle: Any
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/ErrorStatusInternal.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/ErrorStatusInternal.java
deleted file mode 100644
index f7599df..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/ErrorStatusInternal.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl;
-
-import androidx.annotation.RestrictTo;
-
-/** A class to define exceptions that are reported from dialog capability API. */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-public enum ErrorStatusInternal {
- // Unexpected error which doesn't fall into any other error status.
- UNKNOWN_ERROR_STATUS,
- // Exception occurred which is internal to the capabilities library.
- INTERNAL,
- // The current capability session was cancelled, likely because a new request was sent to the
- // capability before the first had time to complete.
- CANCELED,
- // Developer provided callback has timed out.
- TIMEOUT,
- // Invalid data was sent to the capability. This could be a nonsensical request Type or
- // malformed arguments (e.g. wrong data format for a BII argument).
- INVALID_REQUEST,
- // An exception was thrown from a developer-provided callback.
- EXTERNAL_EXCEPTION,
- // Tried to send request to a particular capability session, but that session never started
- // or has already ended.
- SESSION_NOT_FOUND,
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/FulfillmentResult.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/FulfillmentResult.kt
deleted file mode 100644
index c73f75b..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/FulfillmentResult.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl
-
-import androidx.annotation.RestrictTo
-import androidx.appactions.interaction.proto.FulfillmentResponse
-
-/**
- * A union type between FulfillmentResponse proto and ErrorStatusInternal value
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-class FulfillmentResult(
- val fulfillmentResponse: FulfillmentResponse?,
- val errorStatus: ErrorStatusInternal?,
-) {
- constructor(
- fulfillmentResponse: FulfillmentResponse,
- ) : this(fulfillmentResponse, null)
-
- constructor(
- errorStatus: ErrorStatusInternal,
- ) : this(null, errorStatus)
-
- fun applyToCallback(callback: CallbackInternal) {
- if (fulfillmentResponse != null) {
- callback.onSuccess(fulfillmentResponse)
- } else {
- callback.onError(errorStatus!!)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/OperationType.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/OperationType.java
deleted file mode 100644
index b5e29d1..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/OperationType.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl;
-
-/**
- * Represents different operations possible in the Search/Update protocol.
- */
-public enum OperationType {
- /** Supports adding to a field of the target object, for example adding to a list. */
- ADD_OPERATION("AddOperation"),
- /**
- * Supports incrementing the value of a field of the target object, for example incrementing
- * the remaining duration of a timer.
- */
- INCREMENT_OPERATION("IncrementOperation"),
- /**
- * Supports overwriting a field of the target object, for example overwriting the name of an
- * alarm.
- */
- OVERWRITE_OPERATION("OverwriteOperation");
-
- private final String mOperationType;
-
- OperationType(String operationType) {
- this.mOperationType = operationType;
- }
-
- @Override
- public String toString() {
- return mOperationType;
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/RequestMetadata.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/RequestMetadata.kt
deleted file mode 100644
index f85735f..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/RequestMetadata.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl
-
-import androidx.annotation.RestrictTo
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment
-
-@RestrictTo(RestrictTo.Scope.LIBRARY)
-data class RequestMetadata internal constructor(
- val requestType: Fulfillment.Type,
- val syncStatus: Fulfillment.SyncStatus
-) {
- companion object {
- @JvmStatic
- fun create(requestType: Fulfillment.Type, syncStatus: Fulfillment.SyncStatus):
- RequestMetadata {
- return RequestMetadata(requestType, syncStatus)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityImpl.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityImpl.kt
deleted file mode 100644
index a939b03..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityImpl.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl
-
-import androidx.annotation.RestrictTo
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpec
-import androidx.appactions.interaction.capabilities.core.impl.spec.BoundProperty
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import kotlinx.coroutines.sync.Mutex
-
-@RestrictTo(RestrictTo.Scope.LIBRARY)
-internal class SingleTurnCapabilityImpl<
- ArgumentsT,
- OutputT,
- > constructor(
- id: String,
- val actionSpec: ActionSpec<ArgumentsT, OutputT>,
- val boundProperties: List<BoundProperty<*>>,
- val executionCallback: ExecutionCallback<ArgumentsT, OutputT>,
-) : Capability(id) {
- private val mutex = Mutex()
-
- override val appAction: AppAction get() = actionSpec.createAppAction(
- id,
- boundProperties,
- supportsPartialFulfillment = false
- )
-
- override fun createSession(
- sessionId: String,
- hostProperties: HostProperties,
- ): CapabilitySession {
- return SingleTurnCapabilitySession(
- sessionId,
- actionSpec,
- executionCallback,
- mutex,
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilitySession.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilitySession.kt
deleted file mode 100644
index 2d7fd2d..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilitySession.kt
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl
-
-import androidx.annotation.RestrictTo
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpec
-import androidx.appactions.interaction.capabilities.core.impl.utils.CapabilityLogger
-import androidx.appactions.interaction.capabilities.core.impl.utils.LoggerInternal
-import androidx.appactions.interaction.capabilities.core.impl.utils.handleExceptionFromRequestProcessing
-import androidx.appactions.interaction.capabilities.core.impl.utils.invokeExternalSuspendBlock
-import androidx.appactions.interaction.proto.AppActionsContext.AppDialogState
-import androidx.appactions.interaction.proto.FulfillmentResponse
-import androidx.appactions.interaction.proto.ParamValue
-import java.util.concurrent.atomic.AtomicBoolean
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.CoroutineStart
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.sync.Mutex
-
-/**
- * CapabilitySession implementation for executing single-turn fulfillment requests.
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY)
-internal class SingleTurnCapabilitySession<
- ArgumentsT,
- OutputT,
- >(
- override val sessionId: String,
- private val actionSpec: ActionSpec<ArgumentsT, OutputT>,
- private val executionCallback: ExecutionCallback<ArgumentsT, OutputT>,
- private val mutex: Mutex,
- private val scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
-) : CapabilitySession {
- private val isActiveAtomic = AtomicBoolean(true)
-
- override val state: AppDialogState? = null
- override val isActive: Boolean get() = isActiveAtomic.get()
-
- override val uiHandle: Any = executionCallback.uiHandle
-
- override fun destroy() {}
-
- // single-turn capability does not have touch events
- override fun setTouchEventCallback(callback: TouchEventCallback) {
- throw UnsupportedOperationException()
- }
-
- override fun execute(
- argumentsWrapper: ArgumentsWrapper,
- callback: CallbackInternal,
- ) {
- if (!isActiveAtomic.getAndSet(false)) {
- callback.onError(ErrorStatusInternal.SESSION_NOT_FOUND)
- return
- }
- val paramValuesMap: Map<String, List<ParamValue>> =
- argumentsWrapper.paramValues.mapValues { entry -> entry.value.mapNotNull { it.value } }
- val arguments = actionSpec.buildArguments(paramValuesMap)
- scope.launch(start = CoroutineStart.UNDISPATCHED) {
- try {
- mutex.lock(owner = this@SingleTurnCapabilitySession)
- UiHandleRegistry.registerUiHandle(uiHandle, sessionId)
- val output = invokeExternalSuspendBlock("onExecute") {
- executionCallback.onExecute(arguments)
- }
- callback.onSuccess(convertToFulfillmentResponse(output))
- } catch (t: Throwable) {
- LoggerInternal.log(
- CapabilityLogger.LogLevel.ERROR,
- LOG_TAG,
- "single-turn capability execution failed."
- )
- handleExceptionFromRequestProcessing(t, callback::onError)
- } finally {
- UiHandleRegistry.unregisterUiHandle(uiHandle)
- mutex.unlock(owner = this@SingleTurnCapabilitySession)
- }
- }
- }
-
- /** Converts typed {@link ExecutionResult} to {@link FulfillmentResponse} proto. */
- private fun convertToFulfillmentResponse(
- executionResult: ExecutionResult<OutputT>,
- ): FulfillmentResponse {
- val fulfillmentResponseBuilder =
- FulfillmentResponse.newBuilder().setStartDictation(executionResult.shouldStartDictation)
- executionResult.output?.let {
- fulfillmentResponseBuilder.setExecutionOutput(
- actionSpec.convertOutputToProto(it),
- )
- }
- return fulfillmentResponseBuilder.build()
- }
-
- companion object {
- private const val LOG_TAG = "SingleTurnCapability"
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/TouchEventCallback.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/TouchEventCallback.java
deleted file mode 100644
index 9c629bb..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/TouchEventCallback.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RestrictTo;
-import androidx.appactions.interaction.proto.FulfillmentResponse;
-import androidx.appactions.interaction.proto.TouchEventMetadata;
-
-/**
- * An internal interface to allow the AppInteraction SDKs to be notified of results from processing
- * touch events.
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-public interface TouchEventCallback {
-
- /** Results from a successful touch event invocation. */
- void onSuccess(
- @NonNull FulfillmentResponse fulfillmentResponse,
- @NonNull TouchEventMetadata touchEventMetadata);
-
- /** Results from an unsuccessful touch event invocation. */
- void onError(@NonNull ErrorStatusInternal errorStatus);
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/UiHandleRegistry.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/UiHandleRegistry.kt
deleted file mode 100644
index e3438d2..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/UiHandleRegistry.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl
-
-import androidx.annotation.GuardedBy
-import androidx.annotation.RestrictTo
-import java.util.IdentityHashMap
-
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-object UiHandleRegistry {
- private val lock = Any()
-
- @GuardedBy("lock")
- private val uiHandleToSessionId = IdentityHashMap<Any, String>()
-
- internal fun registerUiHandle(uiHandle: Any, sessionId: String) {
- synchronized(lock) {
- uiHandleToSessionId[uiHandle] = sessionId
- }
- }
-
- internal fun unregisterUiHandle(uiHandle: Any) {
- synchronized(lock) {
- uiHandleToSessionId.remove(uiHandle)
- }
- }
-
- fun getSessionIdFromUiHandle(uiHandle: Any): String? {
- synchronized(lock) {
- return uiHandleToSessionId[uiHandle]
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/concurrent/FutureCallback.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/concurrent/FutureCallback.kt
deleted file mode 100644
index bd063bb..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/concurrent/FutureCallback.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.concurrent
-
-/**
- * A FutureCallback that can be attached to a ListenableFuture with Futures#addCallback.
- */
-interface FutureCallback<V> {
- /** Called with the ListenableFuture's result if it completes successfully. */
- fun onSuccess(result: V)
-
- /** Called with the ListenableFuture's exception if it fails. */
- fun onFailure(t: Throwable)
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/concurrent/Futures.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/concurrent/Futures.kt
deleted file mode 100644
index 1830574..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/concurrent/Futures.kt
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.concurrent
-
-import androidx.concurrent.futures.CallbackToFutureAdapter
-import com.google.common.util.concurrent.ListenableFuture
-import java.util.concurrent.ExecutionException
-import java.util.concurrent.Executor
-import java.util.concurrent.Future
-import java.util.function.Function
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-
-/** Future/ListenableFuture related utility methods. */
-object Futures {
- /** Attach a FutureCallback to a ListenableFuture instance. */
- fun <V> addCallback(
- future: ListenableFuture<V>,
- callback: FutureCallback<in V>,
- executor: Executor
- ) {
- future.addListener(CallbackListener(future, callback), executor)
- }
-
- /**
- * Transforms an input ListenableFuture into a second ListenableFuture by applying a
- * transforming
- * function to the result of the input ListenableFuture.
- */
- fun <I, O> transform(
- input: ListenableFuture<I>,
- function: Function<I, O>,
- executor: Executor,
- tag: String?
- ): ListenableFuture<O> {
- return CallbackToFutureAdapter.getFuture {
- completer: CallbackToFutureAdapter.Completer<O> ->
- addCallback(input, transformFutureCallback(completer, function), executor)
- tag
- }
- }
-
- /**
- * Transforms an input ListenableFuture into a second ListenableFuture by applying an
- * asynchronous
- * transforming function to the result of the input ListenableFuture.
- */
- fun <I, O> transformAsync(
- input: ListenableFuture<I>,
- asyncFunction: Function<I, ListenableFuture<O>>,
- executor: Executor,
- tag: String
- ): ListenableFuture<O> {
- return CallbackToFutureAdapter.getFuture {
- completer: CallbackToFutureAdapter.Completer<O> ->
- addCallback(
- input, asyncTransformFutureCallback(completer, asyncFunction),
- executor
- )
- tag
- }
- }
-
- /** Returns a Future that is immediately complete with the given value. */
- fun <V> immediateFuture(value: V): ListenableFuture<V> {
- return CallbackToFutureAdapter.getFuture {
- completer: CallbackToFutureAdapter.Completer<V> ->
- completer.set(
- value
- )
- }
- }
-
- /** Returns a Future that is immediately complete with null value. */
- fun immediateVoidFuture(): ListenableFuture<Void> {
- return CallbackToFutureAdapter.getFuture {
- completer: CallbackToFutureAdapter.Completer<Void> ->
- completer.set(
- null
- )
- }
- }
-
- /** Returns a Future that is immediately complete with an exception. */
- fun <V> immediateFailedFuture(throwable: Throwable): ListenableFuture<V> {
- return CallbackToFutureAdapter.getFuture {
- completer: CallbackToFutureAdapter.Completer<V> ->
- completer.setException(
- throwable
- )
- }
- }
-
- /**
- * Returns a FutureCallback that transform the result in onSuccess, and then set the result in
- * completer.
- */
- fun <I, O> transformFutureCallback(
- completer: CallbackToFutureAdapter.Completer<O>,
- function: Function<I, O>
- ): FutureCallback<I> {
- return object : FutureCallback<I> {
- override fun onSuccess(result: I) {
- try {
- completer.set(function.apply(result))
- } catch (t: Throwable) {
- if (t is InterruptedException) {
- Thread.currentThread().interrupt()
- }
- completer.setException(t)
- }
- }
-
- override fun onFailure(t: Throwable) {
- completer.setException(t)
- }
- }
- }
-
- /** Returns a FutureCallback that asynchronously transform the result. */
- private fun <I, O> asyncTransformFutureCallback(
- completer: CallbackToFutureAdapter.Completer<O>,
- asyncFunction: Function<I, ListenableFuture<O>>
- ): FutureCallback<I> {
- return object : FutureCallback<I> {
- override fun onSuccess(result: I) {
- try {
- addCallback(
- asyncFunction.apply(result),
- transformFutureCallback(completer, Function.identity())
- ) { obj: Runnable -> obj.run() }
- } catch (t: Throwable) {
- if (t is InterruptedException) {
- Thread.currentThread().interrupt()
- }
- completer.setException(t)
- }
- }
-
- override fun onFailure(t: Throwable) {
- completer.setException(t)
- }
- }
- }
-
- @Throws(ExecutionException::class)
- fun <V> getDone(future: Future<V>): V {
- if (!future.isDone) {
- throw IllegalStateException("future is expected to be done already.")
- }
- var interrupted = false
- try {
- while (true) {
- interrupted = try {
- return future.get()
- } catch (e: InterruptedException) {
- true
- }
- }
- } finally {
- if (interrupted) {
- Thread.currentThread().interrupt()
- }
- }
- }
-
- private class CallbackListener<V> internal constructor(
- val mFuture: Future<V>,
- val mCallback: FutureCallback<in V>
- ) : Runnable {
- override fun run() {
- val value: V
- value = try {
- getDone(mFuture)
- } catch (e: ExecutionException) {
- val cause = e.cause
- mCallback.onFailure(cause ?: e)
- return
- } catch (e: RuntimeException) {
- mCallback.onFailure(e)
- return
- } catch (e: Error) {
- mCallback.onFailure(e)
- return
- }
- mCallback.onSuccess(value)
- }
- }
-}
-
-fun <T> convertToListenableFuture(
- tag: String,
- block: suspend CoroutineScope.() -> T,
-): ListenableFuture<T> {
- return CallbackToFutureAdapter.getFuture { completer ->
- val job = CoroutineScope(Dispatchers.Unconfined).launch {
- try {
- completer.set(block())
- } catch (t: Throwable) {
- completer.setException(t)
- }
- }
- completer.addCancellationListener(
- { job.cancel() },
- Runnable::run,
- )
- "ListenableFutureHelper#convertToListenableFuture for '$tag'"
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/CheckedInterfaces.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/CheckedInterfaces.java
deleted file mode 100644
index eba3f11..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/CheckedInterfaces.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.converters;
-
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException;
-
-/** Contains function interfaces that throw checked exceptions. */
-public final class CheckedInterfaces {
-
- private CheckedInterfaces() {
- }
-
- /** A BiConsumer interface that can throw StructConversionException. */
- @FunctionalInterface
- interface BiConsumer<T, U> {
- void accept(T t, U u) throws StructConversionException;
- }
-
- /**
- * A Function interface that can throw StructConversionException.
- *
- * @param <T>
- * @param <R>
- */
- @FunctionalInterface
- interface Function<T, R> {
- R apply(T t) throws StructConversionException;
- }
-
- /** A Consumer interface that can throw StructConversionException. */
- @FunctionalInterface
- interface Consumer<T> {
- void accept(T t) throws StructConversionException;
- }
-}
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
deleted file mode 100644
index 164fa59..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/EntityConverter.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.converters
-
-import androidx.appactions.interaction.proto.Entity
-import androidx.appactions.interaction.protobuf.Value
-
-/**
- * Converter from any Type to the Entity proto. This converter is usually used in the direction from
- * app to Assistant. Examples where the converter is needed is the developer setting possible values
- * in Properties or returning "disambiguation entities" from an inventory listener.
- *
- * @param T The T instance is usually a value object provided by the app, e.g. a Timer object from
- * the built-in-types library. </T>
- */
-fun interface EntityConverter<T> {
-
- /** Converter to an Entity proto. */
- fun convert(obj: T): Entity
-
- companion object {
- /**
- * @param typeSpec the TypeSpec of the structured type.
- */
- @JvmStatic
- fun <T> of(typeSpec: TypeSpec<T>): EntityConverter<T> {
- return EntityConverter { obj ->
- val builder = valueToEntity(typeSpec.toValue(obj)).toBuilder()
- typeSpec.getIdentifier(obj)?.let { builder.setIdentifier(it) }
- builder.build()
- }
- }
-
- internal fun valueToEntity(value: Value): Entity {
- val builder = Entity.newBuilder()
- when {
- 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/FieldBinding.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/FieldBinding.kt
deleted file mode 100644
index 490b74a..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/FieldBinding.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.converters
-
-import androidx.appactions.interaction.protobuf.Value
-import java.util.function.Function
-
-internal data class FieldBinding<T, BuilderT> constructor(
- val name: String,
- val valueGetter: Function<T, Value?>,
- val valueSetter: CheckedInterfaces.BiConsumer<BuilderT, Value>
-) {
- companion object {
- @JvmStatic
- fun <T, BuilderT> create(
- name: String,
- valueGetter: Function<T, Value?>,
- valueSetter: CheckedInterfaces.BiConsumer<BuilderT, Value>
- ): FieldBinding<T, BuilderT> {
- return FieldBinding(name, valueGetter, valueSetter)
- }
- }
-}
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
deleted file mode 100644
index 7875724..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/ParamValueConverter.kt
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.converters
-
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.protobuf.Value
-
-/**
- * Converts to and from ParamValue (Assistant protocol for a slot).
- *
- * @param T the type of slot. This will usually be a type or property from the BIT library.
- */
-interface ParamValueConverter<T> {
-
- /** Convert ParamValue sent from Assistant (e.g. BII Argument). */
- @Throws(StructConversionException::class)
- fun fromParamValue(paramValue: ParamValue): T
-
- /** Convert to ParamValue to send to Assistant (e.g. BIO). */
- fun toParamValue(obj: T): ParamValue
-
- companion object {
- /**
- * @param typeSpec the TypeSpec of the structured type, which can
- * read/write objects to/from Struct.
- */
- @JvmStatic
- fun <T> of(typeSpec: TypeSpec<T>) = object : ParamValueConverter<T> {
- override fun fromParamValue(paramValue: ParamValue): T {
- return typeSpec.fromValue(paramValueToValue(paramValue))
- }
-
- override fun toParamValue(obj: T): ParamValue {
- val builder = valueToParamValue(typeSpec.toValue(obj)).toBuilder()
- typeSpec.getIdentifier(obj)?.let { builder.setIdentifier(it) }
- return builder.build()
- }
- }
-
- internal fun paramValueToValue(paramValue: ParamValue): Value {
- val builder = Value.newBuilder()
- when {
- 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 protobuf" +
- " Value because it has no data types set.")
- }
- return builder.build()
- }
-
- internal fun valueToParamValue(value: Value): ParamValue {
- val builder = ParamValue.newBuilder()
- when {
- 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/SearchActionConverter.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/SearchActionConverter.java
deleted file mode 100644
index e93d84b..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/SearchActionConverter.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.converters;
-
-import androidx.annotation.NonNull;
-import androidx.appactions.interaction.capabilities.core.SearchAction;
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException;
-import androidx.appactions.interaction.proto.ParamValue;
-
-/**
- * Converts an ungrounded ParamValue to a SearchAction object.
- *
- * @param <T>
- */
-@FunctionalInterface
-public interface SearchActionConverter<T> {
- @NonNull
- SearchAction<T> toSearchAction(@NonNull ParamValue paramValue) throws StructConversionException;
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/SlotTypeConverter.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/SlotTypeConverter.java
deleted file mode 100644
index 20ef55b..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/SlotTypeConverter.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.converters;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RestrictTo;
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException;
-import androidx.appactions.interaction.proto.ParamValue;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Converts from internal proto representation as defined in the AppActionContext to a public java
- * type which can be consumed by developers.
- *
- * @param <T>
- */
-@FunctionalInterface
-@RestrictTo(RestrictTo.Scope.LIBRARY)
-public interface SlotTypeConverter<T> {
- @NonNull
- static <T> SlotTypeConverter<List<T>> ofRepeated(
- @NonNull ParamValueConverter<T> singularConverter) {
- return (paramValues) -> {
- List<T> results = new ArrayList<>();
- for (ParamValue paramValue : paramValues) {
- results.add(singularConverter.fromParamValue(paramValue));
- }
- return results;
- };
- }
-
- /** This converter will throw IndexOutOfBoundsException if the input List is empty. */
- @NonNull
- static <T> SlotTypeConverter<T> ofSingular(
- @NonNull ParamValueConverter<T> singularConverter) {
- return (paramValues) -> singularConverter.fromParamValue(paramValues.get(0));
- }
-
- T convert(@NonNull List<ParamValue> protoList) throws StructConversionException;
-}
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
deleted file mode 100644
index 840b476..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeConverters.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.converters;
-
-import androidx.annotation.NonNull;
-import androidx.appactions.builtintypes.experimental.properties.Attendee;
-import androidx.appactions.builtintypes.experimental.properties.EndDate;
-import androidx.appactions.builtintypes.experimental.properties.ItemListElement;
-import androidx.appactions.builtintypes.experimental.properties.Name;
-import androidx.appactions.builtintypes.experimental.properties.Participant;
-import androidx.appactions.builtintypes.experimental.properties.Recipient;
-import androidx.appactions.builtintypes.experimental.properties.StartDate;
-import androidx.appactions.builtintypes.experimental.properties.Text;
-import androidx.appactions.builtintypes.experimental.types.CalendarEvent;
-import androidx.appactions.builtintypes.experimental.types.Call;
-import androidx.appactions.builtintypes.experimental.types.ItemList;
-import androidx.appactions.builtintypes.experimental.types.ListItem;
-import androidx.appactions.builtintypes.experimental.types.Message;
-import androidx.appactions.builtintypes.experimental.types.Person;
-import androidx.appactions.builtintypes.experimental.types.SafetyCheck;
-import androidx.appactions.interaction.capabilities.core.SearchAction;
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException;
-import androidx.appactions.interaction.capabilities.core.properties.StringValue;
-import androidx.appactions.interaction.proto.Entity;
-import androidx.appactions.interaction.proto.ParamValue;
-
-import java.time.Duration;
-import java.time.LocalDate;
-import java.time.LocalTime;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
-import java.util.List;
-import java.util.Optional;
-
-/** Converters for capability argument values. Convert from internal proto types to public types. */
-public final class TypeConverters {
- public static final String FIELD_NAME_TYPE = "@type";
- public static final TypeSpec<ListItem> LIST_ITEM_TYPE_SPEC =
- TypeSpecBuilder.newBuilderForThing(
- "ListItem",
- ListItem::Builder,
- ListItem.Builder::build).build();
- public static final TypeSpec<ItemListElement> ITEM_LIST_ELEMENT_TYPE_SPEC =
- new UnionTypeSpec.Builder<ItemListElement>()
- .bindMemberType(
- ItemListElement::asListItem,
- ItemListElement::new,
- LIST_ITEM_TYPE_SPEC)
- .build();
- public static final TypeSpec<ItemList> ITEM_LIST_TYPE_SPEC =
- TypeSpecBuilder.newBuilderForThing(
- "ItemList",
- ItemList::Builder,
- ItemList.Builder::build)
- .bindRepeatedSpecField(
- "itemListElement",
- ItemList::getItemListElements,
- ItemList.Builder::addItemListElements,
- ITEM_LIST_ELEMENT_TYPE_SPEC)
- .build();
-
- public static final TypeSpec<Person> PERSON_TYPE_SPEC =
- TypeSpecBuilder.newBuilderForThing("Person", Person::Builder, Person.Builder::build)
- .bindStringField("email", Person::getEmail, Person.Builder::setEmail)
- .bindStringField(
- "telephone", Person::getTelephone, Person.Builder::setTelephone)
- .bindStringField(
- "name",
- person ->
- Optional.ofNullable(person)
- .map(Person::getName)
- .map(Name::asText)
- .orElse(null),
- Person.Builder::setName)
- .build();
- public static final TypeSpec<Attendee> ATTENDEE_TYPE_SPEC =
- new UnionTypeSpec.Builder<Attendee>()
- .bindMemberType(
- Attendee::asPerson,
- Attendee::new,
- PERSON_TYPE_SPEC)
- .build();
- public static final TypeSpec<CalendarEvent> CALENDAR_EVENT_TYPE_SPEC =
- TypeSpecBuilder.newBuilderForThing(
- "CalendarEvent",
- CalendarEvent::Builder,
- CalendarEvent.Builder::build)
- .bindSpecField(
- "startDate",
- calendarEvent ->
- Optional.ofNullable(calendarEvent)
- .map(CalendarEvent::getStartDate)
- .map(StartDate::asZonedDateTime)
- .orElse(null),
- CalendarEvent.Builder::setStartDate,
- TypeSpec.ZONED_DATE_TIME_TYPE_SPEC)
- .bindSpecField(
- "endDate",
- calendarEvent ->
- Optional.ofNullable(calendarEvent)
- .map(CalendarEvent::getEndDate)
- .map(EndDate::asZonedDateTime)
- .orElse(null),
- CalendarEvent.Builder::setEndDate,
- TypeSpec.ZONED_DATE_TIME_TYPE_SPEC)
- .bindRepeatedSpecField(
- "attendee",
- CalendarEvent::getAttendeeList,
- CalendarEvent.Builder::addAttendees,
- ATTENDEE_TYPE_SPEC)
- .build();
- public static final TypeSpec<SafetyCheck> SAFETY_CHECK_TYPE_SPEC =
- TypeSpecBuilder.newBuilderForThing(
- "SafetyCheck",
- SafetyCheck::Builder,
- SafetyCheck.Builder::build)
- .bindSpecField(
- "duration",
- SafetyCheck::getDuration,
- SafetyCheck.Builder::setDuration,
- TypeSpec.DURATION_TYPE_SPEC)
- .bindSpecField(
- "checkInTime",
- SafetyCheck::getCheckInTime,
- SafetyCheck.Builder::setCheckInTime,
- TypeSpec.ZONED_DATE_TIME_TYPE_SPEC)
- .build();
- public static final TypeSpec<Recipient> RECIPIENT_TYPE_SPEC =
- new UnionTypeSpec.Builder<Recipient>()
- .bindMemberType(
- Recipient::asPerson,
- Recipient::new,
- PERSON_TYPE_SPEC)
- .build();
- public static final TypeSpec<Participant> PARTICIPANT_TYPE_SPEC =
- new UnionTypeSpec.Builder<Participant>()
- .bindMemberType(
- Participant::asPerson,
- Participant::new,
- PERSON_TYPE_SPEC)
- .build();
- public static final TypeSpec<Message> MESSAGE_TYPE_SPEC =
- TypeSpecBuilder.newBuilderForThing("Message", Message::Builder, Message.Builder::build)
- .bindIdentifier(Message::getIdentifier)
- .bindRepeatedSpecField(
- "recipient",
- Message::getRecipientList,
- Message.Builder::addRecipients,
- RECIPIENT_TYPE_SPEC)
- .bindStringField(
- "text",
- message ->
- Optional.ofNullable(message)
- .map(Message::getText)
- .map(Text::asText)
- .orElse(null),
- Message.Builder::setText)
- .build();
- public static final TypeSpec<Call> CALL_TYPE_SPEC =
- TypeSpecBuilder.newBuilderForThing(
- "Call",
- Call::Builder,
- Call.Builder::build)
- .bindIdentifier(Call::getIdentifier)
- .bindRepeatedSpecField(
- "participant",
- Call::getParticipantList,
- Call.Builder::addAllParticipant,
- PARTICIPANT_TYPE_SPEC)
- .build();
-
- public static final ParamValueConverter<Integer> INTEGER_PARAM_VALUE_CONVERTER =
- ParamValueConverter.of(TypeSpec.INTEGER_TYPE_SPEC);
-
- public static final ParamValueConverter<Boolean> BOOLEAN_PARAM_VALUE_CONVERTER =
- ParamValueConverter.of(TypeSpec.BOOL_TYPE_SPEC);
-
- public static final ParamValueConverter<String> STRING_PARAM_VALUE_CONVERTER =
- ParamValueConverter.of(TypeSpec.STRING_TYPE_SPEC);
-
- public static final ParamValueConverter<LocalDate> LOCAL_DATE_PARAM_VALUE_CONVERTER =
- ParamValueConverter.of(TypeSpec.LOCAL_DATE_TYPE_SPEC);
-
- public static final ParamValueConverter<LocalTime> LOCAL_TIME_PARAM_VALUE_CONVERTER =
- ParamValueConverter.of(TypeSpec.LOCAL_TIME_TYPE_SPEC);
-
- public static final ParamValueConverter<ZoneId> ZONE_ID_PARAM_VALUE_CONVERTER =
- ParamValueConverter.of(TypeSpec.ZONE_ID_TYPE_SPEC);
-
- public static final ParamValueConverter<ZonedDateTime> ZONED_DATE_TIME_PARAM_VALUE_CONVERTER =
- ParamValueConverter.of(TypeSpec.ZONED_DATE_TIME_TYPE_SPEC);
-
- public static final ParamValueConverter<Duration> DURATION_PARAM_VALUE_CONVERTER =
- ParamValueConverter.of(TypeSpec.DURATION_TYPE_SPEC);
-
- public static final ParamValueConverter<Call.CanonicalValue.CallFormat>
- CALL_FORMAT_PARAM_VALUE_CONVERTER =
- new ParamValueConverter<Call.CanonicalValue.CallFormat>() {
-
- @NonNull
- @Override
- public ParamValue toParamValue(Call.CanonicalValue.CallFormat value) {
- return ParamValue.newBuilder()
- .setStringValue(value.getTextValue())
- .build();
- }
-
- @Override
- public Call.CanonicalValue.CallFormat fromParamValue(@NonNull ParamValue paramValue)
- throws StructConversionException {
- String identifier = paramValue.getIdentifier();
- if (identifier.equals(Call.CanonicalValue.CallFormat.Audio.getTextValue())) {
- return Call.CanonicalValue.CallFormat.Audio;
- } else if (identifier.equals(
- Call.CanonicalValue.CallFormat.Video.getTextValue())) {
- return Call.CanonicalValue.CallFormat.Video;
- }
- throw new StructConversionException(
- String.format("Unknown enum format '%s'.", identifier));
- }
- };
- public static final EntityConverter<StringValue> STRING_VALUE_ENTITY_CONVERTER =
- (stringValue) ->
- Entity.newBuilder()
- .setIdentifier(stringValue.getName())
- .setName(stringValue.getName())
- .addAllAlternateNames(stringValue.getAlternateNames())
- .build();
- public static final EntityConverter<ZonedDateTime> ZONED_DATE_TIME_ENTITY_CONVERTER =
- EntityConverter.of(TypeSpec.ZONED_DATE_TIME_TYPE_SPEC);
- public static final EntityConverter<LocalTime> LOCAL_TIME_ENTITY_CONVERTER =
- EntityConverter.of(TypeSpec.LOCAL_TIME_TYPE_SPEC);
- public static final EntityConverter<Duration> DURATION_ENTITY_CONVERTER =
- EntityConverter.of(TypeSpec.DURATION_TYPE_SPEC);
- public static final EntityConverter<Call.CanonicalValue.CallFormat>
- CALL_FORMAT_ENTITY_CONVERTER =
- (callFormat) ->
- Entity.newBuilder().setIdentifier(callFormat.getTextValue()).build();
-
- @NonNull
- public static <T> TypeSpec<SearchAction<T>> createSearchActionTypeSpec(
- @NonNull TypeSpec<T> nestedTypeSpec) {
- return TypeSpecBuilder.newBuilder(
- "SearchAction",
- SearchAction.Builder<T>::new,
- SearchAction.Builder::build)
- .bindStringField(
- "query",
- SearchAction::getQuery,
- SearchAction.Builder::setQuery)
- .bindSpecField(
- "filter",
- SearchAction::getFilter,
- SearchAction.Builder::setFilter,
- nestedTypeSpec)
- .build();
- }
-
- /** Given some class with a corresponding TypeSpec, create a SearchActionConverter instance. */
- @NonNull
- public static <T> SearchActionConverter<T> createSearchActionConverter(
- @NonNull TypeSpec<T> nestedTypeSpec) {
- final TypeSpec<SearchAction<T>> typeSpec = createSearchActionTypeSpec(nestedTypeSpec);
- return ParamValueConverter.Companion.of(typeSpec)::fromParamValue;
- }
-
- /** Given a list of supported Enum Types, creates a ParamValueConverter instance. */
- @NonNull
- public static <T> ParamValueConverter<T> createEnumParamValueConverter(
- @NonNull List<T> supportedValues) {
- return new ParamValueConverter<T>() {
- @Override
- public T fromParamValue(@NonNull ParamValue paramValue) throws
- StructConversionException {
- for (T supportedValue : supportedValues) {
- if (supportedValue.toString().equals(paramValue.getIdentifier())) {
- return supportedValue;
- }
- }
- throw new StructConversionException("cannot convert paramValue to protobuf "
- + "Value because identifier " + paramValue.getIdentifier() + " is not "
- + "one of the supported values");
- }
-
- @NonNull
- @Override
- public ParamValue toParamValue(@NonNull T obj) {
- for (T supportedValue : supportedValues) {
- if (supportedValue.equals(obj)) {
- return ParamValue.newBuilder().setIdentifier(obj.toString()).build();
- }
- }
- throw new IllegalStateException("cannot convert " + obj + " to ParamValue "
- + "because it did not match one of the supported values");
- }
- };
- }
-
- /** Given a list of supported Enum Types, creates a EntityConverter instance. */
- @NonNull
- public static <T> EntityConverter<T> createEnumEntityConverter(
- @NonNull List<T> supportedValues) {
- return new EntityConverter<T>() {
- @NonNull
- @Override
- public Entity convert(T obj) throws IllegalStateException {
- for (T supportedValue : supportedValues) {
- if (supportedValue.toString().equals(obj.toString())) {
- return Entity.newBuilder().setIdentifier(obj.toString()).build();
- }
- }
- throw new IllegalStateException("cannot convert " + obj + " to entity "
- + "because it did not match one of the supported values");
- }
- };
- }
-
- private TypeConverters() {
- }
-}
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
deleted file mode 100644
index c0e7de9..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeSpec.kt
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.converters
-
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException
-import androidx.appactions.interaction.protobuf.Value
-import java.time.Duration
-import java.time.Instant
-import java.time.LocalDate
-import java.time.LocalDateTime
-import java.time.LocalTime
-import java.time.ZoneId
-import java.time.ZonedDateTime
-import java.time.format.DateTimeFormatter
-import java.time.format.DateTimeParseException
-
-/**
- * TypeSpec is used to convert between native objects in capabilities/values and Value proto.
- */
-interface TypeSpec<T> {
- /* Given the object, returns its identifier, which can be null. */
- fun getIdentifier(obj: T): String?
-
- /** Converts a object into a Value proto. */
- fun toValue(obj: T): Value
-
- /**
- * Converts a Value into an object.
- *
- * @throws StructConversionException if the Struct is malformed.
- */
- @Throws(StructConversionException::class)
- fun fromValue(value: Value): T
-
- companion object {
- /** Create a TypeSpec that serializes to/from Value.stringValue. */
- @JvmStatic
- fun <T> createStringBasedTypeSpec(
- toString: (T) -> String,
- fromString: (String) -> T
- ): TypeSpec<T> = object : TypeSpec<T> {
- override fun getIdentifier(obj: T): String? = null
- override fun toValue(obj: T): Value = Value.newBuilder()
- .setStringValue(toString(obj)).build()
- override fun fromValue(value: Value): T = when {
- value.hasStringValue() -> fromString(value.stringValue)
- else -> throw StructConversionException(
- "cannot convert $value, expected Value.stringValue to be present")
- }
- }
-
- @JvmField
- val STRING_TYPE_SPEC = createStringBasedTypeSpec<String>(
- toString = { it },
- fromString = { it }
- )
-
- @JvmField
- val BOOL_TYPE_SPEC = object : TypeSpec<Boolean> {
- override fun getIdentifier(obj: Boolean): String? = null
-
- override fun toValue(
- obj: Boolean,
- ): Value = Value.newBuilder().setBoolValue(obj).build()
-
- override fun fromValue(value: Value): Boolean = when {
- value.hasBoolValue() -> value.boolValue
- else -> throw StructConversionException("BOOL_TYPE_SPEC cannot convert $value")
- }
- }
-
- @JvmField
- val NUMBER_TYPE_SPEC = object : TypeSpec<Double> {
- override fun getIdentifier(obj: Double): String? = null
-
- override fun toValue(
- obj: Double,
- ): Value = Value.newBuilder().setNumberValue(obj).build()
-
- override fun fromValue(value: Value): Double = when {
- value.hasNumberValue() -> value.numberValue
- else -> throw StructConversionException("NUMBER_TYPE_SPEC cannot convert $value")
- }
- }
-
- @JvmField
- val INTEGER_TYPE_SPEC = object : TypeSpec<Int> {
- override fun getIdentifier(obj: Int): String? = null
-
- override fun toValue(
- obj: Int,
- ): Value = Value.newBuilder().setNumberValue(obj.toDouble()).build()
-
- override fun fromValue(value: Value): Int = when {
- value.hasNumberValue() -> value.numberValue.toInt()
- else -> throw StructConversionException("INTEGER_TYPE_SPEC cannot convert $value")
- }
- }
-
- // TODO(remove this when Long is no longer used in BIT library)
- @JvmField
- /** Serialize Long to/from string field due to precision limit with nunmber value. */
- val LONG_TYPE_SPEC = object : TypeSpec<Long> {
- override fun getIdentifier(obj: Long): String? = null
-
- override fun toValue(
- obj: Long,
- ): Value = Value.newBuilder().setNumberValue(obj.toDouble()).build()
-
- override fun fromValue(value: Value): Long = when {
- value.hasNumberValue() -> value.numberValue.toLong()
- else -> throw StructConversionException("LONG_TYPE_SPEC cannot convert $value")
- }
- }
-
- @JvmField
- val LOCAL_DATE_TYPE_SPEC = createStringBasedTypeSpec<LocalDate>(
- toString = { it.format(DateTimeFormatter.ISO_LOCAL_DATE) },
- fromString = { try {
- LocalDate.parse(it)
- } catch (e: DateTimeParseException) {
- throw StructConversionException(
- "Failed to parse ISO 8601 string to LocalDate", e)
- } }
- )
-
- @JvmField
- val LOCAL_TIME_TYPE_SPEC = createStringBasedTypeSpec<LocalTime>(
- toString = { it.format(DateTimeFormatter.ISO_LOCAL_TIME) },
- fromString = { try {
- LocalTime.parse(it)
- } catch (e: DateTimeParseException) {
- throw StructConversionException(
- "Failed to parse ISO 8601 string to LocalTime", e)
- } }
- )
-
- @JvmField
- val LOCAL_DATE_TIME_TYPE_SPEC = createStringBasedTypeSpec<LocalDateTime>(
- toString = { it.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) },
- fromString = { try {
- LocalDateTime.parse(it)
- } catch (e: DateTimeParseException) {
- throw StructConversionException(
- "Failed to parse ISO 8601 string to LocalDateTime", e)
- } }
- )
-
- @JvmField
- val ZONED_DATE_TIME_TYPE_SPEC = createStringBasedTypeSpec<ZonedDateTime>(
- toString = { it.toOffsetDateTime().toString() },
- fromString = { try {
- ZonedDateTime.parse(it)
- } catch (e: DateTimeParseException) {
- throw StructConversionException(
- "Failed to parse ISO 8601 string to ZonedDateTime", e)
- } }
- )
-
- @JvmField
- val INSTANT_TYPE_SPEC = createStringBasedTypeSpec<Instant>(
- toString = Instant::toString,
- fromString = { try {
- Instant.parse(it)
- } catch (e: DateTimeParseException) {
- throw StructConversionException(
- "Failed to parse ISO 8601 string to Instant", e)
- } }
- )
-
- @JvmField
- val DURATION_TYPE_SPEC = createStringBasedTypeSpec<Duration>(
- toString = Duration::toString,
- fromString = { try {
- Duration.parse(it)
- } catch (e: DateTimeParseException) {
- throw StructConversionException(
- "Failed to parse ISO 8601 string to Duration", e)
- } }
- )
-
- @JvmField
- val ZONE_ID_TYPE_SPEC = createStringBasedTypeSpec<ZoneId>(
- toString = ZoneId::toString,
- fromString = { try {
- ZoneId.of(it)
- } catch (e: Exception) {
- throw StructConversionException(
- "Failed to parse string to ZoneId", e)
- } }
- )
- }
-}
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
deleted file mode 100644
index 458f41b..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeSpecBuilder.java
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.converters;
-
-import static androidx.appactions.interaction.capabilities.core.impl.utils.ImmutableCollectors.toImmutableList;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RestrictTo;
-import androidx.appactions.builtintypes.experimental.types.Thing;
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException;
-import androidx.appactions.interaction.protobuf.ListValue;
-import androidx.appactions.interaction.protobuf.Struct;
-import androidx.appactions.interaction.protobuf.Value;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.function.BiConsumer;
-import java.util.function.Function;
-import java.util.function.Supplier;
-
-/**
- * Builder for {@link TypeSpec}. TypeSpec converts T instance to and from {@code Value.structValue}
- * @param <T> the type this TypeSpec is for
- * @param <BuilderT> the type that builds T objects
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-public final class TypeSpecBuilder<T, BuilderT> {
- private final List<FieldBinding<T, BuilderT>> mBindings = new ArrayList<>();
- private final Supplier<BuilderT> mBuilderSupplier;
- private final Function<BuilderT, T> mBuilderFinalizer;
- private CheckedInterfaces.Consumer<Struct> mStructValidator;
- private Function<T, String> mIdentifierGetter = (unused) -> null;
-
- private TypeSpecBuilder(
- String typeName,
- Supplier<BuilderT> builderSupplier,
- Function<BuilderT, T> builderFinalizer) {
- this.mBuilderSupplier = builderSupplier;
- this.mBuilderFinalizer = builderFinalizer;
- this.bindStringField("@type", (unused) -> typeName, (builder, val) -> {})
- .setStructValidator(
- struct -> {
- if (!getFieldFromStruct(struct, "@type")
- .getStringValue()
- .equals(typeName)) {
- throw new StructConversionException(
- String.format(
- "Struct @type field must be equal to %s.",
- typeName));
- }
- });
- }
-
- private static Value getStringValue(String string) {
- return Value.newBuilder().setStringValue(string).build();
- }
-
- private static Value getListValue(List<Value> values) {
- return Value.newBuilder()
- .setListValue(ListValue.newBuilder().addAllValues(values).build())
- .build();
- }
-
- /**
- * Returns a Value in a Struct, IllegalArgumentException is caught and wrapped in
- * StructConversionException.
- *
- * @param struct the Struct to get values from.
- * @param key the String key of the field to retrieve.
- */
- private static Value getFieldFromStruct(Struct struct, String key)
- throws StructConversionException {
- try {
- return struct.getFieldsOrThrow(key);
- } catch (IllegalArgumentException e) {
- throw new StructConversionException(
- String.format("%s does not exist in Struct", key), e);
- }
- }
-
- /**
- * Creates a new instance of TypeSpecBuilder.
- *
- * @param typeName the name of the type.
- * @param builderSupplier a function which supplies new Builder instances for the type.
- * @param builderFinalizer a function that gets the built object from the builder.
- */
- @NonNull
- public static <T, BuilderT> TypeSpecBuilder<T, BuilderT> newBuilder(
- @NonNull String typeName,
- @NonNull Supplier<BuilderT> builderSupplier,
- @NonNull Function<BuilderT, T> builderFinalizer) {
- return new TypeSpecBuilder<>(typeName, builderSupplier, builderFinalizer);
- }
-
- /**
- * Creates a new TypeSpecBuilder for a child class of Thing (temporary BuiltInTypes).
- *
- * <p>Comes with bindings for Thing fields.
- */
- static <T extends Thing, BuilderT extends Thing.Builder<?>>
- TypeSpecBuilder<T, BuilderT> newBuilderForThing(
- String typeName,
- Supplier<BuilderT> builderSupplier,
- Function<BuilderT, T> builderFinalizer) {
- return new TypeSpecBuilder<>(typeName, builderSupplier, builderFinalizer)
- .bindIdentifier(Thing::getIdentifier)
- .bindStringField("identifier", Thing::getIdentifier, BuilderT::setIdentifier)
- .bindStringField(
- "name",
- thing -> {
- if (thing.getName() == null) {
- return null;
- }
- return thing.getName().asText();
- },
- BuilderT::setName);
- }
-
- private TypeSpecBuilder<T, BuilderT> setStructValidator(
- CheckedInterfaces.Consumer<Struct> structValidator) {
- this.mStructValidator = structValidator;
- return this;
- }
-
- /**
- * Binds a function that returns the identifier of the object.
- */
- @NonNull
- public TypeSpecBuilder<T, BuilderT> bindIdentifier(
- @NonNull Function<T, String> identifierGetter
- ) {
- this.mIdentifierGetter = identifierGetter;
- return this;
- }
-
- private TypeSpecBuilder<T, BuilderT> bindFieldInternal(
- String name,
- Function<T, Value> valueGetter,
- CheckedInterfaces.BiConsumer<BuilderT, Value> valueSetter) {
- mBindings.add(FieldBinding.create(name, valueGetter, valueSetter));
- return this;
- }
-
- private <V> TypeSpecBuilder<T, BuilderT> bindRepeatedFieldInternal(
- String name,
- Function<T, List<V>> valueGetter,
- BiConsumer<BuilderT, List<V>> valueSetter,
- Function<V, Value> toValue,
- CheckedInterfaces.Function<Value, V> fromValue) {
- return bindFieldInternal(
- name,
- /* valueGetter= */
- object -> {
- List<V> valueList = valueGetter.apply(object);
- if (valueList == null) {
- return null;
- }
- return getListValue(
- valueList.stream()
- .map(toValue)
- .filter(Objects::nonNull)
- .collect(toImmutableList()));
- },
- /* valueSetter= */
- (builder, repeatedValue) -> {
- if (repeatedValue.getListValue() == null) {
- return;
- }
- List<Value> values = repeatedValue.getListValue().getValuesList();
- List<V> convertedValues = new ArrayList<>();
- for (Value value : values) {
- convertedValues.add(fromValue.apply(value));
- }
- valueSetter.accept(builder, Collections.unmodifiableList(convertedValues));
- });
- }
-
- /** binds a String field to read from / write to Struct */
- @NonNull
- public TypeSpecBuilder<T, BuilderT> bindStringField(
- @NonNull String name,
- @NonNull Function<T, String> stringGetter,
- @NonNull BiConsumer<BuilderT, String> stringSetter) {
- return bindFieldInternal(
- name,
- (object) -> {
- String value = stringGetter.apply(object);
- if (value == null) {
- return null;
- }
- return TypeSpecBuilder.getStringValue(value);
- },
- (builder, value) -> {
- if (value.hasStringValue()) {
- stringSetter.accept(builder, value.getStringValue());
- }
- });
- }
-
- /** Binds a spec field to read from / write to Struct. */
- @SuppressWarnings("LambdaLast")
- @NonNull
- public <V> TypeSpecBuilder<T, BuilderT> bindSpecField(
- @NonNull String name,
- @NonNull Function<T, V> valueGetter,
- @NonNull BiConsumer<BuilderT, V> valueSetter,
- @NonNull TypeSpec<V> spec) {
- return bindFieldInternal(
- name,
- (object) -> {
- V value = valueGetter.apply(object);
- if (value == null) {
- return null;
- }
- return spec.toValue(value);
- },
- (builder, value) -> valueSetter.accept(builder, spec.fromValue(value)));
- }
-
- /** binds a repeated spec field to read from / write to Struct. */
- @SuppressWarnings("LambdaLast")
- @NonNull
- public <V> TypeSpecBuilder<T, BuilderT> bindRepeatedSpecField(
- @NonNull String name,
- @NonNull Function<T, List<V>> valueGetter,
- @NonNull BiConsumer<BuilderT, List<V>> valueSetter,
- @NonNull TypeSpec<V> spec) {
- return bindRepeatedFieldInternal(
- name,
- valueGetter,
- valueSetter,
- spec::toValue,
- spec::fromValue);
- }
-
- /**
- * Builds the TypeSpec instance.
- */
- @NonNull
- public TypeSpec<T> build() {
- return new TypeSpecImpl<>(
- mIdentifierGetter,
- mBindings,
- mBuilderSupplier,
- mBuilderFinalizer,
- mStructValidator);
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeSpecImpl.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeSpecImpl.java
deleted file mode 100644
index da4488c..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeSpecImpl.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.converters;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException;
-import androidx.appactions.interaction.protobuf.Struct;
-import androidx.appactions.interaction.protobuf.Value;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
-import java.util.function.Supplier;
-
-/**
- * TypeSpecImpl is used to convert between java/kotlin objects in capabilities/values and Value
- * proto.
- */
-final class TypeSpecImpl<T, BuilderT> implements TypeSpec<T> {
- /* The function to retrieve the identifier. */
- @NonNull
- final Function<T, String> mIdentifierGetter;
-
- /** The list of FieldBinding objects. */
- @NonNull
- final List<FieldBinding<T, BuilderT>> mBindings;
-
- /** Validates the Struct during conversion to java object. */
- @Nullable
- final CheckedInterfaces.Consumer<Struct> mStructValidator;
-
- /** Supplies BuilderT instances. */
- @NonNull
- final Supplier<BuilderT> mBuilderSupplier;
-
- /** Builds the object instance. */
- @NonNull
- final Function<BuilderT, T> mBuilderFinalizer;
-
- TypeSpecImpl(
- @NonNull Function<T, String> identifierGetter,
- @NonNull List<FieldBinding<T, BuilderT>> bindings,
- @NonNull Supplier<BuilderT> builderSupplier,
- @NonNull Function<BuilderT, T> builderFinalizer,
- @Nullable CheckedInterfaces.Consumer<Struct> structValidator) {
- this.mIdentifierGetter = identifierGetter;
- this.mBindings = Collections.unmodifiableList(bindings);
- this.mBuilderSupplier = builderSupplier;
- this.mStructValidator = structValidator;
- this.mBuilderFinalizer = builderFinalizer;
- }
-
- @Nullable
- @Override
- public String getIdentifier(T obj) {
- return mIdentifierGetter.apply(obj);
- }
-
- /** Converts a java object into a Struct proto using List of FieldBinding. */
- @NonNull
- @Override
- public Value toValue(@NonNull T obj) {
- Struct.Builder structBuilder = Struct.newBuilder();
- for (FieldBinding<T, BuilderT> binding : mBindings) {
- Value value = binding.getValueGetter().apply(obj);
- if (value != null) {
- structBuilder.putFields(binding.getName(), value);
- }
- }
- return Value.newBuilder().setStructValue(structBuilder).build();
- }
-
- /**
- * Converts a Struct back into java object.
- *
- * @throws StructConversionException if the Struct is malformed.
- */
- @NonNull
- @Override
- public T fromValue(@NonNull Value value) throws StructConversionException {
- Struct struct = value.getStructValue();
- if (struct == null) {
- throw new StructConversionException(
- String.format("TypeSpecImpl cannot deserializes non-Struct value: %s", value));
- }
- if (mStructValidator != null) {
- mStructValidator.accept(struct);
- }
-
- BuilderT builder = mBuilderSupplier.get();
- Map<String, Value> fieldsMap = struct.getFieldsMap();
- for (FieldBinding<T, BuilderT> binding : mBindings) {
- Value fieldValue = fieldsMap.get(binding.getName());
- if (fieldValue != null) {
- binding.getValueSetter().accept(builder, fieldValue);
- }
- }
- return mBuilderFinalizer.apply(builder);
- }
-}
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
deleted file mode 100644
index 0e79006..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/UnionTypeSpec.kt
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.converters
-
-import androidx.annotation.RestrictTo
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException
-import androidx.appactions.interaction.protobuf.Value
-
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-class UnionTypeSpec<T : Any> internal constructor(
- private val bindings: List<MemberBinding<T, *>>,
-) : TypeSpec<T> {
- internal class MemberBinding<T, M>(
- private val memberGetter: (T) -> M?,
- private val ctor: (M) -> T,
- private val typeSpec: TypeSpec<M>,
- ) {
- @Throws(StructConversionException::class)
- fun tryDeserialize(value: Value): T {
- return ctor(typeSpec.fromValue(value))
- }
-
- fun serialize(obj: T): Value {
- return typeSpec.toValue(memberGetter(obj)!!)
- }
-
- fun getIdentifier(obj: T): String? {
- return typeSpec.getIdentifier(memberGetter(obj)!!)
- }
-
- fun isMemberSet(obj: T): Boolean {
- return memberGetter(obj) != null
- }
- }
-
- private fun getApplicableBinding(obj: T): MemberBinding<T, *> {
- 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]
- else -> throw IllegalStateException(
- "$obj is invalid, multiple union members are non-null."
- )
- }
- }
-
- override fun getIdentifier(obj: T): String? {
- return getApplicableBinding(obj).getIdentifier(obj)
- }
-
- override fun toValue(obj: T): Value {
- return getApplicableBinding(obj).serialize(obj)
- }
-
- @Throws(StructConversionException::class)
- override fun fromValue(value: Value): T {
- for (binding in bindings) {
- try {
- return binding.tryDeserialize(value)
- } catch (e: StructConversionException) {
- continue
- }
- }
- throw StructConversionException("all member TypeSpecs failed to deserialize input Value.")
- }
-
- class Builder<T : Any> {
- private val bindings = mutableListOf<MemberBinding<T, *>>()
-
- /** During deserialization, bindings will be tried in the order they are bound. */
- fun <M> bindMemberType(
- memberGetter: (T) -> M?,
- ctor: (M) -> T,
- typeSpec: TypeSpec<M>,
- ) = apply {
- bindings.add(
- MemberBinding(
- memberGetter,
- ctor,
- typeSpec,
- ),
- )
- }
-
- fun build() = UnionTypeSpec(bindings.toList())
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/exceptions/ExternalException.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/exceptions/ExternalException.kt
deleted file mode 100644
index 4147e62..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/exceptions/ExternalException.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.exceptions
-
-/**
- * This exception wraps an externally thrown exception.
- *
- * For example, an exception occurred in a listener or some method implemented as part
- * of some Session interface.
- */
-class ExternalException(message: String, cause: Throwable) : Exception(message, cause)
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/exceptions/InvalidRequestException.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/exceptions/InvalidRequestException.kt
deleted file mode 100644
index 557cc1c..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/exceptions/InvalidRequestException.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.exceptions
-
-/** Represents exceptions that happen as a result of some incoming request that is invalid. */
-open class InvalidRequestException : Exception {
- constructor(message: String?) : super(message)
- constructor(message: String?, cause: Throwable?) : super(message, cause)
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/exceptions/StructConversionException.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/exceptions/StructConversionException.kt
deleted file mode 100644
index 450c533..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/exceptions/StructConversionException.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.exceptions
-
-/** Represents exceptions that happen during object conversion to/from Struct proto. */
-class StructConversionException : InvalidRequestException {
- constructor(message: String?) : super(message)
- constructor(message: String?, cause: Throwable?) : super(message, cause)
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/package-info.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/package-info.java
deleted file mode 100644
index 8d0f6b6..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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.
- */
-
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-package androidx.appactions.interaction.capabilities.core.impl;
-
-import androidx.annotation.RestrictTo;
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpec.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpec.kt
deleted file mode 100644
index 9d4ddf9..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpec.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.spec
-
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException
-import androidx.appactions.interaction.proto.AppActionsContext
-import androidx.appactions.interaction.proto.FulfillmentResponse
-import androidx.appactions.interaction.proto.ParamValue
-
-/**
- * A specification for an action, describing it from the app's point of view.
- *
- * @param ArgumentsT typed representation of action's arguments.
- * @param OutputT typed action's execution output.
- */
-interface ActionSpec<ArgumentsT, OutputT> {
-
- /**
- * The BII capability name this ActionSpec is for.
- */
- val capabilityName: String
-
- /**
- * Converts the input parameters to the `AppAction` proto.
- * @param identifier the capability identifier
- * @param boundProperties the list of BoundProperty instances.
- * @param supportsPartialFulfillment whether or not this capability supports partial
- * fulfillment.
- */
- fun createAppAction(
- identifier: String,
- boundProperties: List<BoundProperty<*>>,
- supportsPartialFulfillment: Boolean
- ): AppActionsContext.AppAction
-
- /** Builds this action's arguments from a map of slot name to param values. */
- @Throws(StructConversionException::class)
- fun buildArguments(args: Map<String, List<ParamValue>>): ArgumentsT
-
- /**
- * Converts an [ArgumentsT] instance to a Fulfillment proto
- */
- fun serializeArguments(args: ArgumentsT): Map<String, List<ParamValue>>
-
- /** Converts the output to the `StructuredOutput` proto. */
- fun convertOutputToProto(output: OutputT): FulfillmentResponse.StructuredOutput
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecBuilder.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecBuilder.kt
deleted file mode 100644
index 50aa83d..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecBuilder.kt
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.spec
-
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.SlotTypeConverter
-import androidx.appactions.interaction.capabilities.core.impl.spec.ParamBinding.ArgumentSetter
-import androidx.appactions.interaction.capabilities.core.impl.utils.ImmutableCollectors
-import androidx.appactions.interaction.proto.ParamValue
-import java.util.function.BiConsumer
-import java.util.function.Function
-import java.util.function.Supplier
-
-/**
- * A builder for the `ActionSpec`.
- */
-class ActionSpecBuilder<ArgumentsT, ArgumentsBuilderT, OutputT>
-private constructor(
- private val capabilityName: String,
- private val argumentBuilderSupplier: Supplier<ArgumentsBuilderT>,
- private val builderFinalizer: Function<ArgumentsBuilderT, ArgumentsT>
-) {
- private val paramBindingList: MutableList<ParamBinding<ArgumentsT, ArgumentsBuilderT>> =
- ArrayList()
- private val outputBindings: MutableMap<String, Function<OutputT, List<ParamValue>>> = HashMap()
-
- /** Sets the argument type and its builder and returns a new `ActionSpecBuilder`. */
- @Suppress("UNUSED_PARAMETER")
- fun <NewArgumentsT, NewArgumentsBuilderT> setArguments(
- unused: Class<NewArgumentsT>,
- argumentBuilderSupplier: Supplier<NewArgumentsBuilderT>,
- builderFinalizer: Function<NewArgumentsBuilderT, NewArgumentsT>
- ): ActionSpecBuilder<NewArgumentsT, NewArgumentsBuilderT, OutputT> {
- return ActionSpecBuilder(this.capabilityName, argumentBuilderSupplier, builderFinalizer)
- }
-
- @Suppress("UNUSED_PARAMETER")
- fun <NewOutputT> setOutput(
- unused: Class<NewOutputT>
- ): ActionSpecBuilder<ArgumentsT, ArgumentsBuilderT, NewOutputT> {
- return ActionSpecBuilder(this.capabilityName,
- this.argumentBuilderSupplier,
- this.builderFinalizer
- )
- }
-
- /**
- * Binds the parameter name, getter and setter.
- *
- * @param paramName the name of this action' parameter.
- * @param paramGetter a getter of the param-specific info from the property.
- * @param argumentSetter a setter to the argument with the input from `ParamValue`.
- * @param argumentSerializer a function that serializes this slot on an argument instance.
- * @return the builder itself.
- */
- private fun bindParameterInternal(
- paramName: String,
- argumentSetter: ArgumentSetter<ArgumentsBuilderT>,
- argumentSerializer: (ArgumentsT) -> List<ParamValue>
- ): ActionSpecBuilder<ArgumentsT, ArgumentsBuilderT, OutputT> {
- paramBindingList.add(ParamBinding(paramName, argumentSetter, argumentSerializer))
- return this
- }
-
- /**
- * Binds the parameter name, and corresponding method references for setting Argument value.
- *
- * If the Property getter returns a null value, this parameter will not exist in the parameter
- * definition of the capability.
- *
- * @param paramName the name of this action' parameter.
- * @param paramGetter the function reference that returns the parameter given [Arguments].
- * @param paramConsumer a setter to set the string value in the argument builder.
- * @param paramValueConverter converter FROM assistant ParamValue proto
- * @return the builder itself.
- */
- fun <T> bindParameter(
- paramName: String,
- paramGetter: (ArgumentsT) -> T?,
- paramConsumer: BiConsumer<in ArgumentsBuilderT, T>,
- paramValueConverter: ParamValueConverter<T>,
- ): ActionSpecBuilder<ArgumentsT, ArgumentsBuilderT, OutputT> {
- return bindParameterInternal(
- paramName,
- { argBuilder: ArgumentsBuilderT, paramList: List<ParamValue> ->
- if (paramList.isNotEmpty()) {
- paramConsumer.accept(
- argBuilder,
- SlotTypeConverter.ofSingular(paramValueConverter).convert(paramList)
- )
- }
- },
- {
- arguments ->
- listOf(
- paramGetter(arguments)?.let(paramValueConverter::toParamValue)
- ).filterNotNull()
- }
- )
- }
-
- /**
- * This is similar to [ActionSpecBuilder.bindParameter] but for setting a list of
- * entities instead.
- *
- * If the Property getter returns a null value, this parameter will not exist in the parameter
- * definition of the capability.
- */
- fun <T> bindRepeatedParameter(
- paramName: String,
- paramGetter: (ArgumentsT) -> List<T>,
- paramConsumer: BiConsumer<in ArgumentsBuilderT, List<T>>,
- paramValueConverter: ParamValueConverter<T>
- ): ActionSpecBuilder<ArgumentsT, ArgumentsBuilderT, OutputT> {
- return bindParameterInternal(
- paramName,
- { argBuilder: ArgumentsBuilderT, paramList: List<ParamValue?>? ->
- paramConsumer.accept(
- argBuilder,
- SlotTypeConverter.ofRepeated(paramValueConverter).convert(paramList!!)
- )
- },
- {
- arguments -> paramGetter(arguments).filterNotNull().map(
- paramValueConverter::toParamValue
- )
- }
- )
- }
-
- /**
- * Binds an optional output.
- *
- * @param name the BII output slot name of this parameter.
- * @param outputFieldGetter a getter of the output from the `OutputT` instance.
- * @param converter a converter from an output object to a ParamValue.
- */
- // TODO(dennistwo) after all usages of this overload is removed, remove this method
- fun <T> bindOutput(
- name: String,
- outputFieldGetter: Function<OutputT, T?>,
- converter: Function<T, ParamValue>
- ): ActionSpecBuilder<ArgumentsT, ArgumentsBuilderT, OutputT> {
- outputBindings[name] = Function { output: OutputT ->
- val outputField: T? = outputFieldGetter.apply(output)
- val paramValues: MutableList<ParamValue> =
- ArrayList()
- if (outputField != null) {
- paramValues.add(converter.apply(outputField))
- }
- paramValues.toList()
- }
- return this
- }
-
- fun <T> bindOutput(
- name: String,
- outputFieldGetter: Function<OutputT, T?>,
- converter: ParamValueConverter<T>
- ) = bindOutput(name, outputFieldGetter, converter::toParamValue)
-
- /**
- * Binds a repeated output.
- *
- * @param name the BII output slot name of this parameter.
- * @param outputGetter a getter of the output from the `OutputT` instance.
- * @param converter a converter from an output object to a ParamValue.
- */
- fun <T> bindRepeatedOutput(
- name: String,
- outputGetter: Function<OutputT, List<T>>,
- converter: Function<T, ParamValue>
- ): ActionSpecBuilder<ArgumentsT, ArgumentsBuilderT, OutputT> {
- outputBindings[name] = Function { output: OutputT ->
- outputGetter.apply(output).stream()
- .map(converter)
- .collect(ImmutableCollectors.toImmutableList())
- }
- return this
- }
-
- fun <T> bindRepeatedOutput(
- name: String,
- outputGetter: Function<OutputT, List<T>>,
- converter: ParamValueConverter<T>
- ) = bindRepeatedOutput(name, outputGetter, converter::toParamValue)
-
- /** Builds an `ActionSpec` from this builder. */
- fun build(): ActionSpec<ArgumentsT, OutputT> {
- return ActionSpecImpl(
- capabilityName,
- argumentBuilderSupplier,
- paramBindingList.toList(),
- outputBindings.toMap(),
- builderFinalizer
- )
- }
-
- companion object {
- /**
- * Creates an empty `ActionSpecBuilder` with the given capability name. ArgumentsT is set
- * to Object as a placeholder, which must be replaced by calling setArgument.
- */
- fun ofCapabilityNamed(
- capabilityName: String
- ): ActionSpecBuilder<Any, Any, Any> {
- return ActionSpecBuilder(capabilityName, { Supplier { Object() } }) {
- Function<Any, Any> { Object() }
- }
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecImpl.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecImpl.kt
deleted file mode 100644
index 45fe447..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecImpl.kt
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.spec
-
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import androidx.appactions.interaction.proto.FulfillmentResponse
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.proto.TaskInfo
-import java.util.function.Function
-import java.util.function.Supplier
-
-/** The implementation of `ActionSpec` interface. */
-internal class ActionSpecImpl<ArgumentsT, ArgumentsBuilderT, OutputT>(
- override val capabilityName: String,
- private val argumentBuilderSupplier: Supplier<ArgumentsBuilderT>,
- private val paramBindingList: List<ParamBinding<ArgumentsT, ArgumentsBuilderT>>,
- private val outputBindings: Map<String, Function<OutputT, List<ParamValue>>>,
- private val builderFinalizer: Function<ArgumentsBuilderT, ArgumentsT>
-) : ActionSpec<ArgumentsT, OutputT> {
- override fun createAppAction(
- identifier: String,
- boundProperties: List<BoundProperty<*>>,
- supportsPartialFulfillment: Boolean
- ): AppAction = AppAction.newBuilder()
- .setName(capabilityName)
- .setIdentifier(identifier)
- .addAllParams(
- boundProperties.map(BoundProperty<*>::convertToProto)
- )
- .setTaskInfo(
- TaskInfo.newBuilder().setSupportsPartialFulfillment(supportsPartialFulfillment)
- )
- .build()
-
- @Throws(StructConversionException::class)
- override fun buildArguments(args: Map<String, List<ParamValue>>): ArgumentsT {
- val argumentBuilder = argumentBuilderSupplier.get()
- paramBindingList.forEach { binding ->
- val paramValues = args[binding.name] ?: return@forEach
- try {
- binding.argumentSetter.setArguments(argumentBuilder, paramValues)
- } catch (e: StructConversionException) {
- // Wrap the exception with a more meaningful error message.
- throw StructConversionException(
- "Failed to parse parameter '${binding.name}' from assistant because of" +
- " failure: ${e.message}"
- )
- }
- }
- return builderFinalizer.apply(argumentBuilder)
- }
-
- override fun serializeArguments(args: ArgumentsT): Map<String, List<ParamValue>> {
- val paramValuesMap = mutableMapOf<String, List<ParamValue>>()
- paramBindingList.forEach {
- binding ->
- val paramValues = binding.argumentSerializer(args)
- if (paramValues.size > 0) {
- paramValuesMap[binding.name] = paramValues
- }
- }
- return paramValuesMap.toMap()
- }
-
- override fun convertOutputToProto(output: OutputT): FulfillmentResponse.StructuredOutput {
- val outputBuilder = FulfillmentResponse.StructuredOutput.newBuilder()
- outputBindings.entries.forEach { entry ->
- val paramValues = entry.value.apply(output)
- if (paramValues.isNotEmpty()) {
- outputBuilder.addOutputValues(
- FulfillmentResponse.StructuredOutput.OutputValue.newBuilder()
- .setName(entry.key)
- .addAllValues(paramValues)
- .build()
- )
- }
- }
- return outputBuilder.build()
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecRegistry.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecRegistry.kt
deleted file mode 100644
index 662e2f1..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecRegistry.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-
-/*
- * 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.appactions.interaction.capabilities.core.impl.spec
-
-import androidx.annotation.VisibleForTesting
-import java.util.IdentityHashMap
-import kotlin.reflect.KClass
-
-/**
- * Contains a mapping of argument Class to its ActionSpec. This is used for testing.
- * The ActionSpec can be used to convert an Arguments instance into wire-format representation.
- */
-object ActionSpecRegistry {
- private val argumentsClassToActionSpec = IdentityHashMap<Class<*>, ActionSpec<Any, *>>()
- private val outputClassToActionSpec = IdentityHashMap<Class<*>, ActionSpec<*, Any>>()
-
- @Suppress("UNCHECKED_CAST")
- fun <T : Any, R : Any> registerActionSpec(
- argumentsClass: KClass<T>,
- outputClass: KClass<R>,
- actionSpec: ActionSpec<T, R>
- ) {
- argumentsClassToActionSpec.put(
- argumentsClass.java,
- actionSpec as ActionSpec<Any, *>
- )
- outputClassToActionSpec.put(
- outputClass.java,
- actionSpec as ActionSpec<*, Any>
- )
- }
-
- @VisibleForTesting
- fun getActionSpecForArguments(arguments: Any): ActionSpec<Any, *>? {
- return argumentsClassToActionSpec[arguments.javaClass]
- }
-
- @VisibleForTesting
- fun getActionSpecForOutput(output: Any): ActionSpec<*, Any>? {
- return outputClassToActionSpec[output.javaClass]
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/BoundProperty.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/BoundProperty.kt
deleted file mode 100644
index 8b336bf..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/BoundProperty.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.spec
-
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter
-import androidx.appactions.interaction.capabilities.core.impl.utils.invokeExternalBlock
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter
-
-/** Wrapper around [Property] and a type-specific EntityConverter. */
-data class BoundProperty<T> internal constructor(
- val slotName: String,
- val property: Property<T>,
- val entityConverter: EntityConverter<T>
-) {
- /** * Convert this wrapped Property into [IntentParameter] proto representation with
- * current inventory.
- */
- fun convertToProto(): IntentParameter {
- val builder = IntentParameter.newBuilder()
- .setName(slotName)
- .setIsRequired(property.isRequiredForExecution)
- .setEntityMatchRequired(property.shouldMatchPossibleValues)
- .setIsProhibited(!property.isSupported)
- invokeExternalBlock("retrieving possibleValues for $slotName property") {
- property.possibleValues
- }.map {
- entityConverter.convert(it)
- }.forEach {
- builder.addPossibleEntities(it)
- }
- return builder.build()
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ParamBinding.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ParamBinding.kt
deleted file mode 100644
index ec9f996..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/spec/ParamBinding.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.spec
-
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException
-import androidx.appactions.interaction.proto.ParamValue
-
-data class ParamBinding<ArgumentsT, ArgumentsBuilderT>
-internal constructor(
- val name: String,
- val argumentSetter: ArgumentSetter<ArgumentsBuilderT>,
- /**
- * Given a ArgumentsT instance, return a list of ParamValue for this slot.
- */
- val argumentSerializer: (ArgumentsT) -> List<ParamValue>
-) {
- /**
- * Given a `List<ParamValue>`, convert it to user-visible type and set it into
- * ArgumentBuilder.
- */
- fun interface ArgumentSetter<ArgumentsBuilderT> {
- /** Conversion from protos to user-visible type. */
- @Throws(StructConversionException::class)
- fun setArguments(builder: ArgumentsBuilderT, paramValues: List<ParamValue>)
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/AbstractTaskUpdater.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/AbstractTaskUpdater.java
deleted file mode 100644
index d97ea1a..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/AbstractTaskUpdater.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task;
-
-import androidx.annotation.NonNull;
-import androidx.appactions.interaction.proto.ParamValue;
-
-import java.util.List;
-import java.util.Map;
-
-/** Base class for BII-specific TaskUpdater for manual input. */
-public abstract class AbstractTaskUpdater {
-
- private TaskUpdateHandler mTaskUpdateHandler;
- private boolean mIsDestroyed = false;
-
- /** Will fail silently if task processing is in the middle of another SYNC request. */
- protected void updateParamValues(@NonNull Map<String, List<ParamValue>> paramValuesMap) {
- if (mIsDestroyed || mTaskUpdateHandler == null) {
- return;
- }
- this.mTaskUpdateHandler.updateParamValues(paramValuesMap);
- }
-
- void init(@NonNull TaskUpdateHandler taskUpdateHandler) {
- this.mTaskUpdateHandler = taskUpdateHandler;
- }
-
- void destroy() {
- this.mIsDestroyed = true;
- }
-
- /** Returns true if the applicable task is terminated. */
- public boolean isDestroyed() {
- return mIsDestroyed;
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/AppGroundingResult.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/AppGroundingResult.kt
deleted file mode 100644
index 638c212e..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/AppGroundingResult.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task
-
-import androidx.appactions.interaction.proto.CurrentValue
-import androidx.appactions.interaction.proto.ParamValue
-
-data class AppGroundingResult private constructor(
- val kind: Kind,
- val success: ParamValue?,
- val failure: CurrentValue?
-) {
- enum class Kind {
- SUCCESS,
- FAILURE
- }
-
- companion object {
- @JvmStatic
- fun ofSuccess(paramValue: ParamValue) = AppGroundingResult(Kind.SUCCESS, paramValue, null)
-
- @JvmStatic
- fun ofFailure(currentValue: CurrentValue) =
- AppGroundingResult(Kind.FAILURE, null, currentValue)
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/AssistantUpdateRequest.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/AssistantUpdateRequest.kt
deleted file mode 100644
index 06a6d39..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/AssistantUpdateRequest.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task
-
-import androidx.appactions.interaction.capabilities.core.impl.ArgumentsWrapper
-import androidx.appactions.interaction.capabilities.core.impl.CallbackInternal
-
-/**
- * Represents a fulfillment request coming from Assistant.
- *
- * @param argumentsWrapper The fulfillment request data.
- * @param callbackInternal The callback to report results from handling this request.
- */
-internal data class AssistantUpdateRequest(
- val argumentsWrapper: ArgumentsWrapper,
- val callbackInternal: CallbackInternal,
-)
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/EmptyTaskUpdater.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/EmptyTaskUpdater.java
deleted file mode 100644
index 0f341da..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/EmptyTaskUpdater.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task;
-
-/** Useful for capabilities that do not support a TaskUpdater. */
-public final class EmptyTaskUpdater extends AbstractTaskUpdater {
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/GenericResolverInternal.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/GenericResolverInternal.kt
deleted file mode 100644
index 32813dc..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/GenericResolverInternal.kt
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task
-
-import androidx.appactions.interaction.capabilities.core.AppEntityListListener
-import androidx.appactions.interaction.capabilities.core.AppEntityListener
-import androidx.appactions.interaction.capabilities.core.EntitySearchResult
-import androidx.appactions.interaction.capabilities.core.InventoryListListener
-import androidx.appactions.interaction.capabilities.core.InventoryListener
-import androidx.appactions.interaction.capabilities.core.SearchAction
-import androidx.appactions.interaction.capabilities.core.ValidationResult
-import androidx.appactions.interaction.capabilities.core.ValueListener
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.SlotTypeConverter
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException
-import androidx.appactions.interaction.capabilities.core.impl.task.exceptions.InvalidResolverException
-import androidx.appactions.interaction.capabilities.core.impl.utils.invokeExternalSuspendBlock
-import androidx.appactions.interaction.proto.ParamValue
-
-/**
- * A wrapper around all types of slot resolvers (value listeners + disambig resolvers).
- *
- * This allows one type of resolver to be bound for each slot, and abstracts the details of the
- * individual resolvers. It is also the place where repeated fields are handled.
- *
- * </ValueTypeT>
- */
-internal class GenericResolverInternal<ValueTypeT>
-private constructor(
- val value: ValueListener<ValueTypeT>? = null,
- val valueList: ValueListener<List<ValueTypeT>>? = null,
- val appEntity: AppEntityListener<ValueTypeT>? = null,
- val appEntityList: AppEntityListListener<ValueTypeT>? = null,
- val inventory: InventoryListener<ValueTypeT>? = null,
- val inventoryList: InventoryListListener<ValueTypeT>? = null
-) {
-
- /** Wrapper which should invoke the `lookupAndRender` provided by the developer. */
- @Throws(InvalidResolverException::class)
- suspend fun invokeLookup(
- searchAction: SearchAction<ValueTypeT>
- ): EntitySearchResult<ValueTypeT> {
- return if (appEntity != null) {
- invokeExternalSuspendBlock("lookupAndRender") {
- appEntity.lookupAndRender(searchAction)
- }
- } else if (appEntityList != null) {
- invokeExternalSuspendBlock("lookupAndRender") {
- appEntityList.lookupAndRender(searchAction)
- }
- } else {
- throw InvalidResolverException("invokeLookup is not supported on this resolver")
- }
- }
-
- /**
- * Wrapper which should invoke the EntityRender#renderEntities method when the Assistant is
- * prompting for disambiguation.
- */
- @Throws(InvalidResolverException::class)
- suspend fun invokeEntityRender(entityIds: List<String>) {
- if (inventory != null) {
- invokeExternalSuspendBlock("renderChoices") {
- inventory.renderChoices(entityIds)
- }
- } else if (inventoryList != null) {
- invokeExternalSuspendBlock("renderChoices") {
- inventoryList.renderChoices(entityIds)
- }
- } else {
- throw InvalidResolverException("invokeEntityRender is not supported on this resolver")
- }
- }
-
- /**
- * Notifies the app that a new value for this argument has been set by Assistant. This method
- * should only be called with completely grounded values.
- */
- @Throws(StructConversionException::class)
- suspend fun notifyValueChange(
- paramValues: List<ParamValue>,
- converter: ParamValueConverter<ValueTypeT>
- ): ValidationResult {
- val singularValue = SlotTypeConverter.ofSingular(converter).convert(paramValues)
- val repeatedValues = SlotTypeConverter.ofRepeated(converter).convert(paramValues)
- return invokeExternalSuspendBlock("onReceived") {
- when {
- value != null -> value.onReceived(singularValue)
- valueList != null -> valueList.onReceived(repeatedValues)
- appEntity != null -> appEntity.onReceived(singularValue)
- appEntityList != null -> appEntityList.onReceived(repeatedValues)
- inventory != null -> inventory.onReceived(singularValue)
- inventoryList != null -> inventoryList.onReceived(repeatedValues)
- else -> throw IllegalStateException("unreachable")
- }
- }
- }
-
- companion object {
- fun <ValueTypeT> fromValueListener(valueListener: ValueListener<ValueTypeT>) =
- GenericResolverInternal(value = valueListener)
-
- fun <ValueTypeT> fromValueListListener(valueListListener: ValueListener<List<ValueTypeT>>) =
- GenericResolverInternal(valueList = valueListListener)
-
- fun <ValueTypeT> fromAppEntityListener(appEntity: AppEntityListener<ValueTypeT>) =
- GenericResolverInternal(appEntity = appEntity)
-
- fun <ValueTypeT> fromAppEntityListListener(
- appEntityList: AppEntityListListener<ValueTypeT>
- ) = GenericResolverInternal(appEntityList = appEntityList)
-
- fun <ValueTypeT> fromInventoryListener(inventory: InventoryListener<ValueTypeT>) =
- GenericResolverInternal(inventory = inventory)
-
- fun <ValueTypeT> fromInventoryListListener(
- inventoryList: InventoryListListener<ValueTypeT>
- ) = GenericResolverInternal(inventoryList = inventoryList)
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/OnReadyToConfirmListener.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/OnReadyToConfirmListener.kt
deleted file mode 100644
index ed30805..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/OnReadyToConfirmListener.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task
-
-import androidx.annotation.RestrictTo
-import androidx.appactions.interaction.capabilities.core.ConfirmationOutput
-
-/**
- * Generic onReadyToConfirm listener for a task capability.
- * This should wrap only the external Session#onReadyToConfirm and nothing else.
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-interface OnReadyToConfirmListener<ArgumentsT, ConfirmationT> {
- /** onReadyToConfirm callback for a task session. */
- suspend fun onReadyToConfirm(arguments: ArgumentsT): ConfirmationOutput<ConfirmationT>
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/SessionBridge.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/SessionBridge.kt
deleted file mode 100644
index 225f3f8..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/SessionBridge.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task
-
-import androidx.annotation.RestrictTo
-
-/**
- * Converts an external Session into TaskHandler instance.
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-fun interface SessionBridge<
- ExecutionSessionT,
- ArgumentsT,
- ConfirmationT
-> {
- fun createTaskHandler(
- externalSession: ExecutionSessionT
- ): TaskHandler<ArgumentsT, ConfirmationT>
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/SlotProcessingResult.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/SlotProcessingResult.kt
deleted file mode 100644
index 7813bdd..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/SlotProcessingResult.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task
-
-import androidx.appactions.interaction.proto.CurrentValue
-
-/**
- * @param isSuccessful Whether or not the next slot should be processed. This is true if the
- * following conditions were met during processing.
- * * there are no ungrounded values remaining (either rejected or disambig)
- * * listener#onReceived returned ACCEPTED for all grounded values (which could be empty list)
- *
- * @param processedValues Processed CurrentValue objects.
- */
-internal data class SlotProcessingResult(
- val isSuccessful: Boolean,
- val processedValues: List<CurrentValue>,
-)
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilityImpl.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilityImpl.kt
deleted file mode 100644
index dc0dd7e..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilityImpl.kt
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task
-
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.core.impl.CapabilitySession
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpec
-import androidx.appactions.interaction.capabilities.core.impl.spec.BoundProperty
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import java.util.function.Supplier
-
-/**
- * @param id a unique id for this capability, can be null
- * @param actionSpec the ActionSpec for this capability
- * @param sessionFactory the function usd to create a ExecutionSession from HostProperties.
- * @param sessionBridge a SessionBridge object that converts ExecutionSessionT into TaskHandler
- * instance
- * @param sessionUpdaterSupplier a Supplier of SessionUpdaterT instances
- */
-internal class TaskCapabilityImpl<
- ArgumentsT,
- OutputT,
- ExecutionSessionT : BaseExecutionSession<ArgumentsT, OutputT>,
- ConfirmationT,
- SessionUpdaterT
- >
-constructor(
- id: String,
- private val actionSpec: ActionSpec<ArgumentsT, OutputT>,
- private val boundProperties: List<BoundProperty<*>>,
- private val sessionFactory: (hostProperties: HostProperties?) -> ExecutionSessionT,
- private val sessionBridge: SessionBridge<ExecutionSessionT, ArgumentsT, ConfirmationT>,
- private val sessionUpdaterSupplier: Supplier<SessionUpdaterT>
-) : Capability(id) {
-
- override val appAction: AppAction get() = actionSpec.createAppAction(
- id,
- boundProperties,
- supportsPartialFulfillment = true
- )
-
- override fun createSession(
- sessionId: String,
- hostProperties: HostProperties
- ): CapabilitySession {
- val externalSession = sessionFactory.invoke(hostProperties)
- return TaskCapabilitySession(
- sessionId,
- actionSpec,
- appAction,
- sessionBridge.createTaskHandler(externalSession),
- externalSession
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilitySession.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilitySession.kt
deleted file mode 100644
index f51e21b12..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilitySession.kt
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task
-
-import androidx.annotation.GuardedBy
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.impl.ArgumentsWrapper
-import androidx.appactions.interaction.capabilities.core.impl.CallbackInternal
-import androidx.appactions.interaction.capabilities.core.impl.CapabilitySession
-import androidx.appactions.interaction.capabilities.core.impl.ErrorStatusInternal
-import androidx.appactions.interaction.capabilities.core.impl.TouchEventCallback
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpec
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import androidx.appactions.interaction.proto.AppActionsContext.AppDialogState
-import androidx.appactions.interaction.proto.ParamValue
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.CoroutineStart
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.cancel
-import kotlinx.coroutines.launch
-
-internal class TaskCapabilitySession<
- ArgumentsT,
- OutputT,
- ConfirmationT,
->(
- override val sessionId: String,
- actionSpec: ActionSpec<ArgumentsT, OutputT>,
- appAction: AppAction,
- taskHandler: TaskHandler<ArgumentsT, ConfirmationT>,
- externalSession: BaseExecutionSession<ArgumentsT, OutputT>,
- private val scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
-) : CapabilitySession, TaskUpdateHandler {
- override val state: AppDialogState
- get() = sessionOrchestrator.appDialogState
-
- // single-turn capability does not have status
- override val isActive: Boolean
- get() = when (sessionOrchestrator.status) {
- TaskOrchestrator.Status.DESTROYED -> false
- else -> true
- }
-
- override fun destroy() {
- this.sessionOrchestrator.terminate()
- scope.cancel()
- }
-
- override val uiHandle: Any = externalSession
-
- /** synchronize on this lock to enqueue assistant/manual input requests. */
- private val requestLock = Any()
-
- /** Contains session state and request processing logic. */
- private val sessionOrchestrator:
- TaskOrchestrator<
- ArgumentsT,
- OutputT,
- ConfirmationT,
- > =
- TaskOrchestrator(
- sessionId,
- actionSpec,
- appAction,
- taskHandler,
- externalSession,
- scope,
- )
- @GuardedBy("requestLock")
- private var pendingAssistantRequest: AssistantUpdateRequest? = null
- @GuardedBy("requestLock") private var pendingTouchEventRequest: TouchEventUpdateRequest? = null
-
- override fun execute(argumentsWrapper: ArgumentsWrapper, callback: CallbackInternal) {
- enqueueAssistantRequest(AssistantUpdateRequest(argumentsWrapper, callback))
- }
-
- override fun updateParamValues(paramValuesMap: Map<String, List<ParamValue>>) {
- enqueueTouchEventRequest(TouchEventUpdateRequest(paramValuesMap))
- }
-
- override fun setTouchEventCallback(callback: TouchEventCallback) {
- sessionOrchestrator.setTouchEventCallback(callback)
- }
-
- /**
- * If there is a pendingAssistantRequest, we will overwrite that request (and send CANCELLED
- * response to that request).
- *
- * <p>This is done because assistant requests contain the full state, so we can safely ignore
- * existing requests if a new one arrives.
- */
- private fun enqueueAssistantRequest(request: AssistantUpdateRequest) {
- synchronized(requestLock) {
- pendingAssistantRequest?.callbackInternal?.onError(ErrorStatusInternal.CANCELED)
- pendingAssistantRequest = request
- dispatchPendingRequestIfIdle()
- }
- }
-
- private fun enqueueTouchEventRequest(request: TouchEventUpdateRequest) {
- synchronized(requestLock) {
- pendingTouchEventRequest =
- if (pendingTouchEventRequest == null) request
- else pendingTouchEventRequest!!.mergeWith(request)
- dispatchPendingRequestIfIdle()
- }
- }
-
- /**
- * If sessionOrchestrator is idle, select the next request to dispatch to sessionOrchestrator
- * (if there are any pending requests).
- *
- * <p>If sessionOrchestrator is not idle, do nothing, since this method will automatically be
- * called when sessionOrchestrator becomes idle.
- */
- private fun dispatchPendingRequestIfIdle() {
- synchronized(requestLock) {
- if (!sessionOrchestrator.isIdle()) {
- return
- }
- var nextRequest: UpdateRequest? = null
- if (pendingAssistantRequest != null) {
- nextRequest = UpdateRequest(pendingAssistantRequest!!)
- pendingAssistantRequest = null
- } else if (pendingTouchEventRequest != null) {
- nextRequest = UpdateRequest(pendingTouchEventRequest!!)
- pendingTouchEventRequest = null
- }
- if (nextRequest != null) {
- scope.launch(start = CoroutineStart.UNDISPATCHED) {
- sessionOrchestrator.processUpdateRequest(nextRequest)
- dispatchPendingRequestIfIdle()
- }
- }
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilityUtils.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilityUtils.kt
deleted file mode 100644
index 3ecc58c..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilityUtils.kt
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task
-
-import androidx.appactions.interaction.proto.AppActionsContext
-import androidx.appactions.interaction.proto.CurrentValue
-import androidx.appactions.interaction.proto.DisambiguationData
-import androidx.appactions.interaction.proto.Entity
-import androidx.appactions.interaction.proto.FulfillmentRequest
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.protobuf.Struct
-import java.util.Arrays
-
-/** Utility methods used for implementing Task Capabilities. */
-internal object TaskCapabilityUtils {
- /** Uses Property to detect if all required arguments are present. */
- fun isSlotFillingComplete(
- finalArguments: Map<String, List<ParamValue>>,
- paramsList: List<AppActionsContext.IntentParameter>
- ) = paramsList.filter { it.isRequired }.map { it.name }.all { finalArguments.containsKey(it) }
-
- fun paramValuesToCurrentValue(
- paramValueList: List<ParamValue>,
- status: CurrentValue.Status
- ): List<CurrentValue> = paramValueList.map { toCurrentValue(it, status) }
-
- private fun paramValuesToFulfillmentValues(
- paramValueList: List<ParamValue>
- ): List<FulfillmentRequest.Fulfillment.FulfillmentValue> =
- paramValueList.map {
- FulfillmentRequest.Fulfillment.FulfillmentValue.newBuilder().setValue(it).build()
- }
-
- fun paramValuesMapToFulfillmentValuesMap(
- paramValueMap: Map<String, List<ParamValue>>
- ): Map<String, List<FulfillmentRequest.Fulfillment.FulfillmentValue>> =
- paramValueMap.entries.associate { entry ->
- entry.key to paramValuesToFulfillmentValues(entry.value)
- }
-
- fun fulfillmentValuesToCurrentValues(
- fulfillmentValueList: List<FulfillmentRequest.Fulfillment.FulfillmentValue>,
- status: CurrentValue.Status
- ): List<CurrentValue> = fulfillmentValueList.map { toCurrentValue(it, status) }
-
- fun toCurrentValue(paramValue: ParamValue, status: CurrentValue.Status): CurrentValue =
- CurrentValue.newBuilder().setValue(paramValue).setStatus(status).build()
-
- private fun toCurrentValue(
- fulfillmentValue: FulfillmentRequest.Fulfillment.FulfillmentValue,
- status: CurrentValue.Status
- ): CurrentValue {
- val result = CurrentValue.newBuilder()
- if (fulfillmentValue.hasValue()) {
- result.value = fulfillmentValue.value
- }
- if (fulfillmentValue.hasDisambigData()) {
- result.disambiguationData = fulfillmentValue.disambigData
- }
- return result.setStatus(status).build()
- }
-
- fun groundedValueToParamValue(groundedEntity: Entity): ParamValue =
- if (groundedEntity.hasStructValue())
- ParamValue.newBuilder()
- .setIdentifier(groundedEntity.identifier)
- .setStructValue(groundedEntity.structValue)
- .build()
- else
- ParamValue.newBuilder()
- .setIdentifier(groundedEntity.identifier)
- .setStringValue(groundedEntity.name)
- .build()
-
- /** Create a [CurrentValue] based on Disambiguation result for a ParamValue. */
- fun getCurrentValueForDisambiguation(
- paramValue: ParamValue,
- disambiguationEntities: List<Entity>
- ): CurrentValue =
- CurrentValue.newBuilder()
- .setValue(paramValue)
- .setStatus(CurrentValue.Status.DISAMBIG)
- .setDisambiguationData(
- DisambiguationData.newBuilder().addAllEntities(disambiguationEntities)
- )
- .build()
-
- /** Compares two [ParamValue], returns false if they are equivalent, true otherwise. */
- private fun hasParamValueDiff(oldArg: ParamValue, newArg: ParamValue): Boolean {
- if (oldArg.valueCase.number != newArg.valueCase.number) {
- return true
- }
- return if (oldArg.identifier != newArg.identifier) {
- true
- } else
- when (oldArg.valueCase) {
- ParamValue.ValueCase.VALUE_NOT_SET -> false
- ParamValue.ValueCase.STRING_VALUE -> oldArg.stringValue != newArg.stringValue
- ParamValue.ValueCase.BOOL_VALUE -> oldArg.boolValue != newArg.boolValue
- ParamValue.ValueCase.NUMBER_VALUE -> oldArg.numberValue != newArg.numberValue
- ParamValue.ValueCase.STRUCT_VALUE ->
- !Arrays.equals(
- oldArg.structValue.toByteArray(),
- newArg.structValue.toByteArray()
- )
- else -> true
- }
- }
-
- /**
- * Returns true if we can skip processing of new [fulfillmentValues] for a slot.
- *
- * There are two required conditions for skipping processing:
- * * 1. [currentValues] are all ACCEPTED.
- * * 2. there are no differences between the [ParamValue]s in [currentValues] and
- * [fulfillmentValues].
- */
- fun canSkipSlotProcessing(
- currentValues: List<CurrentValue>,
- fulfillmentValues: List<FulfillmentRequest.Fulfillment.FulfillmentValue>
- ): Boolean =
- currentValues.all { it.status == CurrentValue.Status.ACCEPTED } &&
- currentValues.size == fulfillmentValues.size &&
- fulfillmentValues.indices.all {
- !hasParamValueDiff(currentValues[it].value, fulfillmentValues[it].value)
- }
-
- /** Given a [List<CurrentValue>], find all the Struct in them as a Map. */
- private fun getStructsFromCurrentValues(
- currentValues: List<CurrentValue>
- ): Map<String, Struct> {
- val candidates = mutableMapOf<String, Struct>()
- for (currentValue in currentValues) {
- if (
- currentValue.status == CurrentValue.Status.ACCEPTED &&
- currentValue.value.hasStructValue()
- ) {
- candidates[currentValue.value.identifier] = currentValue.value.structValue
- } else if (currentValue.status == CurrentValue.Status.DISAMBIG) {
- for (entity in currentValue.disambiguationData.entitiesList) {
- if (entity.hasStructValue()) {
- candidates[entity.identifier] = entity.structValue
- }
- }
- }
- }
- return candidates.toMap()
- }
-
- /**
- * Grounded values for donated inventory slots are sent as identifier only, so find matching
- * Struct from previous turn and add them to the fulfillment values.
- */
- fun getMaybeModifiedSlotValues(
- currentValues: List<CurrentValue>,
- newSlotValues: List<FulfillmentRequest.Fulfillment.FulfillmentValue>
- ): List<FulfillmentRequest.Fulfillment.FulfillmentValue> {
- val candidates = getStructsFromCurrentValues(currentValues)
- return if (candidates.isEmpty()) {
- newSlotValues
- } else
- newSlotValues.map {
- val paramValue = it.value
- if (
- paramValue.hasIdentifier() &&
- !paramValue.hasStructValue() &&
- candidates.containsKey(paramValue.identifier)
- ) {
- // TODO(b/243944366) throw error if struct filling fails for an
- // inventory slot.
- return@map it.toBuilder()
- .setValue(
- paramValue.toBuilder().setStructValue(candidates[paramValue.identifier])
- )
- .build()
- }
- it
- }
- }
-}
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
deleted file mode 100644
index d4d418a..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskHandler.kt
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task
-
-import androidx.annotation.RestrictTo
-import androidx.appactions.interaction.capabilities.core.AppEntityListListener
-import androidx.appactions.interaction.capabilities.core.AppEntityListener
-import androidx.appactions.interaction.capabilities.core.InventoryListListener
-import androidx.appactions.interaction.capabilities.core.InventoryListener
-import androidx.appactions.interaction.capabilities.core.ValueListener
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.SearchActionConverter
-import androidx.appactions.interaction.proto.ParamValue
-
-/** Container of multi-turn Task related function references. */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-data class TaskHandler<ArgumentsT, ConfirmationT>
-internal constructor(
- internal val taskParamMap: Map<String, TaskParamBinding<*>>,
- internal val confirmationDataBindings: Map<String, (ConfirmationT) -> List<ParamValue>>,
- internal val onReadyToConfirmListener: OnReadyToConfirmListener<ArgumentsT, ConfirmationT>?,
-) {
- class Builder<ArgumentsT, ConfirmationT> {
- private val mutableTaskParamMap = mutableMapOf<String, TaskParamBinding<*>>()
- private val confirmationDataBindings =
- mutableMapOf<String, (ConfirmationT) -> List<ParamValue>>()
- private var onReadyToConfirmListener: OnReadyToConfirmListener<ArgumentsT, ConfirmationT>? =
- null
-
- fun <ValueTypeT> registerInventoryTaskParam(
- paramName: String,
- listener: InventoryListener<ValueTypeT>,
- converter: ParamValueConverter<ValueTypeT>,
- ) = apply {
- mutableTaskParamMap[paramName] =
- TaskParamBinding(
- paramName,
- GROUND_NEVER,
- GenericResolverInternal.fromInventoryListener(listener),
- converter,
- null,
- null,
- )
- }
-
- fun <ValueTypeT> registerInventoryListTaskParam(
- paramName: String,
- listener: InventoryListListener<ValueTypeT>,
- converter: ParamValueConverter<ValueTypeT>,
- ) = apply {
- mutableTaskParamMap[paramName] =
- TaskParamBinding(
- paramName,
- GROUND_NEVER,
- GenericResolverInternal.fromInventoryListListener(listener),
- converter,
- null,
- null,
- )
- }
-
- fun <ValueTypeT> registerAppEntityTaskParam(
- paramName: String,
- listener: AppEntityListener<ValueTypeT>,
- converter: ParamValueConverter<ValueTypeT>,
- entityConverter: EntityConverter<ValueTypeT>,
- searchActionConverter: SearchActionConverter<ValueTypeT>,
- ) = apply {
- mutableTaskParamMap[paramName] =
- TaskParamBinding(
- paramName,
- GROUND_IF_NO_IDENTIFIER,
- GenericResolverInternal.fromAppEntityListener(listener),
- converter,
- entityConverter,
- searchActionConverter,
- )
- }
-
- fun <ValueTypeT> registerAppEntityListTaskParam(
- paramName: String,
- listener: AppEntityListListener<ValueTypeT>,
- converter: ParamValueConverter<ValueTypeT>,
- entityConverter: EntityConverter<ValueTypeT>,
- searchActionConverter: SearchActionConverter<ValueTypeT>,
- ) = apply {
- mutableTaskParamMap[paramName] =
- TaskParamBinding(
- paramName,
- GROUND_IF_NO_IDENTIFIER,
- GenericResolverInternal.fromAppEntityListListener(listener),
- converter,
- entityConverter,
- searchActionConverter,
- )
- }
-
- fun <ValueTypeT> registerValueTaskParam(
- paramName: String,
- listener: ValueListener<ValueTypeT>,
- converter: ParamValueConverter<ValueTypeT>,
- ) = apply {
- mutableTaskParamMap[paramName] =
- TaskParamBinding(
- paramName,
- GROUND_NEVER,
- GenericResolverInternal.fromValueListener(listener),
- converter,
- null,
- null,
- )
- }
-
- fun <ValueTypeT> registerValueListTaskParam(
- paramName: String,
- listener: ValueListener<List<ValueTypeT>>,
- converter: ParamValueConverter<ValueTypeT>,
- ) = apply {
- mutableTaskParamMap[paramName] =
- TaskParamBinding(
- paramName,
- GROUND_NEVER,
- GenericResolverInternal.fromValueListListener(listener),
- converter,
- null,
- null,
- )
- }
-
- /**
- * Registers an optional, non-repeated confirmation data.
- *
- * @param paramName the BIC confirmation data slot name of this parameter.
- * @param confirmationGetter a getter of the confirmation data from the {@code
- * ConfirmationT} instance.
- * @param converter a converter from confirmation data to a ParamValue.
- */
- fun <T> registerConfirmationOutput(
- paramName: String,
- confirmationGetter: (ConfirmationT) -> T?,
- converter: (T) -> ParamValue,
- ) = apply {
- confirmationDataBindings[paramName] = { output: ConfirmationT ->
- listOfNotNull(confirmationGetter(output)).map(converter)
- }
- }
-
- /** Sets the onReadyToConfirmListener for this session. */
- fun setOnReadyToConfirmListener(
- onReadyToConfirmListener: OnReadyToConfirmListener<ArgumentsT, ConfirmationT>,
- ) = apply {
- this.onReadyToConfirmListener = onReadyToConfirmListener
- }
-
- fun build() = TaskHandler(
- mutableTaskParamMap.toMap(),
- confirmationDataBindings,
- onReadyToConfirmListener,
- )
-
- companion object {
- val GROUND_IF_NO_IDENTIFIER = { paramValue: ParamValue -> !paramValue.hasIdentifier() }
- val GROUND_NEVER = { _: ParamValue -> false }
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskOrchestrator.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskOrchestrator.kt
deleted file mode 100644
index 865d603..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskOrchestrator.kt
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task
-
-import androidx.annotation.GuardedBy
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.ConfirmationOutput
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.SessionConfig
-import androidx.appactions.interaction.capabilities.core.impl.ArgumentsWrapper
-import androidx.appactions.interaction.capabilities.core.impl.ErrorStatusInternal
-import androidx.appactions.interaction.capabilities.core.impl.FulfillmentResult
-import androidx.appactions.interaction.capabilities.core.impl.TouchEventCallback
-import androidx.appactions.interaction.capabilities.core.impl.UiHandleRegistry
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpec
-import androidx.appactions.interaction.capabilities.core.impl.task.exceptions.InvalidResolverException
-import androidx.appactions.interaction.capabilities.core.impl.task.exceptions.MissingEntityConverterException
-import androidx.appactions.interaction.capabilities.core.impl.task.exceptions.MissingSearchActionConverterException
-import androidx.appactions.interaction.capabilities.core.impl.utils.CapabilityLogger
-import androidx.appactions.interaction.capabilities.core.impl.utils.LoggerInternal
-import androidx.appactions.interaction.capabilities.core.impl.utils.handleExceptionFromRequestProcessing
-import androidx.appactions.interaction.capabilities.core.impl.utils.invokeExternalBlock
-import androidx.appactions.interaction.capabilities.core.impl.utils.invokeExternalSuspendBlock
-import androidx.appactions.interaction.proto.AppActionsContext
-import androidx.appactions.interaction.proto.CurrentValue
-import androidx.appactions.interaction.proto.FulfillmentRequest
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.SyncStatus
-import androidx.appactions.interaction.proto.FulfillmentResponse
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.proto.TouchEventMetadata
-import java.util.concurrent.locks.ReentrantReadWriteLock
-import kotlin.concurrent.read
-import kotlin.concurrent.write
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.isActive
-
-/**
- * TaskOrchestrator is responsible for holding session state, and processing assistant / manual
- * input updates to update session state.
- *
- * TaskOrchestrator is also responsible to communicating state updates to developer provided
- * listeners.
- *
- * Only one request can be processed at a time.
- */
-internal class TaskOrchestrator<ArgumentsT, OutputT, ConfirmationT>(
- private val sessionId: String,
- private val actionSpec: ActionSpec<ArgumentsT, OutputT>,
- private val appAction: AppActionsContext.AppAction,
- private val taskHandler: TaskHandler<ArgumentsT, ConfirmationT>,
- private val externalSession: BaseExecutionSession<ArgumentsT, OutputT>,
- private val scope: CoroutineScope,
-) {
- /** This enum describes the current status of the TaskOrchestrator. */
- internal enum class Status {
- UNINITIATED,
- IN_PROGRESS,
- DESTROYED,
- }
- /**
- * A [reader-writer lock](https://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock) to protect
- * the synchronizing operation on [currentValuesMap]
- */
- private val valuesMapLock = ReentrantReadWriteLock()
-
- /** Map of argument name to the [CurrentValue] which wraps the argument name and status . */
- @GuardedBy("valuesMapLock")
- private val currentValuesMap = mutableMapOf<String, List<CurrentValue>>()
-
- /**
- * The callback that should be invoked when manual input processing finishes. This sends the
- * processing results to the AppInteraction SDKs. Note, this field is not provided on
- * construction because the callback is not available at the time when the developer creates the
- * capability.
- */
- private var touchEventCallback: TouchEventCallback? = null
-
- /** Current status of the overall task (i.e. status of the task). */
- internal var status: Status = Status.UNINITIATED
- private set
-
- /**
- * Last known Sync Status of the request. Required to process Touch Event Updates
- */
- private var lastKnownSyncStatus = SyncStatus.UNKNOWN_SYNC_STATUS
-
- private val inProgressLock = Any()
-
- // Set a TouchEventCallback instance. This callback is invoked when state changes from manual
- // input.
- internal fun setTouchEventCallback(touchEventCallback: TouchEventCallback?) {
- this.touchEventCallback = touchEventCallback
- }
-
- @GuardedBy("inProgressLock")
- private var inProgress = false
-
- /** Returns whether or not a request is currently being processed */
- internal fun isIdle(): Boolean = synchronized(inProgressLock) { !inProgress }
-
- internal val appDialogState: AppActionsContext.AppDialogState
- get() =
- AppActionsContext.AppDialogState.newBuilder()
- .addAllParams(
- valuesMapLock.read {
- appAction.paramsList.map { intentParam ->
- val dialogParameterBuilder =
- AppActionsContext.DialogParameter.newBuilder()
- .setName(intentParam.name)
- currentValuesMap[intentParam.name]?.let {
- dialogParameterBuilder.addAllCurrentValue(it)
- }
- dialogParameterBuilder.build()
- }
- },
- )
- .setFulfillmentIdentifier(appAction.identifier)
- .build()
-
- /**
- * processes the provided UpdateRequest asynchronously.
- *
- * Returns when the request handling is completed.
- *
- * An unhandled exception when handling an UpdateRequest will cause all future update requests
- * to fail.
- *
- * This method should never be called when isIdle() returns false.
- */
- internal suspend fun processUpdateRequest(updateRequest: UpdateRequest) {
- synchronized(inProgressLock) {
- if (inProgress) {
- throw IllegalStateException(
- "processUpdateRequest should never be called when the task orchestrator" +
- " isn't idle.",
- )
- }
- inProgress = true
- }
- try {
- if (status == Status.DESTROYED) {
- if (updateRequest.assistantRequest != null) {
- FulfillmentResult(ErrorStatusInternal.SESSION_NOT_FOUND)
- .applyToCallback(updateRequest.assistantRequest.callbackInternal)
- } else if (updateRequest.touchEventRequest != null && touchEventCallback != null) {
- touchEventCallback!!.onError(ErrorStatusInternal.SESSION_NOT_FOUND)
- }
- } else if (updateRequest.assistantRequest != null) {
- processAssistantUpdateRequest(updateRequest.assistantRequest)
- } else if (updateRequest.touchEventRequest != null) {
- processTouchEventUpdateRequest(updateRequest.touchEventRequest)
- } else {
- throw IllegalArgumentException("unknown UpdateRequest type")
- }
- } finally {
- synchronized(inProgressLock) { inProgress = false }
- }
- }
-
- private suspend fun <T> withUiHandleRegistered(block: suspend () -> T): T {
- UiHandleRegistry.registerUiHandle(externalSession, sessionId)
- try {
- return block()
- } finally {
- UiHandleRegistry.unregisterUiHandle(externalSession)
- }
- }
-
- /** Processes an assistant update request. */
- private suspend fun processAssistantUpdateRequest(
- assistantUpdateRequest: AssistantUpdateRequest,
- ) = withUiHandleRegistered {
- val argumentsWrapper = assistantUpdateRequest.argumentsWrapper
- val callback = assistantUpdateRequest.callbackInternal
- try {
- val fulfillmentResult: FulfillmentResult = when (
- argumentsWrapper.requestMetadata?.requestType
- ) {
- FulfillmentRequest.Fulfillment.Type.SYNC ->
- handleSyncStatus(argumentsWrapper)
- FulfillmentRequest.Fulfillment.Type.CANCEL -> {
- terminate()
- FulfillmentResult(FulfillmentResponse.getDefaultInstance())
- }
- else -> FulfillmentResult(ErrorStatusInternal.INVALID_REQUEST)
- }
- fulfillmentResult.applyToCallback(callback)
- } catch (t: Throwable) {
- LoggerInternal.log(
- CapabilityLogger.LogLevel.ERROR,
- LOG_TAG,
- "Assistant request processing failed",
- )
- handleExceptionFromRequestProcessing(t, callback::onError)
- }
- }
-
- private suspend fun processTouchEventUpdateRequest(
- touchEventUpdateRequest: TouchEventUpdateRequest,
- ) = withUiHandleRegistered {
- val paramValuesMap = touchEventUpdateRequest.paramValuesMap
- if (
- touchEventCallback == null ||
- paramValuesMap.isEmpty() ||
- status !== Status.IN_PROGRESS
- ) {
- return@withUiHandleRegistered
- }
- valuesMapLock.write {
- for ((argName, value) in paramValuesMap) {
- currentValuesMap[argName] =
- value.map {
- TaskCapabilityUtils.toCurrentValue(it, CurrentValue.Status.ACCEPTED)
- }
- }
- }
-
- try {
- if (!anyParamsOfStatus(CurrentValue.Status.DISAMBIG)) {
- val fulfillmentValuesMap =
- TaskCapabilityUtils.paramValuesMapToFulfillmentValuesMap(
- getCurrentPendingArguments(),
- )
- processFulfillmentValues(fulfillmentValuesMap)
- }
- val fulfillmentResponse = maybeConfirmOrExecute()
- LoggerInternal.log(CapabilityLogger.LogLevel.INFO, LOG_TAG, "Manual input success")
- if (touchEventCallback != null) {
- touchEventCallback!!.onSuccess(
- fulfillmentResponse,
- TouchEventMetadata.getDefaultInstance(),
- )
- } else {
- LoggerInternal.log(
- CapabilityLogger.LogLevel.ERROR,
- LOG_TAG,
- "Manual input null callback",
- )
- }
- } catch (t: Throwable) {
- LoggerInternal.log(CapabilityLogger.LogLevel.ERROR, LOG_TAG, "Manual input fail")
- if (touchEventCallback == null) {
- LoggerInternal.log(
- CapabilityLogger.LogLevel.ERROR,
- LOG_TAG,
- "Manual input null callback",
- )
- }
- handleExceptionFromRequestProcessing(t) {
- touchEventCallback?.onError(it)
- }
- }
- }
-
- internal fun terminate() {
- externalSession.onDestroy()
- status = Status.DESTROYED
- }
-
- /**
- * If slot filling is incomplete, the future contains default FulfillmentResponse.
- *
- * Otherwise, the future contains a FulfillmentResponse containing BIC or BIO data.
- */
- @Throws(StructConversionException::class)
- private suspend fun maybeConfirmOrExecute(): FulfillmentResponse {
- val finalArguments = getCurrentAcceptedArguments()
- if (
- anyParamsOfStatus(CurrentValue.Status.REJECTED) ||
- !TaskCapabilityUtils.isSlotFillingComplete(finalArguments, appAction.paramsList) ||
- lastKnownSyncStatus != SyncStatus.SLOTS_COMPLETE
- ) {
- return FulfillmentResponse.getDefaultInstance()
- }
- return if (taskHandler.onReadyToConfirmListener != null) {
- getFulfillmentResponseForConfirmation(finalArguments)
- } else {
- getFulfillmentResponseForExecution(finalArguments)
- }
- }
-
- private fun maybeInitializeTask() {
- if (status === Status.UNINITIATED) {
- val sessionConfig = SessionConfig()
- invokeExternalBlock("onCreate") {
- externalSession.onCreate(sessionConfig)
- }
- }
- status = Status.IN_PROGRESS
- }
-
- /**
- * Decides if the SDK should perform execution or not based on the Sync Status of the request
- *
- * SyncStatus - SLOTS_INCOMPLETE : Execution is blocked even if all validations pass
- * SyncStatus - SLOTS_COMPLETE : Execution is completed if all validations pass
- * SyncStatus - INTENT_CONFIRMED : User has confirmed the request and execution will be completed
- */
- private suspend fun handleSyncStatus(argumentsWrapper: ArgumentsWrapper):
- FulfillmentResult {
- lastKnownSyncStatus = argumentsWrapper.requestMetadata!!.syncStatus
- return when (lastKnownSyncStatus) {
- SyncStatus.SLOTS_INCOMPLETE,
- SyncStatus.SLOTS_COMPLETE,
- ->
- handleSyncFulfillmentRequest(argumentsWrapper)
- SyncStatus.INTENT_CONFIRMED
- ->
- handleConfirm()
- else -> FulfillmentResult(ErrorStatusInternal.INVALID_REQUEST)
- }
- }
-
- /**
- * Handles a SYNC request from assistant.
- *
- * Control-flow logic for a single task turn. Note, a task may start and finish in the same
- * turn, so the logic should include onEnter, arg validation, and onExit.
- */
- private suspend fun handleSyncFulfillmentRequest(argumentsWrapper: ArgumentsWrapper):
- FulfillmentResult {
- maybeInitializeTask()
- clearMissingArgs(argumentsWrapper)
- processFulfillmentValues(argumentsWrapper.paramValues)
- val fulfillmentResponse = maybeConfirmOrExecute()
- LoggerInternal.log(CapabilityLogger.LogLevel.INFO, LOG_TAG, "Task sync success")
- return FulfillmentResult(fulfillmentResponse)
- }
-
- /**
- * Control-flow logic for a single task turn in which the user has confirmed in the previous
- * turn.
- */
- private suspend fun handleConfirm(): FulfillmentResult {
- val finalArguments = getCurrentAcceptedArguments()
- val fulfillmentResponse = getFulfillmentResponseForExecution(finalArguments)
- LoggerInternal.log(CapabilityLogger.LogLevel.INFO, LOG_TAG, "Task confirm success")
- return FulfillmentResult(fulfillmentResponse)
- }
-
- private fun clearMissingArgs(assistantArgs: ArgumentsWrapper) {
- valuesMapLock.write {
- val argsCleared =
- currentValuesMap.keys.filter { !assistantArgs.paramValues.containsKey(it) }
- for (arg in argsCleared) {
- currentValuesMap.remove(arg)
- // TODO(b/234170829): notify listener#onReceived of the cleared arguments
- }
- }
- }
-
- /**
- * Main processing chain for both assistant requests and manual input requests. All pending
- * parameters contained in fulfillmentValuesMap are chained together in a serial fashion. We use
- * Futures here to make sure long running app processing (such as argument grounding or argument
- * validation) are executed asynchronously.
- */
- @Throws(
- MissingSearchActionConverterException::class,
- StructConversionException::class,
- InvalidResolverException::class,
- )
- private suspend fun processFulfillmentValues(
- fulfillmentValuesMap: Map<String, List<FulfillmentRequest.Fulfillment.FulfillmentValue>>,
- ) {
- var currentResult = SlotProcessingResult(true, emptyList())
- for ((name, fulfillmentValues) in fulfillmentValuesMap) {
- if (!scope.isActive) {
- break
- }
- currentResult =
- maybeProcessSlotAndUpdateCurrentValues(currentResult, name, fulfillmentValues)
- }
- }
-
- @Throws(
- MissingEntityConverterException::class,
- MissingSearchActionConverterException::class,
- StructConversionException::class,
- InvalidResolverException::class,
- )
- private suspend fun maybeProcessSlotAndUpdateCurrentValues(
- previousResult: SlotProcessingResult,
- slotKey: String,
- newSlotValues: List<FulfillmentRequest.Fulfillment.FulfillmentValue>,
- ): SlotProcessingResult {
- val currentSlotValues =
- valuesMapLock.read { currentValuesMap.getOrDefault(slotKey, emptyList()) }
- val modifiedSlotValues =
- TaskCapabilityUtils.getMaybeModifiedSlotValues(currentSlotValues, newSlotValues)
- if (TaskCapabilityUtils.canSkipSlotProcessing(currentSlotValues, modifiedSlotValues)) {
- return previousResult
- }
- val pendingArgs =
- TaskCapabilityUtils.fulfillmentValuesToCurrentValues(
- modifiedSlotValues,
- CurrentValue.Status.PENDING,
- )
- val currentResult = processSlot(slotKey, previousResult, pendingArgs)
- valuesMapLock.write { currentValuesMap[slotKey] = currentResult.processedValues }
- return currentResult
- }
-
- /**
- * Process pending param values for a slot.
- *
- * If the previous slot was accepted, go through grounding/validation with TaskSlotProcessor,
- * otherwise just return the pending values as is.
- */
- @Throws(
- MissingEntityConverterException::class,
- MissingSearchActionConverterException::class,
- StructConversionException::class,
- InvalidResolverException::class,
- )
- private suspend fun processSlot(
- name: String,
- previousResult: SlotProcessingResult,
- pendingArgs: List<CurrentValue>,
- ): SlotProcessingResult {
- return if (!previousResult.isSuccessful) {
- SlotProcessingResult(false, pendingArgs)
- } else {
- TaskSlotProcessor.processSlot(name, pendingArgs, taskHandler.taskParamMap)
- }
- }
-
- /**
- * Retrieve all ParamValue from accepted slots in currentValuesMap.
- *
- * A slot is considered accepted if all CurrentValues in the slot has ACCEPTED status.
- */
- private fun getCurrentAcceptedArguments(): Map<String, List<ParamValue>> =
- valuesMapLock
- .read {
- currentValuesMap.filterValues { currentValues ->
- currentValues.all { it.status == CurrentValue.Status.ACCEPTED }
- }
- }
- .mapValues { currentValue -> currentValue.value.map { it.value } }
-
- /**
- * Retrieve all ParamValue from pending slots in currentValuesMap.
- *
- * A slot is considered pending if any CurrentValues in the slot has PENDING status.
- */
- private fun getCurrentPendingArguments(): Map<String, List<ParamValue>> =
- valuesMapLock
- .read {
- currentValuesMap.filterValues { currentValues ->
- currentValues.any { it.status == CurrentValue.Status.PENDING }
- }
- }
- .mapValues { currentValues -> currentValues.value.map { it.value } }
-
- /** Returns true if any CurrentValue in currentValuesMap has the given Status. */
- private fun anyParamsOfStatus(status: CurrentValue.Status) =
- valuesMapLock.read {
- currentValuesMap.values.any { currentValues ->
- currentValues.any { it.status == status }
- }
- }
-
- @Throws(StructConversionException::class)
- private suspend fun getFulfillmentResponseForConfirmation(
- finalArguments: Map<String, List<ParamValue>>,
- ): FulfillmentResponse {
- val arguments = actionSpec.buildArguments(finalArguments)
- requireNotNull(taskHandler.onReadyToConfirmListener) {
- "caller must ensure TaskHandler.onReadyToConfirmListener is not null"
- }
- val result = invokeExternalSuspendBlock("onReadyToConfirm") {
- taskHandler.onReadyToConfirmListener.onReadyToConfirm(arguments)
- }
- val fulfillmentResponse = FulfillmentResponse.newBuilder()
- convertToConfirmationOutput(result)?.let { fulfillmentResponse.confirmationData = it }
- return fulfillmentResponse.build()
- }
-
- @Throws(StructConversionException::class)
- private suspend fun getFulfillmentResponseForExecution(
- finalArguments: Map<String, List<ParamValue>>,
- ): FulfillmentResponse {
- val arguments = actionSpec.buildArguments(finalArguments)
- val result = invokeExternalSuspendBlock("onExecute") {
- externalSession.onExecute(arguments)
- }
- terminate()
- val fulfillmentResponse =
- FulfillmentResponse.newBuilder().setStartDictation(result.shouldStartDictation)
- convertToExecutionOutput(result)?.let { fulfillmentResponse.executionOutput = it }
- return fulfillmentResponse.build()
- }
-
- /**
- * Convert from java capabilities [ExecutionResult] to [FulfillmentResponse.StructuredOutput]
- * proto.
- */
- private fun convertToExecutionOutput(
- executionResult: ExecutionResult<OutputT>,
- ): FulfillmentResponse.StructuredOutput? =
- executionResult.output?.let { actionSpec.convertOutputToProto(it) }
-
- /**
- * Convert from java capabilities [ConfirmationOutput] to [FulfillmentResponse.StructuredOutput]
- * proto.
- */
- private fun convertToConfirmationOutput(
- confirmationOutput: ConfirmationOutput<ConfirmationT>,
- ): FulfillmentResponse.StructuredOutput? {
- val confirmation = confirmationOutput.confirmation ?: return null
- return FulfillmentResponse.StructuredOutput.newBuilder()
- .addAllOutputValues(
- taskHandler.confirmationDataBindings.entries.map {
- FulfillmentResponse.StructuredOutput.OutputValue.newBuilder()
- .setName(it.key)
- .addAllValues(it.value.invoke(confirmation))
- .build()
- },
- )
- .build()
- }
-
- companion object {
- private const val LOG_TAG = "TaskOrchestrator"
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskParamBinding.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskParamBinding.kt
deleted file mode 100644
index 2990015..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskParamBinding.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task
-
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.SearchActionConverter
-import androidx.appactions.interaction.proto.ParamValue
-
-/**
- * A binding between a parameter and its Property converter / Argument setter.
- *
- * </ValueTypeT>
- */
-internal data class TaskParamBinding<ValueTypeT>
-constructor(
- val name: String,
- val groundingPredicate: (ParamValue) -> Boolean,
- val resolver: GenericResolverInternal<ValueTypeT>,
- val converter: ParamValueConverter<ValueTypeT>,
- val entityConverter: EntityConverter<ValueTypeT>?,
- val searchActionConverter: SearchActionConverter<ValueTypeT>?,
-)
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskSlotProcessor.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskSlotProcessor.kt
deleted file mode 100644
index fee2fd0..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskSlotProcessor.kt
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task
-
-import androidx.appactions.interaction.capabilities.core.EntitySearchResult
-import androidx.appactions.interaction.capabilities.core.ValidationResult
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException
-import androidx.appactions.interaction.capabilities.core.impl.task.exceptions.InvalidResolverException
-import androidx.appactions.interaction.capabilities.core.impl.task.exceptions.MissingEntityConverterException
-import androidx.appactions.interaction.capabilities.core.impl.task.exceptions.MissingSearchActionConverterException
-import androidx.appactions.interaction.proto.CurrentValue
-import androidx.appactions.interaction.proto.DisambiguationData
-import androidx.appactions.interaction.proto.ParamValue
-import kotlin.String
-import kotlin.Throws
-
-/**
- * Contains static utility methods that handles processing argument slots for TaskCapabilityImpl.
- */
-internal object TaskSlotProcessor {
- /**
- * Processes all ParamValue for a single slot.
- *
- * @return a [SlotProcessingResult] object.
- */
- @Throws(
- MissingEntityConverterException::class,
- MissingSearchActionConverterException::class,
- StructConversionException::class,
- InvalidResolverException::class,
- )
- suspend fun processSlot(
- name: String,
- pendingArgs: List<CurrentValue>,
- taskParamMap: Map<String, TaskParamBinding<*>>,
- ): SlotProcessingResult {
- // TODO(b/234655571) use slot metadata to ensure that we never auto accept values
- // for reference slots.
- val taskParamBinding =
- taskParamMap[name]
- ?: return SlotProcessingResult(
- true,
- pendingArgs.map {
- TaskCapabilityUtils.toCurrentValue(it.value, CurrentValue.Status.ACCEPTED)
- },
- )
- val groundedValues = mutableListOf<ParamValue>()
- val ungroundedValues = mutableListOf<CurrentValue>()
- var groundingResult = AppGroundingResult.ofSuccess(ParamValue.getDefaultInstance())
- for (pendingValue in pendingArgs) {
- if (pendingValue.hasDisambiguationData()) {
- // assistant-driven disambiguation
- groundingResult =
- consumeGroundingResult(
- chainAssistantGrounding(groundingResult, pendingValue, taskParamBinding),
- groundedValues,
- ungroundedValues,
- )
- } else if (taskParamBinding.groundingPredicate.invoke(pendingValue.value)) {
- // app-driven disambiguation
- groundingResult =
- consumeGroundingResult(
- chainAppGrounding(groundingResult, pendingValue, taskParamBinding),
- groundedValues,
- ungroundedValues,
- )
- } else {
- groundedValues.add(pendingValue.value)
- }
- }
- return if (groundedValues.isEmpty()) {
- SlotProcessingResult(
- /* isSuccessful= */ false,
- ungroundedValues.toList(),
- )
- } else {
- processValidationResult(
- invokeValueChange(groundedValues, taskParamBinding),
- groundedValues,
- ungroundedValues,
- )
- }
- }
-
- /** enqueues processing of a pending value that requires assistant-driven grounding. */
- @Throws(InvalidResolverException::class)
- private suspend fun chainAssistantGrounding(
- groundingResult: AppGroundingResult,
- pendingValue: CurrentValue,
- taskParamBinding: TaskParamBinding<*>,
- ) =
- when (groundingResult.kind) {
- AppGroundingResult.Kind.SUCCESS -> {
- renderAssistantDisambigData(pendingValue.disambiguationData, taskParamBinding)
- AppGroundingResult.ofFailure(
- CurrentValue.newBuilder(pendingValue)
- .setStatus(CurrentValue.Status.DISAMBIG)
- .build(),
- )
- }
- AppGroundingResult.Kind.FAILURE -> AppGroundingResult.ofFailure(pendingValue)
- }
-
- /** enqueues processing of a pending value that requires app-driven grounding. */
- @Throws(
- MissingEntityConverterException::class,
- MissingSearchActionConverterException::class,
- StructConversionException::class,
- InvalidResolverException::class,
- )
- private suspend fun chainAppGrounding(
- groundingResult: AppGroundingResult,
- pendingValue: CurrentValue,
- taskParamBinding: TaskParamBinding<*>,
- ) =
- when (groundingResult.kind) {
- AppGroundingResult.Kind.SUCCESS -> ground(pendingValue.value, taskParamBinding)
- AppGroundingResult.Kind.FAILURE -> AppGroundingResult.ofFailure(pendingValue)
- }
-
- /**
- * Consumes the result of grounding.
- *
- * If grounding was successful (app-driven with 1 returned result) the grounded ParamValue is
- * added to groundedValues.
- *
- * otherwise the ungrounded CurrentValue is added to ungroundedValues.
- */
- private fun consumeGroundingResult(
- groundingResult: AppGroundingResult,
- groundedValues: MutableList<ParamValue>,
- ungroundedValues: MutableList<CurrentValue>,
- ): AppGroundingResult {
- when (groundingResult.kind) {
- AppGroundingResult.Kind.SUCCESS -> groundedValues.add(groundingResult.success!!)
- AppGroundingResult.Kind.FAILURE -> ungroundedValues.add(groundingResult.failure!!)
- }
- return groundingResult
- }
-
- /**
- * Applies "wildcard capture" technique. For more details see
- * [...](https://docs.oracle.com/javase/tutorial/java/generics/capture.html)
- */
- @Throws(StructConversionException::class)
- private suspend fun <T> invokeValueChange(
- updatedValue: List<ParamValue>,
- binding: TaskParamBinding<T>,
- ): ValidationResult {
- return binding.resolver.notifyValueChange(updatedValue, binding.converter)
- }
-
- @Throws(InvalidResolverException::class)
- private suspend fun renderAssistantDisambigData(
- disambiguationData: DisambiguationData,
- binding: TaskParamBinding<*>,
- ) {
- val entityIds = disambiguationData.entitiesList.map { it.identifier }
- binding.resolver.invokeEntityRender(entityIds)
- }
-
- /**
- * Processes the ValidationResult from sending argument updates to onReceived.
- *
- * @param validationResult the ValidationResult returned from value listener.
- * @param groundedValues a List of all grounded ParamValue.
- * @param ungroundedValues a List of all ungrounded CurrentValue.
- */
- private fun processValidationResult(
- validationResult: ValidationResult,
- groundedValues: List<ParamValue>,
- ungroundedValues: List<CurrentValue>,
- ): SlotProcessingResult {
- val combinedValues = mutableListOf<CurrentValue>()
- when (validationResult.kind) {
- ValidationResult.Kind.ACCEPTED ->
- combinedValues.addAll(
- TaskCapabilityUtils.paramValuesToCurrentValue(
- groundedValues,
- CurrentValue.Status.ACCEPTED,
- ),
- )
- ValidationResult.Kind.REJECTED ->
- combinedValues.addAll(
- TaskCapabilityUtils.paramValuesToCurrentValue(
- groundedValues,
- CurrentValue.Status.REJECTED,
- ),
- )
- }
- combinedValues.addAll(ungroundedValues)
- return SlotProcessingResult(
- /* isSuccessful= */ ungroundedValues.isEmpty() &&
- validationResult.kind === ValidationResult.Kind.ACCEPTED,
- combinedValues.toList(),
- )
- }
-
- /** perform an in-app search for an ungrounded ParamValue */
- @Throws(
- MissingEntityConverterException::class,
- MissingSearchActionConverterException::class,
- StructConversionException::class,
- InvalidResolverException::class,
- )
- private suspend fun <T> ground(
- ungroundedParamValue: ParamValue,
- binding: TaskParamBinding<T>,
- ): AppGroundingResult {
- if (binding.entityConverter == null) {
- throw MissingEntityConverterException("No entity converter found in the binding.")
- }
- if (binding.searchActionConverter == null) {
- throw MissingSearchActionConverterException(
- "No search action converter found in the binding.",
- )
- }
- val entityConverter = binding.entityConverter
- val searchActionConverter = binding.searchActionConverter
- val searchAction = searchActionConverter.toSearchAction(ungroundedParamValue)
- val entitySearchResult = binding.resolver.invokeLookup(searchAction)
- return processEntitySearchResult(entitySearchResult, entityConverter, ungroundedParamValue)
- }
-
- /**
- * Processes the EntitySearchResult from performing an entity search.
- *
- * @param entitySearchResult the EntitySearchResult returned from the app resolver.
- * @param ungroundedValue the original ungrounded ParamValue.
- */
- @Throws(StructConversionException::class)
- private fun <T> processEntitySearchResult(
- entitySearchResult: EntitySearchResult<T>,
- entityConverter: EntityConverter<T>,
- ungroundedValue: ParamValue,
- ): AppGroundingResult {
- return when (entitySearchResult.possibleValues.size) {
- 0 ->
- AppGroundingResult.ofFailure(
- TaskCapabilityUtils.toCurrentValue(
- ungroundedValue,
- CurrentValue.Status.REJECTED,
- ),
- )
- 1 -> {
- val groundedEntity = entityConverter.convert(entitySearchResult.possibleValues[0]!!)
- AppGroundingResult.ofSuccess(
- TaskCapabilityUtils.groundedValueToParamValue(groundedEntity),
- )
- }
- else -> {
- val disambigEntities =
- entitySearchResult.possibleValues.map { entityConverter.convert(it!!) }
- AppGroundingResult.ofFailure(
- TaskCapabilityUtils.getCurrentValueForDisambiguation(
- ungroundedValue,
- disambigEntities,
- ),
- )
- }
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskUpdateHandler.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskUpdateHandler.java
deleted file mode 100644
index ff37ccf..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskUpdateHandler.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task;
-
-import androidx.appactions.interaction.proto.ParamValue;
-
-import java.util.List;
-import java.util.Map;
-
-/** Implemented by TaskCapabilityImpl to handle manual input updates and BIC input. */
-interface TaskUpdateHandler {
- void updateParamValues(Map<String, List<ParamValue>> paramValuesMap);
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TouchEventUpdateRequest.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TouchEventUpdateRequest.kt
deleted file mode 100644
index b072ff6..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TouchEventUpdateRequest.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task
-
-import androidx.appactions.interaction.proto.ParamValue
-
-/** Represents a fulfillment request coming from user tap. */
-internal data class TouchEventUpdateRequest(val paramValuesMap: Map<String, List<ParamValue>>) {
- /**
- * merge two TouchEventUpdateRequest instances. Map entries in newRequest will take priority in
- * case of conflict.
- */
- fun mergeWith(newRequest: TouchEventUpdateRequest): TouchEventUpdateRequest {
- val mergedParamValuesMap = this.paramValuesMap.toMutableMap()
- mergedParamValuesMap.putAll(newRequest.paramValuesMap)
- return TouchEventUpdateRequest(mergedParamValuesMap.toMap())
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/UpdateRequest.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/UpdateRequest.kt
deleted file mode 100644
index 4ca9c8c..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/UpdateRequest.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task
-
-/** Contains either an [AssistantUpdateRequest] or a [TouchEventUpdateRequest] */
-internal class UpdateRequest
-private constructor(
- val assistantRequest: AssistantUpdateRequest?,
- val touchEventRequest: TouchEventUpdateRequest?,
-) {
- constructor(assistantRequest: AssistantUpdateRequest) : this(assistantRequest, null)
-
- constructor(touchEventRequest: TouchEventUpdateRequest) : this(null, touchEventRequest)
-}
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
deleted file mode 100644
index 616c7b3..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/exceptions/DisambigStateException.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task.exceptions;
-
-import androidx.annotation.NonNull;
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.InvalidRequestException;
-
-/**
- * Represents an internal issue with the state sync between the SDK and Assistant. One example is
- * 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 {
-
- public DisambigStateException(@NonNull String message) {
- super(message);
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/exceptions/InvalidResolverException.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/exceptions/InvalidResolverException.java
deleted file mode 100644
index e6f5328..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/exceptions/InvalidResolverException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task.exceptions;
-
-import androidx.annotation.NonNull;
-
-/**
- * Represents an internal issue with Resolvers, such as an "app-driven" method being invoked on a
-* "assistant-driven" resolver.
-*/
-public final class InvalidResolverException extends Exception {
-
- public InvalidResolverException(@NonNull String message) {
- super(message);
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/exceptions/MissingEntityConverterException.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/exceptions/MissingEntityConverterException.java
deleted file mode 100644
index af097f6..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/exceptions/MissingEntityConverterException.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task.exceptions;
-
-import androidx.annotation.NonNull;
-
-/** No entity converter is present in the {@code TaskParamBinding}. */
-public final class MissingEntityConverterException extends Exception {
-
- public MissingEntityConverterException(@NonNull String message) {
- super(message);
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/exceptions/MissingSearchActionConverterException.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/exceptions/MissingSearchActionConverterException.java
deleted file mode 100644
index f907f1cb..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/exceptions/MissingSearchActionConverterException.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task.exceptions;
-
-import androidx.annotation.NonNull;
-
-/** No SearchAction converter is present in the {@code DialogParamBinding}. */
-public final class MissingSearchActionConverterException extends Exception {
-
- public MissingSearchActionConverterException(@NonNull String message) {
- super(message);
- }
-}
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
deleted file mode 100644
index 2f27a8b..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/utils/CallbackUtils.kt
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.utils
-
-import androidx.appactions.interaction.capabilities.core.impl.ErrorStatusInternal
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.ExternalException
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.InvalidRequestException
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException
-import androidx.appactions.interaction.capabilities.core.impl.task.exceptions.DisambigStateException
-import androidx.appactions.interaction.capabilities.core.impl.task.exceptions.InvalidResolverException
-import kotlin.reflect.KClass
-import kotlinx.coroutines.CancellationException
-import kotlinx.coroutines.TimeoutCancellationException
-import kotlinx.coroutines.withTimeout
-
-private const val LOG_TAG = "CallbackUtils"
-
-/** invoke an externally implemented method, wrapping any exceptions with ExternalException.
- */
-internal fun <T> invokeExternalBlock(description: String, block: () -> T): T {
- try {
- return block()
- } catch (t: Throwable) {
- throw ExternalException("exception occurred during '$description'", t)
- }
-}
-
-/** Maximum allowed time for a single external async operation. e.g. invoking a slot listener. */
-internal const val EXTERNAL_TIMEOUT_MILLIS = 10000L
-
-/** invoke an externally implemented suspend method, wrapping any exceptions with
- * ExternalException.
- */
-internal suspend fun <T> invokeExternalSuspendBlock(
- description: String,
- block: suspend () -> T
-): T {
- return withTimeout(EXTERNAL_TIMEOUT_MILLIS) {
- try {
- block()
- } catch (t: Throwable) {
- throw ExternalException("exception occurred during '$description'", t)
- }
- }
-}
-
-/** Determines whether or not this exception is caused by some type, directly or indirectly. */
-private fun <T : Throwable> Throwable.isCausedBy(clazz: KClass<T>): Boolean {
- if (clazz.isInstance(this)) {
- return true
- }
- return this.cause?.isCausedBy(clazz) == true
-}
-
-/**
- * Returns an ErrorStatusInternal corresponding to this Throwable.
- */
-private fun Throwable.toErrorStatusInternal(): ErrorStatusInternal {
- return when {
- this.isCausedBy(
- ExternalException::class
- ) -> ErrorStatusInternal.EXTERNAL_EXCEPTION
- // Handle StructConversion first, because it's a subtype of InvalidRequestException below.
- this.isCausedBy(StructConversionException::class) ||
- this.isCausedBy(InvalidResolverException::class) ||
- this.isCausedBy(DisambigStateException::class)
- -> ErrorStatusInternal.INTERNAL
-
- this.isCausedBy(
- InvalidRequestException::class
- ) -> ErrorStatusInternal.INVALID_REQUEST
-
- this is TimeoutCancellationException -> ErrorStatusInternal.TIMEOUT
- else -> ErrorStatusInternal.UNKNOWN_ERROR_STATUS
- }
-}
-
-/**
- * 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(
- t: Throwable,
- errorCallback: (ErrorStatusInternal) -> Unit
-) {
- LoggerInternal.log(
- CapabilityLogger.LogLevel.ERROR,
- LOG_TAG,
- "exception encountered during request processing, this exception.",
- t
- )
- errorCallback.invoke(t.toErrorStatusInternal())
- when {
- t.isCausedBy(
- InvalidRequestException::class
- ) || t.isCausedBy(
- CancellationException::class
- ) -> Unit
- else -> {
- LoggerInternal.log(
- CapabilityLogger.LogLevel.ERROR,
- LOG_TAG,
- """Rethrowing exception because it was likely thrown from an app-implemented
- callback.""",
- t
- )
- throw t
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/utils/CapabilityLogger.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/utils/CapabilityLogger.java
deleted file mode 100644
index 8ed5fbe..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/utils/CapabilityLogger.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.utils;
-
-import androidx.annotation.NonNull;
-
-/**
- * Define the logger interface to hide specific logger implementations from the capability library.
- * This is needed because the capabilities library cannot depend on android deps directly.
- */
-public interface CapabilityLogger {
-
- void log(@NonNull LogLevel logLevel, @NonNull String logTag, @NonNull String message);
-
- void log(
- @NonNull LogLevel logLevel,
- @NonNull String logTag,
- @NonNull String message,
- @NonNull Throwable throwable);
-
- /** Log levels to match the visibility of log errors from android.util.Log. */
- enum LogLevel {
- INFO,
- WARN,
- ERROR,
- DEBUG,
- }
-
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/utils/ImmutableCollectors.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/utils/ImmutableCollectors.java
deleted file mode 100644
index 8f30f68..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/utils/ImmutableCollectors.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.utils;
-
-import static java.util.stream.Collectors.collectingAndThen;
-
-import androidx.annotation.NonNull;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.stream.Collector;
-import java.util.stream.Collectors;
-
-/**
- * Immutable collectors without guava dependencies. Collectors.toUnmodifiable*() function calls
- * should not be used because they are only available on API 33+.
- */
-public final class ImmutableCollectors {
-
- private ImmutableCollectors() {
- }
-
- /** Collecting to immutable list. */
- @NonNull
- public static <E> Collector<E, ?, List<E>> toImmutableList() {
- return collectingAndThen(Collectors.toList(), Collections::unmodifiableList);
- }
-
- /** Collecting to immutable set. */
- @NonNull
- public static <E> Collector<E, ?, Set<E>> toImmutableSet() {
- return collectingAndThen(Collectors.toSet(), Collections::unmodifiableSet);
- }
-
- /** Collecting to immutable map. */
- @NonNull
- public static <T, K, V> Collector<T, ?, Map<K, V>> toImmutableMap(
- @NonNull Function<? super T, ? extends K> keyFunction,
- @NonNull Function<? super T, ? extends V> valueFunction) {
- return collectingAndThen(
- Collectors.toMap(keyFunction, valueFunction), Collections::unmodifiableMap);
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/utils/LoggerInternal.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/utils/LoggerInternal.java
deleted file mode 100644
index 7a9d7d6..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/utils/LoggerInternal.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.utils;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.appactions.interaction.capabilities.core.impl.utils.CapabilityLogger.LogLevel;
-
-/**
- * A singleton class to define the logger allows logger implementations to be defined outside of the
- * capabilities classes, where it is permitted to depend on Android Logger(android.util.Log).
- */
-public final class LoggerInternal {
-
- @Nullable
- private static CapabilityLogger sDelegate = null;
-
- private LoggerInternal() {
- }
-
- public static void setLogger(@NonNull CapabilityLogger logger) {
- sDelegate = logger;
- }
-
- public static void log(
- @NonNull LogLevel logLevel, @NonNull String logTag, @NonNull String message) {
- if (sDelegate != null) {
- sDelegate.log(logLevel, logTag, message);
- }
- }
-
- public static void log(
- @NonNull LogLevel logLevel,
- @NonNull String logTag,
- @NonNull String message,
- @NonNull Throwable t) {
- if (sDelegate != null) {
- sDelegate.log(logLevel, logTag, message, t);
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/properties/Property.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/properties/Property.kt
deleted file mode 100644
index b233745..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/properties/Property.kt
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.properties
-
-/**
- * Configure parameters for the capability such as providing possible values of some type, or
- * marking a parameter as required for execution.
- */
-class Property<T>
-internal constructor(
- /** Possible values which can fill the slot. */
- private val possibleValueSupplier: () -> List<T> = { emptyList() },
- /**
- * Indicates that a value for this property is required to be present for fulfillment. The
- * default value is false.
- */
- @get:JvmName("isRequiredForExecution")
- val isRequiredForExecution: Boolean = false,
- /**
- * Indicates that the value for this parameter must be one of [Property.possibleValues].
- * The default value is false.
- *
- * <p>If true, then the assistant should not trigger this capability if there is no match for
- * this parameter.
- */
- @get:JvmName("shouldMatchPossibleValues")
- val shouldMatchPossibleValues: Boolean = false,
- /**
- * If false, the {@code Capability} will be rejected by assistant if corresponding param is set
- * in Argument. Also, the value of |isRequired| and |entityMatchRequired| will be ignored by
- * assistant. Default value is true and can be set false with static method
- * [Property.unsupported].
- */
- @get:JvmName("isSupported")
- val isSupported: Boolean = true,
-) {
- /**
- * The current list of possible values for this parameter, can change over time if this property
- * was constructed with a possible values supplier.
- */
- val possibleValues: List<T>
- get() = possibleValueSupplier()
-
- /** Creates a property using a static list of possible values. */
- @JvmOverloads
- constructor(
- possibleValues: List<T> = emptyList(),
- isRequiredForExecution: Boolean = false,
- shouldMatchPossibleValues: Boolean = false,
- ) : this({ possibleValues }, isRequiredForExecution, shouldMatchPossibleValues, true)
-
- /**
- * Creates a property using a supplier of possible values. This allows for inventory to be
- * dynamic, i.e. change every time the assistant reads the list of app-supported
- * capabilities. With background service execution, the supplier may be called once on every
- * request to the capability.
- */
- @JvmOverloads
- constructor(
- possibleValueSupplier: () -> List<T>,
- isRequiredForExecution: Boolean = false,
- shouldMatchPossibleValues: Boolean = false,
- ) : this(possibleValueSupplier, isRequiredForExecution, shouldMatchPossibleValues, true)
-
- companion object {
- /**
- * Sets the parameter as unsupported. Declares that the app does not support this particular
- * intent parameter, so it should not be sent to the app.
- */
- @JvmStatic
- fun <T> unsupported(): Property<T> {
- return Property(
- possibleValueSupplier = { emptyList() },
- isRequiredForExecution = false,
- shouldMatchPossibleValues = false,
- isSupported = false,
- )
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/properties/StringValue.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/properties/StringValue.kt
deleted file mode 100644
index 550dbcf..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/properties/StringValue.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.properties
-
-/**
- * One of the [Property.possibleValues] types, which is used when a particular capability slot is
- * of type [String]
- */
-class StringValue @JvmOverloads constructor(
- /**
- * The primary name of the string value (e.g. "banana"). This should be the most canonical way
- * that a user might refer to the entity with voice. If this entity is matched, either through
- * the primary [name] or the [alternateNames], the [name] will be the value sent to the app as
- * an Argument. This allows for flexible NLU matching and also simpler fulfillment processing
- * in the app.
- */
- val name: String,
- /** Other ways which the user may refer to this entity (e.g. ["plantain", "manzano"]) */
- val alternateNames: List<String> = listOf(),
-) {
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is StringValue) return false
- if (this.name != other.name) return false
- if (this.alternateNames != other.alternateNames) return false
- return true
- }
-
- override fun hashCode(): Int {
- var result = name.hashCode()
- result += 31 * alternateNames.hashCode()
- return result
- }
-
- override fun toString(): String =
- "StringValue(name='$name', alternateNames=[${alternateNames.joinToString(",")}])"
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/filters/TextFilter.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/filters/TextFilter.kt
deleted file mode 100644
index 3ff45db..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/filters/TextFilter.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.filters
-
-/** Filter class for text values, contains either some exact String, or a [TextMatcher] instance. */
-class TextFilter private constructor(
- @get:JvmName("asMatcher")
- val asMatcher: TextMatcher?,
- @get:JvmName("asExactText")
- val asExactText: String?
-) {
- /** Creates a [TextFilter] instance with a [TextMatcher]. */
- constructor(matcher: TextMatcher) : this(matcher, null)
-
- /** Creates a [TextFilter] instance with some text to match exactly. */
- constructor(exactText: String) : this(null, exactText)
-}
-
-/** Matches some text. */
-class TextMatcher(
- /** The filtered text should start with this String. */
- val startsWith: String?,
-
- /** The filtered text should contain this String. */
- val contains: String?
-) {
- init {
- require(startsWith != null || contains != null) {
- "at least one of 'startsWith' and 'contains' must be non-null"
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/filters/TimeFilter.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/filters/TimeFilter.kt
deleted file mode 100644
index e72b003..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/filters/TimeFilter.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.filters
-
-import java.time.LocalTime
-
-/** Filter class for [LocalTime] values. */
-class TimeFilter(
- @get:JvmName("asRangeFilter")
- val asRangeFilter: TimeRangeFilter?,
- @get:JvmName("asExactTime")
- val asExactTime: LocalTime?
-) {
- /** Creates a [TimeFilter] instance with a [TimeRangeFilter]. */
- constructor(rangeFilter: TimeRangeFilter) : this(rangeFilter, null)
- /** Creates a [TimeFilter] instance with a [LocalTime]. */
- constructor(exactTime: LocalTime) : this(null, exactTime)
-}
-
-/** Matches [LocalTime] values within a range. * If only minTime is non-null, any [LocalTime] at or after minTime satisfies this filter.
- * If only maxTime is non-null, any [LocalTime] at or before maxTime satisfies this filter.
- */
-class TimeRangeFilter(
- /** The minimum time to satisfy this filter. (inclusive) */
- val minTime: LocalTime?,
- /** The maximum time to satisfy this filter. (inclusive) */
- val maxTime: LocalTime?
-) {
- init {
- require(minTime != null || maxTime != null) {
- "at least one of 'minTime' and 'maxTime' must be non-null"
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/filters/package-info.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/filters/package-info.java
deleted file mode 100644
index 3d84cde..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/filters/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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.
- */
-
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-package androidx.appactions.interaction.capabilities.filters;
-
-import androidx.annotation.RestrictTo;
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/filters/properties/NameFilter.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/filters/properties/NameFilter.kt
deleted file mode 100644
index 02dbc12..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/filters/properties/NameFilter.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.filters.properties
-
-import androidx.appactions.builtintypes.properties.Name
-import androidx.appactions.interaction.capabilities.filters.TextFilter
-
-/**
- * Represents a filter for the [Name] property.
- */
-class NameFilter(
- /**
- * Matches some text for [Name.asText].
- */
- @get:JvmName("whenText")
- val whenText: TextFilter?
-)
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/filters/types/ThingFilter.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/filters/types/ThingFilter.kt
deleted file mode 100644
index 39b532e..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/filters/types/ThingFilter.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.filters.types
-
-import androidx.appactions.interaction.capabilities.filters.properties.NameFilter
-
-/**
- * Represents a filter for [androidx.appactions.builtintypes.types.Thing] objects.
- * * All nested filters should be satisfied for an object to satisfy this filter.
- */
-interface ThingFilter {
- /**
- * The exact id of the [Thing] being looked up. If non-null, other fields can be ignored.
- */
- val id: String?
-
- /**
- * The filter for the name property of [Thing].
- */
- val nameFilter: NameFilter?
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/ValueUtils.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/ValueUtils.kt
deleted file mode 100644
index 14611c9..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/ValueUtils.kt
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers
-
-import androidx.appactions.interaction.protobuf.ListValue
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-
-fun stringValue(string: String): Value {
- return Value.newBuilder().setStringValue(string).build()
-}
-
-fun numberValue(number: Double): Value {
- return Value.newBuilder().setNumberValue(number).build()
-}
-
-fun boolValue(bool: Boolean): Value {
- return Value.newBuilder().setBoolValue(bool).build()
-}
-
-fun structValue(jsonObj: Struct): Value {
- return Value.newBuilder().setStructValue(jsonObj).build()
-}
-
-fun listValue(elements: Iterable<Value>): Value {
- return Value.newBuilder()
- .setListValue(ListValue.newBuilder().addAllValues(elements).build())
- .build()
-}
-
-/**
- * Returns the string value if the [Value] holds a string or the first element in the list if
- * the [Value] holds a list with a single string element.
- *
- * ```
- * "Hello" -> "Hello"
- * ["Hello"] -> "Hello"
- * ["Hello", "World"] -> null
- * {...} -> null
- * ```
- *
- * This behavior can provide a bit of extra forward-compat where the JSON value originated from
- * a newer process where it has been promoted to be repeated.
- */
-val Value.singleStringValue: String?
- get() {
- return when {
- hasStringValue() -> stringValue
- hasListValue() ->
- listValue.valuesList.onlyElementOrNull
- ?.let { if (it.hasStringValue()) it.stringValue else null }
- else -> null
- }
- }
-
-/**
- * Returns the number value if the [Value] holds a number or the first element in the list if
- * the [Value] holds a list with a single number element.
- *
- * ```
- * 123 -> 123
- * [123] -> 123
- * [123, 456] -> null
- * {...} -> null
- * ```
- *
- * This behavior can provide a bit of extra forward-compat where the JSON value originated from
- * a newer process where it has been promoted to be repeated.
- */
-val Value.singleNumberValue: Double?
- get() {
- return when {
- hasNumberValue() -> numberValue
- hasListValue() ->
- listValue.valuesList.onlyElementOrNull
- ?.let { if (it.hasNumberValue()) it.numberValue else null }
- else -> null
- }
- }
-
-/**
- * Returns the bool value if the [Value] holds a bool or the first element in the list if
- * the [Value] holds a list with a single bool element.
- *
- * ```
- * true -> true
- * [true] -> true
- * [true, false] -> null
- * {...} -> null
- * ```
- *
- * This behavior can provide a bit of extra forward-compat where the JSON value originated from
- * a newer process where it has been promoted to be repeated.
- */
-val Value.singleBoolValue: Boolean?
- get() {
- return when {
- hasBoolValue() -> boolValue
- hasListValue() ->
- listValue.valuesList.onlyElementOrNull
- ?.let { if (it.hasBoolValue()) it.boolValue else null }
- else -> null
- }
- }
-
-private val <T> List<T>.onlyElementOrNull: T?
- get() = if (size == 1) first() else null
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/package-info.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/package-info.java
deleted file mode 100644
index f9b204c..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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.
- */
-
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-package androidx.appactions.interaction.capabilities.serializers;
-
-import androidx.annotation.RestrictTo;
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/ByDaySerializer.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/ByDaySerializer.kt
deleted file mode 100644
index e7f8d45..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/ByDaySerializer.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.properties
-
-import androidx.appactions.builtintypes.properties.ByDay
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-import androidx.appactions.interaction.capabilities.serializers.types.DAY_OF_WEEK_TYPE_SPEC
-
-val BY_DAY_TYPE_SPEC = UnionTypeSpec.Builder<ByDay>().bindMemberType(
- memberGetter = ByDay::asDayOfWeek,
- ctor = { ByDay(it) },
- typeSpec = DAY_OF_WEEK_TYPE_SPEC,
-).build()
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/EndDateSerializer.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/EndDateSerializer.kt
deleted file mode 100644
index d0b5db7..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/EndDateSerializer.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.properties
-
-import androidx.appactions.builtintypes.properties.EndDate
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-
-val END_DATE_TYPE_SPEC = UnionTypeSpec.Builder<EndDate>().bindMemberType(
- memberGetter = EndDate::asDate,
- ctor = { EndDate(it) },
- typeSpec = TypeSpec.LOCAL_DATE_TYPE_SPEC
-).build()
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/EndTimeSerializer.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/EndTimeSerializer.kt
deleted file mode 100644
index 88e6979..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/EndTimeSerializer.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.properties
-
-import androidx.appactions.builtintypes.properties.EndTime
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-
-val END_TIME_TYPE_SPEC = UnionTypeSpec.Builder<EndTime>().bindMemberType(
- memberGetter = EndTime::asTime,
- ctor = { EndTime(it) },
- typeSpec = TypeSpec.LOCAL_TIME_TYPE_SPEC
-).build()
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/ExceptDate.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/ExceptDate.kt
deleted file mode 100644
index 868f941..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/ExceptDate.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.properties
-
-import androidx.appactions.builtintypes.properties.ExceptDate
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-
-val EXCEPT_DATE_TYPE_SPEC = UnionTypeSpec.Builder<ExceptDate>().bindMemberType(
- memberGetter = ExceptDate::asDate,
- ctor = { ExceptDate(it) },
- typeSpec = TypeSpec.LOCAL_DATE_TYPE_SPEC
-).bindMemberType(
- memberGetter = ExceptDate::asLocalDateTime,
- ctor = { ExceptDate(it) },
- typeSpec = TypeSpec.LOCAL_DATE_TIME_TYPE_SPEC
-).bindMemberType(
- memberGetter = ExceptDate::asInstant,
- ctor = { ExceptDate(it) },
- typeSpec = TypeSpec.INSTANT_TYPE_SPEC
-).build()
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/NameSerializer.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/NameSerializer.kt
deleted file mode 100644
index 7fa89eb..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/NameSerializer.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.properties
-
-import androidx.appactions.builtintypes.properties.Name
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-
-val NAME_TYPE_SPEC = UnionTypeSpec.Builder<Name>().bindMemberType(
- memberGetter = Name::asText,
- ctor = { Name(it) },
- typeSpec = TypeSpec.STRING_TYPE_SPEC,
-).build()
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/RepeatFrequencySerializer.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/RepeatFrequencySerializer.kt
deleted file mode 100644
index 78185b3..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/RepeatFrequencySerializer.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.properties
-
-import androidx.appactions.builtintypes.properties.RepeatFrequency
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-
-/** Note: The order of [bindMemberType] calls matters here. */
-val REPEAT_FREQUENCY_TYPE_SPEC = UnionTypeSpec.Builder<RepeatFrequency>().bindMemberType(
- memberGetter = RepeatFrequency::asDuration,
- ctor = { RepeatFrequency(it) },
- typeSpec = TypeSpec.DURATION_TYPE_SPEC
-).build()
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/StartDateSerializer.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/StartDateSerializer.kt
deleted file mode 100644
index 9a1bd7f..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/StartDateSerializer.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.properties
-
-import androidx.appactions.builtintypes.properties.StartDate
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-
-val START_DATE_TYPE_SPEC = UnionTypeSpec.Builder<StartDate>().bindMemberType(
- memberGetter = StartDate::asDate,
- ctor = { StartDate(it) },
- typeSpec = TypeSpec.LOCAL_DATE_TYPE_SPEC
-).build()
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/StartTimeTypeSpec.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/StartTimeTypeSpec.kt
deleted file mode 100644
index d08bbd4..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/properties/StartTimeTypeSpec.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.properties
-
-import androidx.appactions.builtintypes.properties.StartTime
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-
-val START_TIME_TYPE_SPEC = UnionTypeSpec.Builder<StartTime>().bindMemberType(
- memberGetter = StartTime::asTime,
- ctor = { StartTime(it) },
- typeSpec = TypeSpec.LOCAL_TIME_TYPE_SPEC
-).build()
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/AlarmSerializer.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/AlarmSerializer.kt
deleted file mode 100644
index fc2bc5d..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/AlarmSerializer.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.types
-
-import androidx.appactions.builtintypes.types.Alarm
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpecBuilder
-import androidx.appactions.interaction.capabilities.serializers.properties.NAME_TYPE_SPEC
-
-val ALARM_TYPE_SPEC: TypeSpec<Alarm> = TypeSpecBuilder.newBuilder(
- "Alarm",
- Alarm::Builder,
- Alarm.Builder<*>::build
-).bindSpecField(
- "alarmSchedule",
- { it.alarmSchedule },
- Alarm.Builder<*>::setAlarmSchedule,
- SCHEDULE_TYPE_SPEC
-).bindSpecField(
- "name",
- { it.name },
- Alarm.Builder<*>::setName,
- NAME_TYPE_SPEC
-).bindStringField(
- "identifier",
- { it.identifier.ifEmpty { null } },
- Alarm.Builder<*>::setIdentifier
-).bindIdentifier {
- it.identifier.ifEmpty { null }
-}.build()
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/AllCoreSerializers.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/AllCoreSerializers.kt
deleted file mode 100644
index e03eba5..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/AllCoreSerializers.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-// 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.appactions.interaction.capabilities.serializers.types
-
-import kotlin.jvm.JvmStatic
-
-/**
- * Exposes static methods to access all serializers in interaction-capabilities-core.
- *
- * Not intended to be used directly but instead to be accessed via reflection by the serialization
- * runtime. In that sense, this object acts as a sort-of registry of serializers.
- *
- * Some of the static factory methods in this object may get pruned by r8/proguard based on what
- * types the application code explicitly references.
- *
- * Also see the proguard file for this lib for more context.
- */
-public object AllCoreSerializers {
- @JvmStatic public fun getIntangibleSerializer(): IntangibleSerializer = IntangibleSerializer()
-
- @JvmStatic public fun getPersonSerializer(): PersonSerializer = PersonSerializer()
-
- @JvmStatic public fun getThingSerializer(): ThingSerializer = ThingSerializer()
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/BuiltInTypeSerializer.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/BuiltInTypeSerializer.kt
deleted file mode 100644
index c325e62..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/BuiltInTypeSerializer.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.types
-
-import androidx.appactions.builtintypes.types.Thing
-import androidx.appactions.interaction.protobuf.Struct
-
-/**
- * Serializes some structured Built-in Type [T] to and from a [Struct] i.e. a JSON object.
- *
- * Structured Built-in Types refer to the top-level types under
- * `androidx.appactions.builtintypes.types.*` that are [Thing] or its subtypes.
- */
-interface BuiltInTypeSerializer<T : Thing> {
- /** The schema.org type's name as it appears in the serialized format e.g. `Person`. */
- val typeName: String
-
- /** Reference to the structured Built-in Type's class e.g. `Person::class.java`. */
- val classRef: Class<T>
-
- fun serialize(instance: T): Struct
- fun deserialize(jsonObj: Struct): T
-
- /**
- * Returns the set of valid [CanonicalValue]s that can be used within the context of [T].
- *
- * For example,
- *
- * ```kt
- * alarmSerializer.getCanonicalValues(DisambiguatingDescription.CanonicalValue::class.java)
- * ```
- *
- * returns all the values for `Alarm.DisambiguatingDescriptionValue`.
- */
- fun <CanonicalValue> getCanonicalValues(cls: Class<CanonicalValue>): List<CanonicalValue>
-}
-
-inline fun <reified CanonicalValue, T : Thing> BuiltInTypeSerializer<T>.getCanonicalValues():
- List<CanonicalValue> {
- return getCanonicalValues(CanonicalValue::class.java)
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/BuiltInTypeSerializerRegistry.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/BuiltInTypeSerializerRegistry.kt
deleted file mode 100644
index f80c2f3..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/BuiltInTypeSerializerRegistry.kt
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.types
-
-import androidx.appactions.builtintypes.types.Thing
-import androidx.appactions.interaction.capabilities.core.impl.utils.CapabilityLogger.LogLevel.DEBUG
-import androidx.appactions.interaction.capabilities.core.impl.utils.CapabilityLogger.LogLevel.INFO
-import androidx.appactions.interaction.capabilities.core.impl.utils.LoggerInternal
-import java.lang.reflect.Method
-import java.lang.reflect.Modifier
-import java.util.Collections
-import java.util.LinkedList
-import java.util.Queue
-
-/** A global singleton to avoid reflection upon every instance creation. */
-val builtInTypeSerializerRegistry: BuiltInTypeSerializerRegistry by lazy {
- BuiltInTypeSerializerRegistry(
- serializerRegistryClassNames =
- listOf(
- "androidx.appactions.interaction.capabilities.serializers.types.AllCoreSerializers",
- ),
- ::getClassByNameOrNull)
-}
-
-private const val LOG_TAG = "BuiltInTypeSerializerRegistry"
-
-/**
- * A registry of [BuiltInTypeSerializer]s that allows getting serializers by type.
- *
- * Computes the entire set of serializers using reflection upon construction. This can be relatively
- * compute expensive.
- *
- * This class is thread-safe.
- *
- * @param serializerRegistryClassNames The canonical class names of the `All*Serializers` objects
- * e.g. [androidx.appactions.interaction.capabilities.serializers.types.AllCoreSerializers]. These
- * objects are expected to have top-level, zero param, static methods that return instances of
- * [BuiltInTypeSerializer].
- * @param getClassOrNull Functor that returns a class ref given its canonical name, or null.
- */
-@Suppress("BanUncheckedReflection")
-class BuiltInTypeSerializerRegistry(
- serializerRegistryClassNames: List<String>,
- getClassOrNull: (canonicalName: String) -> Class<*>?
-) {
- // Person::class.java -> PersonSerializer, PersonImpl::class.java -> PersonSerializer
- private val classToSerializer: MutableMap<Class<*>, BuiltInTypeSerializer<*>> =
- Collections.synchronizedMap(mutableMapOf())
-
- init {
- // Need to use reflection to dynamically access serializers based on type-name. These
- // serializers may be coming from a downstream artifact and are not available at
- // compile-time. This also aids in a binary-bloat optimization where all serializers start
- // off a dead code and then we instruct proguard to only retain the serializers for types
- // that are explicitly referenced and prune others.
- val serializers =
- serializerRegistryClassNames
- // object AllProductivitySerializers
- .mapNotNull { className -> getClassOrNull(className) }
- .flatMap { cls -> cls.methods.toList() }
- // @JvmStatic fun getPersonSerializer(): PersonSerializer
- .filter { it.isStatic && it.hasNoParams && it.returnsSomeSerializer }
- .map { it.invoke(null) as BuiltInTypeSerializer<*> }
-
- for (serializer in serializers) {
- classToSerializer[serializer.classRef] = serializer
- }
- }
-
- @Suppress("UNCHECKED_CAST")
- fun <T : Thing> getSerializer(instance: T): BuiltInTypeSerializer<T>? {
- val instanceClass = instance::class.java
- val serializer = classToSerializer[instanceClass]
- if (serializer != null) return serializer as BuiltInTypeSerializer<T>
-
- logDebug(instanceClass, "No serializer found. Moving up the class hierarchy")
-
- // instance is likely not a Built-in Type (interface) itself but a concrete impl
- // e.g. PersonImpl. Go up the type hierarchy and try to find the first Built-in Type
- // interface that we have a serializer for.
- for ((i, classes) in instanceClass.traverseUpInLevelOrder().withIndex()) {
- logDebug(instanceClass, "Searching for serializers ${i + 1} levels above")
- val serializersAtThisLevel = classes.mapNotNull { cls -> classToSerializer[cls] }
- return when (serializersAtThisLevel.size) {
- 0 -> continue
- // Match!
- 1 -> {
- val matchedSerializer = serializersAtThisLevel.first()
- // Cache for next time so we don't have to traverse up the hierarchy then
- classToSerializer.putIfAbsent(instanceClass, matchedSerializer)
- logDebug(instanceClass, "Returning '${matchedSerializer.typeName}' serializer")
- matchedSerializer as BuiltInTypeSerializer<T>
- }
- else -> {
- val typeNames = serializersAtThisLevel.map { it.typeName }
- logInfo(
- instanceClass,
- "Found multiple serializers for $typeNames. There is ambiguity " +
- "in picking one. This can happen because of bad proguard configs or " +
- "if the user manually inherited from 2+ Built-in Type interfaces. " +
- "Bailing out and returning null.")
- null
- }
- }
- }
-
- logInfo(instanceClass, "No serializer found. Returning null.")
- return null
- }
-
- private val Method.isStatic: Boolean
- get() = Modifier.isStatic(modifiers)
-
- private val Method.hasNoParams: Boolean
- get() = parameterTypes.isEmpty()
-
- private val Method.returnsSomeSerializer: Boolean
- get() = BuiltInTypeSerializer::class.java.isAssignableFrom(returnType)
-
- /**
- * Yields all the ancestor types in levels. For example, given:
- * ```
- * GreatGrandparent
- * ↑
- * Grandparent
- * ↗ ↖
- * ParentA ParentB
- * ↖ ↗
- * Child
- * ```
- *
- * `Child::class.java.traverseUpInLevelOrder()` yields in this order:
- * ```
- * [ParentA, ParentB],
- * [Grandparent],
- * [GreatGrandparent]
- * ```
- *
- * Duplicates are ignored guaranteeing the [Sequence] terminates.
- */
- private fun Class<*>.traverseUpInLevelOrder(): Sequence<Set<Class<*>>> = sequence {
- // Level-order traversal (very similar to BFS)
- val seen: MutableSet<Class<*>> = mutableSetOf(this@traverseUpInLevelOrder)
- val queue: Queue<Class<*>> = LinkedList()
-
- if (superclass != null) queue += superclass
- queue += interfaces
-
- while (queue.isNotEmpty()) {
- val classesInCurrentLevel = mutableSetOf<Class<*>>()
- val currentLevelSize = queue.size
- repeat(currentLevelSize) {
- val cls = queue.remove()
- seen += cls
- classesInCurrentLevel += cls
-
- // Add classes from the next level, i.e. parents, to the queue
- if (cls.superclass != null && cls.superclass !in seen) queue += cls.superclass
- queue += cls.interfaces.filter { it !in seen }
- }
- yield(classesInCurrentLevel)
- }
- }
-
- private fun logDebug(instanceClass: Class<out Thing>, message: String) {
- LoggerInternal.log(
- DEBUG, LOG_TAG, "While finding serializer for class: $instanceClass - $message")
- }
-
- private fun logInfo(instanceClass: Class<out Thing>, message: String) {
- LoggerInternal.log(
- INFO, LOG_TAG, "While finding serializer for class: $instanceClass - $message")
- }
-}
-
-private fun getClassByNameOrNull(canonicalName: String): Class<*>? {
- return try {
- Class.forName(canonicalName)
- } catch (_: ClassNotFoundException) {
- null
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/DayOfWeekSerializer.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/DayOfWeekSerializer.kt
deleted file mode 100644
index 2872151..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/DayOfWeekSerializer.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.types
-
-import androidx.appactions.builtintypes.types.DayOfWeek
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException
-
-private val supportedDayOfWeekValues = listOf(
- DayOfWeek.FRIDAY, DayOfWeek.MONDAY,
- DayOfWeek.PUBLIC_HOLIDAYS,
- DayOfWeek.SATURDAY,
- DayOfWeek.SUNDAY,
- DayOfWeek.THURSDAY,
- DayOfWeek.TUESDAY,
- DayOfWeek.WEDNESDAY
-)
-
-val DAY_OF_WEEK_TYPE_SPEC = TypeSpec.createStringBasedTypeSpec<DayOfWeek>(
- toString = DayOfWeek::canonicalUrl,
- fromString = {
- str ->
- supportedDayOfWeekValues.find {
- it.canonicalUrl == str
- } ?: throw StructConversionException(
- "failed to deserialize DayOfWeek with canonicalUrl=$str"
- )
- }
-)
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/GenericErrorStatusSerializer.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/GenericErrorStatusSerializer.kt
deleted file mode 100644
index f09704be1..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/GenericErrorStatusSerializer.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.types
-
-import androidx.appactions.builtintypes.types.GenericErrorStatus
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpecBuilder
-import androidx.appactions.interaction.capabilities.serializers.properties.NAME_TYPE_SPEC
-
-val GENERIC_ERROR_STATUS_TYPE_SPEC: TypeSpec<GenericErrorStatus> = TypeSpecBuilder.newBuilder(
- "GenericErrorStatus",
- GenericErrorStatus::Builder,
- GenericErrorStatus.Builder<*>::build
-).bindSpecField(
- "name",
- { it.name },
- GenericErrorStatus.Builder<*>::setName,
- NAME_TYPE_SPEC
-).bindStringField(
- "identifier",
- { it.identifier.ifEmpty { null } },
- GenericErrorStatus.Builder<*>::setIdentifier
-).bindIdentifier {
- it.identifier.ifEmpty { null }
-}.build()
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/IntangibleSerializer.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/IntangibleSerializer.kt
deleted file mode 100644
index c8e05c5..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/IntangibleSerializer.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-// 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.appactions.interaction.capabilities.serializers.types
-
-import androidx.appactions.builtintypes.types.Intangible
-import androidx.appactions.interaction.capabilities.serializers.stringValue
-import androidx.appactions.interaction.protobuf.Struct
-import java.lang.Class
-import kotlin.String
-import kotlin.collections.List
-import kotlin.collections.emptyList
-
-/** Serializes [Intangible] to and from a [Struct] i.e. JSON obj. */
-public class IntangibleSerializer : BuiltInTypeSerializer<Intangible> {
- public override val typeName: String = "Intangible"
-
- public override val classRef: Class<Intangible> = Intangible::class.java
-
- public override fun serialize(instance: Intangible): Struct =
- Struct.newBuilder().putFields("@type", stringValue("Intangible")).build()
-
- public override fun deserialize(jsonObj: Struct): Intangible = Intangible.Builder().build()
-
- public override fun <CanonicalValue> getCanonicalValues(
- cls: Class<CanonicalValue>
- ): List<CanonicalValue> = emptyList()
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/ObjectCreationLimitReachedStatusSerializer.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/ObjectCreationLimitReachedStatusSerializer.kt
deleted file mode 100644
index 1283b22..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/ObjectCreationLimitReachedStatusSerializer.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.types
-
-import androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpecBuilder
-import androidx.appactions.interaction.capabilities.serializers.properties.NAME_TYPE_SPEC
-
-val OBJECT_CREATION_LIMIT_REACHED_STATUS_TYPE_SPEC: TypeSpec<ObjectCreationLimitReachedStatus> =
-TypeSpecBuilder.newBuilder(
- "ObjectCreationLimitReachedStatus",
- ObjectCreationLimitReachedStatus::Builder,
- ObjectCreationLimitReachedStatus.Builder<*>::build
-).bindSpecField(
- "name",
- { it.name },
- ObjectCreationLimitReachedStatus.Builder<*>::setName,
- NAME_TYPE_SPEC
-).bindStringField(
- "identifier",
- { it.identifier.ifEmpty { null } },
- ObjectCreationLimitReachedStatus.Builder<*>::setIdentifier
-).bindIdentifier {
- it.identifier.ifEmpty { null }
-}.build()
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/PersonSerializer.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/PersonSerializer.kt
deleted file mode 100644
index beceab9..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/PersonSerializer.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-// 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.appactions.interaction.capabilities.serializers.types
-
-import androidx.appactions.builtintypes.types.Person
-import androidx.appactions.interaction.capabilities.serializers.stringValue
-import androidx.appactions.interaction.protobuf.Struct
-import java.lang.Class
-import kotlin.String
-import kotlin.collections.List
-import kotlin.collections.emptyList
-
-/** Serializes [Person] to and from a [Struct] i.e. JSON obj. */
-public class PersonSerializer : BuiltInTypeSerializer<Person> {
- public override val typeName: String = "Person"
-
- public override val classRef: Class<Person> = Person::class.java
-
- public override fun serialize(instance: Person): Struct =
- Struct.newBuilder().putFields("@type", stringValue("Person")).build()
-
- public override fun deserialize(jsonObj: Struct): Person = Person.Builder().build()
-
- public override fun <CanonicalValue> getCanonicalValues(
- cls: Class<CanonicalValue>
- ): List<CanonicalValue> = emptyList()
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/ScheduleSerializer.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/ScheduleSerializer.kt
deleted file mode 100644
index 9f9cacc..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/ScheduleSerializer.kt
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.types
-
-import androidx.appactions.builtintypes.types.Schedule
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpecBuilder
-import androidx.appactions.interaction.capabilities.serializers.properties.BY_DAY_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.properties.END_DATE_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.properties.END_TIME_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.properties.EXCEPT_DATE_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.properties.NAME_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.properties.REPEAT_FREQUENCY_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.properties.START_DATE_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.properties.START_TIME_TYPE_SPEC
-
-val SCHEDULE_TYPE_SPEC: TypeSpec<Schedule> = TypeSpecBuilder.newBuilder(
- "Schedule",
- Schedule::Builder,
- Schedule.Builder<*>::build
-).bindRepeatedSpecField(
- "byDays",
- { it.byDays },
- Schedule.Builder<*>::addByDays,
- BY_DAY_TYPE_SPEC
-).bindRepeatedSpecField(
- "byMonths",
- { it.byMonths },
- Schedule.Builder<*>::addByMonths,
- TypeSpec.LONG_TYPE_SPEC
-).bindRepeatedSpecField(
- "byMonthDays",
- { it.byMonthDays },
- Schedule.Builder<*>::addByMonthDays,
- TypeSpec.LONG_TYPE_SPEC
-).bindRepeatedSpecField(
- "byMonthWeeks",
- { it.byMonthWeeks },
- Schedule.Builder<*>::addByMonthWeeks,
- TypeSpec.LONG_TYPE_SPEC
-).bindSpecField(
- "endDate",
- { it.endDate },
- Schedule.Builder<*>::setEndDate,
- END_DATE_TYPE_SPEC
-).bindSpecField(
- "endTime",
- { it.endTime },
- Schedule.Builder<*>::setEndTime,
- END_TIME_TYPE_SPEC
-).bindSpecField(
- "exceptDate",
- { it.exceptDate },
- Schedule.Builder<*>::setExceptDate,
- EXCEPT_DATE_TYPE_SPEC
-).bindSpecField(
- "repeatCount",
- { it.repeatCount },
- Schedule.Builder<*>::setRepeatCount,
- TypeSpec.LONG_TYPE_SPEC
-).bindSpecField(
- "repeatFrequency",
- { it.repeatFrequency },
- Schedule.Builder<*>::setRepeatFrequency,
- REPEAT_FREQUENCY_TYPE_SPEC
-).bindStringField(
- "scheduleTimeZone",
- { it.scheduleTimezone },
- Schedule.Builder<*>::setScheduleTimezone
-).bindSpecField(
- "startDate",
- { it.startDate },
- Schedule.Builder<*>::setStartDate,
- START_DATE_TYPE_SPEC
-).bindSpecField(
- "startTime",
- { it.startTime },
- Schedule.Builder<*>::setStartTime,
- START_TIME_TYPE_SPEC
-).bindSpecField(
- "name",
- { it.name },
- Schedule.Builder<*>::setName,
- NAME_TYPE_SPEC
-).bindStringField(
- "identifier",
- { it.identifier.ifEmpty { null } },
- Schedule.Builder<*>::setIdentifier
-).bindIdentifier {
- it.identifier.ifEmpty { null }
-}.build()
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/Serialize.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/Serialize.kt
deleted file mode 100644
index dd2e527..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/Serialize.kt
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.types
-
-import androidx.appactions.builtintypes.types.Thing
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException
-import androidx.appactions.interaction.protobuf.Struct
-
-/**
- * Converts the specified [Thing] (or subtype) to a JSON-LD conforming [Struct].
- *
- * Takes care of dynamically invoking the correct serializer based on the runtime type of the
- * [instance]. For example,
- * ```kt
- * val person =
- * Person.Builder()
- * .setName("Jane")
- * .setEmail("[email protected]")
- * .build()
- * // {
- * // "@type": "Person",
- * // "name": "Jane",
- * // "email": "[email protected]"
- * // }
- * val struct = serialize(person)
- * ```
- *
- * @throws StructConversionException if some internal error occurs during serialization.
- */
-fun serialize(instance: Thing): Struct {
- val serializer =
- builtInTypeSerializerRegistry.getSerializer(instance)
- ?: throw StructConversionException(
- "Could not unambiguously determine the serializer for instance: $instance")
- return serializer.serialize(instance)
-}
-
-/**
- * Converts a JSON-LD conforming [Struct] to a [Thing] (or subtype).
- *
- * Takes care of dynamically invoking the correct serializer based on the "@type" field in the
- * [struct]. For example,
- * ```kt
- * // {
- * // "@type": "Person",
- * // "name": "Jane",
- * // "email": "[email protected]"
- * // }
- * val struct: Struct
- * val thing = deserialize(struct)
- *
- * print(thing.name) // Jane
- * if (thing is Person) {
- * println(thing.email) // [email protected]
- * }
- * ```
- *
- * @throws StructConversionException If the [struct] refers to some unknown type.
- */
-fun deserialize(@Suppress("UNUSED_PARAMETER") struct: Struct): Thing = TODO()
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/SuccessStatusSerializer.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/SuccessStatusSerializer.kt
deleted file mode 100644
index e0171f1..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/SuccessStatusSerializer.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.types
-
-import androidx.appactions.builtintypes.types.SuccessStatus
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpecBuilder
-import androidx.appactions.interaction.capabilities.serializers.properties.NAME_TYPE_SPEC
-
-val SUCCESS_STATUS_TYPE_SPEC: TypeSpec<SuccessStatus> = TypeSpecBuilder.newBuilder(
- "SuccessStatus",
- SuccessStatus::Builder,
- SuccessStatus.Builder<*>::build
-).bindSpecField(
- "name",
- { it.name },
- SuccessStatus.Builder<*>::setName,
- NAME_TYPE_SPEC
-).bindStringField(
- "identifier",
- { it.identifier.ifEmpty { null } },
- SuccessStatus.Builder<*>::setIdentifier
-).bindIdentifier {
- it.identifier.ifEmpty { null }
-}.build()
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/ThingSerializer.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/ThingSerializer.kt
deleted file mode 100644
index 4df96bf..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/ThingSerializer.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-// 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.appactions.interaction.capabilities.serializers.types
-
-import androidx.appactions.builtintypes.types.Thing
-import androidx.appactions.interaction.capabilities.serializers.stringValue
-import androidx.appactions.interaction.protobuf.Struct
-import java.lang.Class
-import kotlin.String
-import kotlin.collections.List
-import kotlin.collections.emptyList
-
-/** Serializes [Thing] to and from a [Struct] i.e. JSON obj. */
-public class ThingSerializer : BuiltInTypeSerializer<Thing> {
- public override val typeName: String = "Thing"
-
- public override val classRef: Class<Thing> = Thing::class.java
-
- public override fun serialize(instance: Thing): Struct =
- Struct.newBuilder().putFields("@type", stringValue("Thing")).build()
-
- public override fun deserialize(jsonObj: Struct): Thing = Thing.Builder().build()
-
- public override fun <CanonicalValue> getCanonicalValues(
- cls: Class<CanonicalValue>
- ): List<CanonicalValue> = emptyList()
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/TimerSerializer.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/TimerSerializer.kt
deleted file mode 100644
index 9b0c91e..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/TimerSerializer.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.types
-
-import androidx.appactions.builtintypes.types.Timer
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpecBuilder
-import androidx.appactions.interaction.capabilities.serializers.properties.NAME_TYPE_SPEC
-
-@JvmField
-val TIMER_TYPE_SPEC: TypeSpec<Timer> = TypeSpecBuilder.newBuilder(
- "Timer",
- Timer::Builder,
- Timer.Builder<*>::build
-).bindSpecField(
- "duration",
- { it.duration },
- Timer.Builder<*>::setDuration,
- TypeSpec.DURATION_TYPE_SPEC
-).bindSpecField(
- "name",
- { it.name },
- Timer.Builder<*>::setName,
- NAME_TYPE_SPEC
-).bindStringField(
- "identifier",
- { it.identifier.ifEmpty { null } },
- Timer.Builder<*>::setIdentifier
-).bindIdentifier {
- it.identifier.ifEmpty { null }
-}.build()
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/UnsupportedOperationStatusSerializer.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/UnsupportedOperationStatusSerializer.kt
deleted file mode 100644
index 4561ad5..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/serializers/types/UnsupportedOperationStatusSerializer.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.types
-
-import androidx.appactions.builtintypes.types.UnsupportedOperationStatus
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpecBuilder
-import androidx.appactions.interaction.capabilities.serializers.properties.NAME_TYPE_SPEC
-
-val UNSUPPORTED_OPERATION_STATUS_TYPE_SPEC: TypeSpec<UnsupportedOperationStatus> =
-TypeSpecBuilder.newBuilder(
- "UnsupportedOperationStatus",
- UnsupportedOperationStatus::Builder,
- UnsupportedOperationStatus.Builder<*>::build
-).bindSpecField(
- "name",
- { it.name },
- UnsupportedOperationStatus.Builder<*>::setName,
- NAME_TYPE_SPEC
-).bindStringField(
- "identifier",
- { it.identifier.ifEmpty { null } },
- UnsupportedOperationStatus.Builder<*>::setIdentifier
-).bindIdentifier {
- it.identifier.ifEmpty { null }
-}.build()
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/EntitySearchResultTest.java b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/EntitySearchResultTest.java
deleted file mode 100644
index c796b34..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/EntitySearchResultTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-public final class EntitySearchResultTest {
-
- @Test
- public void emptyList() {
- assertThat(new EntitySearchResult.Builder<Object>().build().getPossibleValues()).isEmpty();
- }
-
- @Test
- public void test() {
- EntitySearchResult.Builder<String> builder = new EntitySearchResult.Builder<String>();
- builder.addPossibleValue("foo");
- builder.addPossibleValue("bar");
-
- assertThat(builder.build().getPossibleValues()).containsExactly("foo", "bar");
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/LibInfoTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/LibInfoTest.kt
deleted file mode 100644
index f6e083e..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/LibInfoTest.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core
-
-import androidx.appactions.interaction.capabilities.core.LibInfo.Version
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class LibInfoTest {
- @Test
- fun getVersion_fromValidString_returnsVersion() {
- val versionString = "1.0.0-alpha01"
- val version: Version = Version.parse(versionString)
- assertThat(version.major).isEqualTo(1)
- assertThat(version.minor).isEqualTo(0)
- assertThat(version.patch).isEqualTo(0)
- assertThat(version.preReleaseId).isEqualTo("alpha01")
- }
-
- @Test
- fun getVersion_fromInvalidString_throwsException() {
- val versionString = "1A"
- var version: Version? = null
- var exceptionMsg: String? = null
- try {
- version = Version.parse(versionString)
- } catch (e: IllegalArgumentException) {
- exceptionMsg = e.message
- }
- assertThat(version).isNull()
- assertThat(exceptionMsg).isEqualTo("Can not parse version: 1A")
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/entity/AlarmProvider.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/entity/AlarmProvider.kt
deleted file mode 100644
index d5d6016..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/entity/AlarmProvider.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.entity
-
-import androidx.appactions.builtintypes.types.Alarm
-import androidx.appactions.interaction.capabilities.serializers.types.ALARM_TYPE_SPEC
-
-/** Internal testing object for entity provider */
-class AlarmProvider internal constructor(
- override val id: String,
- private var response: EntityLookupResponse<Alarm>,
-) : EntityProvider<Alarm>(ALARM_TYPE_SPEC) {
- override suspend fun lookup(request: EntityLookupRequest<Alarm>):
- EntityLookupResponse<Alarm> = response
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/entity/EntityProviderTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/entity/EntityProviderTest.kt
deleted file mode 100644
index fcd1086..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/entity/EntityProviderTest.kt
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.entity
-
-import androidx.appactions.builtintypes.types.Alarm
-import androidx.appactions.interaction.proto.Entity
-import androidx.appactions.interaction.proto.GroundingRequest
-import androidx.appactions.interaction.proto.GroundingResponse
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.protobuf.ByteString
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.runBlocking
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-private val VALID_GROUNDING_REQUEST = GroundingRequest.newBuilder()
- .setRequest(
- GroundingRequest.Request.newBuilder()
- .setSearchAction(
- ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields(
- "@type",
- Value.newBuilder().setStringValue("SearchAction").build(),
- )
- .putFields(
- "filter",
- Value.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields(
- "@type",
- Value.newBuilder()
- .setStringValue("Alarm")
- .build(),
- ),
- )
- .build(),
- ),
- ),
- ),
- )
- .build()
-
-@RunWith(JUnit4::class)
-class EntityProviderTest {
- private fun createExternalResponse(
- candidateList: List<EntityLookupCandidate<Alarm>>,
- status: Int,
- ): EntityLookupResponse<Alarm> {
- return EntityLookupResponse.Builder<Alarm>()
- .setCandidateList(candidateList)
- .setStatus(status)
- .setNextPageToken(ByteString.EMPTY)
- .build()
- }
-
- private fun createInternalResponse(
- candidateList: List<GroundingResponse.Candidate>,
- status: GroundingResponse.Status,
- ): GroundingResponse? {
- return GroundingResponse.newBuilder().setResponse(
- GroundingResponse.Response.newBuilder().addAllCandidates(candidateList)
- .setStatus(status).build(),
- ).build()
- }
-
- private fun createExternalCandidate(id: String, name: String): EntityLookupCandidate<Alarm> {
- val candidateBuilder: EntityLookupCandidate.Builder<Alarm> =
- EntityLookupCandidate.Builder()
- candidateBuilder.setCandidate(Alarm.Builder().setName(name).setIdentifier(id).build())
- return candidateBuilder.build()
- }
-
- private fun createInternalCandidate(id: String, name: String): GroundingResponse.Candidate {
- return GroundingResponse.Candidate.newBuilder()
- .setGroundedEntity(
- Entity.newBuilder()
- .setIdentifier(id)
- .setStructValue(
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("Alarm").build())
- .putFields("identifier", Value.newBuilder().setStringValue(id).build())
- .putFields("name", Value.newBuilder().setStringValue(name).build()),
- ),
- )
- .build()
- }
-
- @Test
- fun invalidEntity_returnError() = runBlocking<Unit> {
- val entityProvider = AlarmProvider(
- "id",
- createExternalResponse(
- listOf(),
- EntityLookupResponse.SUCCESS,
- ),
- )
-
- val response =
- entityProvider.lookupInternal(GroundingRequest.getDefaultInstance())
-
- assertThat(response)
- .isEqualTo(
- createInternalResponse(
- listOf(),
- GroundingResponse.Status.INVALID_ENTITY_ARGUMENT,
- ),
- )
- }
-
- @Test
- fun errorInExternalResponse_returnError() = runBlocking<Unit> {
- val entityProvider = AlarmProvider(
- "id",
- createExternalResponse(
- listOf(),
- EntityLookupResponse.CANCELED,
- ),
- )
-
- val response =
- entityProvider.lookupInternal(VALID_GROUNDING_REQUEST)
-
- assertThat(response)
- .isEqualTo(createInternalResponse(listOf(), GroundingResponse.Status.CANCELED))
- }
-
- @Test
- fun success() = runBlocking<Unit> {
- val candidateBuilder: EntityLookupCandidate.Builder<Alarm> =
- EntityLookupCandidate.Builder()
- candidateBuilder.setCandidate(Alarm.Builder().setName("testing-alarm").build())
- val entityProvider = AlarmProvider(
- "id",
- createExternalResponse(
- listOf(
- createExternalCandidate("id-1", "name-1"),
- createExternalCandidate("id-2", "name-2"),
- ),
- EntityLookupResponse.SUCCESS,
- ),
- )
-
- val response =
- entityProvider.lookupInternal(VALID_GROUNDING_REQUEST)
-
- assertThat(response)
- .isEqualTo(
- createInternalResponse(
- listOf(
- createInternalCandidate("id-1", "name-1"),
- createInternalCandidate("id-2", "name-2"),
- ),
- GroundingResponse.Status.SUCCESS,
- ),
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityTest.kt
deleted file mode 100644
index e5353d8..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/SingleTurnCapabilityTest.kt
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl
-
-import android.util.SizeF
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.ExecutionCallbackAsync
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpec
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.BoundProperty
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.core.properties.StringValue
-import androidx.appactions.interaction.capabilities.core.testing.spec.Arguments
-import androidx.appactions.interaction.capabilities.core.testing.spec.Output
-import androidx.appactions.interaction.capabilities.core.toExecutionCallback
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils
-import androidx.appactions.interaction.capabilities.testing.internal.FakeCallbackInternal
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.BLOCKING_TIMEOUT
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.CB_TIMEOUT
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter
-import androidx.appactions.interaction.proto.FulfillmentResponse
-import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput
-import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput.OutputValue
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.proto.TaskInfo
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.withTimeoutOrNull
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class SingleTurnCapabilityTest {
- private val hostProperties =
- HostProperties.Builder().setMaxHostSizeDp(SizeF(300f, 500f)).build()
- private val fakeSessionId = "fakeSessionId"
-
- @Test
- fun appAction_computedProperty() {
- val mutableEntityList = mutableListOf<StringValue>()
- val dynamicStringProperty = Property(possibleValueSupplier = mutableEntityList::toList)
- val capability = SingleTurnCapabilityImpl(
- id = "capabilityId",
- actionSpec = ACTION_SPEC,
- boundProperties = listOf(
- BoundProperty(
- "requiredString",
- dynamicStringProperty,
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
- ),
- executionCallback = ExecutionCallback<Arguments, Output> {
- ExecutionResult.Builder<Output>().build()
- }
- )
- mutableEntityList.add(StringValue("entity1"))
-
- assertThat(capability.appAction).isEqualTo(
- AppAction.newBuilder()
- .setIdentifier("capabilityId")
- .setName("actions.intent.TEST")
- .addParams(
- IntentParameter.newBuilder()
- .setName("requiredString")
- .addPossibleEntities(
- androidx.appactions.interaction.proto.Entity.newBuilder()
- .setIdentifier("entity1")
- .setName("entity1")
- )
- )
- .setTaskInfo(TaskInfo.newBuilder().setSupportsPartialFulfillment(false))
- .build()
- )
-
- mutableEntityList.add(StringValue("entity2"))
- assertThat(capability.appAction).isEqualTo(
- AppAction.newBuilder()
- .setIdentifier("capabilityId")
- .setName("actions.intent.TEST")
- .addParams(
- IntentParameter.newBuilder()
- .setName("requiredString")
- .addPossibleEntities(
- androidx.appactions.interaction.proto.Entity.newBuilder()
- .setIdentifier("entity1")
- .setName("entity1")
- )
- .addPossibleEntities(
- androidx.appactions.interaction.proto.Entity.newBuilder()
- .setIdentifier("entity2")
- .setName("entity2")
- )
- )
- .setTaskInfo(TaskInfo.newBuilder().setSupportsPartialFulfillment(false))
- .build()
- )
- }
-
- @Test
- fun oneShotCapability_successWithOutput() {
- val executionCallback =
- ExecutionCallback<Arguments, Output> {
- ExecutionResult.Builder<Output>()
- .setOutput(
- Output.Builder().setOptionalStringField("stringOutput").build()
- )
- .build()
- }
- val capability =
- SingleTurnCapabilityImpl(
- id = "capabilityId",
- actionSpec = ACTION_SPEC,
- boundProperties = listOf(
- BoundProperty(
- "requiredString",
- Property<StringValue>(),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- ),
- BoundProperty(
- "optionalString",
- Property.unsupported<StringValue>(),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
- ),
- executionCallback = executionCallback
- )
-
- val capabilitySession = capability.createSession(fakeSessionId, hostProperties)
- assertThat(capabilitySession.sessionId).isEqualTo(fakeSessionId)
- assertThat(capabilitySession.state).isNull()
- assertThat(capabilitySession.isActive).isTrue()
-
- val callbackInternal = FakeCallbackInternal(CB_TIMEOUT)
- capabilitySession.execute(
- ArgumentUtils.buildArgs(
- mapOf(
- "optionalString" to
- ParamValue.newBuilder().setStringValue("string argument value").build()
- )
- ),
- callbackInternal
- )
-
- assertThat(capabilitySession.isActive).isFalse()
- val response = callbackInternal.receiveResponse()
- assertThat(response.fulfillmentResponse).isNotNull()
- assertThat(response.fulfillmentResponse)
- .isEqualTo(
- FulfillmentResponse.newBuilder()
- .setExecutionOutput(
- StructuredOutput.newBuilder()
- .addOutputValues(
- OutputValue.newBuilder()
- .setName("optionalStringOutput")
- .addValues(
- ParamValue.newBuilder()
- .setStringValue("stringOutput")
- .build()
- )
- .build()
- )
- .build()
- )
- .build()
- )
- }
-
- @Test
- fun oneShotCapability_exceptionInExecutionCallback() {
- val executionCallback =
- ExecutionCallback<Arguments, Output> { throw IllegalStateException("") }
- val capability =
- SingleTurnCapabilityImpl(
- id = "capabilityId",
- actionSpec = ACTION_SPEC,
- boundProperties = listOf(
- BoundProperty(
- "requiredString",
- Property<StringValue>(),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- ),
- BoundProperty(
- "optionalString",
- Property.unsupported<StringValue>(),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
- ),
- executionCallback = executionCallback
- )
-
- val capabilitySession = capability.createSession(fakeSessionId, hostProperties)
- val callbackInternal = FakeCallbackInternal(CB_TIMEOUT)
- capabilitySession.execute(
- ArgumentUtils.buildArgs(
- mapOf(
- "optionalString" to
- ParamValue.newBuilder().setStringValue("string argument value").build()
- )
- ),
- callbackInternal
- )
-
- val response = callbackInternal.receiveResponse()
- assertThat(response.errorStatus).isNotNull()
- assertThat(response.errorStatus).isEqualTo(ErrorStatusInternal.EXTERNAL_EXCEPTION)
- }
-
- @Test
- fun oneShotSession_uiHandle_withExecutionCallback() {
- val executionCallback =
- ExecutionCallback<Arguments, Output> { ExecutionResult.Builder<Output>().build() }
- val capability =
- SingleTurnCapabilityImpl(
- id = "capabilityId",
- actionSpec = ACTION_SPEC,
- boundProperties = listOf(
- BoundProperty(
- "requiredString",
- Property<StringValue>(),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- ),
- ),
- executionCallback = executionCallback
- )
- val session = capability.createSession(fakeSessionId, hostProperties)
- assertThat(session.uiHandle).isSameInstanceAs(executionCallback)
- }
-
- @Test
- fun oneShotSession_uiHandle_withExecutionCallbackAsync() {
- val executionCallbackAsync =
- ExecutionCallbackAsync<Arguments, Output> {
- Futures.immediateFuture(ExecutionResult.Builder<Output>().build())
- }
- val capability =
- SingleTurnCapabilityImpl(
- id = "capabilityId",
- actionSpec = ACTION_SPEC,
- boundProperties = listOf(
- BoundProperty(
- "requiredString",
- Property<StringValue>(),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
- ),
- executionCallback = executionCallbackAsync.toExecutionCallback()
- )
- val session = capability.createSession(fakeSessionId, hostProperties)
- assertThat(session.uiHandle).isSameInstanceAs(executionCallbackAsync)
- }
-
- @Test
- fun multipleSessions_sequentialExecution(): Unit = runBlocking {
- val executionResultChannel = Channel<ExecutionResult<Output>>()
- val argumentChannel = Channel<Arguments>()
-
- val executionCallback = ExecutionCallback<Arguments, Output> {
- argumentChannel.send(it)
- executionResultChannel.receive()
- }
- val capability = SingleTurnCapabilityImpl(
- id = "capabilityId",
- actionSpec = ACTION_SPEC,
- boundProperties = listOf(
- BoundProperty(
- "requiredString",
- Property<StringValue>(),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
- ),
- executionCallback = executionCallback
- )
- val session1 = capability.createSession("session1", hostProperties)
- val session2 = capability.createSession("session2", hostProperties)
-
- val callbackInternal1 = FakeCallbackInternal(CB_TIMEOUT)
- val callbackInternal2 = FakeCallbackInternal(CB_TIMEOUT)
-
- session1.execute(
- ArgumentUtils.buildArgs(
- mapOf(
- "optionalString" to
- ParamValue.newBuilder().setStringValue("string value 1").build()
- )
- ),
- callbackInternal1
- )
- session2.execute(
- ArgumentUtils.buildArgs(
- mapOf(
- "optionalString" to
- ParamValue.newBuilder().setStringValue("string value 2").build()
- )
- ),
- callbackInternal2
- )
-
- // verify ExecutionCallback receives 1st request.
- assertThat(argumentChannel.receive()).isEqualTo(
- Arguments.Builder().setOptionalStringField("string value 1").build()
- )
- // verify the 2nd request cannot be received due to mutex.
- assertThat(withTimeoutOrNull(BLOCKING_TIMEOUT) { argumentChannel.receive() }).isNull()
-
- // unblock first request handling.
- executionResultChannel.send(ExecutionResult.Builder<Output>().build())
- assertThat(callbackInternal1.receiveResponse().fulfillmentResponse).isEqualTo(
- FulfillmentResponse.getDefaultInstance()
- )
-
- assertThat(argumentChannel.receive()).isEqualTo(
- Arguments.Builder().setOptionalStringField("string value 2").build()
- )
- executionResultChannel.send(ExecutionResult.Builder<Output>().build())
- assertThat(callbackInternal2.receiveResponse().fulfillmentResponse).isEqualTo(
- FulfillmentResponse.getDefaultInstance()
- )
- }
-
- companion object {
- val ACTION_SPEC: ActionSpec<Arguments, Output> =
- ActionSpecBuilder.ofCapabilityNamed("actions.intent.TEST")
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindParameter(
- "requiredString",
- Arguments::requiredStringField,
- Arguments.Builder::setRequiredStringField,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER,
- )
- .bindParameter(
- "optionalString",
- Arguments::optionalStringField,
- Arguments.Builder::setOptionalStringField,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER,
- )
- .bindOutput(
- "optionalStringOutput",
- Output::optionalStringField,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER::toParamValue
- )
- .build()
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/concurrent/ConvertToListenableFutureTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/concurrent/ConvertToListenableFutureTest.kt
deleted file mode 100644
index 2422b97..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/concurrent/ConvertToListenableFutureTest.kt
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.concurrent
-
-import com.google.common.truth.Truth.assertThat
-import kotlin.coroutines.cancellation.CancellationException
-import kotlin.time.Duration.Companion.seconds
-import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.channels.ReceiveChannel
-import kotlinx.coroutines.channels.SendChannel
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.withTimeout
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class ConvertToListenableFutureTest {
- val TAG = "tag"
-
- @Test
- fun suspendToListenableFuture_smokeTest() {
- val stringFuture = convertToListenableFuture<String>(TAG) { "hello" }
- assertThat(stringFuture.get()).isEqualTo("hello")
- }
-
- @Test
- fun suspendToListenableFuture_pollingTest() {
- val stringChannel = Channel<String>(1)
- val stringFuture =
- convertToListenableFuture<String>(TAG) { getNextValueFromChannel(stringChannel) }
- assertThat(stringFuture.isDone()).isFalse()
-
- runBlocking { withTimeout(1.seconds) { stringChannel.send("hello") } }
- assertThat(stringFuture.get()).isEqualTo("hello")
- }
-
- @Test
- fun suspendToListenableFuture_cancellationTest() {
- val stringChannel = Channel<String>(1)
- val cancellationChannel = Channel<Boolean>(1)
- val stringFuture =
- convertToListenableFuture<String>(TAG) {
- getNextValueFromChannel(stringChannel, cancellationChannel)
- }
- stringFuture.cancel(true)
- assertThat(stringFuture.isCancelled()).isTrue()
- runBlocking {
- withTimeout(1.seconds) { assertThat(cancellationChannel.receive()).isTrue() }
- }
- }
-
- private suspend fun <T> getNextValueFromChannel(
- valueChannel: ReceiveChannel<T>,
- cancellationChannel: SendChannel<Boolean>? = null,
- ): T {
- try {
- return valueChannel.receive()
- } catch (e: CancellationException) {
- cancellationChannel?.send(true)
- throw e
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/concurrent/FuturesTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/concurrent/FuturesTest.kt
deleted file mode 100644
index c7140ba..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/concurrent/FuturesTest.kt
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.concurrent
-
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.CB_TIMEOUT
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.awaitSync
-import androidx.concurrent.futures.CallbackToFutureAdapter
-import androidx.concurrent.futures.CallbackToFutureAdapter.Completer
-import com.google.common.truth.Truth.assertThat
-import java.util.concurrent.ExecutionException
-import java.util.concurrent.TimeUnit.MILLISECONDS
-import kotlinx.coroutines.CompletableDeferred
-import org.junit.Assert.assertThrows
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class FuturesTest {
- @Test
- fun addCallback_onSuccess() {
- lateinit var integerCompleter: Completer<Int>
- val integerFuture = CallbackToFutureAdapter.getFuture<Int> {
- integerCompleter = it
- "integerFuture"
- }
- val calbackSuccessDeferred = CompletableDeferred<Boolean>()
- Futures.addCallback(
- integerFuture,
- object : FutureCallback<Int> {
- override fun onSuccess(result: Int) {
- calbackSuccessDeferred.complete(true)
- }
-
- override fun onFailure(t: Throwable) {
- calbackSuccessDeferred.complete(false)
- }
- },
- Runnable::run,
- )
-
- assertThat(calbackSuccessDeferred.isCompleted).isFalse()
-
- integerCompleter.set(25)
-
- assertThat(calbackSuccessDeferred.awaitSync()).isTrue()
- }
-
- @Test
- fun addCallback_onFailure() {
- lateinit var integerCompleter: Completer<Int>
- val integerFuture = CallbackToFutureAdapter.getFuture<Int> {
- integerCompleter = it
- "integerFuture"
- }
- val calbackSuccessDeferred = CompletableDeferred<Boolean>()
- Futures.addCallback(
- integerFuture,
- object : FutureCallback<Int> {
- override fun onSuccess(result: Int) {
- calbackSuccessDeferred.complete(true)
- }
-
- override fun onFailure(t: Throwable) {
- calbackSuccessDeferred.complete(false)
- }
- },
- Runnable::run,
- )
-
- assertThat(calbackSuccessDeferred.isCompleted).isFalse()
-
- integerCompleter.setException(IllegalStateException())
-
- assertThat(calbackSuccessDeferred.awaitSync()).isFalse()
- }
-
- @Test
- fun transform_success() {
- lateinit var integerCompleter: Completer<Int>
- val integerFuture = CallbackToFutureAdapter.getFuture<Int> {
- integerCompleter = it
- "integerFuture"
- }
- val transformedFuture = Futures.transform(
- integerFuture,
- { it + 10 },
- Runnable::run,
- "add 10",
- )
- integerCompleter.set(25)
- assertThat(transformedFuture.get(CB_TIMEOUT, MILLISECONDS)).isEqualTo(35)
- }
-
- @Test
- fun transformAsync_success() {
- lateinit var integerCompleter: Completer<Int>
- val integerFuture = CallbackToFutureAdapter.getFuture<Int> {
- integerCompleter = it
- "integerFuture"
- }
- val transformedFuture = Futures.transformAsync(
- integerFuture,
- { Futures.immediateFuture(it + 10) },
- Runnable::run,
- "add 10",
- )
- integerCompleter.set(25)
- assertThat(transformedFuture.get(CB_TIMEOUT, MILLISECONDS)).isEqualTo(35)
- }
-
- @Test
- fun immediateFuture_success() {
- val immediateFuture = Futures.immediateFuture(25)
- immediateFuture.cancel(true)
- assertThat(immediateFuture.isCancelled()).isFalse()
- assertThat(immediateFuture.isDone()).isTrue()
- assertThat(immediateFuture.get(CB_TIMEOUT, MILLISECONDS)).isEqualTo(25)
- }
-
- @Test
- fun immediateVoidFuture_success() {
- val immediateVoidFuture = Futures.immediateVoidFuture()
- immediateVoidFuture.cancel(true)
- assertThat(immediateVoidFuture.isCancelled()).isFalse()
- assertThat(immediateVoidFuture.isDone()).isTrue()
- assertThat(immediateVoidFuture.get(CB_TIMEOUT, MILLISECONDS)).isNull()
- }
-
- @Test
- fun immediateFailedFuture_failure() {
- val immediateFailedFuture =
- Futures.immediateFailedFuture<Any>(CustomException())
- val transformedFuture =
- Futures.transform(
- immediateFailedFuture,
- { it },
- Runnable::run,
- "test",
- )
-
- assertThat(transformedFuture.isDone()).isTrue()
- val e = assertThrows(ExecutionException::class.java, transformedFuture::get)
- assertThat(e).hasCauseThat().isInstanceOf(CustomException::class.java)
- }
-
- @Test
- fun transform_synchronousExceptionPropagated() {
- val transformedFuture =
- Futures.transform(
- Futures.immediateFuture(25),
- { throw IllegalStateException() },
- Runnable::run,
- "badTransform",
- )
- assertThat(transformedFuture.isDone()).isTrue()
-
- val errorDeferred = CompletableDeferred<Throwable>()
- Futures.addCallback(
- transformedFuture,
- object : FutureCallback<Int> {
- override fun onSuccess(result: Int) {}
-
- override fun onFailure(t: Throwable) {
- errorDeferred.complete(t)
- }
- },
- Runnable::run,
- )
- assertThat(errorDeferred.awaitSync()).isInstanceOf(
- IllegalStateException::class.java,
- )
- val e = assertThrows(ExecutionException::class.java, transformedFuture::get)
- assertThat(e).hasCauseThat().isInstanceOf(IllegalStateException::class.java)
- }
-
- @Test
- fun transformAsync_synchronousExceptionPropagated() {
- val transformedFuture =
- Futures.transformAsync<Int, Int>(
- Futures.immediateFuture(25),
- { throw IllegalStateException() },
- Runnable::run,
- "badTransform",
- )
- assertThat(transformedFuture.isDone()).isTrue()
-
- val errorDeferred = CompletableDeferred<Throwable>()
- Futures.addCallback(
- transformedFuture,
- object : FutureCallback<Int> {
- override fun onSuccess(result: Int) {}
-
- override fun onFailure(t: Throwable) {
- errorDeferred.complete(t)
- }
- },
- Runnable::run,
- )
- assertThat(errorDeferred.awaitSync()).isInstanceOf(
- IllegalStateException::class.java,
- )
- val e = assertThrows(ExecutionException::class.java, transformedFuture::get)
- assertThat(e).hasCauseThat().isInstanceOf(IllegalStateException::class.java)
- }
-
- class CustomException : Exception()
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/converters/EntityConverterTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/converters/EntityConverterTest.kt
deleted file mode 100644
index f04f5cf..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/converters/EntityConverterTest.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.converters
-
-import androidx.appactions.interaction.proto.Entity
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class EntityConverterTest {
- @Test
- fun stringConverter_correctBehavior() {
- val stringConverter = EntityConverter.of(TypeSpec.STRING_TYPE_SPEC)
- assertThat(stringConverter.convert("hello")).isEqualTo(
- Entity.newBuilder().setStringValue("hello").build(),
- )
- }
-
- @Test
- fun booleanConverter_correctBehavior() {
- val booleanConverter = EntityConverter.of(TypeSpec.BOOL_TYPE_SPEC)
-
- assertThat(booleanConverter.convert(true)).isEqualTo(
- Entity.newBuilder().setBoolValue(true).build(),
- )
- }
-
- @Test
- fun numberConverter_correctBehavior() {
- val numberConverter = EntityConverter.of(TypeSpec.NUMBER_TYPE_SPEC)
-
- assertThat(numberConverter.convert(3.14)).isEqualTo(
- Entity.newBuilder().setNumberValue(3.14).build(),
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/converters/ParamValueConverterTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/converters/ParamValueConverterTest.kt
deleted file mode 100644
index b7117db..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/converters/ParamValueConverterTest.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.converters
-
-import androidx.appactions.interaction.proto.ParamValue
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class ParamValueConverterTest {
- @Test
- fun stringConverter_correctBehavior() {
- val stringParamValue = ParamValue.newBuilder().setStringValue("hello").build()
- val stringConverter = ParamValueConverter.of(TypeSpec.STRING_TYPE_SPEC)
-
- assertThat(stringConverter.fromParamValue(stringParamValue)).isEqualTo("hello")
- assertThat(stringConverter.toParamValue("hello")).isEqualTo(stringParamValue)
- }
-
- @Test
- fun booleanConverter_correctBehavior() {
- val booleanParamValue = ParamValue.newBuilder().setBoolValue(true).build()
- val booleanConverter = ParamValueConverter.of(TypeSpec.BOOL_TYPE_SPEC)
-
- assertThat(booleanConverter.fromParamValue(booleanParamValue)).isEqualTo(true)
- assertThat(booleanConverter.toParamValue(true)).isEqualTo(booleanParamValue)
- }
-
- @Test
- fun numberConverter_correctBehavior() {
- val numberParamValue = ParamValue.newBuilder().setNumberValue(3.14).build()
- val numberConverter = ParamValueConverter.of(TypeSpec.NUMBER_TYPE_SPEC)
-
- assertThat(numberConverter.fromParamValue(numberParamValue)).isEqualTo(3.14)
- assertThat(numberConverter.toParamValue(3.14)).isEqualTo(numberParamValue)
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeConvertersTest.java b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeConvertersTest.java
deleted file mode 100644
index 5f7da3b..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeConvertersTest.java
+++ /dev/null
@@ -1,880 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.converters;
-
-import static androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters.BOOLEAN_PARAM_VALUE_CONVERTER;
-import static androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters.CALL_TYPE_SPEC;
-import static androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters.INTEGER_PARAM_VALUE_CONVERTER;
-import static androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters.ITEM_LIST_TYPE_SPEC;
-import static androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters.LIST_ITEM_TYPE_SPEC;
-import static androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters.MESSAGE_TYPE_SPEC;
-import static androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters.PARTICIPANT_TYPE_SPEC;
-import static androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters.RECIPIENT_TYPE_SPEC;
-import static androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters.SAFETY_CHECK_TYPE_SPEC;
-import static androidx.appactions.interaction.capabilities.serializers.types.TimerSerializerKt.TIMER_TYPE_SPEC;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.assertThrows;
-
-import androidx.appactions.builtintypes.experimental.properties.Attendee;
-import androidx.appactions.builtintypes.experimental.properties.Participant;
-import androidx.appactions.builtintypes.experimental.properties.Recipient;
-import androidx.appactions.builtintypes.experimental.types.CalendarEvent;
-import androidx.appactions.builtintypes.experimental.types.Call;
-import androidx.appactions.builtintypes.experimental.types.ItemList;
-import androidx.appactions.builtintypes.experimental.types.ListItem;
-import androidx.appactions.builtintypes.experimental.types.Message;
-import androidx.appactions.builtintypes.experimental.types.Person;
-import androidx.appactions.builtintypes.experimental.types.SafetyCheck;
-import androidx.appactions.builtintypes.types.DayOfWeek;
-import androidx.appactions.builtintypes.types.Timer;
-import androidx.appactions.interaction.capabilities.core.SearchAction;
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException;
-import androidx.appactions.interaction.proto.Entity;
-import androidx.appactions.interaction.proto.ParamValue;
-import androidx.appactions.interaction.protobuf.ListValue;
-import androidx.appactions.interaction.protobuf.Struct;
-import androidx.appactions.interaction.protobuf.Value;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.time.Duration;
-import java.time.LocalDate;
-import java.time.LocalTime;
-import java.time.ZoneId;
-import java.time.ZoneOffset;
-import java.time.ZonedDateTime;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-@RunWith(JUnit4.class)
-public final class TypeConvertersTest {
- private static Value structToValue(Struct struct) {
- return Value.newBuilder().setStructValue(struct).build();
- }
-
- private static final String EMPTY_PARAM_VALUE_MESSAGE =
- "cannot convert ParamValue into protobuf Value because it has no data types set.";
- private static final Person PERSON_JAVA_THING =
- Person.Builder()
- .setName("name")
- .setEmail("email")
- .setTelephone("telephone")
- .setIdentifier("id")
- .build();
- private static final Person PERSON_JAVA_THING_2 = Person.Builder().setIdentifier("id2").build();
- private static final CalendarEvent CALENDAR_EVENT_JAVA_THING =
- CalendarEvent.Builder()
- .setStartDate(ZonedDateTime.of(2022, 1, 1, 8, 0, 0, 0, ZoneOffset.UTC))
- .setEndDate(ZonedDateTime.of(2023, 1, 1, 8, 0, 0, 0, ZoneOffset.UTC))
- .addAttendee(new Attendee(PERSON_JAVA_THING))
- .addAttendee(new Attendee(PERSON_JAVA_THING_2))
- .build();
- private static final Call CALL_JAVA_THING =
- Call.Builder().setIdentifier("id").addParticipant(PERSON_JAVA_THING).build();
- private static final Message MESSAGE_JAVA_THING =
- Message.Builder()
- .setIdentifier("id")
- .addRecipient(PERSON_JAVA_THING)
- .setText("hello")
- .build();
- private static final SafetyCheck SAFETY_CHECK_JAVA_THING =
- SafetyCheck.Builder()
- .setIdentifier("id")
- .setDuration(Duration.ofMinutes(5))
- .setCheckInTime(ZonedDateTime.of(2023, 01, 10, 10, 0, 0, 0, ZoneOffset.UTC))
- .build();
-
- private static final Struct PERSON_STRUCT =
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("Person").build())
- .putFields("identifier", Value.newBuilder().setStringValue("id").build())
- .putFields("name", Value.newBuilder().setStringValue("name").build())
- .putFields("email", Value.newBuilder().setStringValue("email").build())
- .putFields("telephone", Value.newBuilder().setStringValue("telephone").build())
- .build();
- private static final Struct PERSON_STRUCT_2 =
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("Person").build())
- .putFields("identifier", Value.newBuilder().setStringValue("id2").build())
- .build();
- private static final Value CALENDAR_EVENT_VALUE =
- structToValue(
- Struct.newBuilder()
- .putFields(
- "@type",
- Value.newBuilder().setStringValue("CalendarEvent").build())
- .putFields(
- "startDate",
- Value.newBuilder().setStringValue("2022-01-01T08:00Z").build())
- .putFields(
- "endDate",
- Value.newBuilder().setStringValue("2023-01-01T08:00Z").build())
- .putFields(
- "attendee",
- Value.newBuilder()
- .setListValue(
- ListValue.newBuilder()
- .addValues(
- Value.newBuilder()
- .setStructValue(
- PERSON_STRUCT)
- .build())
- .addValues(
- Value.newBuilder()
- .setStructValue(
- PERSON_STRUCT_2)
- .build()))
- .build())
- .build());
- private static final Struct CALL_STRUCT =
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("Call").build())
- .putFields("identifier", Value.newBuilder().setStringValue("id").build())
- .putFields(
- "participant",
- Value.newBuilder()
- .setListValue(
- ListValue.newBuilder()
- .addValues(
- Value.newBuilder()
- .setStructValue(PERSON_STRUCT)))
- .build())
- .build();
- private static final Struct MESSAGE_STRUCT =
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("Message").build())
- .putFields("identifier", Value.newBuilder().setStringValue("id").build())
- .putFields(
- "recipient",
- Value.newBuilder()
- .setListValue(
- ListValue.newBuilder()
- .addValues(
- Value.newBuilder()
- .setStructValue(PERSON_STRUCT))
- .build())
- .build())
- .putFields("text", Value.newBuilder().setStringValue("hello").build())
- .build();
- private static final Struct SAFETY_CHECK_STRUCT =
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("SafetyCheck").build())
- .putFields("identifier", Value.newBuilder().setStringValue("id").build())
- .putFields("duration", Value.newBuilder().setStringValue("PT5M").build())
- .putFields(
- "checkInTime",
- Value.newBuilder().setStringValue("2023-01-10T10:00Z").build())
- .build();
-
- private static ParamValue toParamValue(Struct struct, String identifier) {
- return ParamValue.newBuilder().setIdentifier(identifier).setStructValue(struct).build();
- }
-
- @Test
- public void toIntegerValue() throws Exception {
- ParamValue paramValue = ParamValue.newBuilder().setNumberValue(5).build();
- List<ParamValue> input = Collections.singletonList(paramValue);
-
- assertThat(SlotTypeConverter.ofSingular(INTEGER_PARAM_VALUE_CONVERTER).convert(input))
- .isEqualTo(5);
-
- assertThat(INTEGER_PARAM_VALUE_CONVERTER.toParamValue(5)).isEqualTo(paramValue);
- assertThat(INTEGER_PARAM_VALUE_CONVERTER.fromParamValue(paramValue)).isEqualTo(5);
- }
-
- @Test
- public void toStringValue_fromList() throws Exception {
- List<ParamValue> input =
- Collections.singletonList(
- ParamValue.newBuilder().setStringValue("hello world").build());
-
- assertThat(
- SlotTypeConverter.ofSingular(TypeConverters.STRING_PARAM_VALUE_CONVERTER)
- .convert(input))
- .isEqualTo("hello world");
- }
-
- @Test
- public void toStringValue_fromSingleParam() throws Exception {
- ParamValue input = ParamValue.newBuilder().setStringValue("hello world").build();
-
- assertThat(TypeConverters.STRING_PARAM_VALUE_CONVERTER.fromParamValue(input))
- .isEqualTo("hello world");
- }
-
- @Test
- public void listItem_conversions_matchesExpected() throws Exception {
- ListItem listItem = ListItem.Builder().setIdentifier("itemId").setName("Test Item").build();
- Struct listItemStruct =
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("ListItem").build())
- .putFields(
- "identifier", Value.newBuilder().setStringValue("itemId").build())
- .putFields("name", Value.newBuilder().setStringValue("Test Item").build())
- .build();
- Entity listItemProto =
- Entity.newBuilder().setIdentifier("itemId").setStructValue(listItemStruct).build();
-
- assertThat(EntityConverter.Companion.of(LIST_ITEM_TYPE_SPEC).convert(listItem))
- .isEqualTo(listItemProto);
- assertThat(
- ParamValueConverter.Companion.of(LIST_ITEM_TYPE_SPEC)
- .fromParamValue(toParamValue(listItemStruct, "itemId")))
- .isEqualTo(listItem);
- }
-
- @Test
- public void itemList_conversions_matchesExpected() throws Exception {
- ItemList itemList =
- ItemList.Builder()
- .setIdentifier("testList")
- .setName("Test List")
- .addItemListElement(
- ListItem.Builder().setIdentifier("item1").setName("apple").build())
- .addItemListElement(
- ListItem.Builder().setIdentifier("item2").setName("banana").build())
- .build();
- Struct itemListStruct =
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("ItemList").build())
- .putFields(
- "identifier", Value.newBuilder().setStringValue("testList").build())
- .putFields("name", Value.newBuilder().setStringValue("Test List").build())
- .putFields(
- "itemListElement",
- Value.newBuilder()
- .setListValue(
- ListValue.newBuilder()
- .addValues(
- Value.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields(
- "@type",
- Value
- .newBuilder()
- .setStringValue(
- "ListItem")
- .build())
- .putFields(
- "identifier",
- Value
- .newBuilder()
- .setStringValue(
- "item1")
- .build())
- .putFields(
- "name",
- Value
- .newBuilder()
- .setStringValue(
- "apple")
- .build())
- .build())
- .build())
- .addValues(
- Value.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields(
- "@type",
- Value
- .newBuilder()
- .setStringValue(
- "ListItem")
- .build())
- .putFields(
- "identifier",
- Value
- .newBuilder()
- .setStringValue(
- "item2")
- .build())
- .putFields(
- "name",
- Value
- .newBuilder()
- .setStringValue(
- "banana")
- .build())
- .build())
- .build())
- .build())
- .build())
- .build();
- Entity itemListProto =
- Entity.newBuilder()
- .setIdentifier("testList")
- .setStructValue(itemListStruct)
- .build();
-
- assertThat(EntityConverter.Companion.of(ITEM_LIST_TYPE_SPEC).convert(itemList))
- .isEqualTo(itemListProto);
- assertThat(
- ParamValueConverter.Companion.of(ITEM_LIST_TYPE_SPEC)
- .fromParamValue(toParamValue(itemListStruct, "testList")))
- .isEqualTo(itemList);
- }
-
- @Test
- public void participant_conversions_matchesExpected() throws Exception {
- ParamValueConverter<Participant> paramValueConverter =
- ParamValueConverter.Companion.of(PARTICIPANT_TYPE_SPEC);
- ParamValue paramValue =
- ParamValue.newBuilder()
- .setIdentifier(PERSON_JAVA_THING.getIdentifier())
- .setStructValue(PERSON_STRUCT)
- .build();
- Participant participant = new Participant(PERSON_JAVA_THING);
-
- assertThat(paramValueConverter.toParamValue(participant)).isEqualTo(paramValue);
- assertThat(paramValueConverter.fromParamValue(paramValue)).isEqualTo(participant);
- }
-
- @Test
- public void calendarEvent_conversions_matchesExpected() throws Exception {
- assertThat(TypeConverters.CALENDAR_EVENT_TYPE_SPEC.toValue(CALENDAR_EVENT_JAVA_THING))
- .isEqualTo(CALENDAR_EVENT_VALUE);
- assertThat(TypeConverters.CALENDAR_EVENT_TYPE_SPEC.fromValue(CALENDAR_EVENT_VALUE))
- .isEqualTo(CALENDAR_EVENT_JAVA_THING);
- }
-
- @Test
- public void recipient_conversions_matchesExpected() throws Exception {
- ParamValueConverter<Recipient> paramValueConverter =
- ParamValueConverter.Companion.of(RECIPIENT_TYPE_SPEC);
- ParamValue paramValue =
- ParamValue.newBuilder()
- .setIdentifier(
- PERSON_JAVA_THING.getIdentifier() == null
- ? "id"
- : PERSON_JAVA_THING.getIdentifier())
- .setStructValue(PERSON_STRUCT)
- .build();
- Recipient recipient = new Recipient(PERSON_JAVA_THING);
-
- assertThat(paramValueConverter.toParamValue(recipient)).isEqualTo(paramValue);
- assertThat(paramValueConverter.fromParamValue(paramValue)).isEqualTo(recipient);
- }
-
- @Test
- public void toParticipant_unexpectedType_throwsException() {
- ParamValueConverter<Participant> paramValueConverter =
- ParamValueConverter.Companion.of(PARTICIPANT_TYPE_SPEC);
- Struct malformedStruct =
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("Malformed").build())
- .build();
-
- assertThrows(
- StructConversionException.class,
- () -> paramValueConverter.fromParamValue(toParamValue(malformedStruct, "id")));
- }
-
- @Test
- public void toRecipient_unexpectedType_throwsException() {
- ParamValueConverter<Recipient> paramValueConverter =
- ParamValueConverter.Companion.of(RECIPIENT_TYPE_SPEC);
- Struct malformedStruct =
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("Malformed").build())
- .build();
-
- assertThrows(
- StructConversionException.class,
- () -> paramValueConverter.fromParamValue(toParamValue(malformedStruct, "id")));
- }
-
- @Test
- public void itemList_malformedStruct_throwsException() {
- ParamValueConverter<ItemList> paramValueConverter =
- ParamValueConverter.Companion.of(ITEM_LIST_TYPE_SPEC);
- Struct malformedStruct =
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("Malformed").build())
- .putFields("name", Value.newBuilder().setStringValue("List Name").build())
- .putFields("identifier", Value.newBuilder().setStringValue("list1").build())
- .build();
-
- assertThrows(
- StructConversionException.class,
- () -> paramValueConverter.fromParamValue(toParamValue(malformedStruct, "list1")));
- }
-
- @Test
- public void listItem_malformedStruct_throwsException() throws Exception {
- ParamValueConverter<ListItem> paramValueConverter =
- ParamValueConverter.Companion.of(LIST_ITEM_TYPE_SPEC);
- Struct malformedStruct =
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("Malformed").build())
- .putFields("name", Value.newBuilder().setStringValue("Apple").build())
- .putFields("identifier", Value.newBuilder().setStringValue("item1").build())
- .build();
-
- assertThrows(
- StructConversionException.class,
- () -> paramValueConverter.fromParamValue(toParamValue(malformedStruct, "item1")));
- }
-
- @Test
- public void toBoolean_success() throws Exception {
- List<ParamValue> input =
- Collections.singletonList(ParamValue.newBuilder().setBoolValue(false).build());
-
- assertThat(SlotTypeConverter.ofSingular(BOOLEAN_PARAM_VALUE_CONVERTER).convert(input))
- .isFalse();
- }
-
- @Test
- public void toBoolean_throwsException() {
- List<ParamValue> input = Collections.singletonList(ParamValue.getDefaultInstance());
-
- StructConversionException thrown =
- assertThrows(
- StructConversionException.class,
- () ->
- SlotTypeConverter.ofSingular(BOOLEAN_PARAM_VALUE_CONVERTER)
- .convert(input));
- assertThat(thrown).hasMessageThat().isEqualTo(EMPTY_PARAM_VALUE_MESSAGE);
- }
-
- @Test
- public void toInteger_throwsException() {
- List<ParamValue> input = Collections.singletonList(ParamValue.getDefaultInstance());
-
- StructConversionException thrown =
- assertThrows(
- StructConversionException.class,
- () ->
- SlotTypeConverter.ofSingular(INTEGER_PARAM_VALUE_CONVERTER)
- .convert(input));
- assertThat(thrown).hasMessageThat().isEqualTo(EMPTY_PARAM_VALUE_MESSAGE);
- }
-
- @Test
- public void localDate_success() throws Exception {
- ParamValueConverter<LocalDate> converter = TypeConverters.LOCAL_DATE_PARAM_VALUE_CONVERTER;
- ParamValue paramValue = ParamValue.newBuilder().setStringValue("2018-06-17").build();
- LocalDate localDate = LocalDate.of(2018, 6, 17);
-
- assertThat(converter.fromParamValue(paramValue)).isEqualTo(localDate);
- assertThat(converter.toParamValue(localDate)).isEqualTo(paramValue);
- }
-
- @Test
- public void toLocalDate_throwsException() {
- List<ParamValue> input =
- Collections.singletonList(
- ParamValue.newBuilder().setStringValue("2018-0617").build());
-
- StructConversionException thrown =
- assertThrows(
- StructConversionException.class,
- () ->
- SlotTypeConverter.ofSingular(
- TypeConverters.LOCAL_DATE_PARAM_VALUE_CONVERTER)
- .convert(input));
- assertThat(thrown)
- .hasMessageThat()
- .isEqualTo("Failed to parse ISO 8601 string to LocalDate");
- }
-
- @Test
- public void toLocalDateMissingValue_throwsException() {
- List<ParamValue> input = Collections.singletonList(ParamValue.getDefaultInstance());
-
- StructConversionException thrown =
- assertThrows(
- StructConversionException.class,
- () ->
- SlotTypeConverter.ofSingular(
- TypeConverters.LOCAL_DATE_PARAM_VALUE_CONVERTER)
- .convert(input));
- assertThat(thrown).hasMessageThat().isEqualTo(EMPTY_PARAM_VALUE_MESSAGE);
- }
-
- @Test
- public void localTime_success() throws Exception {
- ParamValueConverter<LocalTime> converter = TypeConverters.LOCAL_TIME_PARAM_VALUE_CONVERTER;
- ParamValue paramValue = ParamValue.newBuilder().setStringValue("15:10:05").build();
- LocalTime localTime = LocalTime.of(15, 10, 5);
-
- assertThat(converter.fromParamValue(paramValue)).isEqualTo(localTime);
- assertThat(converter.toParamValue(localTime)).isEqualTo(paramValue);
- }
-
- @Test
- public void toLocalTime_throwsException() {
- List<ParamValue> input =
- Collections.singletonList(ParamValue.newBuilder().setStringValue("15:1:5").build());
-
- StructConversionException thrown =
- assertThrows(
- StructConversionException.class,
- () ->
- SlotTypeConverter.ofSingular(
- TypeConverters.LOCAL_TIME_PARAM_VALUE_CONVERTER)
- .convert(input));
- assertThat(thrown)
- .hasMessageThat()
- .isEqualTo("Failed to parse ISO 8601 string to LocalTime");
- }
-
- @Test
- public void toLocalTimeMissingValue_throwsException() {
- List<ParamValue> input = Collections.singletonList(ParamValue.getDefaultInstance());
-
- StructConversionException thrown =
- assertThrows(
- StructConversionException.class,
- () ->
- SlotTypeConverter.ofSingular(
- TypeConverters.LOCAL_TIME_PARAM_VALUE_CONVERTER)
- .convert(input));
- assertThat(thrown).hasMessageThat().isEqualTo(EMPTY_PARAM_VALUE_MESSAGE);
- }
-
- @Test
- public void zoneId_success() throws Exception {
- ParamValueConverter<ZoneId> converter = TypeConverters.ZONE_ID_PARAM_VALUE_CONVERTER;
- ParamValue paramValue = ParamValue.newBuilder().setStringValue("America/New_York").build();
- ZoneId zoneId = ZoneId.of("America/New_York");
-
- assertThat(converter.fromParamValue(paramValue)).isEqualTo(zoneId);
- assertThat(converter.toParamValue(zoneId)).isEqualTo(paramValue);
- }
-
- @Test
- public void toZoneId_invalidZone_throwsException() {
- List<ParamValue> invalidZoneInput =
- Collections.singletonList(
- ParamValue.newBuilder().setStringValue("America/New_Yo").build());
-
- StructConversionException thrown =
- assertThrows(
- StructConversionException.class,
- () ->
- SlotTypeConverter.ofSingular(
- TypeConverters.ZONE_ID_PARAM_VALUE_CONVERTER)
- .convert(invalidZoneInput));
- assertThat(thrown).hasMessageThat().isEqualTo("Failed to parse string to ZoneId");
- assertThat(thrown.getCause())
- .hasMessageThat()
- .isEqualTo("Unknown time-zone ID: America/New_Yo");
- }
-
- @Test
- public void toZoneIdMissingValue_throwsException() {
- List<ParamValue> input = Collections.singletonList(ParamValue.getDefaultInstance());
-
- StructConversionException thrown =
- assertThrows(
- StructConversionException.class,
- () ->
- SlotTypeConverter.ofSingular(
- TypeConverters.ZONE_ID_PARAM_VALUE_CONVERTER)
- .convert(input));
- assertThat(thrown).hasMessageThat().isEqualTo(EMPTY_PARAM_VALUE_MESSAGE);
- }
-
- @Test
- public void zonedDateTime_success() throws Exception {
- ParamValueConverter<ZonedDateTime> converter =
- TypeConverters.ZONED_DATE_TIME_PARAM_VALUE_CONVERTER;
- ParamValue paramValue =
- ParamValue.newBuilder().setStringValue("2018-06-17T15:10:05Z").build();
- ZonedDateTime zonedDateTime = ZonedDateTime.of(2018, 6, 17, 15, 10, 5, 0, ZoneOffset.UTC);
-
- assertThat(converter.fromParamValue(paramValue)).isEqualTo(zonedDateTime);
- assertThat(converter.toParamValue(zonedDateTime)).isEqualTo(paramValue);
- }
-
- @Test
- public void toZonedDateTime_invalidStringFormat_throwsException() {
- List<ParamValue> input =
- Collections.singletonList(
- ParamValue.newBuilder()
- .setStringValue("Failed to parse ISO 8601 string to ZonedDateTime")
- .build());
-
- StructConversionException thrown =
- assertThrows(
- StructConversionException.class,
- () ->
- SlotTypeConverter.ofSingular(
- TypeConverters
- .ZONED_DATE_TIME_PARAM_VALUE_CONVERTER)
- .convert(input));
- assertThat(thrown)
- .hasMessageThat()
- .isEqualTo("Failed to parse ISO 8601 string to ZonedDateTime");
- }
-
- @Test
- public void toZonedDateTime_stringTypeMissing_throwsException() {
- List<ParamValue> input =
- Collections.singletonList(ParamValue.newBuilder().setNumberValue(100).build());
-
- StructConversionException thrown =
- assertThrows(
- StructConversionException.class,
- () ->
- SlotTypeConverter.ofSingular(
- TypeConverters
- .ZONED_DATE_TIME_PARAM_VALUE_CONVERTER)
- .convert(input));
- assertThat(thrown).hasMessageThat().contains("expected Value.stringValue to be present");
- }
-
- @Test
- public void duration_success() throws Exception {
- ParamValueConverter<Duration> converter = TypeConverters.DURATION_PARAM_VALUE_CONVERTER;
- ParamValue paramValue = ParamValue.newBuilder().setStringValue("PT5M").build();
- Duration duration = Duration.ofMinutes(5);
-
- assertThat(converter.fromParamValue(paramValue)).isEqualTo(duration);
- assertThat(converter.toParamValue(duration)).isEqualTo(paramValue);
- }
-
- @Test
- public void toDuration_stringTypeMissing_throwsException() {
- List<ParamValue> input =
- Collections.singletonList(ParamValue.newBuilder().setNumberValue(100).build());
-
- StructConversionException thrown =
- assertThrows(
- StructConversionException.class,
- () ->
- SlotTypeConverter.ofSingular(
- TypeConverters.DURATION_PARAM_VALUE_CONVERTER)
- .convert(input));
- assertThat(thrown)
- .hasMessageThat()
- .contains("expected Value.stringValue to be present");
- }
-
- @Test
- public void searchActionConverter_withoutNestedObject() throws Exception {
- ParamValue input =
- ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields(
- "@type",
- Value.newBuilder()
- .setStringValue("SearchAction")
- .build())
- .putFields(
- "query",
- Value.newBuilder()
- .setStringValue("grocery")
- .build())
- .build())
- .build();
-
- SearchAction<ItemList> output =
- TypeConverters.createSearchActionConverter(TypeConverters.ITEM_LIST_TYPE_SPEC)
- .toSearchAction(input);
-
- assertThat(output)
- .isEqualTo(new SearchAction.Builder<String>().setQuery("grocery").build());
- }
-
- @Test
- public void searchActionConverter_withNestedObject() throws Exception {
- ItemList itemList =
- ItemList.Builder()
- .addItemListElement(ListItem.Builder().setName("sugar").build())
- .build();
- Struct nestedObject = TypeConverters.ITEM_LIST_TYPE_SPEC.toValue(itemList).getStructValue();
- ParamValue input =
- ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields(
- "@type",
- Value.newBuilder()
- .setStringValue("SearchAction")
- .build())
- .putFields(
- "filter",
- Value.newBuilder()
- .setStructValue(nestedObject)
- .build())
- .build())
- .build();
-
- SearchAction<ItemList> output =
- TypeConverters.createSearchActionConverter(TypeConverters.ITEM_LIST_TYPE_SPEC)
- .toSearchAction(input);
-
- assertThat(output)
- .isEqualTo(new SearchAction.Builder<ItemList>().setFilter(itemList).build());
- }
-
- @Test
- public void createEnumParamValueConverter_withValidSupportedType() throws Exception {
- ParamValueConverter<DayOfWeek> testEnumParamValueConverter =
- TypeConverters.createEnumParamValueConverter(
- Arrays.asList(DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY)
- );
- ParamValue paramValue = ParamValue.newBuilder()
- .setIdentifier(DayOfWeek.MONDAY.toString())
- .build();
-
- assertThat(testEnumParamValueConverter.fromParamValue(paramValue)).isEqualTo(
- DayOfWeek.MONDAY
- );
-
- assertThat(testEnumParamValueConverter.toParamValue(DayOfWeek.MONDAY)).isEqualTo(
- paramValue
- );
- }
-
- @Test
- public void createEnumParamValueConverter_withInValidSupportedType_shouldThrowException() {
- ParamValueConverter<DayOfWeek> testEnumParamValueConverter =
- TypeConverters.createEnumParamValueConverter(
- Arrays.asList(DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY)
- );
- ParamValue paramValue = ParamValue.newBuilder().setIdentifier("invalid").build();
-
- StructConversionException thrown = assertThrows(
- StructConversionException.class,
- () -> testEnumParamValueConverter.fromParamValue(paramValue)
- );
-
- assertThat(thrown)
- .hasMessageThat()
- .contains(
- "cannot convert paramValue to protobuf Value because identifier "
- + paramValue.getIdentifier() + " is not one of "
- + "the supported values");
-
- IllegalStateException illegalStateException = assertThrows(
- IllegalStateException.class,
- () -> testEnumParamValueConverter.toParamValue(DayOfWeek.PUBLIC_HOLIDAYS)
- );
-
- assertThat(illegalStateException)
- .hasMessageThat()
- .contains("cannot convert " + DayOfWeek.PUBLIC_HOLIDAYS + " to ParamValue "
- + "because it did not match one of the supported values");
- }
-
- @Test
- public void createEnumEntityConverter_withValidSupportedType() throws Exception {
- EntityConverter<DayOfWeek> testEnumEntityConverter =
- TypeConverters.createEnumEntityConverter(
- Arrays.asList(DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY)
- );
-
- assertThat(testEnumEntityConverter.convert(DayOfWeek.MONDAY)).isEqualTo(
- Entity.newBuilder().setIdentifier(DayOfWeek.MONDAY.toString()).build()
- );
- }
-
- @Test
- public void createEnumEntityConverter_withInValidSupportedType_shouldThrowException() {
- EntityConverter<DayOfWeek> testEnumEntityConverter =
- TypeConverters.createEnumEntityConverter(
- Arrays.asList(DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY)
- );
-
- IllegalStateException thrown = assertThrows(
- IllegalStateException.class,
- () -> testEnumEntityConverter.convert(DayOfWeek.PUBLIC_HOLIDAYS)
- );
-
- assertThat(thrown)
- .hasMessageThat()
- .contains("cannot convert " + DayOfWeek.PUBLIC_HOLIDAYS + " to entity "
- + "because it did not match one of the supported values");
- }
-
- @Test
- public void toParamValues_string_success() {
- ParamValue output = TypeConverters.STRING_PARAM_VALUE_CONVERTER.toParamValue("grocery");
-
- assertThat(output).isEqualTo(ParamValue.newBuilder().setStringValue("grocery").build());
- }
-
- @Test
- public void toTimer_success() throws Exception {
- ParamValueConverter<Timer> paramValueConverter =
- ParamValueConverter.Companion.of(TIMER_TYPE_SPEC);
- Timer timer = Timer.Builder().setIdentifier("abc").build();
-
- assertThat(
- paramValueConverter.fromParamValue(
- ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields(
- "@type",
- Value.newBuilder()
- .setStringValue("Timer")
- .build())
- .putFields(
- "identifier",
- Value.newBuilder()
- .setStringValue("abc")
- .build()))
- .build()))
- .isEqualTo(timer);
- }
-
- @Test
- public void toParamValues_call_success() {
- assertThat(ParamValueConverter.Companion.of(CALL_TYPE_SPEC).toParamValue(CALL_JAVA_THING))
- .isEqualTo(
- ParamValue.newBuilder()
- .setStructValue(CALL_STRUCT)
- .setIdentifier("id")
- .build());
- }
-
- @Test
- public void toParamValues_message_success() {
- assertThat(
- ParamValueConverter.Companion.of(MESSAGE_TYPE_SPEC)
- .toParamValue(MESSAGE_JAVA_THING))
- .isEqualTo(
- ParamValue.newBuilder()
- .setStructValue(MESSAGE_STRUCT)
- .setIdentifier("id")
- .build());
- }
-
- @Test
- public void toParamValues_safetyCheck_success() {
- assertThat(
- ParamValueConverter.Companion.of(SAFETY_CHECK_TYPE_SPEC)
- .toParamValue(SAFETY_CHECK_JAVA_THING))
- .isEqualTo(
- ParamValue.newBuilder()
- .setStructValue(SAFETY_CHECK_STRUCT)
- .setIdentifier("id")
- .build());
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeSpecImplTest.java b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeSpecImplTest.java
deleted file mode 100644
index 77ca407..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeSpecImplTest.java
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.converters;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.assertThrows;
-
-import androidx.appactions.builtintypes.experimental.properties.Name;
-import androidx.appactions.builtintypes.experimental.types.Thing;
-import androidx.appactions.interaction.capabilities.core.impl.exceptions.StructConversionException;
-import androidx.appactions.interaction.capabilities.core.testing.spec.TestEntity;
-import androidx.appactions.interaction.protobuf.Struct;
-import androidx.appactions.interaction.protobuf.Value;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.time.Duration;
-import java.time.ZoneId;
-import java.time.ZoneOffset;
-import java.time.ZonedDateTime;
-
-@RunWith(JUnit4.class)
-public final class TypeSpecImplTest {
- private static Value structToValue(Struct struct) {
- return Value.newBuilder().setStructValue(struct).build();
- }
-
- @Test
- public void bindIdentifier_success() {
- TypeSpec<TestEntity> entityTypeSpec =
- TypeSpecBuilder.newBuilder(
- "TestEntity", TestEntity.Builder::new, TestEntity.Builder::build)
- .bindIdentifier(TestEntity::getId)
- .build();
- assertThat(
- entityTypeSpec.getIdentifier(
- new TestEntity.Builder().setId("identifier1").build()))
- .isEqualTo("identifier1");
- assertThat(entityTypeSpec.getIdentifier(new TestEntity.Builder().build())).isNull();
- }
-
- @Test
- public void bindDurationField_convertsSuccessfully() throws Exception {
- TypeSpec<TestEntity> entityTypeSpec =
- TypeSpecBuilder.newBuilder(
- "TestEntity", TestEntity.Builder::new, TestEntity.Builder::build)
- .bindSpecField(
- "duration",
- TestEntity::getDuration,
- TestEntity.Builder::setDuration,
- TypeSpec.DURATION_TYPE_SPEC)
- .build();
- TestEntity entity = new TestEntity.Builder().setDuration(Duration.ofMinutes(5)).build();
- Value entityValue =
- structToValue(
- Struct.newBuilder()
- .putFields(
- "@type",
- Value.newBuilder().setStringValue("TestEntity").build())
- .putFields(
- "duration",
- Value.newBuilder().setStringValue("PT5M").build())
- .build());
-
- assertThat(entityTypeSpec.toValue(entity)).isEqualTo(entityValue);
- assertThat(entityTypeSpec.fromValue(entityValue)).isEqualTo(entity);
- }
-
- @Test
- public void bindZonedDateTimeField_withZoneOffset_convertsSuccessfully() throws Exception {
- TypeSpec<TestEntity> entityTypeSpec =
- TypeSpecBuilder.newBuilder(
- "TestEntity", TestEntity.Builder::new, TestEntity.Builder::build)
- .bindSpecField(
- "date",
- TestEntity::getZonedDateTime,
- TestEntity.Builder::setZonedDateTime,
- TypeSpec.ZONED_DATE_TIME_TYPE_SPEC)
- .build();
- TestEntity entity =
- new TestEntity.Builder()
- .setZonedDateTime(ZonedDateTime.of(2022, 1, 2, 3, 4, 5, 0, ZoneOffset.UTC))
- .build();
- Value entityValue =
- structToValue(
- Struct.newBuilder()
- .putFields(
- "@type",
- Value.newBuilder().setStringValue("TestEntity").build())
- .putFields(
- "date",
- Value.newBuilder()
- .setStringValue("2022-01-02T03:04:05Z")
- .build())
- .build());
-
- assertThat(entityTypeSpec.toValue(entity)).isEqualTo(entityValue);
- assertThat(entityTypeSpec.fromValue(entityValue)).isEqualTo(entity);
- }
-
- @Test
- public void bindZonedDateTimeField_withZoneId_convertsSuccessfully() throws Exception {
- TypeSpec<TestEntity> entityTypeSpec =
- TypeSpecBuilder.newBuilder(
- "TestEntity", TestEntity.Builder::new, TestEntity.Builder::build)
- .bindSpecField(
- "date",
- TestEntity::getZonedDateTime,
- TestEntity.Builder::setZonedDateTime,
- TypeSpec.ZONED_DATE_TIME_TYPE_SPEC)
- .build();
- TestEntity entity =
- new TestEntity.Builder()
- .setZonedDateTime(
- ZonedDateTime.of(2022, 1, 2, 3, 4, 5, 0, ZoneId.of("UTC+01:00")))
- .build();
- Value entityValue =
- structToValue(
- Struct.newBuilder()
- .putFields(
- "@type",
- Value.newBuilder().setStringValue("TestEntity").build())
- .putFields(
- "date",
- Value.newBuilder()
- .setStringValue("2022-01-02T03:04:05+01:00")
- .build())
- .build());
- TestEntity expectedEntity =
- new TestEntity.Builder()
- .setZonedDateTime(
- ZonedDateTime.of(2022, 1, 2, 3, 4, 5, 0, ZoneOffset.of("+01:00")))
- .build();
-
- assertThat(entityTypeSpec.toValue(entity)).isEqualTo(entityValue);
- assertThat(entityTypeSpec.fromValue(entityValue)).isEqualTo(expectedEntity);
- }
-
- @Test
- public void bindZonedDateTimeField_throwsException() throws Exception {
- TypeSpec<TestEntity> entityTypeSpec =
- TypeSpecBuilder.newBuilder(
- "TestEntity", TestEntity.Builder::new, TestEntity.Builder::build)
- .bindSpecField(
- "date",
- TestEntity::getZonedDateTime,
- TestEntity.Builder::setZonedDateTime,
- TypeSpec.ZONED_DATE_TIME_TYPE_SPEC)
- .build();
- Value malformedValue =
- structToValue(
- Struct.newBuilder()
- .putFields(
- "@type",
- Value.newBuilder().setStringValue("TestEntity").build())
- .putFields(
- "date",
- Value.newBuilder().setStringValue("2022-01-01T08").build())
- .build());
-
- assertThrows(
- StructConversionException.class, () -> entityTypeSpec.fromValue(malformedValue));
- }
-
- @Test
- public void bindSpecField_convertsSuccessfully() throws Exception {
- TypeSpec<TestEntity> entityTypeSpec =
- TypeSpecBuilder.newBuilder(
- "TestEntity", TestEntity.Builder::new, TestEntity.Builder::build)
- .bindSpecField(
- "entity",
- TestEntity::getEntity,
- TestEntity.Builder::setEntity,
- TypeSpecBuilder.newBuilder(
- "TestEntity",
- TestEntity.Builder::new,
- TestEntity.Builder::build)
- .bindStringField(
- "name",
- TestEntity::getName,
- TestEntity.Builder::setName)
- .build())
- .build();
- TestEntity entity =
- new TestEntity.Builder()
- .setEntity(new TestEntity.Builder().setName("entity name").build())
- .build();
- Value entityValue = structToValue(
- Struct.newBuilder()
- .putFields(
- "@type",
- Value.newBuilder().setStringValue("TestEntity").build())
- .putFields(
- "entity",
- Value.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields(
- "@type",
- Value.newBuilder()
- .setStringValue(
- "TestEntity")
- .build())
- .putFields(
- "name",
- Value.newBuilder()
- .setStringValue(
- "entity"
- + " name")
- .build())
- .build())
- .build())
- .build());
-
- assertThat(entityTypeSpec.toValue(entity)).isEqualTo(entityValue);
- assertThat(entityTypeSpec.fromValue(entityValue)).isEqualTo(entity);
- }
-
- @Test
- public void bindSpecField_throwsException() throws Exception {
- TypeSpec<TestEntity> entityTypeSpec =
- TypeSpecBuilder.newBuilder(
- "TestEntity", TestEntity.Builder::new, TestEntity.Builder::build)
- .bindSpecField(
- "entity",
- TestEntity::getEntity,
- TestEntity.Builder::setEntity,
- TypeSpecBuilder.newBuilder(
- "TestEntity",
- TestEntity.Builder::new,
- TestEntity.Builder::build)
- .bindStringField(
- "name",
- TestEntity::getName,
- TestEntity.Builder::setName)
- .build())
- .build();
- Value malformedValue =
- structToValue(
- Struct.newBuilder()
- .putFields(
- "@type",
- Value.newBuilder().setStringValue("TestEntity").build())
- .putFields(
- "entity",
- Value.newBuilder().setStringValue("wrong value").build())
- .build());
-
- assertThrows(
- StructConversionException.class, () -> entityTypeSpec.fromValue(malformedValue));
- }
-
- @Test
- public void newBuilderForThing_builtInTypes_smokeTest() throws Exception {
- TypeSpec<Thing> thingTypeSpec =
- TypeSpecBuilder.newBuilderForThing("Thing", Thing::Builder, Thing.Builder::build)
- .build();
-
- Thing thing = Thing.Builder().setIdentifier("thing").setName(new Name("Thing One")).build();
- Value thingValue =
- structToValue(
- Struct.newBuilder()
- .putFields(
- "@type", Value.newBuilder().setStringValue("Thing").build())
- .putFields(
- "identifier",
- Value.newBuilder().setStringValue("thing").build())
- .putFields(
- "name",
- Value.newBuilder().setStringValue("Thing One").build())
- .build());
-
- assertThat(thingTypeSpec.getIdentifier(thing)).isEqualTo("thing");
- assertThat(thingTypeSpec.toValue(thing)).isEqualTo(thingValue);
- assertThat(thingTypeSpec.fromValue(thingValue).getIdentifier())
- .isEqualTo(thing.getIdentifier());
- assertThat(thingTypeSpec.fromValue(thingValue).getName().asText())
- .isEqualTo(thing.getName().asText());
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/converters/UnionTypeSpecTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/converters/UnionTypeSpecTest.kt
deleted file mode 100644
index f3e41f6..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/converters/UnionTypeSpecTest.kt
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.converters
-
-import androidx.appactions.builtintypes.types.Alarm
-import androidx.appactions.builtintypes.types.Timer
-import androidx.appactions.interaction.capabilities.serializers.types.ALARM_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.TIMER_TYPE_SPEC
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-/* Union type for testing */
-class AlarmOrTimer private constructor(
- val asAlarm: Alarm? = null,
- val asTimer: Timer? = null,
-) {
- constructor(alarm: Alarm) : this(asAlarm = alarm)
- constructor(timer: Timer) : this(asTimer = timer)
-}
-
-private val ALARM_OR_TIMER_TYPE_SPEC = UnionTypeSpec.Builder<AlarmOrTimer>()
- .bindMemberType(
- memberGetter = AlarmOrTimer::asAlarm,
- ctor = { AlarmOrTimer(it) },
- typeSpec = ALARM_TYPE_SPEC,
- )
- .bindMemberType(
- memberGetter = AlarmOrTimer::asTimer,
- ctor = { AlarmOrTimer(it) },
- typeSpec = TIMER_TYPE_SPEC,
- ).build()
-
-@RunWith(JUnit4::class)
-class UnionTypeSpecTest {
- @Test
- fun unionType_identifier() {
- val alarmUnion = AlarmOrTimer(Alarm.Builder().setIdentifier("alarmId").build())
- val timerUnion = AlarmOrTimer(Timer.Builder().setIdentifier("timerId").build())
- val timerUnionWithoutId = AlarmOrTimer(Timer.Builder().build())
- assertThat(ALARM_OR_TIMER_TYPE_SPEC.getIdentifier(alarmUnion)).isEqualTo("alarmId")
- assertThat(ALARM_OR_TIMER_TYPE_SPEC.getIdentifier(timerUnion)).isEqualTo("timerId")
- assertThat(ALARM_OR_TIMER_TYPE_SPEC.getIdentifier(timerUnionWithoutId)).isNull()
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecRegistryTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecRegistryTest.kt
deleted file mode 100644
index 85747d4..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecRegistryTest.kt
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.spec
-
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.testing.spec.Arguments
-import androidx.appactions.interaction.capabilities.core.testing.spec.Output
-import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput.OutputValue
-import androidx.appactions.interaction.proto.ParamValue
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-public class ActionSpecRegistryTest {
- @Test
- fun actionSpecRegistry_retrieveRegisteredSpecForArguments() {
- val arguments = Arguments.Builder()
- .setRequiredStringField("a")
- .setRepeatedStringField(listOf("a", "b", "c"))
- .build()
- val actionSpec = ActionSpecRegistry.getActionSpecForArguments(arguments)!!
- assertThat(actionSpec.capabilityName).isEqualTo("actions.intent.TEST")
- assertThat(actionSpec.serializeArguments(arguments)).isEqualTo(
- mapOf(
- "requiredString" to listOf(
- ParamValue.newBuilder().setStringValue("a").build()
- ),
- "repeatedString" to listOf(
- ParamValue.newBuilder().setStringValue("a").build(),
- ParamValue.newBuilder().setStringValue("b").build(),
- ParamValue.newBuilder().setStringValue("c").build()
- )
- )
- )
- }
-
- @Test
- fun actionSpecRegistry_retrieveRegisteredSpecForOutput() {
- val output = Output.Builder()
- .setOptionalStringField("a")
- .setRepeatedStringField(listOf("a", "b", "c"))
- .build()
- val actionSpec = ActionSpecRegistry.getActionSpecForOutput(output)!!
- assertThat(actionSpec.capabilityName).isEqualTo("actions.intent.TEST")
- assertThat(
- actionSpec.convertOutputToProto(output).getOutputValuesList()
- ).containsExactly(
- OutputValue.newBuilder()
- .setName("repeatedStringOutput")
- .addValues(
- ParamValue.newBuilder().setStringValue("a")
- )
- .addValues(
- ParamValue.newBuilder().setStringValue("b")
- )
- .addValues(
- ParamValue.newBuilder().setStringValue("c")
- ).build(),
- OutputValue.newBuilder()
- .setName("optionalStringOutput")
- .addValues(
- ParamValue.newBuilder().setStringValue("a")
- ).build()
- )
- }
-
- companion object {
- val ACTION_SPEC: ActionSpec<Arguments, Output> =
- ActionSpecBuilder.ofCapabilityNamed("actions.intent.TEST")
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindParameter(
- "requiredString",
- Arguments::requiredStringField,
- Arguments.Builder::setRequiredStringField,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER)
- .bindParameter(
- "optionalString",
- Arguments::optionalStringField,
- Arguments.Builder::setOptionalStringField,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER)
- .bindRepeatedParameter(
- "repeatedString",
- Arguments::repeatedStringField,
- Arguments.Builder::setRepeatedStringField,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER)
- .bindOutput(
- "optionalStringOutput",
- Output::optionalStringField,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER::toParamValue)
- .bindRepeatedOutput(
- "repeatedStringOutput",
- Output::repeatedStringField,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER::toParamValue)
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(
- Arguments::class,
- Output::class,
- ACTION_SPEC
- )
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecTest.java b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecTest.java
deleted file mode 100644
index 20658d74..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/spec/ActionSpecTest.java
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.spec;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import androidx.annotation.NonNull;
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter;
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter;
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters;
-import androidx.appactions.interaction.capabilities.core.properties.Property;
-import androidx.appactions.interaction.capabilities.core.properties.StringValue;
-import androidx.appactions.interaction.capabilities.core.testing.spec.Arguments;
-import androidx.appactions.interaction.capabilities.core.testing.spec.GenericEntityArguments;
-import androidx.appactions.interaction.capabilities.core.testing.spec.Output;
-import androidx.appactions.interaction.capabilities.core.testing.spec.TestEntity;
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction;
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter;
-import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput;
-import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput.OutputValue;
-import androidx.appactions.interaction.proto.ParamValue;
-import androidx.appactions.interaction.proto.TaskInfo;
-import androidx.appactions.interaction.protobuf.Struct;
-import androidx.appactions.interaction.protobuf.Value;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-@RunWith(JUnit4.class)
-@SuppressWarnings("unchecked")
-public final class ActionSpecTest {
- private static final ActionSpec<Arguments, Output> ACTION_SPEC =
- ActionSpecBuilder.Companion.ofCapabilityNamed("actions.intent.TEST")
- .setArguments(Arguments.class, Arguments.Builder::new, Arguments.Builder::build)
- .setOutput(Output.class)
- .bindParameter(
- "requiredString",
- Arguments::getRequiredStringField,
- Arguments.Builder::setRequiredStringField,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER)
- .bindParameter(
- "optionalString",
- Arguments::getOptionalStringField,
- Arguments.Builder::setOptionalStringField,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER)
- .bindRepeatedParameter(
- "repeatedString",
- Arguments::getRepeatedStringField,
- Arguments.Builder::setRepeatedStringField,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER)
- .bindOutput(
- "optionalStringOutput",
- Output::getOptionalStringField,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER::toParamValue)
- .bindRepeatedOutput(
- "repeatedStringOutput",
- Output::getRepeatedStringField,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER::toParamValue)
- .build();
- private static final ParamValueConverter<TestEntity> TEST_ENTITY_PARAM_VALUE_CONVERTER =
- new ParamValueConverter<TestEntity>() {
- @NonNull
- @Override
- public ParamValue toParamValue(TestEntity type) {
- return ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields(
- "name",
- Value.newBuilder()
- .setStringValue(type.getName())
- .build())
- .build())
- .build();
- }
-
- @Override
- public TestEntity fromParamValue(@NonNull ParamValue paramValue) {
- String name =
- paramValue.getStructValue().getFieldsOrThrow("name").getStringValue();
- return new TestEntity.Builder().setName(name).build();
- }
- };
- private static final EntityConverter<TestEntity> TEST_ENTITY_CONVERTER =
- (testEntity) ->
- androidx.appactions.interaction.proto.Entity.newBuilder()
- .setIdentifier(testEntity.getId())
- .setName(testEntity.getName())
- .build();
-
- private static final ActionSpec<GenericEntityArguments, Output> GENERIC_TYPES_ACTION_SPEC =
- ActionSpecBuilder.Companion.ofCapabilityNamed("actions.intent.TEST")
- .setArguments(GenericEntityArguments.class,
- GenericEntityArguments.Builder::new,
- GenericEntityArguments.Builder::build)
- .setOutput(Output.class)
- .bindParameter(
- "requiredEntity",
- GenericEntityArguments::getSingularField,
- GenericEntityArguments.Builder::setSingularField,
- TEST_ENTITY_PARAM_VALUE_CONVERTER)
- .bindParameter(
- "optionalEntity",
- GenericEntityArguments::getOptionalField,
- GenericEntityArguments.Builder::setOptionalField,
- TEST_ENTITY_PARAM_VALUE_CONVERTER)
- .bindRepeatedParameter(
- "repeatedEntities",
- GenericEntityArguments::getRepeatedField,
- GenericEntityArguments.Builder::setRepeatedField,
- TEST_ENTITY_PARAM_VALUE_CONVERTER)
- .build();
-
- @Test
- public void foo() {
- Property<TestEntity> foobar = new Property<>(
- Arrays.asList(
- new TestEntity.Builder()
- .setId("one")
- .setName("one")
- .build()),
- /** isRequiredForExecution= */ true);
- foobar.shouldMatchPossibleValues();
- }
-
- @Test
- public void getAppAction_genericParameters() {
- List<BoundProperty<?>> boundProperties = new ArrayList<>();
- boundProperties.add(
- new BoundProperty<>(
- "requiredEntity",
- new Property<>(
- Arrays.asList(
- new TestEntity.Builder()
- .setId("one")
- .setName("one")
- .build()),
- /** isRequiredForExecution= */ true),
- TEST_ENTITY_CONVERTER));
- boundProperties.add(
- new BoundProperty<>(
- "optionalEntity",
- new Property<>(
- Arrays.asList(
- new TestEntity.Builder()
- .setId("two")
- .setName("two")
- .build()),
- /** isRequiredForExecution= */ true),
- TEST_ENTITY_CONVERTER));
- boundProperties.add(
- new BoundProperty<>(
- "repeatedEntities",
- new Property<>(
- Arrays.asList(
- new TestEntity.Builder()
- .setId("three")
- .setName("three")
- .build()),
- /** isRequiredForExecution= */ true),
- TEST_ENTITY_CONVERTER));
-
- assertThat(
- GENERIC_TYPES_ACTION_SPEC.createAppAction(
- "testIdentifier", boundProperties, false))
- .isEqualTo(
- AppAction.newBuilder()
- .setName("actions.intent.TEST")
- .setIdentifier("testIdentifier")
- .addParams(
- IntentParameter.newBuilder()
- .setName("requiredEntity")
- .setIsRequired(true)
- .addPossibleEntities(
- androidx.appactions.interaction.proto.Entity
- .newBuilder()
- .setIdentifier("one")
- .setName("one")))
- .addParams(
- IntentParameter.newBuilder()
- .setName("optionalEntity")
- .setIsRequired(true)
- .addPossibleEntities(
- androidx.appactions.interaction.proto.Entity
- .newBuilder()
- .setIdentifier("two")
- .setName("two")))
- .addParams(
- IntentParameter.newBuilder()
- .setName("repeatedEntities")
- .setIsRequired(true)
- .addPossibleEntities(
- androidx.appactions.interaction.proto.Entity
- .newBuilder()
- .setIdentifier("three")
- .setName("three")))
- .setTaskInfo(
- TaskInfo.newBuilder().setSupportsPartialFulfillment(false))
- .build());
- }
-
- @Test
- public void getAppAction_onlyRequiredProperty() {
- List<BoundProperty<?>> boundProperties = new ArrayList<>();
- boundProperties.add(
- new BoundProperty<>(
- "requiredString",
- new Property<>(
- Arrays.asList(new StringValue("Donald")),
- /** isRequiredForExecution= */ false,
- /** shouldMatchPossibleValues= */ true
- ),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER));
-
- assertThat(ACTION_SPEC.createAppAction("testIdentifier", boundProperties, true))
- .isEqualTo(
- AppAction.newBuilder()
- .setName("actions.intent.TEST")
- .setIdentifier("testIdentifier")
- .addParams(
- IntentParameter.newBuilder()
- .setName("requiredString")
- .setEntityMatchRequired(true)
- .addPossibleEntities(
- androidx.appactions.interaction.proto.Entity
- .newBuilder()
- .setIdentifier("Donald")
- .setName("Donald")))
- .setTaskInfo(
- TaskInfo.newBuilder().setSupportsPartialFulfillment(true))
- .build());
- }
-
- @Test
- public void getAppAction_allProperties() {
- List<BoundProperty<?>> boundProperties = new ArrayList<>();
- boundProperties.add(
- new BoundProperty<>(
- "requiredString",
- new Property<StringValue>(),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER));
- boundProperties.add(
- new BoundProperty<>(
- "optionalString",
- new Property<>(
- Arrays.asList(new StringValue("value1")),
- /** isRequiredForExecution= */ true,
- /** shouldMatchPossibleValues= */ true
- ),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER));
- boundProperties.add(
- new BoundProperty<>(
- "repeatedString",
- Property.unsupported(),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER));
-
- assertThat(ACTION_SPEC.createAppAction("testIdentifier", boundProperties, false))
- .isEqualTo(
- AppAction.newBuilder()
- .setName("actions.intent.TEST")
- .setIdentifier("testIdentifier")
- .addParams(IntentParameter.newBuilder().setName("requiredString"))
- .addParams(
- IntentParameter.newBuilder()
- .setName("optionalString")
- .addPossibleEntities(
- androidx.appactions.interaction.proto.Entity
- .newBuilder()
- .setIdentifier("value1")
- .setName("value1")
- .build())
- .setIsRequired(true)
- .setEntityMatchRequired(true))
- .addParams(
- IntentParameter.newBuilder()
- .setName("repeatedString")
- .setIsProhibited(true))
- .setTaskInfo(
- TaskInfo.newBuilder().setSupportsPartialFulfillment(false))
- .build());
- }
-
- @Test
- public void convertOutputToProto_string() {
- Output output =
- new Output.Builder()
- .setOptionalStringField("test2")
- .setRepeatedStringField(List.of("test3", "test4"))
- .build();
-
- StructuredOutput expectedExecutionOutput =
- StructuredOutput.newBuilder()
- .addOutputValues(
- OutputValue.newBuilder()
- .setName("optionalStringOutput")
- .addValues(
- ParamValue.newBuilder()
- .setStringValue("test2")
- .build())
- .build())
- .addOutputValues(
- OutputValue.newBuilder()
- .setName("repeatedStringOutput")
- .addValues(
- ParamValue.newBuilder()
- .setStringValue("test3")
- .build())
- .addValues(
- ParamValue.newBuilder()
- .setStringValue("test4")
- .build())
- .build())
- .build();
-
- StructuredOutput executionOutput = ACTION_SPEC.convertOutputToProto(output);
-
- assertThat(executionOutput.getOutputValuesList())
- .containsExactlyElementsIn(expectedExecutionOutput.getOutputValuesList());
- }
-
- @Test
- public void convertOutputToProto_emptyOutput() {
- Output output =
- new Output.Builder().setRepeatedStringField(List.of("test3", "test4")).build();
- // No optionalStringOutput since it is not in the output above.
- StructuredOutput expectedExecutionOutput =
- StructuredOutput.newBuilder()
- .addOutputValues(
- OutputValue.newBuilder()
- .setName("repeatedStringOutput")
- .addValues(
- ParamValue.newBuilder()
- .setStringValue("test3")
- .build())
- .addValues(
- ParamValue.newBuilder()
- .setStringValue("test4")
- .build())
- .build())
- .build();
-
- StructuredOutput executionOutput = ACTION_SPEC.convertOutputToProto(output);
-
- assertThat(executionOutput.getOutputValuesList())
- .containsExactlyElementsIn(expectedExecutionOutput.getOutputValuesList());
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilityImplTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilityImplTest.kt
deleted file mode 100644
index a8f0719..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilityImplTest.kt
+++ /dev/null
@@ -1,1724 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task
-
-import android.util.SizeF
-import androidx.appactions.builtintypes.experimental.types.ListItem
-import androidx.appactions.interaction.capabilities.core.AppEntityListener
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.ConfirmationOutput
-import androidx.appactions.interaction.capabilities.core.EntitySearchResult
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.core.SearchAction
-import androidx.appactions.interaction.capabilities.core.SessionConfig
-import androidx.appactions.interaction.capabilities.core.ValidationResult
-import androidx.appactions.interaction.capabilities.core.ValueListener
-import androidx.appactions.interaction.capabilities.core.impl.ErrorStatusInternal
-import androidx.appactions.interaction.capabilities.core.impl.UiHandleRegistry
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.SearchActionConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters.LIST_ITEM_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpec
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.BoundProperty
-import androidx.appactions.interaction.capabilities.core.impl.utils.EXTERNAL_TIMEOUT_MILLIS
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.core.properties.StringValue
-import androidx.appactions.interaction.capabilities.core.testing.spec.Arguments
-import androidx.appactions.interaction.capabilities.core.testing.spec.CapabilityStructFill
-import androidx.appactions.interaction.capabilities.core.testing.spec.CapabilityTwoStrings
-import androidx.appactions.interaction.capabilities.core.testing.spec.Confirmation
-import androidx.appactions.interaction.capabilities.core.testing.spec.ExecutionSession
-import androidx.appactions.interaction.capabilities.core.testing.spec.Output
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils.buildRequestArgs
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils.buildSearchActionParamValue
-import androidx.appactions.interaction.capabilities.testing.internal.FakeCallbackInternal
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.awaitSync
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import androidx.appactions.interaction.proto.AppActionsContext.AppDialogState
-import androidx.appactions.interaction.proto.AppActionsContext.DialogParameter
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter
-import androidx.appactions.interaction.proto.CurrentValue
-import androidx.appactions.interaction.proto.DisambiguationData
-import androidx.appactions.interaction.proto.Entity
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.SyncStatus
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.Type.CANCEL
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.Type.SYNC
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.Type.UNKNOWN_TYPE
-import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput
-import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput.OutputValue
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.proto.TaskInfo
-import androidx.concurrent.futures.CallbackToFutureAdapter
-import androidx.concurrent.futures.CallbackToFutureAdapter.Completer
-import com.google.common.truth.Truth.assertThat
-import com.google.common.util.concurrent.ListenableFuture
-import java.util.concurrent.atomic.AtomicInteger
-import java.util.concurrent.atomic.AtomicReference
-import java.util.function.Supplier
-import kotlinx.coroutines.CompletableDeferred
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.test.advanceTimeBy
-import kotlinx.coroutines.test.runTest
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class TaskCapabilityImplTest {
- private val capability: Capability =
- createCapability<EmptyTaskUpdater>(
- SINGLE_REQUIRED_FIELD_BOUND_PROPERTIES,
- sessionFactory =
- { _ ->
- object : ExecutionSession {
- override fun onExecuteAsync(arguments: Arguments) =
- Futures.immediateFuture(ExecutionResult.Builder<Output>().build())
- }
- },
- sessionBridge = { TaskHandler.Builder<Arguments, Confirmation>().build() },
- sessionUpdaterSupplier = ::EmptyTaskUpdater
- )
- private val hostProperties: HostProperties =
- HostProperties.Builder()
- .setMaxHostSizeDp(
- SizeF(300f, 500f)
- )
- .build()
- private val fakeSessionId = "fakeSessionId"
-
- @Test
- fun appAction_smokeTest() {
- assertThat(capability.appAction)
- .isEqualTo(
- AppAction.newBuilder()
- .setName("actions.intent.TEST")
- .setIdentifier("id")
- .addParams(
- IntentParameter.newBuilder().setName("required").setIsRequired(true)
- )
- .setTaskInfo(
- TaskInfo.newBuilder().setSupportsPartialFulfillment(true)
- )
- .build()
- )
- }
-
- @Test
- fun appAction_computedProperty() {
- val mutableEntityList = mutableListOf<StringValue>()
- val capability = createCapability<EmptyTaskUpdater>(
- listOf(
- BoundProperty(
- "required",
- Property<StringValue>(possibleValueSupplier = mutableEntityList::toList),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
- ),
- sessionFactory =
- {
- object : ExecutionSession {
- override fun onExecuteAsync(arguments: Arguments) =
- Futures.immediateFuture(ExecutionResult.Builder<Output>().build())
- }
- },
- sessionBridge = { TaskHandler.Builder<Arguments, Confirmation>().build() },
- sessionUpdaterSupplier = ::EmptyTaskUpdater
- )
- mutableEntityList.add(StringValue("entity1"))
-
- assertThat(capability.appAction).isEqualTo(
- AppAction.newBuilder()
- .setIdentifier("id")
- .setName("actions.intent.TEST")
- .addParams(
- IntentParameter.newBuilder()
- .setName("required")
- .addPossibleEntities(
- Entity.newBuilder().setIdentifier("entity1").setName("entity1")
- )
- )
- .setTaskInfo(TaskInfo.newBuilder().setSupportsPartialFulfillment(true))
- .build()
- )
-
- mutableEntityList.add(StringValue("entity2"))
- assertThat(capability.appAction).isEqualTo(
- AppAction.newBuilder()
- .setIdentifier("id")
- .setName("actions.intent.TEST")
- .addParams(
- IntentParameter.newBuilder()
- .setName("required")
- .addPossibleEntities(
- Entity.newBuilder().setIdentifier("entity1").setName("entity1")
- )
- .addPossibleEntities(
- Entity.newBuilder().setIdentifier("entity2").setName("entity2")
- )
- )
- .setTaskInfo(TaskInfo.newBuilder().setSupportsPartialFulfillment(true))
- .build()
- )
- }
-
- @Test
- fun capabilitySession_getUiHandle() {
- val externalSession = object : ExecutionSession {}
- val capability =
- createCapability(
- SINGLE_REQUIRED_FIELD_BOUND_PROPERTIES,
- { externalSession },
- { TaskHandler.Builder<Arguments, Confirmation>().build() },
- ::EmptyTaskUpdater
- )
- val session = capability.createSession(fakeSessionId, hostProperties)
- assertThat(session.uiHandle).isSameInstanceAs(externalSession)
- }
-
- @Test
- @kotlin.Throws(Exception::class)
- fun onCreateInvoked_invokedOnce() {
- val onCreateInvocationCount = AtomicInteger(0)
- val capability: Capability =
- createCapability(
- SINGLE_REQUIRED_FIELD_BOUND_PROPERTIES,
- sessionFactory =
- { _ ->
- object : ExecutionSession {
- override fun onCreate(sessionConfig: SessionConfig) {
- onCreateInvocationCount.incrementAndGet()
- }
-
- override fun onExecuteAsync(arguments: Arguments) =
- Futures.immediateFuture(
- ExecutionResult.Builder<Output>().build()
- )
- }
- },
- sessionBridge = SessionBridge {
- TaskHandler.Builder<Arguments, Confirmation>().build()
- },
- sessionUpdaterSupplier = ::EmptyTaskUpdater
- )
- val session = capability.createSession(fakeSessionId, hostProperties)
-
- // TURN 1.
- val callback = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(SYNC, "unknownArgName", "foo"),
- callback
- )
- assertThat(callback.receiveResponse().fulfillmentResponse).isNotNull()
- assertThat(onCreateInvocationCount.get()).isEqualTo(1)
-
- // TURN 2.
- val callback2 = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(
- SYNC,
- "required",
- ParamValue.newBuilder().setIdentifier("foo").setStringValue("foo").build()
- ),
- callback2
- )
- assertThat(callback2.receiveResponse().fulfillmentResponse).isNotNull()
- assertThat(onCreateInvocationCount.get()).isEqualTo(1)
- }
-
- class RequiredTaskUpdater : AbstractTaskUpdater() {
- fun setRequiredForExecutionStringValue(value: String) {
- super.updateParamValues(
- mapOf(
- "required" to
- listOf(
- TypeConverters.STRING_PARAM_VALUE_CONVERTER.toParamValue(value)
- )
- )
- )
- }
- }
-
- private class DeferredValueListener<T> : ValueListener<T> {
- val mCompleterRef: AtomicReference<Completer<ValidationResult>> =
- AtomicReference<Completer<ValidationResult>>()
-
- fun setValidationResult(t: ValidationResult) {
- val completer: Completer<ValidationResult> =
- mCompleterRef.getAndSet(null)
- ?: throw IllegalStateException("no onReceived is waiting")
- completer.set(t)
- }
-
- override fun onReceivedAsync(value: T): ListenableFuture<ValidationResult> {
- return CallbackToFutureAdapter.getFuture { newCompleter ->
- val oldCompleter: Completer<ValidationResult>? =
- mCompleterRef.getAndSet(
- newCompleter
- )
- oldCompleter?.setCancelled()
- "waiting for setValidationResult"
- }
- }
- }
-
- @Test
- fun duringExecution_uiHandleRegistered(): Unit = runBlocking {
- val onExecuteReached = CompletableDeferred<Unit>()
- val onExecuteResult = CompletableDeferred<ExecutionResult<Output>>()
- val externalSession = object : ExecutionSession {
- override suspend fun onExecute(arguments: Arguments): ExecutionResult<Output> {
- onExecuteReached.complete(Unit)
- return onExecuteResult.await()
- }
- }
- val capability: Capability = createCapability(
- SINGLE_REQUIRED_FIELD_BOUND_PROPERTIES,
- sessionFactory = { _ -> externalSession },
- sessionBridge = SessionBridge {
- TaskHandler.Builder<Arguments, Confirmation>().build()
- },
- sessionUpdaterSupplier = ::RequiredTaskUpdater
- )
- val session = capability.createSession("mySessionId", hostProperties)
- val callback = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(
- SYNC,
- "required",
- "hello"
- ),
- callback
- )
- onExecuteReached.await()
- assertThat(UiHandleRegistry.getSessionIdFromUiHandle(externalSession)).isEqualTo(
- "mySessionId"
- )
-
- onExecuteResult.complete(ExecutionResult.Builder<Output>().build())
- assertThat(callback.receiveResponse().fulfillmentResponse).isNotNull()
- assertThat(UiHandleRegistry.getSessionIdFromUiHandle(externalSession)).isNull()
- }
-
- @Test
- @kotlin.Throws(Exception::class)
- fun fulfillmentType_unknown_errorReported() {
- val capability: Capability =
- createCapability(
- SINGLE_REQUIRED_FIELD_BOUND_PROPERTIES,
- sessionFactory =
- { _ ->
- object : ExecutionSession {
- override fun onExecuteAsync(arguments: Arguments) =
- Futures.immediateFuture(
- ExecutionResult.Builder<Output>().build()
- )
- }
- },
- sessionBridge = SessionBridge {
- TaskHandler.Builder<Arguments, Confirmation>().build()
- },
- sessionUpdaterSupplier = ::RequiredTaskUpdater
- )
- val session = capability.createSession(fakeSessionId, hostProperties)
-
- assertThat(capability.appAction)
- .isEqualTo(
- AppAction.newBuilder()
- .setName("actions.intent.TEST")
- .setIdentifier("id")
- .addParams(
- IntentParameter.newBuilder().setName("required").setIsRequired(true)
- )
- .setTaskInfo(
- TaskInfo.newBuilder().setSupportsPartialFulfillment(true)
- )
- .build()
- )
-
- // TURN 1 (UNKNOWN).
- val callback = FakeCallbackInternal()
- session.execute(buildRequestArgs(UNKNOWN_TYPE), callback)
- assertThat(callback.receiveResponse().errorStatus)
- .isEqualTo(ErrorStatusInternal.INVALID_REQUEST)
- }
-
- @Test
- fun slotFilling_isActive_smokeTest() {
- val boundProperties = listOf(
- BoundProperty(
- "stringSlotA",
- Property<StringValue>(isRequiredForExecution = true),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- ),
- BoundProperty(
- "stringSlotB",
- Property<StringValue>(isRequiredForExecution = true),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
- )
- val sessionFactory:
- (hostProperties: HostProperties?) -> CapabilityTwoStrings.ExecutionSession =
- { _ ->
- object : CapabilityTwoStrings.ExecutionSession {
- override suspend fun onExecute(
- arguments: CapabilityTwoStrings.Arguments
- ): ExecutionResult<CapabilityTwoStrings.Output> =
- ExecutionResult.Builder<CapabilityTwoStrings.Output>().build()
- }
- }
- val sessionBridge =
- SessionBridge<
- CapabilityTwoStrings.ExecutionSession,
- CapabilityTwoStrings.Arguments,
- CapabilityTwoStrings.Confirmation> {
- TaskHandler.Builder<
- CapabilityTwoStrings.Arguments,
- CapabilityTwoStrings.Confirmation
- >()
- .registerValueTaskParam(
- "stringSlotA",
- AUTO_ACCEPT_STRING_VALUE,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .registerValueTaskParam(
- "stringSlotB",
- AUTO_ACCEPT_STRING_VALUE,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .build()
- }
- val capability: Capability =
- TaskCapabilityImpl(
- "fakeId",
- CapabilityTwoStrings.ACTION_SPEC,
- boundProperties,
- sessionFactory,
- sessionBridge,
- ::EmptyTaskUpdater
- )
-
- val session = capability.createSession(fakeSessionId, hostProperties)
- assertThat(session.isActive).isTrue()
-
- // turn 1
- val callback = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(
- SYNC,
- "stringSlotA",
- ParamValue.newBuilder().setIdentifier("foo").setStringValue("foo").build()
- ),
- callback
- )
- assertThat(callback.receiveResponse().fulfillmentResponse).isNotNull()
- assertThat(session.isActive).isTrue()
-
- // turn 2
- val callback2 = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(
- SYNC,
- "stringSlotA",
- ParamValue.newBuilder().setStringValue("foo").build(),
- "stringSlotB",
- ParamValue.newBuilder().setStringValue("bar").build()
- ),
- callback2
- )
- assertThat(callback2.receiveResponse().fulfillmentResponse).isNotNull()
- assertThat(session.isActive).isFalse()
-
- // turn 3
- val callback3 = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(CANCEL),
- callback3
- )
- assertThat(session.isActive).isFalse()
- }
-
- @Test
- @kotlin.Throws(Exception::class)
- fun slotFilling_optionalButRejectedParam_onFinishNotInvoked() {
- val onExecuteInvocationCount = AtomicInteger(0)
- val boundProperties = listOf(
- BoundProperty(
- "stringSlotA",
- Property<StringValue>(isRequiredForExecution = true),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- ),
- BoundProperty(
- "stringSlotB",
- Property<StringValue>(isRequiredForExecution = false),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
- )
- val sessionFactory:
- (hostProperties: HostProperties?) -> CapabilityTwoStrings.ExecutionSession =
- { _ ->
- object : CapabilityTwoStrings.ExecutionSession {
- override suspend fun onExecute(
- arguments: CapabilityTwoStrings.Arguments
- ): ExecutionResult<CapabilityTwoStrings.Output> {
- onExecuteInvocationCount.incrementAndGet()
- return ExecutionResult.Builder<CapabilityTwoStrings.Output>().build()
- }
- }
- }
- val sessionBridge =
- SessionBridge<
- CapabilityTwoStrings.ExecutionSession,
- CapabilityTwoStrings.Arguments,
- CapabilityTwoStrings.Confirmation> {
- TaskHandler.Builder<
- CapabilityTwoStrings.Arguments,
- CapabilityTwoStrings.Confirmation
- >()
- .registerValueTaskParam(
- "stringSlotA",
- AUTO_ACCEPT_STRING_VALUE,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .registerValueTaskParam(
- "stringSlotB",
- AUTO_REJECT_STRING_VALUE,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .build()
- }
- val capability: Capability =
- TaskCapabilityImpl(
- "fakeId",
- CapabilityTwoStrings.ACTION_SPEC,
- boundProperties,
- sessionFactory,
- sessionBridge,
- ::EmptyTaskUpdater
- )
- val session = capability.createSession(fakeSessionId, hostProperties)
-
- // TURN 1.
- val callback = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(
- SYNC,
- "stringSlotA",
- ParamValue.newBuilder().setIdentifier("foo").setStringValue("foo").build(),
- "stringSlotB",
- ParamValue.newBuilder().setIdentifier("bar").setStringValue("bar").build()
- ),
- callback
- )
- assertThat(callback.receiveResponse().fulfillmentResponse).isNotNull()
- assertThat(onExecuteInvocationCount.get()).isEqualTo(0)
- assertThat(getCurrentValues("stringSlotA", session.state!!))
- .containsExactly(
- CurrentValue.newBuilder()
- .setValue(
- ParamValue.newBuilder().setIdentifier("foo").setStringValue("foo")
- )
- .setStatus(CurrentValue.Status.ACCEPTED)
- .build()
- )
- assertThat(getCurrentValues("stringSlotB", session.state!!))
- .containsExactly(
- CurrentValue.newBuilder()
- .setValue(
- ParamValue.newBuilder().setIdentifier("bar").setStringValue("bar")
- )
- .setStatus(CurrentValue.Status.REJECTED)
- .build()
- )
- }
-
- @Test
- @kotlin.Throws(Exception::class)
- fun slotFilling_assistantRemovedParam_clearInSdkState() {
- val boundProperties = listOf(
- BoundProperty(
- "required",
- Property<StringValue>(isRequiredForExecution = true),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- ),
- BoundProperty(
- "optional",
- Property<StringValue>(
- possibleValues = listOf(StringValue("VALUE_1"), StringValue("VALUE_2")),
- isRequiredForExecution = true,
- ),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
- )
- val capability: Capability =
- createCapability(
- boundProperties,
- sessionFactory = { _ -> ExecutionSession.DEFAULT },
- sessionBridge = SessionBridge {
- TaskHandler.Builder<Arguments, Confirmation>().build()
- },
- sessionUpdaterSupplier = ::EmptyTaskUpdater
- )
- val session = capability.createSession(fakeSessionId, hostProperties)
-
- // TURN 1.
- val callback = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(
- SYNC,
- "required",
- ParamValue.newBuilder().setIdentifier("foo").setStringValue("foo").build()
- ),
- callback
- )
- assertThat(callback.receiveResponse()).isNotNull()
- assertThat(getCurrentValues("required", session.state!!))
- .containsExactly(
- CurrentValue.newBuilder()
- .setValue(
- ParamValue.newBuilder().setIdentifier("foo").setStringValue("foo")
- )
- .setStatus(CurrentValue.Status.ACCEPTED)
- .build()
- )
- assertThat(getCurrentValues("optional", session.state!!)).isEmpty()
-
- // TURN 2.
- val callback2 = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(SYNC, "optional", "VALUE_2"),
- callback2
- )
- assertThat(callback2.receiveResponse().fulfillmentResponse).isNotNull()
- assertThat(getCurrentValues("required", session.state!!)).isEmpty()
- assertThat(getCurrentValues("optional", session.state!!))
- .containsExactly(
- CurrentValue.newBuilder()
- .setValue(ParamValue.newBuilder().setStringValue("VALUE_2"))
- .setStatus(CurrentValue.Status.ACCEPTED)
- .build()
- )
- }
-
- @Test
- @kotlin.Throws(Exception::class)
- fun disambig_singleParam_disambigEntitiesInContext() {
- val capability: Capability =
- createCapability(
- SINGLE_REQUIRED_FIELD_BOUND_PROPERTIES,
- sessionFactory = {
- object : ExecutionSession {
- override suspend fun onExecute(arguments: Arguments) =
- ExecutionResult.Builder<Output>().build()
-
- override val requiredStringListener =
- object : AppEntityListener<String> {
- override fun lookupAndRenderAsync(
- searchAction: SearchAction<String>
- ): ListenableFuture<EntitySearchResult<String>> {
- return Futures.immediateFuture(
- EntitySearchResult.Builder<String>()
- .addPossibleValue("valid1")
- .addPossibleValue("valid2")
- .build()
- )
- }
-
- override fun onReceivedAsync(
- value: String
- ): ListenableFuture<ValidationResult> {
- return Futures.immediateFuture(ValidationResult.newAccepted())
- }
- }
- }
- },
- sessionBridge =
- SessionBridge<ExecutionSession, Arguments, Confirmation> { session ->
- val builder = TaskHandler.Builder<Arguments, Confirmation>()
- session.requiredStringListener?.let {
- listener: AppEntityListener<String> ->
- builder.registerAppEntityTaskParam(
- "required",
- listener,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER,
- EntityConverter.of(TypeSpec.STRING_TYPE_SPEC),
- getTrivialSearchActionConverter()
- )
- }
- builder.build()
- },
- sessionUpdaterSupplier = ::EmptyTaskUpdater
- )
- val session = capability.createSession(fakeSessionId, hostProperties)
-
- // TURN 1.
- val callback = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(SYNC, "required", buildSearchActionParamValue("invalid")),
- callback
- )
- assertThat(callback.receiveResponse().fulfillmentResponse).isNotNull()
- assertThat(session.state)
- .isEqualTo(
- AppDialogState.newBuilder()
- .setFulfillmentIdentifier("id")
- .addParams(
- DialogParameter.newBuilder()
- .setName("required")
- .addCurrentValue(
- CurrentValue.newBuilder()
- .setValue(
- buildSearchActionParamValue("invalid")
- )
- .setStatus(
- CurrentValue.Status.DISAMBIG
- )
- .setDisambiguationData(
- DisambiguationData.newBuilder()
- .addEntities(
- Entity.newBuilder()
- .setStringValue(
- "valid1"
- )
- )
- .addEntities(
- Entity.newBuilder()
- .setStringValue(
- "valid2"
- )
- )
- )
- )
- ).build()
- )
-
- // TURN 2.
- val callback2 = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(
- SYNC,
- "required",
- ParamValue.newBuilder().setIdentifier("valid2").setStringValue("valid2").build()
- ),
- callback2
- )
- assertThat(callback2.receiveResponse().fulfillmentResponse).isNotNull()
- assertThat(session.state)
- .isEqualTo(
- AppDialogState.newBuilder()
- .setFulfillmentIdentifier("id")
- .addParams(
- DialogParameter.newBuilder()
- .setName("required")
- .addCurrentValue(
- CurrentValue.newBuilder()
- .setValue(
- ParamValue.newBuilder()
- .setIdentifier("valid2")
- .setStringValue(
- "valid2"
- )
- )
- .setStatus(
- CurrentValue.Status.ACCEPTED
- )
- )
- )
- .build()
- )
- }
-
- /**
- * Assistant sends grounded objects as identifier only, but we need to mark the entire value
- * struct as accepted.
- */
- @Test
- @kotlin.Throws(Exception::class)
- fun identifierOnly_refillsStruct() = runBlocking<Unit> {
- val boundProperties = listOf(
- BoundProperty(
- "listItem",
- Property<ListItem>(isRequiredForExecution = true),
- EntityConverter.of(TypeConverters.LIST_ITEM_TYPE_SPEC)
- ),
- BoundProperty(
- "string",
- Property<StringValue>(isRequiredForExecution = true),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
- )
- val item1: ListItem = ListItem.Builder().setName("red apple").setIdentifier("item1").build()
- val item2: ListItem =
- ListItem.Builder().setName("green apple").setIdentifier("item2").build()
- val onReceivedDeferred = CompletableDeferred<ListItem>()
- val onExecuteListItemDeferred = CompletableDeferred<ListItem>()
- val onExecuteStringDeferred = CompletableDeferred<String>()
-
- val sessionFactory:
- (hostProperties: HostProperties?) -> CapabilityStructFill.ExecutionSession =
- { _ ->
- object : CapabilityStructFill.ExecutionSession {
- override suspend fun onExecute(
- arguments: CapabilityStructFill.Arguments
- ): ExecutionResult<CapabilityStructFill.Output> {
- arguments.listItem?.let { onExecuteListItemDeferred.complete(it) }
- arguments.string?.let { onExecuteStringDeferred.complete(it) }
- return ExecutionResult.Builder<CapabilityStructFill.Output>().build()
- }
-
- override val listItemListener =
- object : AppEntityListener<ListItem> {
- override fun onReceivedAsync(
- value: ListItem
- ): ListenableFuture<ValidationResult> {
- onReceivedDeferred.complete(value)
- return Futures.immediateFuture(ValidationResult.newAccepted())
- }
-
- override fun lookupAndRenderAsync(
- searchAction: SearchAction<ListItem>
- ): ListenableFuture<EntitySearchResult<ListItem>> =
- Futures.immediateFuture(
- EntitySearchResult.Builder<ListItem>()
- .addPossibleValue(item1)
- .addPossibleValue(item2)
- .build()
- )
- }
- }
- }
- val sessionBridge =
- SessionBridge<
- CapabilityStructFill.ExecutionSession,
- CapabilityStructFill.Arguments,
- CapabilityStructFill.Confirmation> { session ->
- TaskHandler.Builder<
- CapabilityStructFill.Arguments,
- CapabilityStructFill.Confirmation
- >()
- .registerAppEntityTaskParam(
- "listItem",
- session.listItemListener,
- ParamValueConverter.of(LIST_ITEM_TYPE_SPEC),
- EntityConverter.of(LIST_ITEM_TYPE_SPEC)::convert,
- getTrivialSearchActionConverter()
- )
- .build()
- }
-
- val capability: Capability =
- TaskCapabilityImpl(
- "selectListItem",
- CapabilityStructFill.ACTION_SPEC,
- boundProperties,
- sessionFactory,
- sessionBridge,
- ::EmptyTaskUpdater
- )
- val session = capability.createSession(fakeSessionId, hostProperties)
-
- // first sync request
- val callback = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(SYNC, "listItem", buildSearchActionParamValue("apple")),
- callback
- )
- assertThat(callback.receiveResponse().fulfillmentResponse).isNotNull()
- assertThat(onReceivedDeferred.isCompleted).isFalse()
- assertThat(onExecuteListItemDeferred.isCompleted).isFalse()
- assertThat(session.state)
- .isEqualTo(
- AppDialogState.newBuilder()
- .setFulfillmentIdentifier("selectListItem")
- .addParams(
- DialogParameter.newBuilder()
- .setName("listItem")
- .addCurrentValue(
- CurrentValue.newBuilder()
- .setValue(
- buildSearchActionParamValue(
- "apple"
- )
- )
- .setStatus(CurrentValue.Status.DISAMBIG)
- .setDisambiguationData(
- DisambiguationData.newBuilder()
- .addEntities(
- EntityConverter.of(LIST_ITEM_TYPE_SPEC)
- .convert(item1)
- )
- .addEntities(
- EntityConverter.of(LIST_ITEM_TYPE_SPEC)
- .convert(item2)
- )
- .build()
- )
- .build()
- )
- .build()
- )
- .addParams(DialogParameter.newBuilder().setName("string").build())
- .build()
- )
-
- // second sync request, sending grounded ParamValue with identifier only
- val callback2 = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(
- SYNC,
- "listItem",
- ParamValue.newBuilder().setIdentifier("item2").build()
- ),
- callback2
- )
- assertThat(callback2.receiveResponse().fulfillmentResponse).isNotNull()
- assertThat(onReceivedDeferred.awaitSync()).isEqualTo(item2)
- assertThat(onExecuteListItemDeferred.isCompleted).isFalse()
-
- // third sync request, sending grounded ParamValue with identifier only, completes task
- val callback3 = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(
- SYNC,
- "listItem",
- ParamValue.newBuilder().setIdentifier("item2").build(),
- "string",
- "unused"
- ),
- callback3
- )
- assertThat(callback3.receiveResponse().fulfillmentResponse).isNotNull()
- assertThat(onExecuteListItemDeferred.awaitSync()).isEqualTo(item2)
- assertThat(onExecuteStringDeferred.awaitSync()).isEqualTo("unused")
- }
-
- @Test
- @kotlin.Throws(Exception::class)
- fun executionResult_resultReturned() {
- val sessionFactory: (hostProperties: HostProperties?) -> ExecutionSession =
- { _ ->
- object : ExecutionSession {
- override suspend fun onExecute(arguments: Arguments) =
- ExecutionResult.Builder<Output>()
- .setOutput(
- Output.Builder()
- .setOptionalStringField("bar")
- .setRepeatedStringField(
- listOf("bar1", "bar2")
- )
- .build()
- )
- .build()
- }
- }
- val capability =
- CapabilityBuilder().setId("fakeId").setExecutionSessionFactory(sessionFactory).build()
- val session = capability.createSession(fakeSessionId, hostProperties)
- val callback = FakeCallbackInternal()
- val expectedOutput: StructuredOutput =
- StructuredOutput.newBuilder()
- .addOutputValues(
- OutputValue.newBuilder()
- .setName("optionalStringOutput")
- .addValues(
- ParamValue.newBuilder().setStringValue("bar").build()
- )
- .build()
- )
- .addOutputValues(
- OutputValue.newBuilder()
- .setName("repeatedStringOutput")
- .addValues(
- ParamValue.newBuilder().setStringValue("bar1").build()
- )
- .addValues(
- ParamValue.newBuilder().setStringValue("bar2").build()
- )
- .build()
- )
- .build()
- session.execute(
- buildRequestArgs(
- SYNC, /* args...= */
- "required",
- ParamValue.newBuilder().setIdentifier("foo").setStringValue("foo").build()
- ),
- callback
- )
- assertThat(
- callback.receiveResponse()
- .fulfillmentResponse!!
- .executionOutput
- .outputValuesList
- )
- .containsExactlyElementsIn(expectedOutput.outputValuesList)
- }
-
- @Test
- @kotlin.Throws(Exception::class)
- fun executionResult_shouldStartDictation_resultReturned() {
- val sessionFactory: (hostProperties: HostProperties?) -> ExecutionSession =
- { _ ->
- object : ExecutionSession {
- override suspend fun onExecute(arguments: Arguments) =
- ExecutionResult.Builder<Output>()
- .setShouldStartDictation(true)
- .build()
- }
- }
- val capability =
- CapabilityBuilder().setId("fakeId").setExecutionSessionFactory(sessionFactory).build()
- val session = capability.createSession(fakeSessionId, hostProperties)
- val callback = FakeCallbackInternal()
-
- session.execute(
- buildRequestArgs(
- SYNC, /* args...= */
- "required",
- ParamValue.newBuilder().setIdentifier("foo").setStringValue("foo").build()
- ),
- callback
- )
-
- assertThat(callback.receiveResponse().fulfillmentResponse!!.startDictation).isTrue()
- }
-
- @Test
- @kotlin.Throws(Exception::class)
- fun fulfillmentType_finalSync_stateCleared() {
- val sessionFactory: (hostProperties: HostProperties?) -> ExecutionSession =
- { _ ->
- object : ExecutionSession {
- override suspend fun onExecute(arguments: Arguments) =
- ExecutionResult.Builder<Output>().build()
- }
- }
- val capability: Capability =
- createCapability(
- SINGLE_REQUIRED_FIELD_BOUND_PROPERTIES,
- sessionFactory = sessionFactory,
- sessionBridge = SessionBridge {
- TaskHandler.Builder<Arguments, Confirmation>().build()
- },
- sessionUpdaterSupplier = ::EmptyTaskUpdater
- )
- val session = capability.createSession(fakeSessionId, hostProperties)
-
- // TURN 1. Not providing all the required slots in the SYNC Request
- val callback = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(SYNC),
- callback
- )
- assertThat(callback.receiveResponse()).isNotNull()
- assertThat(getCurrentValues("required", session.state!!)).isEmpty()
- assertThat(session.isActive).isEqualTo(true)
-
- // TURN 2. Providing the required slots so that the task completes and the state gets cleared
- val callback2 = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(
- SYNC,
- "required",
- ParamValue.newBuilder().setIdentifier("foo").setStringValue("foo").build()
- ),
- callback2
- )
- assertThat(callback2.receiveResponse().fulfillmentResponse).isNotNull()
- assertThat(session.isActive).isEqualTo(false)
- }
-
- @Test
- @kotlin.Throws(Exception::class)
- fun fulfillmentType_syncWithConfirmation_stateClearedAfterConfirmation() {
- val sessionFactory: (hostProperties: HostProperties?) -> ExecutionSession =
- { _ ->
- object : ExecutionSession {
- override suspend fun onExecute(arguments: Arguments) =
- ExecutionResult.Builder<Output>().build()
- }
- }
- var onReadyToConfirm =
- object : OnReadyToConfirmListener<Arguments, Confirmation> {
- override suspend fun onReadyToConfirm(arguments: Arguments):
- ConfirmationOutput<Confirmation> {
- return ConfirmationOutput.Builder<Confirmation>()
- .setConfirmation(
- Confirmation.Builder().setOptionalStringField("bar")
- .build()
- )
- .build()
- }
- }
- val capability: Capability =
- createCapability(
- SINGLE_REQUIRED_FIELD_BOUND_PROPERTIES,
- sessionFactory = sessionFactory,
- sessionBridge = SessionBridge {
- TaskHandler.Builder<Arguments, Confirmation>()
- .setOnReadyToConfirmListener(onReadyToConfirm)
- .build()
- },
- sessionUpdaterSupplier = ::EmptyTaskUpdater
- )
- val session = capability.createSession(fakeSessionId, hostProperties)
-
- // TURN 1. Providing all the required slots in the SYNC Request
- val callback = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(
- SYNC,
- "required",
- ParamValue.newBuilder().setIdentifier("foo").setStringValue("foo").build()
- ),
- callback
- )
- assertThat(callback.receiveResponse()).isNotNull()
- assertThat(session.isActive).isEqualTo(true)
-
- // Sending the confirmation request. After the confirm request, the session should not be
- // active
- val callback2 = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(SYNC, SyncStatus.INTENT_CONFIRMED),
- callback2
- )
-
- assertThat(callback2.receiveResponse().fulfillmentResponse).isNotNull()
- assertThat(session.isActive).isEqualTo(false)
- }
-
- @Test
- fun fulfillmentRequest_whenStatusDestroyed_errorReported() {
- val sessionFactory: (hostProperties: HostProperties?) -> ExecutionSession =
- { _ ->
- object : ExecutionSession {
- override suspend fun onExecute(arguments: Arguments) =
- ExecutionResult.Builder<Output>().build()
- }
- }
- val capability: Capability =
- createCapability(
- SINGLE_REQUIRED_FIELD_BOUND_PROPERTIES,
- sessionFactory = sessionFactory,
- sessionBridge = SessionBridge {
- TaskHandler.Builder<Arguments, Confirmation>().build()
- },
- sessionUpdaterSupplier = ::EmptyTaskUpdater
- )
- val session = capability.createSession(fakeSessionId, hostProperties)
-
- // TURN 1. Providing the required slots so that the task completes and the state gets cleared
- val callback = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(
- SYNC,
- "required",
- ParamValue.newBuilder().setIdentifier("foo").setStringValue("foo").build()
- ),
- callback
- )
- assertThat(callback.receiveResponse().fulfillmentResponse).isNotNull()
- assertThat(session.isActive).isEqualTo(false)
-
- // TURN 2. Trying to sync after the session is destroyed
- val callback2 = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(
- SYNC,
- "required",
- ParamValue.newBuilder().setIdentifier("foo").setStringValue("foo").build()
- ),
- callback2
- )
- assertThat(session.isActive).isEqualTo(false)
- assertThat(callback2.receiveResponse().errorStatus)
- .isEqualTo(ErrorStatusInternal.SESSION_NOT_FOUND)
- }
- @Test
- @kotlin.Throws(Exception::class)
- fun syncStatus_unknown_errorReported() {
- val capability: Capability =
- createCapability(
- SINGLE_REQUIRED_FIELD_BOUND_PROPERTIES,
- sessionFactory =
- { _ ->
- object : ExecutionSession {
- override suspend fun onExecute(arguments: Arguments) =
- ExecutionResult.Builder<Output>().build()
- }
- },
- sessionBridge = SessionBridge { TaskHandler.Builder<Arguments, Confirmation>()
- .build() },
- sessionUpdaterSupplier = ::RequiredTaskUpdater,
- )
- val session = capability.createSession(fakeSessionId, hostProperties)
-
- assertThat(capability.appAction)
- .isEqualTo(
- AppAction.newBuilder()
- .setName("actions.intent.TEST")
- .setIdentifier("id")
- .addParams(
- IntentParameter.newBuilder().setName("required").setIsRequired(true),
- )
- .setTaskInfo(
- TaskInfo.newBuilder().setSupportsPartialFulfillment(true),
- )
- .build(),
- )
-
- // TURN 1 (UNKNOWN).
- val errorCallback = FakeCallbackInternal()
- session.execute(buildRequestArgs(SYNC, SyncStatus.UNKNOWN_SYNC_STATUS), errorCallback)
- assertThat(errorCallback.receiveResponse().errorStatus)
- .isEqualTo(ErrorStatusInternal.INVALID_REQUEST)
-
- // TURN 2 (UNRECOGNIZED)
- val errorCallback2 = FakeCallbackInternal()
- session.execute(buildRequestArgs(SYNC, SyncStatus.UNRECOGNIZED), errorCallback2)
- assertThat(errorCallback2.receiveResponse().errorStatus)
- .isEqualTo(ErrorStatusInternal.INVALID_REQUEST)
- }
-
- @Test
- @kotlin.Throws(Exception::class)
- fun syncStatus_slotsIncomplete_taskNotExecuted() {
- val onExecuteInvocationCount = AtomicInteger(0)
- val sessionFactory: (hostProperties: HostProperties?) -> ExecutionSession =
- { _ ->
- object : ExecutionSession {
- override suspend fun onExecute(arguments: Arguments): ExecutionResult<Output> {
- onExecuteInvocationCount.incrementAndGet()
- return ExecutionResult.Builder<Output>().build()
- }
- }
- }
- val capability: Capability =
- createCapability(
- SINGLE_REQUIRED_FIELD_BOUND_PROPERTIES,
- sessionFactory = sessionFactory,
- sessionBridge = SessionBridge { TaskHandler.Builder<Arguments, Confirmation>()
- .build() },
- sessionUpdaterSupplier = ::EmptyTaskUpdater,
- )
- val session = capability.createSession(fakeSessionId, hostProperties)
-
- /** TURN 1. Not providing all the required slots and passing SyncStatus as SLOTS_INCOMPLETE
- * Execution should not happen as sync status is SLOTS_INCOMPLETE
- */
- val callback = FakeCallbackInternal()
- session.execute(buildRequestArgs(SYNC, SyncStatus.SLOTS_INCOMPLETE), callback)
- assertThat(callback.receiveResponse()).isNotNull()
- assertThat(getCurrentValues("required", session.state!!)).isEmpty()
- assertThat(onExecuteInvocationCount.get()).isEqualTo(0)
-
- /** TURN 2. Providing all the required slots but still passing SyncStatus as
- * SLOTS_INCOMPLETE. Execution should not happen as sync status is SLOTS_INCOMPLETE
- */
- val callback2 = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(
- SYNC,
- SyncStatus.SLOTS_INCOMPLETE,
- "required",
- ParamValue.newBuilder().setIdentifier("foo").setStringValue("foo").build(),
- ),
- callback2,
- )
- assertThat(callback2.receiveResponse()).isNotNull()
- assertThat(getCurrentValues("required", session.state!!))
- .containsExactly(
- CurrentValue.newBuilder()
- .setValue(
- ParamValue.newBuilder().setIdentifier("foo").setStringValue("foo"),
- )
- .setStatus(CurrentValue.Status.ACCEPTED)
- .build(),
- )
- assertThat(onExecuteInvocationCount.get()).isEqualTo(0)
-
- /**
- * TURN 3. Providing all the required slots and passing SyncStatus as SLOTS_COMPLETE
- * Execution should happen
- */
- val callback3 = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(
- SYNC,
- SyncStatus.SLOTS_COMPLETE,
- "required",
- ParamValue.newBuilder().setIdentifier("foo").setStringValue("foo").build(),
- ),
- callback3,
- )
- assertThat(callback3.receiveResponse()).isNotNull()
- assertThat(onExecuteInvocationCount.get()).isEqualTo(1)
- }
-
- @Test
- @kotlin.Throws(Exception::class)
- fun syncStatus_intentConfirmed_taskExecuted() {
- val onConfirmationInvocationCount = AtomicInteger(0)
- var onReadyConfirm =
- object : OnReadyToConfirmListener<Arguments, Confirmation> {
- override suspend fun onReadyToConfirm(arguments: Arguments):
- ConfirmationOutput<Confirmation> {
- onConfirmationInvocationCount.incrementAndGet()
- return ConfirmationOutput.Builder<Confirmation>()
- .setConfirmation(Confirmation.Builder().setOptionalStringField("bar")
- .build())
- .build()
- }
- }
- val onExecuteInvocationCount = AtomicInteger(0)
- val sessionFactory: (hostProperties: HostProperties?) -> ExecutionSession =
- { _ ->
- object : ExecutionSession {
- override suspend fun onExecute(arguments: Arguments): ExecutionResult<Output> {
- onExecuteInvocationCount.incrementAndGet()
- return ExecutionResult.Builder<Output>()
- .setOutput(
- Output.Builder()
- .setOptionalStringField("baz")
- .setRepeatedStringField(listOf("baz1", "baz2"))
- .build())
- .build()
- }
- }
- }
- val capability: Capability =
- createCapability(
- SINGLE_REQUIRED_FIELD_BOUND_PROPERTIES,
- sessionFactory = sessionFactory,
- sessionBridge = {
- TaskHandler.Builder<Arguments, Confirmation>()
- .setOnReadyToConfirmListener(onReadyConfirm)
- .registerConfirmationOutput(
- "optionalStringOutput",
- Confirmation::optionalStringField,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- ::toParamValue)
- .build() },
- sessionUpdaterSupplier = ::EmptyTaskUpdater,
- )
-
- val session = capability.createSession(fakeSessionId, hostProperties)
-
- /** TURN 1. Providing all the required slots and passing SyncStatus as SLOTS_COMPLETE
- * This should trigger the confirmation. Execution should not happen
- */
- val callback = FakeCallbackInternal()
- session.execute(buildRequestArgs(
- SYNC,
- SyncStatus.SLOTS_COMPLETE,
- "required",
- ParamValue.newBuilder().setIdentifier("foo").setStringValue("foo").build(),
- ), callback)
- assertThat(callback.receiveResponse()).isNotNull()
- assertThat(getCurrentValues("required", session.state!!))
- .containsExactly(
- CurrentValue.newBuilder()
- .setValue(
- ParamValue.newBuilder().setIdentifier("foo").setStringValue("foo"),
- )
- .setStatus(CurrentValue.Status.ACCEPTED)
- .build(),
- )
- assertThat(onExecuteInvocationCount.get()).isEqualTo(0)
- assertThat(onConfirmationInvocationCount.get()).isEqualTo(1)
-
- // Confirm the BIC
- val expectedConfirmationOutput: StructuredOutput =
- StructuredOutput.newBuilder()
- .addOutputValues(
- OutputValue.newBuilder()
- .setName("optionalStringOutput")
- .addValues(ParamValue.newBuilder().setStringValue("bar").build())
- .build())
- .build()
- assertThat(callback.receiveResponse()
- .fulfillmentResponse!!
- .confirmationData
- .outputValuesList
- )
- .containsExactlyElementsIn(expectedConfirmationOutput.outputValuesList)
-
- /** TURN 2. Send CONFIRM request using INTENT_CONFIRMED sync status.
- * Execution should happen
- */
- val callback2 = FakeCallbackInternal()
- session.execute(
- buildRequestArgs(
- SYNC,
- SyncStatus.INTENT_CONFIRMED,
- ),
- callback2,
- )
- assertThat(callback2.receiveResponse()).isNotNull()
- assertThat(onExecuteInvocationCount.get()).isEqualTo(1)
-
- // Confirm the BIO
- val expectedOutput: StructuredOutput =
- StructuredOutput.newBuilder()
- .addOutputValues(
- OutputValue.newBuilder()
- .setName("optionalStringOutput")
- .addValues(ParamValue.newBuilder().setStringValue("baz"))
- .build())
- .addOutputValues(
- OutputValue.newBuilder()
- .setName("repeatedStringOutput")
- .addValues(ParamValue.newBuilder().setStringValue("baz1").build())
- .addValues(ParamValue.newBuilder().setStringValue("baz2").build())
- .build()
- )
- .build()
- assertThat(callback2.receiveResponse()
- .fulfillmentResponse!!
- .getExecutionOutput()
- .getOutputValuesList())
- .containsExactlyElementsIn(expectedOutput.getOutputValuesList())
- }
-
- @Test
- fun structConversionException_shouldReportInternalFailure() {
- val sessionFactory: (hostProperties: HostProperties?) -> ExecutionSession =
- { _ ->
- object : ExecutionSession {
- override val requiredStringListener = object : AppEntityListener<String> {
- override fun lookupAndRenderAsync(
- searchAction: SearchAction<String>
- ): ListenableFuture<EntitySearchResult<String>> {
- return Futures.immediateFuture(
- EntitySearchResult.Builder<String>().build()
- )
- }
-
- override fun onReceivedAsync(
- value: String
- ): ListenableFuture<ValidationResult> {
- return Futures.immediateFuture(ValidationResult.newAccepted())
- }
- }
- override suspend fun onExecute(arguments: Arguments) =
- ExecutionResult.Builder<Output>()
- .setShouldStartDictation(true)
- .build()
- }
- }
- val capability = CapabilityBuilder()
- .setId("fakeId")
- .setExecutionSessionFactory(sessionFactory)
- .build()
- val session = capability.createSession(fakeSessionId, hostProperties)
- val callback = FakeCallbackInternal()
-
- session.execute(
- buildRequestArgs(
- SYNC,
- "required",
- // this ParamValue can't be parsed as String, and causes StructConversionException
- ParamValue.newBuilder().setIdentifier("foo").setBoolValue(false).build()
- ),
- callback
- )
-
- assertThat(
- callback.receiveResponse().errorStatus
- ).isEqualTo(ErrorStatusInternal.INTERNAL)
- }
-
- @Test
- fun slotListenerException_shouldReportExternalException() {
- val sessionFactory: (hostProperties: HostProperties?) -> ExecutionSession =
- { _ ->
- object : ExecutionSession {
- override val requiredStringListener = object : AppEntityListener<String> {
- override fun lookupAndRenderAsync(
- searchAction: SearchAction<String>
- ): ListenableFuture<EntitySearchResult<String>> {
- throw IllegalStateException("error in lookupAndRender")
- }
-
- override fun onReceivedAsync(
- value: String
- ): ListenableFuture<ValidationResult> {
- throw IllegalStateException("error in onReceivedAsync")
- }
- }
- override suspend fun onExecute(arguments: Arguments) =
- ExecutionResult.Builder<Output>()
- .setShouldStartDictation(true)
- .build()
- }
- }
- val capability = CapabilityBuilder()
- .setId("fakeId")
- .setExecutionSessionFactory(sessionFactory)
- .build()
- val session = capability.createSession(fakeSessionId, hostProperties)
- val callback = FakeCallbackInternal()
-
- session.execute(
- buildRequestArgs(
- SYNC, /* args...= */
- "required",
- ParamValue.newBuilder().setIdentifier("foo").setStringValue("foo").build()
- ),
- callback
- )
-
- assertThat(
- callback.receiveResponse().errorStatus
- ).isEqualTo(ErrorStatusInternal.EXTERNAL_EXCEPTION)
- }
-
- @kotlinx.coroutines.ExperimentalCoroutinesApi
- @Test
- fun slotListenerTimeout_returnsCorrectErrorStatus() = runTest {
- val externalSession = object : ExecutionSession {
- override val requiredStringListener = object : AppEntityListener<String> {
- override suspend fun lookupAndRender(
- searchAction: SearchAction<String>
- ): EntitySearchResult<String> {
- return EntitySearchResult.Builder<String>().build()
- }
-
- override suspend fun onReceived(
- value: String
- ): ValidationResult {
- delay(EXTERNAL_TIMEOUT_MILLIS + 1000L)
- return ValidationResult.newAccepted()
- }
- }
- }
- val session = TaskCapabilitySession(
- "sessionId",
- ACTION_SPEC,
- ACTION_SPEC.createAppAction(
- "fakeCapabilityId",
- SINGLE_REQUIRED_FIELD_BOUND_PROPERTIES,
- supportsPartialFulfillment = true
- ),
- TaskHandler.Builder<Arguments, Confirmation>()
- .registerAppEntityTaskParam(
- "required",
- externalSession.requiredStringListener,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER,
- EntityConverter.of(TypeSpec.STRING_TYPE_SPEC),
- getTrivialSearchActionConverter()
- ).build(),
- externalSession,
- scope = this,
- )
- val callback = FakeCallbackInternal(timeoutMs = EXTERNAL_TIMEOUT_MILLIS + 2000L)
-
- session.execute(
- buildRequestArgs(
- SYNC, /* args...= */
- "required",
- ParamValue.newBuilder().setIdentifier("foo").setStringValue("foo").build()
- ),
- callback
- )
-
- advanceTimeBy(EXTERNAL_TIMEOUT_MILLIS + 2000L)
- val response = callback.receiveResponse()
- assertThat(
- response.errorStatus
- ).isEqualTo(ErrorStatusInternal.EXTERNAL_EXCEPTION)
- }
-
- /**
- * an implementation of Capability.Builder using Argument. Output, etc. defined under
- * testing/spec
- */
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession
- >(ACTION_SPEC) {
-
- init {
- setProperty(
- "required",
- Property<StringValue>(isRequiredForExecution = true),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
- }
-
- public override fun setExecutionSessionFactory(
- sessionFactory: (hostProperties: HostProperties?) -> ExecutionSession
- ) = super.setExecutionSessionFactory(sessionFactory)
-
- override val sessionBridge: SessionBridge<
- ExecutionSession,
- Arguments,
- Confirmation
- > = SessionBridge {
- session ->
- val builder = TaskHandler.Builder<Arguments, Confirmation>()
- session.requiredStringListener?.let {
- listener: AppEntityListener<String> ->
- builder.registerAppEntityTaskParam(
- "required",
- listener,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER,
- EntityConverter.of(TypeSpec.STRING_TYPE_SPEC),
- getTrivialSearchActionConverter()
- )
- }
- builder.build()
- }
- }
-
- companion object {
-
- private val AUTO_ACCEPT_STRING_VALUE: AppEntityListener<String> =
- object : AppEntityListener<String> {
- override fun lookupAndRenderAsync(
- searchAction: SearchAction<String>
- ): ListenableFuture<EntitySearchResult<String>> {
- val result: EntitySearchResult.Builder<String> =
- EntitySearchResult.Builder()
- return Futures.immediateFuture(
- result.addPossibleValue("valid1").build()
- )
- }
-
- override fun onReceivedAsync(
- value: String
- ): ListenableFuture<ValidationResult> {
- return Futures.immediateFuture(ValidationResult.newAccepted())
- }
- }
- private val AUTO_REJECT_STRING_VALUE: AppEntityListener<String> =
- object : AppEntityListener<String> {
- override fun lookupAndRenderAsync(
- searchAction: SearchAction<String>
- ): ListenableFuture<EntitySearchResult<String>> {
- val result: EntitySearchResult.Builder<String> =
- EntitySearchResult.Builder()
- return Futures.immediateFuture(
- result.addPossibleValue("valid1").build()
- )
- }
-
- override fun onReceivedAsync(
- value: String
- ): ListenableFuture<ValidationResult> {
- return Futures.immediateFuture(ValidationResult.newRejected())
- }
- }
-
- private fun <T> getTrivialSearchActionConverter() = SearchActionConverter {
- SearchAction.Builder<T>().build()
- }
-
- private const val CAPABILITY_NAME = "actions.intent.TEST"
- private val ACTION_SPEC: ActionSpec<Arguments, Output> =
- ActionSpecBuilder.ofCapabilityNamed(
- CAPABILITY_NAME
- )
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindParameter(
- "required",
- Arguments::requiredStringField,
- Arguments.Builder::setRequiredStringField,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .bindParameter(
- "optional",
- Arguments::optionalStringField,
- Arguments.Builder::setOptionalStringField,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .bindRepeatedParameter(
- "repeated",
- Arguments::repeatedStringField,
- Arguments.Builder::setRepeatedStringField,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .bindOutput(
- "optionalStringOutput",
- Output::optionalStringField,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER::toParamValue
- )
- .bindRepeatedOutput(
- "repeatedStringOutput",
- Output::repeatedStringField,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER::toParamValue
- )
- .build()
-
- private val SINGLE_REQUIRED_FIELD_BOUND_PROPERTIES = listOf(
- BoundProperty(
- "required",
- Property<StringValue>(isRequiredForExecution = true),
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER)
- )
-
- private fun getCurrentValues(
- argName: String,
- appDialogState: AppDialogState
- ): List<CurrentValue> {
- return appDialogState
- .paramsList
- .stream()
- .filter { dialogParam -> dialogParam.name.equals(argName) }
- .findFirst()
- .orElse(DialogParameter.getDefaultInstance())
- .currentValueList
- }
-
- /**
- * Create a capability instance templated with Property, Argument, Output, Confirmation
- * etc., defined under ../../testing/spec
- */
- private fun <SessionUpdaterT : AbstractTaskUpdater> createCapability(
- boundProperties: List<BoundProperty<*>>,
- sessionFactory: (hostProperties: HostProperties?) -> ExecutionSession,
- sessionBridge: SessionBridge<ExecutionSession, Arguments, Confirmation>,
- sessionUpdaterSupplier: Supplier<SessionUpdaterT>
- ): TaskCapabilityImpl<
- Arguments,
- Output,
- ExecutionSession,
- Confirmation,
- SessionUpdaterT
- > {
- return TaskCapabilityImpl(
- "id",
- ACTION_SPEC,
- boundProperties,
- sessionFactory,
- sessionBridge,
- sessionUpdaterSupplier
- )
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilityUtilsTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilityUtilsTest.kt
deleted file mode 100644
index ab715c5..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskCapabilityUtilsTest.kt
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task
-
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter
-import androidx.appactions.interaction.proto.CurrentValue
-import androidx.appactions.interaction.proto.FulfillmentRequest
-import androidx.appactions.interaction.proto.ParamValue
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class TaskCapabilityUtilsTest {
- @Test
- fun isSlotFillingComplete_allRequiredParamsFilled_returnsTrue() {
- val args: MutableMap<String, List<ParamValue>> = HashMap()
- args["required"] = listOf(ParamValue.newBuilder().setStringValue("Donald").build())
- val intentParameters: MutableList<IntentParameter> = ArrayList()
- intentParameters.add(
- IntentParameter.newBuilder().setName("required").setIsRequired(true).build()
- )
- assertThat(TaskCapabilityUtils.isSlotFillingComplete(args, intentParameters)).isTrue()
- }
-
- @Test
- fun isSlotFillingComplete_notAllRequiredParamsFilled_returnsFalse() {
- val intentParameters: MutableList<IntentParameter> = ArrayList()
- intentParameters.add(
- IntentParameter.newBuilder().setName("required").setIsRequired(true).build()
- )
- assertThat(TaskCapabilityUtils.isSlotFillingComplete(emptyMap(), intentParameters))
- .isFalse()
- }
-
- @Test
- fun canSkipSlotProcessing_true() {
- val currentValues =
- listOf(
- CurrentValue.newBuilder()
- .setValue(ParamValue.newBuilder().setBoolValue(true).build())
- .setStatus(CurrentValue.Status.ACCEPTED)
- .build()
- )
- val fulfillmentValues =
- listOf(
- FulfillmentRequest.Fulfillment.FulfillmentValue.newBuilder()
- .setValue(ParamValue.newBuilder().setBoolValue(true).build())
- .build()
- )
- assertThat(TaskCapabilityUtils.canSkipSlotProcessing(currentValues, fulfillmentValues))
- .isTrue()
- }
-
- @Test
- fun canSkipSlotProcessing_false_sizeDifference() {
- val currentValues =
- listOf(
- CurrentValue.newBuilder()
- .setValue(ParamValue.newBuilder().setStringValue("a").build())
- .setStatus(CurrentValue.Status.ACCEPTED)
- .build()
- )
- val fulfillmentValues: MutableList<FulfillmentRequest.Fulfillment.FulfillmentValue> =
- ArrayList()
- fulfillmentValues.add(
- FulfillmentRequest.Fulfillment.FulfillmentValue.newBuilder()
- .setValue(ParamValue.newBuilder().setStringValue("a").build())
- .build()
- )
- fulfillmentValues.add(
- FulfillmentRequest.Fulfillment.FulfillmentValue.newBuilder()
- .setValue(ParamValue.newBuilder().setStringValue("b").build())
- .build()
- )
- assertThat(TaskCapabilityUtils.canSkipSlotProcessing(currentValues, fulfillmentValues))
- .isFalse()
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskSlotProcessorTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskSlotProcessorTest.kt
deleted file mode 100644
index eca8de0..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskSlotProcessorTest.kt
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.impl.task
-
-import androidx.appactions.interaction.capabilities.core.AppEntityListener
-import androidx.appactions.interaction.capabilities.core.EntitySearchResult
-import androidx.appactions.interaction.capabilities.core.InventoryListener
-import androidx.appactions.interaction.capabilities.core.SearchAction
-import androidx.appactions.interaction.capabilities.core.ValidationResult
-import androidx.appactions.interaction.capabilities.core.ValueListener
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.awaitSync
-import androidx.appactions.interaction.proto.CurrentValue
-import androidx.appactions.interaction.proto.DisambiguationData
-import androidx.appactions.interaction.proto.Entity
-import androidx.appactions.interaction.proto.ParamValue
-import com.google.common.truth.Truth.assertThat
-import com.google.common.util.concurrent.ListenableFuture
-import kotlinx.coroutines.CompletableDeferred
-import kotlinx.coroutines.runBlocking
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class TaskSlotProcessorTest {
- private fun <T> createAssistantDisambigResolver(
- validationResult: ValidationResult,
- valueConsumer: (T) -> Unit,
- renderConsumer: (List<String>) -> Unit,
- ): GenericResolverInternal<T> {
- return GenericResolverInternal.fromInventoryListener(
- object : InventoryListener<T> {
- override fun onReceivedAsync(value: T): ListenableFuture<ValidationResult> {
- valueConsumer.invoke(value)
- return Futures.immediateFuture(validationResult)
- }
-
- override fun renderChoicesAsync(entityIDs: List<String>): ListenableFuture<Void> {
- renderConsumer.invoke(entityIDs)
- return Futures.immediateVoidFuture()
- }
- },
- )
- }
-
- private fun <T> createValueResolver(
- validationResult: ValidationResult,
- valueConsumer: (T) -> Unit,
- ): GenericResolverInternal<T> {
- return GenericResolverInternal.fromValueListener(
- object : ValueListener<T> {
- override fun onReceivedAsync(value: T): ListenableFuture<ValidationResult> {
- valueConsumer.invoke(value)
- return Futures.immediateFuture(validationResult)
- }
- },
- )
- }
-
- private fun <T> createValueResolver(
- validationResult: ValidationResult,
- ): GenericResolverInternal<T> {
- return createValueResolver(validationResult) { _: T -> }
- }
-
- private fun <T> createValueListResolver(
- validationResult: ValidationResult,
- valueConsumer: (List<T>) -> Unit,
- ): GenericResolverInternal<T> {
- return GenericResolverInternal.fromValueListListener(
- object : ValueListener<List<T>> {
- override fun onReceivedAsync(value: List<T>): ListenableFuture<ValidationResult> {
- valueConsumer.invoke(value)
- return Futures.immediateFuture(validationResult)
- }
- },
- )
- }
-
- private fun <T> createAppEntityListener(
- validationResult: ValidationResult,
- valueConsumer: (T) -> Unit,
- appSearchResult: EntitySearchResult<T>,
- appSearchConsumer: (SearchAction<T>) -> Unit,
- ): GenericResolverInternal<T> {
- return GenericResolverInternal.fromAppEntityListener(
- object : AppEntityListener<T> {
- override fun onReceivedAsync(value: T): ListenableFuture<ValidationResult> {
- valueConsumer.invoke(value)
- return Futures.immediateFuture(validationResult)
- }
-
- override fun lookupAndRenderAsync(
- searchAction: SearchAction<T>,
- ): ListenableFuture<EntitySearchResult<T>> {
- appSearchConsumer.invoke(searchAction)
- return Futures.immediateFuture(appSearchResult)
- }
- },
- )
- }
-
- @Test
- @Throws(Exception::class)
- fun processSlot_singleValue_accepted(): Unit = runBlocking {
- val binding =
- TaskParamBinding(
- "singularValue",
- { false },
- createValueResolver(ValidationResult.newAccepted()),
- TypeConverters.STRING_PARAM_VALUE_CONVERTER,
- null,
- null,
- )
- val taskParamMap: MutableMap<String, TaskParamBinding<*>> = HashMap()
- taskParamMap["singularValue"] = binding
- val args = listOf(ParamValue.newBuilder().setStringValue("testValue").build())
- val (isSuccessful, processedValues) =
- TaskSlotProcessor.processSlot(
- "singularValue",
- TaskCapabilityUtils.paramValuesToCurrentValue(args, CurrentValue.Status.PENDING),
- taskParamMap,
- )
- assertThat(isSuccessful).isTrue()
- assertThat(processedValues)
- .containsExactly(
- CurrentValue.newBuilder()
- .setValue(args[0])
- .setStatus(CurrentValue.Status.ACCEPTED)
- .build(),
- )
- }
-
- @Test
- @Throws(Exception::class)
- fun processSlot_singleValue_rejected(): Unit = runBlocking {
- val binding =
- TaskParamBinding(
- "singularValue",
- { false },
- createValueResolver(ValidationResult.newRejected()),
- TypeConverters.STRING_PARAM_VALUE_CONVERTER,
- null,
- null,
- )
- val taskParamMap: MutableMap<String, TaskParamBinding<*>> = HashMap()
- taskParamMap["singularValue"] = binding
- val args = listOf(ParamValue.newBuilder().setStringValue("testValue").build())
- val (isSuccessful, processedValues) =
- TaskSlotProcessor.processSlot(
- "singularValue",
- TaskCapabilityUtils.paramValuesToCurrentValue(args, CurrentValue.Status.PENDING),
- taskParamMap,
- )
- assertThat(isSuccessful).isFalse()
- assertThat(processedValues)
- .containsExactly(
- CurrentValue.newBuilder()
- .setValue(args[0])
- .setStatus(CurrentValue.Status.REJECTED)
- .build(),
- )
- }
-
- @Test
- @Throws(Exception::class)
- fun processSlot_repeatedValue_accepted(): Unit = runBlocking {
- val lastReceivedArgs = CompletableDeferred<List<String>>()
- val binding =
- TaskParamBinding(
- "repeatedValue",
- { false },
- createValueListResolver(
- ValidationResult.newAccepted(),
- ) { lastReceivedArgs.complete(it) },
- TypeConverters.STRING_PARAM_VALUE_CONVERTER,
- null,
- null,
- )
- val taskParamMap: MutableMap<String, TaskParamBinding<*>> = HashMap()
- taskParamMap["repeatedValue"] = binding
- val args =
- listOf(
- ParamValue.newBuilder().setStringValue("testValue1").build(),
- ParamValue.newBuilder().setStringValue("testValue2").build(),
- )
- val (isSuccessful, processedValues) =
- TaskSlotProcessor.processSlot(
- "repeatedValue",
- TaskCapabilityUtils.paramValuesToCurrentValue(args, CurrentValue.Status.PENDING),
- taskParamMap,
- )
- assertThat(isSuccessful).isTrue()
- assertThat(processedValues)
- .containsExactly(
- CurrentValue.newBuilder()
- .setValue(args[0])
- .setStatus(CurrentValue.Status.ACCEPTED)
- .build(),
- CurrentValue.newBuilder()
- .setValue(args[1])
- .setStatus(CurrentValue.Status.ACCEPTED)
- .build(),
- )
- assertThat(lastReceivedArgs.awaitSync()).isEqualTo(
- listOf(
- "testValue1",
- "testValue2",
- ),
- )
- }
-
- @Test
- @Throws(Exception::class)
- fun processSlot_repeatedValue_rejected(): Unit = runBlocking {
- val lastReceivedArgs = CompletableDeferred<List<String>>()
- val binding =
- TaskParamBinding(
- "repeatedValue",
- { false },
- createValueListResolver(
- ValidationResult.newRejected(),
- ) { lastReceivedArgs.complete(it) },
- TypeConverters.STRING_PARAM_VALUE_CONVERTER,
- null,
- null,
- )
- val taskParamMap: MutableMap<String, TaskParamBinding<*>> = HashMap()
- taskParamMap["repeatedValue"] = binding
- val args =
- listOf(
- ParamValue.newBuilder().setStringValue("testValue1").build(),
- ParamValue.newBuilder().setStringValue("testValue2").build(),
- )
- val (isSuccessful, processedValues) =
- TaskSlotProcessor.processSlot(
- "repeatedValue",
- TaskCapabilityUtils.paramValuesToCurrentValue(args, CurrentValue.Status.PENDING),
- taskParamMap,
- )
- assertThat(isSuccessful).isFalse()
- assertThat(processedValues)
- .containsExactly(
- CurrentValue.newBuilder()
- .setValue(args[0])
- .setStatus(CurrentValue.Status.REJECTED)
- .build(),
- CurrentValue.newBuilder()
- .setValue(args[1])
- .setStatus(CurrentValue.Status.REJECTED)
- .build(),
- )
- assertThat(lastReceivedArgs.awaitSync()).isEqualTo(
- listOf(
- "testValue1",
- "testValue2",
- ),
- )
- }
-
- @Test
- @Throws(Exception::class)
- fun listValues_oneAccepted_oneAssistantDisambig_invokesRendererAndOnReceived(): Unit =
- runBlocking {
- val onReceivedDeferred = CompletableDeferred<String>()
- val renderDeferred = CompletableDeferred<List<String>>()
- val binding =
- TaskParamBinding(
- "assistantDrivenSlot",
- { !it.hasIdentifier() },
- createAssistantDisambigResolver(
- ValidationResult.newAccepted(),
- { onReceivedDeferred.complete(it) },
- ) {
- renderDeferred.complete(it)
- },
- TypeConverters.STRING_PARAM_VALUE_CONVERTER,
- null,
- null,
- )
- val taskParamMap: MutableMap<String, TaskParamBinding<*>> = HashMap()
- taskParamMap["assistantDrivenSlot"] = binding
- val previouslyAccepted =
- CurrentValue.newBuilder()
- .setStatus(CurrentValue.Status.ACCEPTED)
- .setValue(
- ParamValue.newBuilder()
- .setIdentifier("id")
- .setStringValue("1234")
- )
- .build()
- val values =
- listOf(
- previouslyAccepted,
- CurrentValue.newBuilder()
- .setStatus(CurrentValue.Status.PENDING)
- .setDisambiguationData(
- DisambiguationData.newBuilder()
- .addEntities(Entity.newBuilder().setIdentifier("entity-1"))
- .addEntities(Entity.newBuilder().setIdentifier("entity-2")),
- )
- .build(),
- )
- val (isSuccessful, processedValues) =
- TaskSlotProcessor.processSlot("assistantDrivenSlot", values, taskParamMap)
- assertThat(isSuccessful).isFalse()
- assertThat(onReceivedDeferred.awaitSync()).isEqualTo("1234")
- assertThat(renderDeferred.awaitSync()).isEqualTo(listOf("entity-1", "entity-2"))
- assertThat(processedValues)
- .containsExactly(
- previouslyAccepted,
- CurrentValue.newBuilder()
- .setStatus(CurrentValue.Status.DISAMBIG)
- .setDisambiguationData(
- DisambiguationData.newBuilder()
- .addEntities(Entity.newBuilder().setIdentifier("entity-1"))
- .addEntities(Entity.newBuilder().setIdentifier("entity-2")),
- )
- .build(),
- )
- }
-
- @Test
- @Throws(Exception::class)
- fun singularValue_appDisambigRejected_onReceivedNotCalled(): Unit = runBlocking {
- val onReceivedDeferred = CompletableDeferred<String>()
- val appSearchDeferred = CompletableDeferred<SearchAction<String>>()
- val entitySearchResult = EntitySearchResult.Builder<String>().build()
- val resolver =
- createAppEntityListener(
- ValidationResult.newAccepted(),
- { result: String -> onReceivedDeferred.complete(result) },
- entitySearchResult,
- ) { result: SearchAction<String> ->
- appSearchDeferred.complete(result)
- }
- val binding =
- TaskParamBinding(
- "appDrivenSlot",
- { true }, // always invoke app-grounding in all cases
- resolver,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER, // Not invoked
- { Entity.getDefaultInstance() },
- ) {
- SearchAction.Builder<String>().setQuery("A").setFilter("nested").build()
- }
- val taskParamMap: MutableMap<String, TaskParamBinding<*>> = HashMap()
- taskParamMap["appDrivenSlot"] = binding
- val values =
- listOf(
- CurrentValue.newBuilder()
- .setStatus(CurrentValue.Status.PENDING)
- .setValue(ArgumentUtils.buildSearchActionParamValue("A"))
- .build(),
- )
- val (isSuccessful, processedValues) =
- TaskSlotProcessor.processSlot("appDrivenSlot", values, taskParamMap)
- assertThat(isSuccessful).isFalse()
-
- assertThat(onReceivedDeferred.isCompleted).isFalse()
- assertThat(appSearchDeferred.isCompleted).isTrue()
- assertThat(appSearchDeferred.awaitSync())
- .isEqualTo(SearchAction.Builder<String>().setQuery("A").setFilter("nested").build())
- assertThat(processedValues)
- .containsExactly(
- CurrentValue.newBuilder()
- .setStatus(CurrentValue.Status.REJECTED)
- .setValue(ArgumentUtils.buildSearchActionParamValue("A"))
- .build(),
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/properties/PropertyJavaTest.java b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/properties/PropertyJavaTest.java
deleted file mode 100644
index dc67adc..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/properties/PropertyJavaTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.properties;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-
-@RunWith(JUnit4.class)
-public class PropertyJavaTest {
-
- @Test
- public void noArgConstructor_reasonableDefaultValues() {
- Property<StringValue> prop = new Property<>();
-
- assertThat(prop.isSupported()).isTrue();
- assertThat(prop.isRequiredForExecution()).isFalse();
- assertThat(prop.shouldMatchPossibleValues()).isFalse();
- assertThat(prop.getPossibleValues()).isEmpty();
- }
-
- @Test
- public void fullConstructor_returnsAllValues() {
- Property<StringValue> prop =
- new Property<>(
- Arrays.asList(new StringValue("test")),
- /** isRequiredForExecution= */
- true,
- /** shouldMatchPossibleValues= */
- true);
-
- assertThat(prop.isSupported()).isTrue();
- assertThat(prop.isRequiredForExecution()).isTrue();
- assertThat(prop.shouldMatchPossibleValues()).isTrue();
- assertThat(prop.getPossibleValues()).containsExactly(new StringValue("test"));
- }
-
- @Test
- public void supplierConstructor_returnsValues() {
- ArrayList<StringValue> mutableValues = new ArrayList<>();
- Property<StringValue> prop = new Property<>(() -> mutableValues);
-
- assertThat(prop.shouldMatchPossibleValues()).isFalse();
- assertThat(prop.getPossibleValues()).isEmpty();
-
- // Mutate list
- mutableValues.add(new StringValue("test"));
-
- assertThat(prop.getPossibleValues()).containsExactly(new StringValue("test"));
- }
-
- @Test
- public void staticUnsupportedMethod_returnsSensibleValues() {
- Property<StringValue> prop = Property.unsupported();
-
- assertThat(prop.isSupported()).isFalse();
- assertThat(prop.isRequiredForExecution()).isFalse();
- assertThat(prop.shouldMatchPossibleValues()).isFalse();
- assertThat(prop.getPossibleValues()).isEmpty();
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/properties/PropertyTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/properties/PropertyTest.kt
deleted file mode 100644
index b3801e4..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/properties/PropertyTest.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.properties
-
-import androidx.appactions.interaction.capabilities.core.properties.Property.Companion.unsupported
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class PropertyTest {
-
- @Test
- fun noArgConstructor_reasonableDefaultValues() {
- val prop: Property<StringValue?> = Property()
-
- assertThat(prop.isSupported).isTrue()
- assertThat(prop.isRequiredForExecution).isFalse()
- assertThat(prop.shouldMatchPossibleValues).isFalse()
- assertThat(prop.possibleValues).isEmpty()
- }
-
- @Test
- fun fullConstructor_returnsAllValues() {
- val prop = Property(
- listOf(StringValue("test")),
- isRequiredForExecution = true,
- shouldMatchPossibleValues = true,
- )
-
- assertThat(prop.isSupported).isTrue()
- assertThat(prop.isRequiredForExecution).isTrue()
- assertThat(prop.shouldMatchPossibleValues).isTrue()
- assertThat(prop.possibleValues).containsExactly(StringValue("test"))
- }
-
- @Test
- fun supplierConstructor_returnsMostRecentPossibleValues() {
- val mutableValues = ArrayList<StringValue>()
- val prop = Property({ mutableValues })
-
- assertThat(prop.shouldMatchPossibleValues).isFalse()
- assertThat(prop.possibleValues).isEmpty()
-
- // Mutate list
- mutableValues.add(StringValue("test"))
-
- assertThat(prop.possibleValues).containsExactly(StringValue("test"))
- }
-
- @Test
- fun staticUnsupportedMethod_returnsSensibleValues() {
- val prop = unsupported<StringValue>()
-
- assertThat(prop.isSupported).isFalse()
- assertThat(prop.isRequiredForExecution).isFalse()
- assertThat(prop.shouldMatchPossibleValues).isFalse()
- assertThat(prop.possibleValues).isEmpty()
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/properties/StringValueTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/properties/StringValueTest.kt
deleted file mode 100644
index 4bfeb8a..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/properties/StringValueTest.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.properties
-
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class StringValueTest {
-
- @Test
- fun constructorWithOnlyName() {
- val stringValue = StringValue("abcd")
-
- assertThat(stringValue.name).isEqualTo("abcd")
- assertThat(stringValue.alternateNames).isEmpty()
- }
-
- @Test
- fun fullConstructor_returnsValues() {
- val stringValue = StringValue("abcd", listOf("alt1", "alt2"))
-
- assertThat(stringValue.name).isEqualTo("abcd")
- assertThat(stringValue.alternateNames).containsExactly("alt1", "alt2")
- }
-
- @Test
- fun objectMethods_overridden() {
- val stringValue = StringValue("abcd", listOf("alt1"))
-
- assertThat(stringValue).isEqualTo(StringValue("abcd", listOf("alt1")))
- assertThat(stringValue.hashCode()).isNotEqualTo(0)
- assertThat(stringValue.toString()).isEqualTo(
- "StringValue(name='abcd', alternateNames=[alt1])"
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/Arguments.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/Arguments.kt
deleted file mode 100644
index 2cd52cd..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/Arguments.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.testing.spec
-
-class Arguments internal constructor(
- val requiredStringField: String?,
- val optionalStringField: String?,
- val repeatedStringField: List<String>
-) {
- override fun toString(): String {
- return "Arguments(requiredStringField=$requiredStringField, " +
- "optionalStringField=$optionalStringField, " +
- "repeatedStringField=$repeatedStringField, " +
- ")"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Arguments
-
- if (requiredStringField != other.requiredStringField) return false
- if (optionalStringField != other.optionalStringField) return false
- if (repeatedStringField != other.repeatedStringField) return false
- return true
- }
-
- override fun hashCode(): Int {
- var result = requiredStringField.hashCode()
- result += 31 * optionalStringField.hashCode()
- result += 31 * repeatedStringField.hashCode()
- return result
- }
-
- class Builder {
- private var requiredStringField: String? = null
- private var optionalStringField: String? = null
- private var repeatedStringField: List<String> = listOf()
-
- fun setRequiredStringField(requiredStringField: String): Builder =
- apply { this.requiredStringField = requiredStringField }
-
- fun setOptionalStringField(optionalStringField: String): Builder =
- apply { this.optionalStringField = optionalStringField }
-
- fun setRepeatedStringField(repeatedStringField: List<String>): Builder =
- apply { this.repeatedStringField = repeatedStringField }
-
- fun build(): Arguments =
- Arguments(requiredStringField, optionalStringField, repeatedStringField)
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/CapabilityStructFill.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/CapabilityStructFill.kt
deleted file mode 100644
index bc30c9a..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/CapabilityStructFill.kt
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.testing.spec
-
-import androidx.appactions.builtintypes.experimental.types.ListItem
-import androidx.appactions.interaction.capabilities.core.AppEntityListener
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-
-private const val CAPABILITY_NAME = "actions.intent.TEST"
-
-/** Used to test the filling behavior of structured entities (e.g. ListItem) */
-class CapabilityStructFill {
-
- class Arguments internal constructor(
- val listItem: ListItem?,
- val string: String?
- ) {
- override fun toString(): String {
- return "Arguments(listItem=$listItem, " +
- "string=$string)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Arguments
-
- if (listItem != other.listItem) return false
- if (string != other.string) return false
- return true
- }
-
- override fun hashCode(): Int {
- var result = listItem.hashCode()
- result += 31 * string.hashCode()
- return result
- }
-
- class Builder {
- private var listItem: ListItem? = null
- private var string: String? = null
-
- fun setListItem(listItem: ListItem): Builder =
- apply { this.listItem = listItem }
-
- fun setAnyString(stringSlotB: String): Builder =
- apply { this.string = stringSlotB }
-
- fun build(): Arguments = Arguments(listItem, string)
- }
- }
-
- class Output internal constructor()
-
- class Confirmation internal constructor()
-
- interface ExecutionSession : BaseExecutionSession<Arguments, Output> {
- val listItemListener: AppEntityListener<ListItem>
- }
-
- companion object {
- val ACTION_SPEC = ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindParameter(
- "listItem",
- Arguments::listItem,
- Arguments.Builder::setListItem,
- ParamValueConverter.of(TypeConverters.LIST_ITEM_TYPE_SPEC)
- )
- .bindParameter(
- "string",
- Arguments::string,
- Arguments.Builder::setAnyString,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .build()
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/CapabilityTwoStrings.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/CapabilityTwoStrings.kt
deleted file mode 100644
index 3667ff4..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/CapabilityTwoStrings.kt
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.testing.spec
-
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-
-private const val CAPABILITY_NAME = "actions.intent.TEST"
-
-@CapabilityFactory(name = CAPABILITY_NAME)
-class CapabilityTwoStrings {
-
- class Arguments internal constructor(
- val stringSlotA: String?,
- val stringSlotB: String?
- ) {
- override fun toString(): String {
- return "Arguments(stringSlotA=$stringSlotA, " +
- "stringSlotB=$stringSlotB)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Arguments
-
- if (stringSlotA != other.stringSlotA) return false
- if (stringSlotB != other.stringSlotB) return false
- return true
- }
-
- override fun hashCode(): Int {
- var result = stringSlotA.hashCode()
- result += 31 * stringSlotB.hashCode()
- return result
- }
-
- class Builder {
- private var stringSlotA: String? = null
- private var stringSlotB: String? = null
-
- fun setStringSlotA(stringSlotA: String): Builder =
- apply { this.stringSlotA = stringSlotA }
-
- fun setStringSlotB(stringSlotB: String): Builder =
- apply { this.stringSlotB = stringSlotB }
-
- fun build(): Arguments = Arguments(stringSlotA, stringSlotB)
- }
- }
-
- class Output internal constructor()
-
- class Confirmation internal constructor()
-
- interface ExecutionSession : BaseExecutionSession<Arguments, Output>
-
- companion object {
- val ACTION_SPEC = ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindParameter(
- "stringSlotA",
- Arguments::stringSlotA,
- Arguments.Builder::setStringSlotA,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .bindParameter(
- "stringSlotB",
- Arguments::stringSlotB,
- Arguments.Builder::setStringSlotB,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .build()
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/Confirmation.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/Confirmation.kt
deleted file mode 100644
index a7834a5..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/Confirmation.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.testing.spec
-
-class Confirmation internal constructor(
- val optionalStringField: String?
-) {
- override fun toString(): String {
- return "Confirmation(optionalStringField=$optionalStringField)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Confirmation
-
- if (optionalStringField != other.optionalStringField) return false
- return true
- }
-
- override fun hashCode(): Int {
- return optionalStringField.hashCode()
- }
-
- class Builder {
- private var optionalStringField: String? = null
-
- fun setOptionalStringField(optionalStringField: String): Builder =
- apply { this.optionalStringField = optionalStringField }
-
- fun build(): Confirmation = Confirmation(optionalStringField)
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/ExecutionSession.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/ExecutionSession.kt
deleted file mode 100644
index 354a117..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/ExecutionSession.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.testing.spec
-
-import androidx.appactions.interaction.capabilities.core.AppEntityListener
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures
-
-interface ExecutionSession : BaseExecutionSession<Arguments, Output> {
-
- val requiredStringListener: AppEntityListener<String>? get() = null
-
- companion object {
- @JvmStatic
- val DEFAULT = object : ExecutionSession {
- override fun onExecuteAsync(arguments: Arguments) =
- Futures.immediateFuture(
- ExecutionResult.Builder<Output>().build(),
- )
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/GenericEntityArguments.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/GenericEntityArguments.kt
deleted file mode 100644
index c91c594..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/GenericEntityArguments.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.testing.spec
-
-class GenericEntityArguments internal constructor(
- val singularField: TestEntity?,
- val optionalField: TestEntity?,
- val repeatedField: List<TestEntity>
-) {
- override fun toString(): String {
- return "GenericEntityArguments(singularField=$singularField, " +
- "optionalField=$optionalField, " +
- "repeatedField=$repeatedField, " +
- ")"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as GenericEntityArguments
-
- if (singularField != other.singularField) return false
- if (optionalField != other.optionalField) return false
- if (repeatedField != other.repeatedField) return false
- return true
- }
-
- override fun hashCode(): Int {
- var result = singularField.hashCode()
- result += 31 * optionalField.hashCode()
- result += 31 * repeatedField.hashCode()
- return result
- }
-
- class Builder {
- private var singularField: TestEntity? = null
- private var optionalField: TestEntity? = null
- private var repeatedField: List<TestEntity> = listOf()
-
- fun setSingularField(singularField: TestEntity): Builder =
- apply { this.singularField = singularField }
-
- fun setOptionalField(optionalField: TestEntity): Builder =
- apply { this.optionalField = optionalField }
-
- fun setRepeatedField(repeatedField: List<TestEntity>): Builder =
- apply { this.repeatedField = repeatedField }
-
- fun build(): GenericEntityArguments =
- GenericEntityArguments(singularField, optionalField, repeatedField)
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/Output.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/Output.kt
deleted file mode 100644
index 198a91b..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/Output.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.testing.spec
-
-class Output internal constructor(
- val optionalStringField: String?,
- val repeatedStringField: List<String>
-) {
- override fun toString(): String {
- return "Output(optionalStringField=$optionalStringField, " +
- "repeatedStringField=$repeatedStringField)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Output
-
- if (optionalStringField != other.optionalStringField) return false
- if (repeatedStringField != other.repeatedStringField) return false
- return true
- }
-
- override fun hashCode(): Int {
- var result = optionalStringField.hashCode()
- result += 31 * repeatedStringField.hashCode()
- return result
- }
-
- class Builder {
- private var optionalStringField: String? = null
- private var repeatedStringField: List<String> = listOf()
-
- fun setOptionalStringField(optionalStringField: String): Builder =
- apply { this.optionalStringField = optionalStringField }
-
- fun setRepeatedStringField(repeatedStringField: List<String>): Builder = apply {
- this.repeatedStringField = repeatedStringField
- }
-
- fun build(): Output = Output(optionalStringField, repeatedStringField)
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/TestEntity.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/TestEntity.kt
deleted file mode 100644
index 254552b..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/core/testing/spec/TestEntity.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.core.testing.spec
-
-import java.time.Duration
-import java.time.ZonedDateTime
-
-class TestEntity internal constructor(
- val id: String?,
- val name: String?,
- val duration: Duration?,
- val zonedDateTime: ZonedDateTime?,
- val entity: TestEntity?
-) {
- override fun toString(): String {
- return "TestEntity(identifier=$id, name=$name, duration=$duration, " +
- "zonedDateTime=$zonedDateTime, entity=$entity)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as TestEntity
-
- if (id != other.id) return false
- if (name != other.name) return false
- if (duration != other.duration) return false
- if (zonedDateTime != other.zonedDateTime) return false
- if (entity != other.entity) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = id.hashCode()
- result += 31 * name.hashCode()
- result += 31 * duration.hashCode()
- result += 31 * zonedDateTime.hashCode()
- result += 31 * entity.hashCode()
- return result
- }
-
- class Builder {
- private var id: String? = null
- private var name: String? = null
- private var duration: Duration? = null
- private var zonedDateTime: ZonedDateTime? = null
- private var entity: TestEntity? = null
-
- fun setId(id: String): Builder = apply { this.id = id }
- fun setName(name: String): Builder = apply { this.name = name }
- fun setDuration(duration: Duration): Builder = apply { this.duration = duration }
- fun setZonedDateTime(zonedDateTime: ZonedDateTime): Builder = apply {
- this.zonedDateTime = zonedDateTime
- }
- fun setEntity(entity: TestEntity): Builder = apply { this.entity = entity }
-
- fun build(): TestEntity = TestEntity(id, name, duration, zonedDateTime, entity)
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/serializers/ValueUtilsTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/serializers/ValueUtilsTest.kt
deleted file mode 100644
index 7900c30..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/serializers/ValueUtilsTest.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers
-
-import androidx.appactions.interaction.protobuf.Struct
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-
-class ValueUtilsTest {
- @Test
- fun getSingleStringValue() {
- assertThat(stringValue("Hello").singleStringValue).isEqualTo("Hello")
- assertThat(listValue(listOf(stringValue("Hello"))).singleStringValue).isEqualTo("Hello")
- assertThat(
- listValue(
- listOf(
- stringValue("Hello"),
- stringValue("World"),
- ))
- .singleStringValue)
- .isNull()
- assertThat(structValue(Struct.getDefaultInstance()).singleStringValue).isNull()
- }
-
- @Test
- fun getSingleNumberValue() {
- assertThat(numberValue(123.0).singleNumberValue).isEqualTo(123.0)
- assertThat(listValue(listOf(numberValue(123.0))).singleNumberValue).isEqualTo(123.0)
- assertThat(
- listValue(
- listOf(
- numberValue(123.0),
- numberValue(456.0),
- ))
- .singleNumberValue)
- .isNull()
- assertThat(structValue(Struct.getDefaultInstance()).singleNumberValue).isNull()
- }
-
- @Test fun getSingleBoolValue() {
- assertThat(boolValue(true).singleBoolValue).isTrue()
- assertThat(listValue(listOf(boolValue(true))).singleBoolValue).isTrue()
- assertThat(
- listValue(
- listOf(
- boolValue(true),
- boolValue(false),
- ))
- .singleBoolValue)
- .isNull()
- assertThat(structValue(Struct.getDefaultInstance()).singleBoolValue).isNull()
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/serializers/types/BuiltInTypeSerializerRegistryTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/serializers/types/BuiltInTypeSerializerRegistryTest.kt
deleted file mode 100644
index ad1def8..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/serializers/types/BuiltInTypeSerializerRegistryTest.kt
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.types
-
-import androidx.appactions.builtintypes.types.AbstractPerson
-import androidx.appactions.builtintypes.types.Person
-import androidx.appactions.builtintypes.types.Thing
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-
-class BuiltInTypeSerializerRegistryTest {
-
- object AllTestSerializers {
- @JvmStatic fun getPersonSerializer() = PersonSerializer()
-
- fun someFunThatShouldBeIgnored() {}
-
- @JvmStatic fun otherFunThatShouldBeIgnored(@Suppress("UNUSED_PARAMETER") int: Int) {}
- }
-
- object MoreTestSerializers {
- @JvmStatic fun getThingSerializer() = ThingSerializer()
- }
-
- class MyPerson internal constructor(person: Person) :
- AbstractPerson<MyPerson, MyPerson.Builder>(person) {
- protected override val selfTypeName = "MyPerson"
- protected override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- protected override fun toBuilderWithAdditionalPropertiesOnly() = Builder()
-
- class Builder : AbstractPerson.Builder<Builder, MyPerson>() {
- protected override val selfTypeName = "MyPerson.Builder"
- override val additionalProperties: Map<String, Any?>
- get() = emptyMap()
-
- protected override fun buildFromPerson(person: Person) = MyPerson(person)
- }
- }
-
- @Test
- fun getSerializer() {
- val registry =
- BuiltInTypeSerializerRegistry(
- serializerRegistryClassNames =
- listOf(
- AllTestSerializers::class.java.canonicalName!!,
- MoreTestSerializers::class.java.canonicalName!!),
- getClassOrNull = { canonicalName ->
- when (canonicalName) {
- AllTestSerializers::class.java.canonicalName ->
- AllTestSerializers::class.java
- MoreTestSerializers::class.java.canonicalName ->
- MoreTestSerializers::class.java
- else -> null
- }
- })
-
- assertThat(registry.getSerializer(Person.Builder().build()))
- .isInstanceOf(PersonSerializer::class.java)
- assertThat(registry.getSerializer(Thing.Builder().build()))
- .isInstanceOf(ThingSerializer::class.java)
- // No serializer for this but should go up the parent chain and realize this is a Person
- assertThat(registry.getSerializer(MyPerson.Builder().build()))
- .isInstanceOf(PersonSerializer::class.java)
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/serializers/types/DayOfWeekSerializerTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/serializers/types/DayOfWeekSerializerTest.kt
deleted file mode 100644
index 2cd82d1..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/serializers/types/DayOfWeekSerializerTest.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.types
-
-import androidx.appactions.builtintypes.types.DayOfWeek
-import androidx.appactions.interaction.protobuf.Value
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class DayOfWeekSerializerTest {
- @Test
- fun DayOfWeek_conversion_success() {
- val MONDAY_VALUE = Value.newBuilder().setStringValue(DayOfWeek.MONDAY.canonicalUrl).build()
-
- assertThat(DAY_OF_WEEK_TYPE_SPEC.toValue(DayOfWeek.MONDAY)).isEqualTo(MONDAY_VALUE)
- assertThat(DAY_OF_WEEK_TYPE_SPEC.fromValue(MONDAY_VALUE)).isSameInstanceAs(DayOfWeek.MONDAY)
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/serializers/types/PersonSerializerTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/serializers/types/PersonSerializerTest.kt
deleted file mode 100644
index 7a22f10..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/serializers/types/PersonSerializerTest.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.types
-
-import androidx.appactions.builtintypes.types.Person
-import androidx.appactions.interaction.capabilities.serializers.stringValue
-import androidx.appactions.interaction.protobuf.Struct
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-
-class PersonSerializerTest {
- @Test
- fun returnsValidTypeNameAndClassRef() {
- assertThat(PersonSerializer().typeName).isEqualTo("Person")
- assertThat(PersonSerializer().classRef).isSameInstanceAs(Person::class.java)
- }
-
- @Test
- fun serializesToStructWithTypeName() {
- val person = Person.Builder().setName("Jane").build()
- assertThat(PersonSerializer().serialize(person).fieldsMap)
- .containsEntry("@type", stringValue("Person"))
- // TODO(kalindthakkar): Add more tests once serialization logic is in
- }
-
- @Test
- fun deserializesFromStruct() {
- val struct = Struct.newBuilder()
- .putFields("@type", stringValue("Person"))
- .build()
- assertThat(PersonSerializer().deserialize(struct)).isEqualTo(Person.Builder().build())
- // TODO(kalindthakkar): Add more tests once deserialization logic is in
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/serializers/types/SerializeTest.kt b/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/serializers/types/SerializeTest.kt
deleted file mode 100644
index 7acf42f..0000000
--- a/appactions/interaction/interaction-capabilities-core/src/test/java/androidx/appactions/interaction/capabilities/serializers/types/SerializeTest.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.serializers.types
-
-import androidx.appactions.builtintypes.types.Person
-import androidx.appactions.builtintypes.types.Thing
-import androidx.appactions.interaction.capabilities.serializers.stringValue
-import androidx.appactions.interaction.protobuf.Struct
-import com.google.common.truth.Truth.assertThat
-import org.junit.Assert.assertThrows
-import org.junit.Test
-
-class SerializeTest {
- @Test
- fun serialize_dynamicallyDispatchesToTheCorrectSerializer() {
- val thing: Thing = Person.Builder().setName("Jane").setEmail("[email protected]").build()
- assertThat(serialize(thing))
- .isEqualTo(Struct.newBuilder().putFields("@type", stringValue("Person")).build())
- // TODO(kalindthakkar): Expand to check the name once serialization logic is in
- }
-
- @Test
- fun deserialize_throwsNotImplementedError() {
- val struct =
- Struct.newBuilder()
- .putFields("@type", stringValue("Person"))
- .putFields("name", stringValue("Jane"))
- .putFields("email", stringValue("[email protected]"))
- .build()
- assertThrows(NotImplementedError::class.java) { deserialize(struct) }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-fitness/api/res-current.txt b/appactions/interaction/interaction-capabilities-fitness/api/res-current.txt
deleted file mode 100644
index e69de29..0000000
--- a/appactions/interaction/interaction-capabilities-fitness/api/res-current.txt
+++ /dev/null
diff --git a/appactions/interaction/interaction-capabilities-fitness/build.gradle b/appactions/interaction/interaction-capabilities-fitness/build.gradle
deleted file mode 100644
index 3017f07..0000000
--- a/appactions/interaction/interaction-capabilities-fitness/build.gradle
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-/**
- * This file was created using the `create_project.py` script located in the
- * `<AndroidX root>/development/project-creator` directory.
- *
- * Please use that script when creating a new project, rather than copying an existing project and
- * modifying its settings.
- */
-import androidx.build.LibraryType
-
-plugins {
- id("AndroidXPlugin")
- id("com.android.library")
- id("org.jetbrains.kotlin.android")
-}
-
-dependencies {
- api(libs.kotlinStdlib)
- implementation("androidx.annotation:annotation:1.1.0")
- implementation(project(":appactions:interaction:interaction-capabilities-core"))
-}
-
-android {
- namespace "androidx.appactions.interaction.capabilities.fitness"
- defaultConfig {
- minSdkVersion 26
- }
-}
-
-androidx {
- name = "androidx.appactions.interaction:interaction-capabilities-fitness"
- type = LibraryType.PUBLISHED_LIBRARY
- inceptionYear = "2023"
- description = "Capability library for health and fitness apps integrating with virtual assistant."
- metalavaK2UastEnabled = true
-}
diff --git a/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/GetExerciseObservation.kt b/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/GetExerciseObservation.kt
deleted file mode 100644
index 906d4fe..0000000
--- a/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/GetExerciseObservation.kt
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.fitness.fitness
-
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import java.time.LocalTime
-
-/** A capability corresponding to actions.intent.GET_EXERCISE_OBSERVATION */
-@CapabilityFactory(name = GetExerciseObservation.CAPABILITY_NAME)
-class GetExerciseObservation private constructor() {
- internal enum class SlotMetadata(val path: String) {
- START_TIME("exerciseObservation.startTime"),
- END_TIME("exerciseObservation.endTime")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder, Arguments, Output, Confirmation, ExecutionSession
- >(ACTION_SPEC) {
- fun setStartTimeProperty(startTime: Property<LocalTime>): CapabilityBuilder = setProperty(
- SlotMetadata.START_TIME.path,
- startTime,
- TypeConverters.LOCAL_TIME_ENTITY_CONVERTER
- )
-
- fun setEndTimeProperty(endTime: Property<LocalTime>): CapabilityBuilder = setProperty(
- SlotMetadata.END_TIME.path,
- endTime,
- TypeConverters.LOCAL_TIME_ENTITY_CONVERTER
- )
- }
-
- class Arguments internal constructor(
- val startTime: LocalTime?,
- val endTime: LocalTime?
- ) {
- override fun toString(): String {
- return "Arguments(startTime=$startTime, endTime=$endTime)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass !== other?.javaClass) return false
-
- other as Arguments
-
- if (startTime != other.startTime) return false
- if (endTime != other.endTime) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = startTime.hashCode()
- result += 31 * endTime.hashCode()
- return result
- }
-
- class Builder {
- private var startTime: LocalTime? = null
- private var endTime: LocalTime? = null
-
- fun setStartTime(startTime: LocalTime): Builder =
- apply { this.startTime = startTime }
-
- fun setEndTime(endTime: LocalTime): Builder =
- apply { this.endTime = endTime }
-
- fun build(): Arguments = Arguments(startTime, endTime)
- }
- }
-
- class Output internal constructor()
-
- class Confirmation internal constructor()
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
-
- companion object {
- /** Canonical name for [GetExerciseObservation] capability. */
- const val CAPABILITY_NAME = "actions.intent.GET_EXERCISE_OBSERVATION"
- // TODO(b/273602015): Update to use Name property from builtintype library.
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(
- Arguments::class.java,
- Arguments::Builder,
- Arguments.Builder::build
- )
- .setOutput(Output::class.java)
- .bindParameter(
- SlotMetadata.START_TIME.path,
- Arguments::startTime,
- Arguments.Builder::setStartTime,
- TypeConverters.LOCAL_TIME_PARAM_VALUE_CONVERTER
- )
- .bindParameter(
- SlotMetadata.END_TIME.path,
- Arguments::endTime,
- Arguments.Builder::setEndTime,
- TypeConverters.LOCAL_TIME_PARAM_VALUE_CONVERTER
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/GetHealthObservation.kt b/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/GetHealthObservation.kt
deleted file mode 100644
index dbbbe38..0000000
--- a/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/GetHealthObservation.kt
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.fitness.fitness
-
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import java.time.LocalTime
-
-/** A capability corresponding to actions.intent.GET_HEALTH_OBSERVATION */
-@CapabilityFactory(name = GetHealthObservation.CAPABILITY_NAME)
-class GetHealthObservation private constructor() {
-
- internal enum class SlotMetadata(val path: String) {
- START_TIME("healthObservation.startTime"),
- END_TIME("healthObservation.endTime")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession
- >(ACTION_SPEC) {
- fun setStartTimeProperty(startTime: Property<LocalTime>): CapabilityBuilder = setProperty(
- SlotMetadata.START_TIME.path,
- startTime,
- TypeConverters.LOCAL_TIME_ENTITY_CONVERTER
- )
-
- fun setEndTimeProperty(endTime: Property<LocalTime>): CapabilityBuilder = setProperty(
- SlotMetadata.END_TIME.path,
- endTime,
- TypeConverters.LOCAL_TIME_ENTITY_CONVERTER
- )
- }
-
- class Arguments internal constructor(
- val startTime: LocalTime?,
- val endTime: LocalTime?
- ) {
- override fun toString(): String {
- return "Arguments(startTime=$startTime, endTime=$endTime)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass !== other?.javaClass) return false
-
- other as Arguments
-
- if (startTime != other.startTime) return false
- if (endTime != other.endTime) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = startTime.hashCode()
- result += 31 * endTime.hashCode()
- return result
- }
-
- class Builder {
- private var startTime: LocalTime? = null
- private var endTime: LocalTime? = null
-
- fun setStartTime(startTime: LocalTime): Builder =
- apply { this.startTime = startTime }
-
- fun setEndTime(endTime: LocalTime): Builder =
- apply { this.endTime = endTime }
-
- fun build(): Arguments = Arguments(startTime, endTime)
- }
- }
-
- class Output internal constructor()
-
- class Confirmation internal constructor()
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
-
- companion object {
- /** Canonical name for [GetHealthObservation] capability */
- const val CAPABILITY_NAME = "actions.intent.GET_HEALTH_OBSERVATION"
- // TODO(b/273602015): Update to use Name property from builtintype library.
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(
- Arguments::class.java,
- Arguments::Builder,
- Arguments.Builder::build
- )
- .setOutput(Output::class.java)
- .bindParameter(
- SlotMetadata.START_TIME.path,
- Arguments::startTime,
- Arguments.Builder::setStartTime,
- TypeConverters.LOCAL_TIME_PARAM_VALUE_CONVERTER
- )
- .bindParameter(
- SlotMetadata.END_TIME.path,
- Arguments::endTime,
- Arguments.Builder::setEndTime,
- TypeConverters.LOCAL_TIME_PARAM_VALUE_CONVERTER
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/PauseExercise.kt b/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/PauseExercise.kt
deleted file mode 100644
index 62b7372..0000000
--- a/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/PauseExercise.kt
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.fitness.fitness
-
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.core.properties.StringValue
-
-/** A capability corresponding to actions.intent.PAUSE_EXERCISE */
-@CapabilityFactory(name = PauseExercise.CAPABILITY_NAME)
-class PauseExercise private constructor() {
- internal enum class SlotMetadata(val path: String) {
- NAME("exercise.name")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession
- >(ACTION_SPEC) {
- fun setNameProperty(name: Property<StringValue>): CapabilityBuilder = setProperty(
- SlotMetadata.NAME.path,
- name,
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
- }
-
- class Arguments internal constructor(
- val name: String?
- ) {
- override fun toString(): String {
- return "Arguments(name=$name)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass !== other?.javaClass) return false
-
- other as Arguments
-
- if (name != other.name) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- return name.hashCode()
- }
-
- class Builder {
- private var name: String? = null
-
- fun setName(name: String): Builder =
- apply { this.name = name }
-
- fun build(): Arguments = Arguments(name)
- }
- }
-
- class Output internal constructor()
-
- class Confirmation internal constructor()
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
-
- companion object {
- /** Canonical name for [PauseExercise] capability */
- const val CAPABILITY_NAME = "actions.intent.PAUSE_EXERCISE"
- // TODO(b/273602015): Update to use Name property from builtintype library.
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindParameter(
- SlotMetadata.NAME.path,
- Arguments::name,
- Arguments.Builder::setName,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/ResumeExercise.kt b/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/ResumeExercise.kt
deleted file mode 100644
index 3d028c5..0000000
--- a/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/ResumeExercise.kt
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.fitness.fitness
-
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.core.properties.StringValue
-
-/** A capability corresponding to actions.intent.RESUME_EXERCISE */
-@CapabilityFactory(name = ResumeExercise.CAPABILITY_NAME)
-class ResumeExercise private constructor() {
- internal enum class SlotMetadata(val path: String) {
- NAME("exercise.name")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession
- >(ACTION_SPEC) {
- fun setNameProperty(name: Property<StringValue>): CapabilityBuilder = setProperty(
- SlotMetadata.NAME.path,
- name,
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
- }
-
- class Arguments internal constructor(
- val name: String?
- ) {
- override fun toString(): String {
- return "Arguments(name=$name)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass !== other?.javaClass) return false
-
- other as Arguments
-
- if (name != other.name) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- return name.hashCode()
- }
-
- class Builder {
- private var name: String? = null
-
- fun setName(name: String): Builder =
- apply { this.name = name }
-
- fun build(): Arguments = Arguments(name)
- }
- }
-
- class Output internal constructor()
-
- class Confirmation internal constructor()
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
-
- companion object {
- /** Canonical name for [ResumeExercise] capability */
- const val CAPABILITY_NAME = "actions.intent.RESUME_EXERCISE"
- // TODO(b/273602015): Update to use Name property from builtintype library.
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindParameter(
- SlotMetadata.NAME.path,
- Arguments::name,
- Arguments.Builder::setName,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/StartExercise.kt b/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/StartExercise.kt
deleted file mode 100644
index 416af07..0000000
--- a/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/StartExercise.kt
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.fitness.fitness
-
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.core.properties.StringValue
-import java.time.Duration
-
-/** A capability corresponding to actions.intent.START_EXERCISE */
-@CapabilityFactory(name = StartExercise.CAPABILITY_NAME)
-class StartExercise private constructor() {
- internal enum class SlotMetadata(val path: String) {
- NAME("exercise.name"),
- DURATION("exercise.duration")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession
- >(ACTION_SPEC) {
- fun setNameProperty(name: Property<StringValue>): CapabilityBuilder = setProperty(
- SlotMetadata.NAME.path,
- name,
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
-
- fun setDurationProperty(duration: Property<Duration>): CapabilityBuilder = setProperty(
- SlotMetadata.DURATION.path,
- duration,
- TypeConverters.DURATION_ENTITY_CONVERTER
- )
- }
-
- class Arguments internal constructor(
- val duration: Duration?,
- val name: String?
- ) {
- override fun toString(): String {
- return "Arguments(duration=$duration, name=$name)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass !== other?.javaClass) return false
-
- other as Arguments
-
- if (duration != other.duration) return false
- if (name != other.name) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = duration.hashCode()
- result += 31 * name.hashCode()
- return result
- }
-
- class Builder {
- private var duration: Duration? = null
- private var name: String? = null
-
- fun setDuration(duration: Duration): Builder =
- apply { this.duration = duration }
-
- fun setName(name: String): Builder =
- apply { this.name = name }
-
- fun build(): Arguments = Arguments(duration, name)
- }
- }
-
- class Output internal constructor()
-
- class Confirmation internal constructor()
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
-
- companion object {
- /** Canonical name for [StartExercise] capability */
- const val CAPABILITY_NAME = "actions.intent.START_EXERCISE"
- // TODO(b/273602015): Update to use Name property from builtintype library.
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindParameter(
- SlotMetadata.DURATION.path,
- Arguments::duration,
- Arguments.Builder::setDuration,
- TypeConverters.DURATION_PARAM_VALUE_CONVERTER
- )
- .bindParameter(
- SlotMetadata.NAME.path,
- Arguments::name,
- Arguments.Builder::setName,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/StopExercise.kt b/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/StopExercise.kt
deleted file mode 100644
index 4568b3c..0000000
--- a/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/StopExercise.kt
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.fitness.fitness
-
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.core.properties.StringValue
-
-/** A capability corresponding to actions.intent.STOP_EXERCISE */
-@CapabilityFactory(name = StopExercise.CAPABILITY_NAME)
-class StopExercise private constructor() {
- internal enum class SlotMetadata(val path: String) {
- NAME("exercise.name")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession
- >(ACTION_SPEC) {
- fun setNameProperty(name: Property<StringValue>): CapabilityBuilder = setProperty(
- SlotMetadata.NAME.path,
- name,
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
- }
-
- class Arguments internal constructor(
- val name: String?
- ) {
- override fun toString(): String {
- return "Arguments(name=$name)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass !== other?.javaClass) return false
-
- other as Arguments
-
- if (name != other.name) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- return name.hashCode()
- }
-
- class Builder {
- private var name: String? = null
-
- fun setName(name: String): Builder =
- apply { this.name = name }
-
- fun build(): Arguments = Arguments(name)
- }
- }
-
- class Output internal constructor()
-
- class Confirmation internal constructor()
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
-
- companion object {
- /** Canonical name for [StopExercise] capability */
- const val CAPABILITY_NAME = "actions.intent.STOP_EXERCISE"
- // TODO(b/273602015): Update to use Name property from builtintype library.
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindParameter(
- SlotMetadata.NAME.path,
- Arguments::name,
- Arguments.Builder::setName,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/package-info.java b/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/package-info.java
deleted file mode 100644
index f90ac95..0000000
--- a/appactions/interaction/interaction-capabilities-fitness/src/main/java/androidx/appactions/interaction/capabilities/fitness/fitness/package-info.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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.
- */
-
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-package androidx.appactions.interaction.capabilities.fitness.fitness;
-
-import androidx.annotation.RestrictTo;
-
diff --git a/appactions/interaction/interaction-capabilities-productivity/api/current.txt b/appactions/interaction/interaction-capabilities-productivity/api/current.txt
deleted file mode 100644
index e6f50d0..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/api/current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 4.0
diff --git a/appactions/interaction/interaction-capabilities-productivity/api/res-current.txt b/appactions/interaction/interaction-capabilities-productivity/api/res-current.txt
deleted file mode 100644
index e69de29..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/api/res-current.txt
+++ /dev/null
diff --git a/appactions/interaction/interaction-capabilities-productivity/api/restricted_current.txt b/appactions/interaction/interaction-capabilities-productivity/api/restricted_current.txt
deleted file mode 100644
index e6f50d0..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/api/restricted_current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 4.0
diff --git a/appactions/interaction/interaction-capabilities-productivity/build.gradle b/appactions/interaction/interaction-capabilities-productivity/build.gradle
deleted file mode 100644
index 3f83e65..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/build.gradle
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-/**
- * This file was created using the `create_project.py` script located in the
- * `<AndroidX root>/development/project-creator` directory.
- *
- * Please use that script when creating a new project, rather than copying an existing project and
- * modifying its settings.
- */
-import androidx.build.LibraryType
-
-plugins {
- id("AndroidXPlugin")
- id("com.android.library")
- id("org.jetbrains.kotlin.android")
-}
-
-dependencies {
- api(libs.kotlinStdlib)
- implementation("androidx.annotation:annotation:1.1.0")
- implementation(project(":appactions:interaction:interaction-capabilities-core"))
-
- testImplementation(project(":appactions:interaction:interaction-capabilities-testing"))
- testImplementation(libs.kotlinCoroutinesCore)
- testImplementation(libs.junit)
- testImplementation(libs.truth)
-}
-
-android {
- namespace "androidx.appactions.interaction.capabilities.productivity"
- defaultConfig {
- minSdkVersion 26
- }
-}
-
-androidx {
- name = "androidx.appactions.interaction:interaction-capabilities-productivity"
- type = LibraryType.PUBLISHED_LIBRARY
- inceptionYear = "2023"
- description = "Capabiility APIs for Productivy vertical."
- metalavaK2UastEnabled = true
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/AlarmReference.kt b/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/AlarmReference.kt
deleted file mode 100644
index 6231c59..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/AlarmReference.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import androidx.appactions.builtintypes.types.Alarm
-import androidx.appactions.interaction.capabilities.core.SearchAction
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-import androidx.appactions.interaction.capabilities.serializers.types.ALARM_TYPE_SPEC
-import java.util.Objects
-
-class AlarmReference private constructor(
- val asAlarm: Alarm?,
- val asSearchAction: SearchAction<Alarm>?
-) {
- constructor(alarm: Alarm) : this(alarm, null)
-
- // TODO(b/268071906) add AlarmFilter type to SearchAction
- constructor(alarmFilter: SearchAction<Alarm>) : this(null, alarmFilter)
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as AlarmReference
-
- return asAlarm == other.asAlarm && asSearchAction == other.asSearchAction
- }
-
- override fun hashCode(): Int {
- return Objects.hash(asAlarm, asSearchAction)
- }
-
- companion object {
- private val TYPE_SPEC =
- UnionTypeSpec.Builder<AlarmReference>()
- .bindMemberType(
- memberGetter = AlarmReference::asAlarm,
- ctor = { AlarmReference(it) },
- typeSpec = ALARM_TYPE_SPEC,
- )
- .bindMemberType(
- memberGetter = AlarmReference::asSearchAction,
- ctor = { AlarmReference(it) },
- typeSpec =
- TypeConverters.createSearchActionTypeSpec(
- ALARM_TYPE_SPEC
- ),
- )
- .build()
- internal val PARAM_VALUE_CONVERTER = ParamValueConverter.of(TYPE_SPEC)
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/CreateAlarm.kt b/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/CreateAlarm.kt
deleted file mode 100644
index 61e677f..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/CreateAlarm.kt
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import androidx.appactions.builtintypes.types.Alarm
-import androidx.appactions.builtintypes.types.GenericErrorStatus
-import androidx.appactions.builtintypes.types.ObjectCreationLimitReachedStatus
-import androidx.appactions.builtintypes.types.Schedule
-import androidx.appactions.builtintypes.types.SuccessStatus
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.core.properties.StringValue
-import androidx.appactions.interaction.capabilities.serializers.types.ALARM_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.GENERIC_ERROR_STATUS_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.OBJECT_CREATION_LIMIT_REACHED_STATUS_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.SCHEDULE_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.SUCCESS_STATUS_TYPE_SPEC
-
-/** A capability corresponding to actions.intent.CREATE_ALARM */
-@CapabilityFactory(name = CreateAlarm.CAPABILITY_NAME)
-class CreateAlarm private constructor() {
- internal enum class SlotMetadata(val path: String) {
- SCHEDULE("alarm.alarmSchedule"),
- NAME("alarm.name"),
- IDENTIFIER("alarm.identifier")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession
- >(ACTION_SPEC) {
- fun setIdentifierProperty(
- identifier: Property<StringValue>
- ): CapabilityBuilder = setProperty(
- SlotMetadata.IDENTIFIER.path,
- identifier,
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
-
- fun setNameProperty(name: Property<StringValue>): CapabilityBuilder = setProperty(
- SlotMetadata.NAME.path,
- name,
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
-
- fun setScheduleProperty(
- alarmSchedule: Property<Schedule>
- ): CapabilityBuilder = setProperty(
- SlotMetadata.SCHEDULE.path,
- alarmSchedule,
- EntityConverter.of(SCHEDULE_TYPE_SPEC)
- )
- }
-
- class Arguments internal constructor(
- val identifier: String?,
- val name: String?,
- val schedule: Schedule?
- ) {
- override fun toString(): String {
- return "Arguments(identifier=$identifier,name=$name,schedule=$schedule)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Arguments
-
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (schedule != other.schedule) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = identifier.hashCode()
- result += 31 * name.hashCode()
- result += 31 * schedule.hashCode()
- return result
- }
-
- class Builder {
- private var identifier: String? = null
- private var name: String? = null
- private var schedule: Schedule? = null
-
- fun setIdentifier(identifier: String): Builder = apply { this.identifier = identifier }
-
- fun setName(name: String): Builder = apply { this.name = name }
-
- fun setSchedule(schedule: Schedule): Builder = apply { this.schedule = schedule }
-
- fun build(): Arguments = Arguments(identifier, name, schedule)
- }
- }
-
- class Output internal constructor(val alarm: Alarm?, val executionStatus: ExecutionStatus?) {
- override fun toString(): String {
- return "Output(alarm=$alarm,executionStatus=$executionStatus)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Output
-
- if (alarm != other.alarm) return false
- if (executionStatus != other.executionStatus) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = alarm.hashCode()
- result += 31 * executionStatus.hashCode()
- return result
- }
-
- class Builder {
- private var alarm: Alarm? = null
- private var executionStatus: ExecutionStatus? = null
-
- fun setAlarm(alarm: Alarm): Builder = apply { this.alarm = alarm }
-
- fun setExecutionStatus(executionStatus: ExecutionStatus) = apply {
- this.executionStatus = executionStatus
- }
-
- fun setExecutionStatus(successStatus: SuccessStatus) = apply {
- this.setExecutionStatus(ExecutionStatus(successStatus))
- }
-
- fun setExecutionStatus(genericErrorStatus: GenericErrorStatus) = apply {
- this.setExecutionStatus(ExecutionStatus(genericErrorStatus))
- }
-
- fun setExecutionStatus(
- objectCreationLimitReachedStatus: ObjectCreationLimitReachedStatus
- ) = apply {
- this.setExecutionStatus(ExecutionStatus(objectCreationLimitReachedStatus))
- }
-
- fun build(): Output = Output(alarm, executionStatus)
- }
- }
-
- class ExecutionStatus {
- private var successStatus: SuccessStatus? = null
- private var genericErrorStatus: GenericErrorStatus? = null
- private var objectCreationLimitReachedStatus: ObjectCreationLimitReachedStatus? = null
-
- constructor(successStatus: SuccessStatus) {
- this.successStatus = successStatus
- }
-
- constructor(genericErrorStatus: GenericErrorStatus) {
- this.genericErrorStatus = genericErrorStatus
- }
-
- constructor(objectCreationLimitReachedStatus: ObjectCreationLimitReachedStatus) {
- this.objectCreationLimitReachedStatus = objectCreationLimitReachedStatus
- }
-
- companion object {
- private val TYPE_SPEC = UnionTypeSpec.Builder<ExecutionStatus>()
- .bindMemberType(
- memberGetter = ExecutionStatus::successStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = SUCCESS_STATUS_TYPE_SPEC
- ).bindMemberType(
- memberGetter = ExecutionStatus::genericErrorStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = GENERIC_ERROR_STATUS_TYPE_SPEC
- ).bindMemberType(
- memberGetter = ExecutionStatus::objectCreationLimitReachedStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = OBJECT_CREATION_LIMIT_REACHED_STATUS_TYPE_SPEC
- ).build()
- internal val PARAM_VALUE_CONVERTER = ParamValueConverter.of(TYPE_SPEC)
- }
- }
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
- class Confirmation internal constructor()
-
- companion object {
- /** Canonical name for [CreateAlarm] capability */
- const val CAPABILITY_NAME = "actions.intent.CREATE_ALARM"
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindParameter(
- SlotMetadata.IDENTIFIER.path,
- Arguments::identifier,
- Arguments.Builder::setIdentifier,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .bindParameter(
- SlotMetadata.NAME.path,
- Arguments::name,
- Arguments.Builder::setName,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .bindParameter(
- SlotMetadata.SCHEDULE.path,
- Arguments::schedule,
- Arguments.Builder::setSchedule,
- ParamValueConverter.of(SCHEDULE_TYPE_SPEC)
- )
- .bindOutput(
- "alarm",
- Output::alarm,
- ParamValueConverter.of(ALARM_TYPE_SPEC)
- )
- .bindOutput(
- "executionStatus",
- Output::executionStatus,
- ExecutionStatus.PARAM_VALUE_CONVERTER
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/DismissAlarm.kt b/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/DismissAlarm.kt
deleted file mode 100644
index 73d5d69..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/DismissAlarm.kt
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import androidx.appactions.builtintypes.types.Alarm
-import androidx.appactions.builtintypes.types.GenericErrorStatus
-import androidx.appactions.builtintypes.types.SuccessStatus
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.serializers.types.ALARM_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.GENERIC_ERROR_STATUS_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.SUCCESS_STATUS_TYPE_SPEC
-
-/** A capability corresponding to actions.intent.DISMISS_ALARM */
-@CapabilityFactory(name = DismissAlarm.CAPABILITY_NAME)
-class DismissAlarm private constructor() {
- internal enum class SlotMetadata(val path: String) {
- ALARM("alarm")
- }
-
- class CapabilityBuilder : Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession
- >(ACTION_SPEC) {
- fun setAlarmProperty(alarm: Property<Alarm>): CapabilityBuilder = setProperty(
- SlotMetadata.ALARM.path,
- alarm,
- EntityConverter.of(ALARM_TYPE_SPEC)
- )
- }
-
- class Arguments internal constructor(val alarm: AlarmReference?) {
- override fun toString(): String {
- return "Arguments(alarm=$alarm)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Arguments
-
- if (alarm != other.alarm) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- return alarm.hashCode()
- }
-
- class Builder {
- private var alarm: AlarmReference? = null
-
- fun setAlarm(alarm: AlarmReference): Builder = apply { this.alarm = alarm }
-
- fun build(): Arguments = Arguments(alarm)
- }
- }
- class Output internal constructor(val executionStatus: ExecutionStatus?) {
- override fun toString(): String {
- return "Output(executionStatus=$executionStatus)"
- }
-
- override fun hashCode(): Int {
- return executionStatus.hashCode()
- }
-
- class Builder {
- private var executionStatus: ExecutionStatus? = null
-
- fun setExecutionStatus(executionStatus: ExecutionStatus): Builder = apply {
- this.executionStatus = executionStatus
- }
-
- fun setExecutionStatus(successStatus: SuccessStatus) = apply {
- this.setExecutionStatus(ExecutionStatus(successStatus))
- }
-
- fun setExecutionStatus(genericErrorStatus: GenericErrorStatus) = apply {
- this.setExecutionStatus(ExecutionStatus(genericErrorStatus))
- }
-
- fun build(): Output = Output(executionStatus)
- }
- }
-
- class ExecutionStatus {
- private var successStatus: SuccessStatus? = null
- private var genericErrorStatus: GenericErrorStatus? = null
-
- constructor(successStatus: SuccessStatus) {
- this.successStatus = successStatus
- }
-
- constructor(genericErrorStatus: GenericErrorStatus) {
- this.genericErrorStatus = genericErrorStatus
- }
-
- companion object {
- private val TYPE_SPEC = UnionTypeSpec.Builder<ExecutionStatus>()
- .bindMemberType(
- memberGetter = ExecutionStatus::successStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = SUCCESS_STATUS_TYPE_SPEC
- ).bindMemberType(
- memberGetter = ExecutionStatus::genericErrorStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = GENERIC_ERROR_STATUS_TYPE_SPEC
- ).build()
- internal val PARAM_VALUE_CONVERTER = ParamValueConverter.of(TYPE_SPEC)
- }
- }
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
- class Confirmation internal constructor()
-
- companion object {
- /** Canonical name for [DismissAlarm] capability */
- const val CAPABILITY_NAME = "actions.intent.DISMISS_ALARM"
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindParameter(
- SlotMetadata.ALARM.path,
- Arguments::alarm,
- Arguments.Builder::setAlarm,
- AlarmReference.PARAM_VALUE_CONVERTER
- )
- .bindOutput(
- "executionStatus",
- Output::executionStatus,
- ExecutionStatus.PARAM_VALUE_CONVERTER
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/GetAlarm.kt b/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/GetAlarm.kt
deleted file mode 100644
index 42474ba..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/GetAlarm.kt
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import androidx.appactions.builtintypes.types.Alarm
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.serializers.types.ALARM_TYPE_SPEC
-
-@CapabilityFactory(name = GetAlarm.CAPABILITY_NAME)
-class GetAlarm private constructor() {
- internal enum class SlotMetadata(val path: String) {
- ALARM("alarm")
- }
-
- class CapabilityBuilder : Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession
- >(ACTION_SPEC) {
- fun setAlarmProperty(alarm: Property<Alarm>) = setProperty(
- SlotMetadata.ALARM.path,
- alarm,
- EntityConverter.of(ALARM_TYPE_SPEC)
- )
- }
-
- class Arguments internal constructor(
- val alarm: AlarmReference?
- ) {
- override fun toString(): String {
- return "Arguments(alarm=$alarm)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Arguments
-
- if (alarm != other.alarm) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- return alarm.hashCode()
- }
-
- class Builder {
- private var alarm: AlarmReference? = null
-
- fun setAlarm(alarm: AlarmReference): Builder = apply { this.alarm = alarm }
-
- fun build(): Arguments = Arguments(alarm)
- }
- }
-
- class Output internal constructor()
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
- class Confirmation internal constructor()
-
- companion object {
- /** Canonical name for [GetAlarm] capability */
- const val CAPABILITY_NAME = "actions.intent.GET_ALARM"
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindParameter(
- SlotMetadata.ALARM.path,
- Arguments::alarm,
- Arguments.Builder::setAlarm,
- AlarmReference.PARAM_VALUE_CONVERTER
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/PauseTimer.kt b/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/PauseTimer.kt
deleted file mode 100644
index dc79ff55..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/PauseTimer.kt
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * 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,
-b * 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.appactions.interaction.capabilities.productivity
-
-import androidx.appactions.builtintypes.types.GenericErrorStatus
-import androidx.appactions.builtintypes.types.SuccessStatus
-import androidx.appactions.builtintypes.types.Timer
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.serializers.types.GENERIC_ERROR_STATUS_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.SUCCESS_STATUS_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.TIMER_TYPE_SPEC
-
-/** A capability corresponding to actions.intent.PAUSE_TIMER */
-@CapabilityFactory(name = PauseTimer.CAPABILITY_NAME)
-class PauseTimer private constructor() {
- internal enum class SlotMetadata(val path: String) {
- TIMER("timer")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession
- >(ACTION_SPEC) {
- fun setTimerProperty(timer: Property<Timer>): CapabilityBuilder = setProperty(
- SlotMetadata.TIMER.path,
- timer,
- EntityConverter.of(TIMER_TYPE_SPEC)
- )
- }
-
- class Arguments
- internal constructor(
- val timerList: List<TimerReference>
- ) {
- override fun toString(): String {
- return "Arguments(timerList=$timerList)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Arguments
-
- if (timerList != other.timerList) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- return timerList.hashCode()
- }
-
- class Builder {
- private var timerList: List<TimerReference> = emptyList()
-
- fun setTimerList(timerList: List<TimerReference>): Builder = apply {
- this.timerList = timerList
- }
-
- fun build(): Arguments = Arguments(timerList)
- }
- }
-
- class Output internal constructor(val executionStatus: ExecutionStatus?) {
- override fun toString(): String {
- return "Output(executionStatus=$executionStatus)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Output
-
- if (executionStatus != other.executionStatus) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- return executionStatus.hashCode()
- }
-
- class Builder {
- private var executionStatus: ExecutionStatus? = null
-
- fun setExecutionStatus(successStatus: SuccessStatus) = setExecutionStatus(
- ExecutionStatus(successStatus)
- )
-
- fun setExecutionStatus(genericErrorStatus: GenericErrorStatus) = setExecutionStatus(
- ExecutionStatus(genericErrorStatus)
- )
-
- fun setExecutionStatus(executionStatus: ExecutionStatus): Builder = apply {
- this.executionStatus = executionStatus
- }
-
- fun build(): Output = Output(executionStatus)
- }
- }
-
- class ExecutionStatus {
- private var successStatus: SuccessStatus? = null
- private var genericErrorStatus: GenericErrorStatus? = null
-
- constructor(successStatus: SuccessStatus) {
- this.successStatus = successStatus
- }
-
- constructor(genericErrorStatus: GenericErrorStatus) {
- this.genericErrorStatus = genericErrorStatus
- }
-
- companion object {
- private val TYPE_SPEC = UnionTypeSpec.Builder<ExecutionStatus>()
- .bindMemberType(
- memberGetter = ExecutionStatus::successStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = SUCCESS_STATUS_TYPE_SPEC
- ).bindMemberType(
- memberGetter = ExecutionStatus::genericErrorStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = GENERIC_ERROR_STATUS_TYPE_SPEC
- ).build()
- internal val PARAM_VALUE_CONVERTER = ParamValueConverter.of(TYPE_SPEC)
- }
- }
-
- class Confirmation internal constructor()
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
-
- companion object {
- /** Canonical name for [PauseTimer] capability */
- const val CAPABILITY_NAME = "actions.intent.PAUSE_TIMER"
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindRepeatedParameter(
- SlotMetadata.TIMER.path,
- Arguments::timerList,
- Arguments.Builder::setTimerList,
- TimerReference.PARAM_VALUE_CONVERTER
- )
- .bindOutput(
- "executionStatus",
- Output::executionStatus,
- ExecutionStatus.PARAM_VALUE_CONVERTER
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/ResetTimer.kt b/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/ResetTimer.kt
deleted file mode 100644
index dba0167..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/ResetTimer.kt
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import androidx.appactions.builtintypes.types.GenericErrorStatus
-import androidx.appactions.builtintypes.types.SuccessStatus
-import androidx.appactions.builtintypes.types.Timer
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.serializers.types.GENERIC_ERROR_STATUS_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.SUCCESS_STATUS_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.TIMER_TYPE_SPEC
-
-/** A capability corresponding to actions.intent.RESET_TIMER */
-@CapabilityFactory(name = ResetTimer.CAPABILITY_NAME)
-class ResetTimer private constructor() {
- internal enum class SlotMetadata(val path: String) {
- TIMER("timer")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession
- >(ACTION_SPEC) {
- fun setTimerProperty(timer: Property<Timer>): CapabilityBuilder = setProperty(
- SlotMetadata.TIMER.path,
- timer,
- EntityConverter.of(TIMER_TYPE_SPEC)
- )
- }
-
- class Arguments internal constructor(val timerList: List<TimerReference>) {
- override fun toString(): String {
- return "Arguments(timerList=$timerList)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Arguments
-
- if (timerList != other.timerList) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- return timerList.hashCode()
- }
-
- class Builder {
- private var timerList: List<TimerReference> = emptyList()
-
- fun setTimerList(
- timerList: List<TimerReference>
- ): Builder = apply { this.timerList = timerList }
-
- fun build(): Arguments = Arguments(timerList)
- }
- }
-
- class Output internal constructor(val executionStatus: ExecutionStatus?) {
- override fun toString(): String {
- return "Output(executionStatus=$executionStatus)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Output
-
- if (executionStatus != other.executionStatus) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- return executionStatus.hashCode()
- }
-
- class Builder {
- private var executionStatus: ExecutionStatus? = null
-
- fun setExecutionStatus(successStatus: SuccessStatus) = setExecutionStatus(
- ExecutionStatus(successStatus)
- )
-
- fun setExecutionStatus(genericErrorStatus: GenericErrorStatus) = setExecutionStatus(
- ExecutionStatus(genericErrorStatus)
- )
-
- fun setExecutionStatus(executionStatus: ExecutionStatus): Builder = apply {
- this.executionStatus = executionStatus
- }
-
- fun build(): Output = Output(executionStatus)
- }
- }
-
- class ExecutionStatus {
- private var successStatus: SuccessStatus? = null
- private var genericErrorStatus: GenericErrorStatus? = null
-
- constructor(successStatus: SuccessStatus) {
- this.successStatus = successStatus
- }
-
- constructor(genericErrorStatus: GenericErrorStatus) {
- this.genericErrorStatus = genericErrorStatus
- }
-
- companion object {
- private val TYPE_SPEC = UnionTypeSpec.Builder<ExecutionStatus>()
- .bindMemberType(
- memberGetter = ExecutionStatus::successStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = SUCCESS_STATUS_TYPE_SPEC
- ).bindMemberType(
- memberGetter = ExecutionStatus::genericErrorStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = GENERIC_ERROR_STATUS_TYPE_SPEC
- ).build()
- internal val PARAM_VALUE_CONVERTER = ParamValueConverter.of(TYPE_SPEC)
- }
- }
-
- class Confirmation internal constructor()
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
-
- companion object {
- /** Canonical name for [ResetTimer] capability */
- const val CAPABILITY_NAME = "actions.intent.RESET_TIMER"
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindRepeatedParameter(
- SlotMetadata.TIMER.path,
- Arguments::timerList,
- Arguments.Builder::setTimerList,
- TimerReference.PARAM_VALUE_CONVERTER
- )
- .bindOutput(
- "executionStatus",
- Output::executionStatus,
- ExecutionStatus.PARAM_VALUE_CONVERTER
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/ResumeTimer.kt b/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/ResumeTimer.kt
deleted file mode 100644
index c80f509..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/ResumeTimer.kt
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import androidx.appactions.builtintypes.types.GenericErrorStatus
-import androidx.appactions.builtintypes.types.SuccessStatus
-import androidx.appactions.builtintypes.types.Timer
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.serializers.types.GENERIC_ERROR_STATUS_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.SUCCESS_STATUS_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.TIMER_TYPE_SPEC
-
-/** A capability corresponding to actions.intent.RESUME_TIMER */
-@CapabilityFactory(name = ResumeTimer.CAPABILITY_NAME)
-class ResumeTimer private constructor() {
- internal enum class SlotMetadata(val path: String) {
- TIMER("timer")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession
- >(ACTION_SPEC) {
- fun setTimerProperty(timer: Property<Timer>): CapabilityBuilder = setProperty(
- SlotMetadata.TIMER.path,
- timer,
- EntityConverter.of(TIMER_TYPE_SPEC)
- )
- }
-
- class Arguments internal constructor(val timerList: List<TimerReference>) {
- override fun toString(): String {
- return "Arguments(timerList=$timerList)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Arguments
-
- if (timerList != other.timerList) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- return timerList.hashCode()
- }
-
- class Builder {
- private var timerList: List<TimerReference> = emptyList()
-
- fun setTimerList(
- timerList: List<TimerReference>
- ): Builder = apply { this.timerList = timerList }
-
- fun build(): Arguments = Arguments(timerList)
- }
- }
-
- class Output internal constructor(val executionStatus: ExecutionStatus?) {
- override fun toString(): String {
- return "Output(executionStatus=$executionStatus)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Output
-
- if (executionStatus != other.executionStatus) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- return executionStatus.hashCode()
- }
-
- class Builder {
- private var executionStatus: ExecutionStatus? = null
-
- fun setExecutionStatus(successStatus: SuccessStatus) = setExecutionStatus(
- ExecutionStatus(successStatus)
- )
-
- fun setExecutionStatus(genericErrorStatus: GenericErrorStatus) = setExecutionStatus(
- ExecutionStatus(genericErrorStatus)
- )
-
- fun setExecutionStatus(executionStatus: ExecutionStatus): Builder = apply {
- this.executionStatus = executionStatus
- }
-
- fun build(): Output = Output(executionStatus)
- }
- }
-
- class ExecutionStatus {
- private var successStatus: SuccessStatus? = null
- private var genericErrorStatus: GenericErrorStatus? = null
-
- constructor(successStatus: SuccessStatus) {
- this.successStatus = successStatus
- }
-
- constructor(genericErrorStatus: GenericErrorStatus) {
- this.genericErrorStatus = genericErrorStatus
- }
-
- companion object {
- private val TYPE_SPEC = UnionTypeSpec.Builder<ExecutionStatus>()
- .bindMemberType(
- memberGetter = ExecutionStatus::successStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = SUCCESS_STATUS_TYPE_SPEC
- ).bindMemberType(
- memberGetter = ExecutionStatus::genericErrorStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = GENERIC_ERROR_STATUS_TYPE_SPEC
- ).build()
- internal val PARAM_VALUE_CONVERTER = ParamValueConverter.of(TYPE_SPEC)
- }
- }
-
- class Confirmation internal constructor()
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
-
- companion object {
- /** Canonical name for [ResumeTimer] capability */
- const val CAPABILITY_NAME = "actions.intent.RESUME_TIMER"
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindRepeatedParameter(
- SlotMetadata.TIMER.path,
- Arguments::timerList,
- Arguments.Builder::setTimerList,
- TimerReference.PARAM_VALUE_CONVERTER
- )
- .bindOutput(
- "executionStatus",
- Output::executionStatus,
- ExecutionStatus.PARAM_VALUE_CONVERTER
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/SnoozeAlarm.kt b/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/SnoozeAlarm.kt
deleted file mode 100644
index 7f8fb62..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/SnoozeAlarm.kt
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import androidx.appactions.builtintypes.types.Alarm
-import androidx.appactions.builtintypes.types.GenericErrorStatus
-import androidx.appactions.builtintypes.types.SuccessStatus
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.serializers.types.ALARM_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.GENERIC_ERROR_STATUS_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.SUCCESS_STATUS_TYPE_SPEC
-import java.time.Duration
-
-/** A capability corresponding to actions.intent.SNOOZE_ALARM */
-@CapabilityFactory(name = SnoozeAlarm.CAPABILITY_NAME)
-class SnoozeAlarm private constructor() {
- internal enum class SlotMetadata(val path: String) {
- DURATION("snoozeDuration"),
- ALARM("alarm")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession
- >(ACTION_SPEC) {
- fun setSnoozeDurationProperty(duration: Property<Duration>):
- CapabilityBuilder = setProperty(
- SlotMetadata.DURATION.path,
- duration,
- TypeConverters.DURATION_ENTITY_CONVERTER
- )
- fun setTargetAlarmProperty(alarm: Property<Alarm>):
- CapabilityBuilder = setProperty(
- SlotMetadata.ALARM.path,
- alarm,
- EntityConverter.of(ALARM_TYPE_SPEC)
- )
- }
-
- class Arguments
- internal constructor(val snoozeDuration: Duration?, val targetAlarm: AlarmReference?) {
- override fun toString(): String {
- return "Arguments(snoozeDuration=$snoozeDuration,targetAlarm=$targetAlarm)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Arguments
-
- if (snoozeDuration != other.snoozeDuration) return false
- if (targetAlarm != other.targetAlarm) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = snoozeDuration.hashCode()
- result += 31 * targetAlarm.hashCode()
- return result
- }
-
- class Builder {
- private var snoozeDuration: Duration? = null
- private var targetAlarm: AlarmReference? = null
-
- fun setSnoozeDuration(snoozeDuration: Duration): Builder = apply {
- this.snoozeDuration = snoozeDuration
- }
-
- fun setTargetAlarm(targetAlarm: AlarmReference): Builder = apply {
- this.targetAlarm = targetAlarm
- }
-
- fun build(): Arguments = Arguments(snoozeDuration, targetAlarm)
- }
- }
-
- class Output internal constructor(val executionStatus: ExecutionStatus?) {
- override fun toString(): String {
- return "Output(executionStatus=$executionStatus)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Output
-
- if (executionStatus != other.executionStatus) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- return executionStatus.hashCode()
- }
-
- class Builder {
- private var executionStatus: ExecutionStatus? = null
-
- fun setExecutionStatus(executionStatus: ExecutionStatus): Builder = apply {
- this.executionStatus = executionStatus
- }
-
- fun setExecutionStatus(successStatus: SuccessStatus) = apply {
- this.setExecutionStatus(ExecutionStatus(successStatus))
- }
-
- fun setExecutionStatus(genericErrorStatus: GenericErrorStatus) = apply {
- this.setExecutionStatus(ExecutionStatus(genericErrorStatus))
- }
-
- fun build(): Output = Output(executionStatus)
- }
- }
-
- class ExecutionStatus {
- private var successStatus: SuccessStatus? = null
- private var genericErrorStatus: GenericErrorStatus? = null
-
- constructor(successStatus: SuccessStatus) {
- this.successStatus = successStatus
- }
-
- constructor(genericErrorStatus: GenericErrorStatus) {
- this.genericErrorStatus = genericErrorStatus
- }
-
- companion object {
- private val TYPE_SPEC = UnionTypeSpec.Builder<ExecutionStatus>()
- .bindMemberType(
- memberGetter = ExecutionStatus::successStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = SUCCESS_STATUS_TYPE_SPEC
- ).bindMemberType(
- memberGetter = ExecutionStatus::genericErrorStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = GENERIC_ERROR_STATUS_TYPE_SPEC
- ).build()
- internal val PARAM_VALUE_CONVERTER = ParamValueConverter.of(TYPE_SPEC)
- }
- }
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
- class Confirmation internal constructor()
-
- companion object {
- /** Canonical name for [SnoozeAlarm] capability */
- const val CAPABILITY_NAME = "actions.intent.SNOOZE_ALARM"
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java,
- Arguments::Builder,
- Arguments.Builder::build
- )
- .setOutput(Output::class.java)
- .bindParameter(
- SlotMetadata.DURATION.path,
- Arguments::snoozeDuration,
- Arguments.Builder::setSnoozeDuration,
- TypeConverters.DURATION_PARAM_VALUE_CONVERTER
- )
- .bindParameter(
- SlotMetadata.ALARM.path,
- Arguments::targetAlarm,
- Arguments.Builder::setTargetAlarm,
- AlarmReference.PARAM_VALUE_CONVERTER
- )
- .bindOutput(
- "executionStatus",
- Output::executionStatus,
- ExecutionStatus.PARAM_VALUE_CONVERTER
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/StartTimer.kt b/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/StartTimer.kt
deleted file mode 100644
index 5812afd..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/StartTimer.kt
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import androidx.appactions.builtintypes.types.GenericErrorStatus
-import androidx.appactions.builtintypes.types.SuccessStatus
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.core.properties.StringValue
-import androidx.appactions.interaction.capabilities.serializers.types.GENERIC_ERROR_STATUS_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.SUCCESS_STATUS_TYPE_SPEC
-import java.time.Duration
-
-/** A capability corresponding to actions.intent.START_TIMER */
-@CapabilityFactory(name = StartTimer.CAPABILITY_NAME)
-class StartTimer private constructor() {
- internal enum class SlotMetadata(val path: String) {
- IDENTIFIER("timer.identifier"),
- NAME("timer.name"),
- DURATION("timer.duration")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession
- >(ACTION_SPEC) {
- fun setIdentifierProperty(
- identifier: Property<StringValue>
- ): CapabilityBuilder = setProperty(
- SlotMetadata.IDENTIFIER.path,
- identifier,
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
-
- fun setNameProperty(name: Property<StringValue>): CapabilityBuilder = setProperty(
- SlotMetadata.NAME.path,
- name,
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
-
- fun setDurationProperty(duration: Property<Duration>): CapabilityBuilder = setProperty(
- SlotMetadata.DURATION.path,
- duration,
- TypeConverters.DURATION_ENTITY_CONVERTER
- )
- }
-
- class Arguments internal constructor(
- val identifier: String?,
- val name: String?,
- val duration: Duration?
- ) {
- override fun toString(): String {
- return "Arguments(identifier=$identifier,name=$name,duration=$duration)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Arguments
-
- if (identifier != other.identifier) return false
- if (name != other.name) return false
- if (duration != other.duration) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = identifier.hashCode()
- result += 31 * name.hashCode()
- result += 31 * duration.hashCode()
- return result
- }
-
- class Builder {
- private var identifier: String? = null
- private var name: String? = null
- private var duration: Duration? = null
-
- fun setIdentifier(identifier: String): Builder = apply { this.identifier = identifier }
-
- fun setName(name: String): Builder = apply { this.name = name }
-
- fun setDuration(duration: Duration): Builder = apply { this.duration = duration }
-
- fun build(): Arguments = Arguments(identifier, name, duration)
- }
- }
- class Output internal constructor(val executionStatus: ExecutionStatus?) {
- override fun toString(): String {
- return "Output(executionStatus=$executionStatus)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Output
-
- if (executionStatus != other.executionStatus) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- return executionStatus.hashCode()
- }
-
- class Builder {
- private var executionStatus: ExecutionStatus? = null
-
- fun setExecutionStatus(successStatus: SuccessStatus) = setExecutionStatus(
- ExecutionStatus(successStatus)
- )
-
- fun setExecutionStatus(genericErrorStatus: GenericErrorStatus) = setExecutionStatus(
- ExecutionStatus(genericErrorStatus)
- )
-
- fun setExecutionStatus(executionStatus: ExecutionStatus): Builder = apply {
- this.executionStatus = executionStatus
- }
-
- fun build(): Output = Output(executionStatus)
- }
- }
-
- class ExecutionStatus {
- private var successStatus: SuccessStatus? = null
- private var genericErrorStatus: GenericErrorStatus? = null
-
- constructor(successStatus: SuccessStatus) {
- this.successStatus = successStatus
- }
-
- constructor(genericErrorStatus: GenericErrorStatus) {
- this.genericErrorStatus = genericErrorStatus
- }
-
- companion object {
- private val TYPE_SPEC = UnionTypeSpec.Builder<ExecutionStatus>()
- .bindMemberType(
- memberGetter = ExecutionStatus::successStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = SUCCESS_STATUS_TYPE_SPEC
- ).bindMemberType(
- memberGetter = ExecutionStatus::genericErrorStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = GENERIC_ERROR_STATUS_TYPE_SPEC
- ).build()
- internal val PARAM_VALUE_CONVERTER = ParamValueConverter.of(TYPE_SPEC)
- }
- }
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
- class Confirmation internal constructor()
-
- companion object {
- /** Canonical name for [StartTimer] capability */
- const val CAPABILITY_NAME = "actions.intent.START_TIMER"
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindParameter(
- SlotMetadata.IDENTIFIER.path,
- Arguments::identifier,
- Arguments.Builder::setIdentifier,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .bindParameter(
- SlotMetadata.NAME.path,
- Arguments::name,
- Arguments.Builder::setName,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .bindParameter(
- SlotMetadata.DURATION.path,
- Arguments::duration,
- Arguments.Builder::setDuration,
- TypeConverters.DURATION_PARAM_VALUE_CONVERTER
- )
- .bindOutput(
- "executionStatus",
- Output::executionStatus,
- ExecutionStatus.PARAM_VALUE_CONVERTER
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/StopTimer.kt b/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/StopTimer.kt
deleted file mode 100644
index 876a07a..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/StopTimer.kt
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import androidx.appactions.builtintypes.types.GenericErrorStatus
-import androidx.appactions.builtintypes.types.SuccessStatus
-import androidx.appactions.builtintypes.types.Timer
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.serializers.types.GENERIC_ERROR_STATUS_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.SUCCESS_STATUS_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.TIMER_TYPE_SPEC
-
-/** A capability corresponding to actions.intent.STOP_TIMER */
-@CapabilityFactory(name = StopTimer.CAPABILITY_NAME)
-class StopTimer private constructor() {
- internal enum class SlotMetadata(val path: String) {
- TIMER("timer")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession
- >(ACTION_SPEC) {
- fun setTimerProperty(timer: Property<Timer>): CapabilityBuilder = setProperty(
- SlotMetadata.TIMER.path,
- timer,
- EntityConverter.of(TIMER_TYPE_SPEC)
- )
- }
-
- class Arguments internal constructor(val timerList: List<TimerReference>) {
- override fun toString(): String {
- return "Arguments(timerList=$timerList)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Arguments
-
- if (timerList != other.timerList) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- return timerList.hashCode()
- }
-
- class Builder {
- private var timerList: List<TimerReference> = emptyList()
-
- fun setTimerList(
- timerList: List<TimerReference>
- ): Builder = apply { this.timerList = timerList }
-
- fun build(): Arguments = Arguments(timerList)
- }
- }
-
- class Output internal constructor(val executionStatus: ExecutionStatus?) {
- override fun toString(): String {
- return "Output(executionStatus=$executionStatus)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Output
-
- if (executionStatus != other.executionStatus) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- return executionStatus.hashCode()
- }
-
- class Builder {
- private var executionStatus: ExecutionStatus? = null
-
- fun setExecutionStatus(successStatus: SuccessStatus) = setExecutionStatus(
- ExecutionStatus(successStatus)
- )
-
- fun setExecutionStatus(genericErrorStatus: GenericErrorStatus) = setExecutionStatus(
- ExecutionStatus(genericErrorStatus)
- )
-
- fun setExecutionStatus(executionStatus: ExecutionStatus): Builder = apply {
- this.executionStatus = executionStatus
- }
-
- fun build(): Output = Output(executionStatus)
- }
- }
-
- class ExecutionStatus {
- private var successStatus: SuccessStatus? = null
- private var genericErrorStatus: GenericErrorStatus? = null
-
- constructor(successStatus: SuccessStatus) {
- this.successStatus = successStatus
- }
-
- constructor(genericErrorStatus: GenericErrorStatus) {
- this.genericErrorStatus = genericErrorStatus
- }
-
- companion object {
- private val TYPE_SPEC = UnionTypeSpec.Builder<ExecutionStatus>()
- .bindMemberType(
- memberGetter = ExecutionStatus::successStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = SUCCESS_STATUS_TYPE_SPEC
- ).bindMemberType(
- memberGetter = ExecutionStatus::genericErrorStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = GENERIC_ERROR_STATUS_TYPE_SPEC
- ).build()
- internal val PARAM_VALUE_CONVERTER = ParamValueConverter.of(TYPE_SPEC)
- }
- }
-
- class Confirmation internal constructor()
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
-
- companion object {
- /** Canonical name for [StopTimer] capability */
- const val CAPABILITY_NAME = "actions.intent.STOP_TIMER"
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindRepeatedParameter(
- SlotMetadata.TIMER.path,
- Arguments::timerList,
- Arguments.Builder::setTimerList,
- TimerReference.PARAM_VALUE_CONVERTER
- )
- .bindOutput(
- "executionStatus",
- Output::executionStatus,
- ExecutionStatus.PARAM_VALUE_CONVERTER
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/TimerReference.kt b/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/TimerReference.kt
deleted file mode 100644
index 6ec9477..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/TimerReference.kt
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import androidx.appactions.builtintypes.types.Timer
-import androidx.appactions.interaction.capabilities.core.SearchAction
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-import androidx.appactions.interaction.capabilities.serializers.types.TIMER_TYPE_SPEC
-import java.util.Objects
-
-class TimerReference
-private constructor(
- val asTimer: Timer?,
- val asSearchAction: SearchAction<Timer>?,
-) {
- constructor(timer: Timer) : this(timer, null)
-
- // TODO(b/268071906) add TimerFilter type to SearchAction
- constructor(timerFilter: SearchAction<Timer>) : this(null, timerFilter)
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as TimerReference
-
- return asTimer == other.asTimer && asSearchAction == other.asSearchAction
- }
-
- override fun hashCode(): Int {
- return Objects.hash(asTimer, asSearchAction)
- }
-
- companion object {
- private val TYPE_SPEC =
- UnionTypeSpec.Builder<TimerReference>()
- .bindMemberType(
- memberGetter = TimerReference::asTimer,
- ctor = { TimerReference(it) },
- typeSpec = TIMER_TYPE_SPEC,
- )
- .bindMemberType(
- memberGetter = TimerReference::asSearchAction,
- ctor = { TimerReference(it) },
- typeSpec =
- TypeConverters.createSearchActionTypeSpec(
- TIMER_TYPE_SPEC,
- ),
- )
- .build()
-
- internal val PARAM_VALUE_CONVERTER = ParamValueConverter.of(TYPE_SPEC)
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/UpdateAlarm.kt b/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/UpdateAlarm.kt
deleted file mode 100644
index ec5cae4..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/UpdateAlarm.kt
+++ /dev/null
@@ -1,556 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import androidx.appactions.builtintypes.types.Alarm
-import androidx.appactions.builtintypes.types.GenericErrorStatus
-import androidx.appactions.builtintypes.types.Schedule
-import androidx.appactions.builtintypes.types.SuccessStatus
-import androidx.appactions.builtintypes.types.UnsupportedOperationStatus
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.OperationType
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.core.properties.StringValue
-import androidx.appactions.interaction.capabilities.serializers.types.ALARM_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.SCHEDULE_TYPE_SPEC
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-
-@CapabilityFactory(name = UpdateAlarm.CAPABILITY_NAME)
-class UpdateAlarm private constructor() {
- class OverwriteAlarmSchedule private constructor() {
- internal enum class SlotMetadata(val path: String) {
- ALARM("targetAlarm"),
- OPERATION("operation.@type"),
- NEW_VALUE("operation.newValue"),
- FIELD_PATH("operation.fieldPath")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession
- >(ACTION_SPEC) {
- fun setAlarmProperty(alarm: Property<Alarm>): CapabilityBuilder = setProperty(
- SlotMetadata.ALARM.path,
- alarm,
- EntityConverter.of(ALARM_TYPE_SPEC)
- )
- fun setScheduleProperty(schedule: Property<Schedule>): CapabilityBuilder =
- setProperty(
- SlotMetadata.NEW_VALUE.path,
- schedule,
- EntityConverter.of(SCHEDULE_TYPE_SPEC)
- )
-
- override fun build(): Capability {
- super.setProperty(
- SlotMetadata.OPERATION.path,
- Property<SupportedOperationType>(
- possibleValues = listOf(SupportedOperationType.OVERWRITE_OPERATION),
- isRequiredForExecution = true,
- shouldMatchPossibleValues = true
- ),
- TypeConverters.createEnumEntityConverter(
- listOf(SupportedOperationType.OVERWRITE_OPERATION)
- )
- )
- super.setProperty(
- SlotMetadata.FIELD_PATH.path,
- Property<FieldPath>(
- possibleValues = listOf(FieldPath.ALARM_SCHEDULE),
- isRequiredForExecution = true,
- shouldMatchPossibleValues = true
- ),
- TypeConverters.createEnumEntityConverter(
- listOf(FieldPath.ALARM_SCHEDULE)
- )
- )
- return super.build()
- }
- }
-
- class Arguments internal constructor(val alarm: AlarmReference?, val schedule: Schedule?) {
- override fun toString(): String {
- return "Arguments(alarm=$alarm, schedule=$schedule)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Arguments
-
- if (alarm != other.alarm) return false
- if (schedule != other.schedule) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = alarm.hashCode()
- result += 31 * schedule.hashCode()
- return result
- }
-
- class Builder {
- private var alarm: AlarmReference? = null
- private var schedule: Schedule? = null
-
- fun setAlarm(alarm: AlarmReference): Builder = apply { this.alarm = alarm }
- fun setSchedule(schedule: Schedule): Builder = apply { this.schedule = schedule }
-
- fun build(): Arguments = Arguments(alarm, schedule)
- }
- }
-
- class Output internal constructor(
- val executionStatus: ExecutionStatus?,
- val alarm: Alarm?
- ) {
- override fun toString(): String {
- return "Output(executionStatus=$executionStatus,alarm=$alarm)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Output
-
- if (executionStatus != other.executionStatus) return false
- if (alarm != other.alarm) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = executionStatus.hashCode()
- result += 31 * alarm.hashCode()
- return result
- }
-
- class Builder {
- private var executionStatus: ExecutionStatus? = null
- private var alarm: Alarm? = null
-
- fun setExecutionStatus(executionStatus: ExecutionStatus): Builder = apply {
- this.executionStatus = executionStatus
- }
-
- fun setExecutionStatus(successStatus: SuccessStatus): Builder = apply {
- this.setExecutionStatus(ExecutionStatus(successStatus))
- }
-
- fun setExecutionStatus(genericErrorStatus: GenericErrorStatus): Builder = apply {
- this.setExecutionStatus(ExecutionStatus(genericErrorStatus))
- }
-
- fun setExecutionStatus(unsupportedOperationStatus: UnsupportedOperationStatus):
- Builder = apply {
- this.setExecutionStatus(ExecutionStatus(unsupportedOperationStatus))
- }
-
- fun setAlarm(alarm: Alarm): Builder = apply { this.alarm = alarm }
-
- fun build(): Output = Output(executionStatus, alarm)
- }
- }
-
- class ExecutionStatus {
- private var successStatus: SuccessStatus? = null
- private var genericErrorStatus: GenericErrorStatus? = null
- private var unsupportedOperationStatus: UnsupportedOperationStatus? = null
-
- constructor(successStatus: SuccessStatus) {
- this.successStatus = successStatus
- }
-
- constructor(genericErrorStatus: GenericErrorStatus) {
- this.genericErrorStatus = genericErrorStatus
- }
-
- constructor(unsupportedOperationStatus: UnsupportedOperationStatus) {
- this.unsupportedOperationStatus = unsupportedOperationStatus
- }
-
- internal fun toParamValue(): ParamValue {
- var status: String = ""
- if (successStatus != null) {
- status = successStatus.toString()
- }
- if (genericErrorStatus != null) {
- status = genericErrorStatus.toString()
- }
- if (unsupportedOperationStatus != null) {
- status = unsupportedOperationStatus.toString()
- }
-
- val value: Value = Value.newBuilder().setStringValue(status).build()
- return ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder().putFields(TypeConverters.FIELD_NAME_TYPE, value).build()
- )
- .build()
- }
- }
-
- private class SupportedOperationType private constructor(val operationType: OperationType) {
-
- override fun toString(): String {
- return operationType.toString()
- }
- companion object {
- val OVERWRITE_OPERATION = SupportedOperationType(OperationType.OVERWRITE_OPERATION)
- }
- }
-
- private class FieldPath private constructor(val path: String) {
-
- override fun toString(): String {
- return path
- }
- companion object {
- val ALARM_SCHEDULE = FieldPath("alarmSchedule")
- }
- }
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
- class Confirmation internal constructor()
-
- companion object {
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java,
- Arguments::Builder,
- Arguments.Builder::build
- )
- .setOutput(Output::class.java)
- .bindParameter(
- SlotMetadata.ALARM.path,
- Arguments::alarm,
- Arguments.Builder::setAlarm,
- AlarmReference.PARAM_VALUE_CONVERTER
- )
- .bindParameter(
- SlotMetadata.NEW_VALUE.path,
- Arguments::schedule,
- Arguments.Builder::setSchedule,
- ParamValueConverter.of(SCHEDULE_TYPE_SPEC)
- )
- .bindParameter(
- SlotMetadata.OPERATION.path,
- { SupportedOperationType.OVERWRITE_OPERATION },
- { _, _ -> },
- TypeConverters.createEnumParamValueConverter(
- listOf(SupportedOperationType.OVERWRITE_OPERATION)
- )
- )
- .bindParameter(
- SlotMetadata.FIELD_PATH.path,
- { FieldPath.ALARM_SCHEDULE },
- { _, _ -> },
- TypeConverters.createEnumParamValueConverter(
- listOf(FieldPath.ALARM_SCHEDULE)
- )
- )
- .bindOutput(
- "alarm",
- Output::alarm,
- ParamValueConverter.of(ALARM_TYPE_SPEC)::toParamValue
- )
- .bindOutput(
- "executionStatus",
- Output::executionStatus,
- ExecutionStatus::toParamValue
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
- }
-
- class OverwriteName private constructor() {
- internal enum class SlotMetadata(val path: String) {
- ALARM("targetAlarm"),
- OPERATION("operation.@type"),
- NEW_VALUE("operation.newValue"),
- FIELD_PATH("operation.fieldPath")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession
- >(ACTION_SPEC) {
- fun setAlarmProperty(alarm: Property<Alarm>): CapabilityBuilder = setProperty(
- SlotMetadata.ALARM.path,
- alarm,
- EntityConverter.of(ALARM_TYPE_SPEC)
- )
- fun setNameProperty(schedule: Property<StringValue>): CapabilityBuilder =
- setProperty(
- SlotMetadata.NEW_VALUE.path,
- schedule,
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
-
- override fun build(): Capability {
- super.setProperty(
- SlotMetadata.OPERATION.path,
- Property<SupportedOperationType>(
- possibleValues = listOf(SupportedOperationType.OVERWRITE_OPERATION),
- isRequiredForExecution = true,
- shouldMatchPossibleValues = true
- ),
- TypeConverters.createEnumEntityConverter(
- listOf(SupportedOperationType.OVERWRITE_OPERATION)
- )
- )
- super.setProperty(
- SlotMetadata.FIELD_PATH.path,
- Property<FieldPath>(
- possibleValues = listOf(FieldPath.NAME),
- isRequiredForExecution = true,
- shouldMatchPossibleValues = true
- ),
- TypeConverters.createEnumEntityConverter(listOf(FieldPath.NAME))
- )
- return super.build()
- }
- }
-
- class Arguments internal constructor(val alarm: AlarmReference?, val name: String?) {
- override fun toString(): String {
- return "Arguments(alarm=$alarm,name=$name)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Arguments
-
- if (alarm != other.alarm) return false
- if (name != other.name) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = alarm.hashCode()
- result += 31 * name.hashCode()
- return result
- }
-
- class Builder {
- private var alarm: AlarmReference? = null
- private var name: String? = null
-
- fun setAlarm(alarm: AlarmReference): Builder = apply { this.alarm = alarm }
- fun setName(name: String): Builder = apply { this.name = name }
-
- fun build(): Arguments = Arguments(alarm, name)
- }
- }
-
- class Output internal constructor(
- val executionStatus: ExecutionStatus?,
- val alarm: Alarm?
- ) {
- override fun toString(): String {
- return "Output(executionStatus=$executionStatus,alarm=$alarm)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Output
-
- if (executionStatus != other.executionStatus) return false
- if (alarm != other.alarm) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = executionStatus.hashCode()
- result += 31 * alarm.hashCode()
- return result
- }
-
- class Builder {
- private var executionStatus: ExecutionStatus? = null
- private var alarm: Alarm? = null
-
- fun setExecutionStatus(executionStatus: ExecutionStatus): Builder = apply {
- this.executionStatus = executionStatus
- }
-
- fun setExecutionStatus(successStatus: SuccessStatus): Builder = apply {
- this.setExecutionStatus(ExecutionStatus(successStatus))
- }
-
- fun setExecutionStatus(genericErrorStatus: GenericErrorStatus): Builder = apply {
- this.setExecutionStatus(ExecutionStatus(genericErrorStatus))
- }
-
- fun setExecutionStatus(unsupportedOperationStatus: UnsupportedOperationStatus):
- Builder = apply {
- this.setExecutionStatus(ExecutionStatus(unsupportedOperationStatus))
- }
-
- fun setAlarm(alarm: Alarm): Builder = apply { this.alarm = alarm }
-
- fun build(): Output = Output(executionStatus, alarm)
- }
- }
-
- class ExecutionStatus {
- private var successStatus: SuccessStatus? = null
- private var genericErrorStatus: GenericErrorStatus? = null
- private var unsupportedOperationStatus: UnsupportedOperationStatus? = null
-
- constructor(successStatus: SuccessStatus) {
- this.successStatus = successStatus
- }
-
- constructor(genericErrorStatus: GenericErrorStatus) {
- this.genericErrorStatus = genericErrorStatus
- }
-
- constructor(unsupportedOperationStatus: UnsupportedOperationStatus) {
- this.unsupportedOperationStatus = unsupportedOperationStatus
- }
-
- internal fun toParamValue(): ParamValue {
- var status: String = ""
- if (successStatus != null) {
- status = successStatus.toString()
- }
- if (genericErrorStatus != null) {
- status = genericErrorStatus.toString()
- }
- if (unsupportedOperationStatus != null) {
- status = unsupportedOperationStatus.toString()
- }
-
- val value: Value = Value.newBuilder().setStringValue(status).build()
- return ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder().putFields(TypeConverters.FIELD_NAME_TYPE, value).build()
- )
- .build()
- }
- }
-
- private class SupportedOperationType private constructor(val operationType: OperationType) {
-
- override fun toString(): String {
- return operationType.toString()
- }
- companion object {
- val OVERWRITE_OPERATION = SupportedOperationType(OperationType.OVERWRITE_OPERATION)
- }
- }
-
- private class FieldPath private constructor(val path: String) {
-
- override fun toString(): String {
- return path
- }
- companion object {
- val NAME = FieldPath("name")
- }
- }
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
- class Confirmation internal constructor()
-
- companion object {
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java,
- Arguments::Builder,
- Arguments.Builder::build
- )
- .setOutput(Output::class.java)
- .bindParameter(
- SlotMetadata.ALARM.path,
- Arguments::alarm,
- Arguments.Builder::setAlarm,
- AlarmReference.PARAM_VALUE_CONVERTER
- )
- .bindParameter(
- SlotMetadata.NEW_VALUE.path,
- Arguments::name,
- Arguments.Builder::setName,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .bindParameter(
- SlotMetadata.OPERATION.path,
- { SupportedOperationType.OVERWRITE_OPERATION },
- { _, _ -> },
- TypeConverters.createEnumParamValueConverter(
- listOf(SupportedOperationType.OVERWRITE_OPERATION)
- )
- )
- .bindParameter(
- SlotMetadata.FIELD_PATH.path,
- { FieldPath.NAME },
- { _, _ -> },
- TypeConverters.createEnumParamValueConverter(
- listOf(FieldPath.NAME)
- )
- )
- .bindOutput(
- "alarm",
- Output::alarm,
- ParamValueConverter.of(ALARM_TYPE_SPEC)::toParamValue
- )
- .bindOutput(
- "executionStatus",
- Output::executionStatus,
- ExecutionStatus::toParamValue
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
- }
-
- companion object {
- const val CAPABILITY_NAME = "actions.intent.UPDATE_ALARM"
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/UpdateTimer.kt b/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/UpdateTimer.kt
deleted file mode 100644
index 48e41df6..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/UpdateTimer.kt
+++ /dev/null
@@ -1,809 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import androidx.appactions.builtintypes.types.GenericErrorStatus
-import androidx.appactions.builtintypes.types.SuccessStatus
-import androidx.appactions.builtintypes.types.Timer
-import androidx.appactions.builtintypes.types.UnsupportedOperationStatus
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.OperationType
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.converters.UnionTypeSpec
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.core.properties.StringValue
-import androidx.appactions.interaction.capabilities.serializers.types.GENERIC_ERROR_STATUS_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.SUCCESS_STATUS_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.TIMER_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.serializers.types.UNSUPPORTED_OPERATION_STATUS_TYPE_SPEC
-import java.time.Duration
-
-@CapabilityFactory(name = UpdateTimer.CAPABILITY_NAME)
-class UpdateTimer private constructor() {
- class IncrementRemainingDuration private constructor() {
- internal enum class SlotMetadata(val path: String) {
- TIMER("targetTimer"),
- OPERATION("operation.@type"),
- CHANGE("operation.change"),
- FIELD_PATH("operation.fieldPath")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession
- >(ACTION_SPEC) {
- fun setTimerProperty(timer: Property<Timer>): CapabilityBuilder = setProperty(
- SlotMetadata.TIMER.path,
- timer,
- EntityConverter.of(TIMER_TYPE_SPEC)
- )
- fun setDurationProperty(duration: Property<Duration>): CapabilityBuilder =
- setProperty(
- SlotMetadata.CHANGE.path,
- duration,
- TypeConverters.DURATION_ENTITY_CONVERTER
- )
-
- override fun build(): Capability {
- super.setProperty(
- SlotMetadata.OPERATION.path,
- Property<SupportedOperationType>(
- possibleValues = listOf(SupportedOperationType.INCREMENT_OPERATION),
- isRequiredForExecution = true,
- shouldMatchPossibleValues = true),
- TypeConverters.createEnumEntityConverter(
- listOf(SupportedOperationType.INCREMENT_OPERATION)
- )
- )
- super.setProperty(
- SlotMetadata.FIELD_PATH.path,
- Property<FieldPath>(
- possibleValues = listOf(FieldPath.REMAINING_DURATION),
- isRequiredForExecution = true,
- shouldMatchPossibleValues = true),
- TypeConverters.createEnumEntityConverter(
- listOf(FieldPath.REMAINING_DURATION)
- )
- )
- return super.build()
- }
- }
-
- class Arguments internal constructor(
- val timer: TimerReference?,
- val durationChange: Duration?,
- ) {
- override fun toString(): String {
- return "Arguments(timer=$timer,durationChange=$durationChange)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Arguments
-
- if (timer != other.timer) return false
- if (durationChange != other.durationChange) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = timer.hashCode()
- result += 31 * durationChange.hashCode()
- return result
- }
-
- class Builder {
- private var timer: TimerReference? = null
- private var durationChange: Duration? = null
-
- fun setTimer(timer: TimerReference): Builder = apply { this.timer = timer }
- fun setDurationChange(durationChange: Duration): Builder = apply {
- this.durationChange = durationChange
- }
-
- fun build(): Arguments = Arguments(timer, durationChange)
- }
- }
-
- class Output internal constructor(
- val executionStatus: ExecutionStatus?,
- val timer: Timer?
- ) {
- override fun toString(): String {
- return "Output(executionStatus=$executionStatus,timer=$timer)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Output
-
- if (executionStatus != other.executionStatus) return false
- if (timer != other.timer) return false
- return true
- }
-
- override fun hashCode(): Int {
- var result = executionStatus.hashCode()
- result += 31 * timer.hashCode()
- return result
- }
-
- class Builder {
- private var executionStatus: ExecutionStatus? = null
- private var timer: Timer? = null
-
- fun setExecutionStatus(executionStatus: ExecutionStatus): Builder = apply {
- this.executionStatus = executionStatus
- }
-
- fun setExecutionStatus(successStatus: SuccessStatus): Builder = apply {
- this.setExecutionStatus(ExecutionStatus(successStatus))
- }
-
- fun setExecutionStatus(genericErrorStatus: GenericErrorStatus): Builder = apply {
- this.setExecutionStatus(ExecutionStatus(genericErrorStatus))
- }
-
- fun setExecutionStatus(unsupportedOperationStatus: UnsupportedOperationStatus):
- Builder = apply {
- this.setExecutionStatus(ExecutionStatus(unsupportedOperationStatus))
- }
- fun setTimer(timer: Timer): Builder = apply { this.timer = timer }
-
- fun build(): Output = Output(executionStatus, timer)
- }
- }
-
- class ExecutionStatus {
- private var successStatus: SuccessStatus? = null
- private var genericErrorStatus: GenericErrorStatus? = null
- private var unsupportedOperationStatus: UnsupportedOperationStatus? = null
-
- constructor(successStatus: SuccessStatus) {
- this.successStatus = successStatus
- }
-
- constructor(genericErrorStatus: GenericErrorStatus) {
- this.genericErrorStatus = genericErrorStatus
- }
-
- constructor(unsupportedOperationStatus: UnsupportedOperationStatus) {
- this.unsupportedOperationStatus = unsupportedOperationStatus
- }
-
- companion object {
- private val TYPE_SPEC = UnionTypeSpec.Builder<ExecutionStatus>()
- .bindMemberType(
- memberGetter = ExecutionStatus::successStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = SUCCESS_STATUS_TYPE_SPEC
- ).bindMemberType(
- memberGetter = ExecutionStatus::genericErrorStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = GENERIC_ERROR_STATUS_TYPE_SPEC
- ).bindMemberType(
- memberGetter = ExecutionStatus::unsupportedOperationStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = UNSUPPORTED_OPERATION_STATUS_TYPE_SPEC
- ).build()
- internal val PARAM_VALUE_CONVERTER = ParamValueConverter.of(TYPE_SPEC)
- }
- }
-
- private class SupportedOperationType private constructor(val operationType: OperationType) {
-
- override fun toString(): String {
- return operationType.toString()
- }
-
- companion object {
- val INCREMENT_OPERATION = SupportedOperationType(OperationType.INCREMENT_OPERATION)
- }
- }
-
- private class FieldPath private constructor(val path: String) {
-
- override fun toString(): String {
- return path
- }
-
- companion object {
- val REMAINING_DURATION = FieldPath("remainingDuration")
- }
- }
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
- class Confirmation internal constructor()
-
- companion object {
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java,
- Arguments::Builder,
- Arguments.Builder::build
- )
- .setOutput(Output::class.java)
- .bindParameter(
- SlotMetadata.TIMER.path,
- Arguments::timer,
- Arguments.Builder::setTimer,
- TimerReference.PARAM_VALUE_CONVERTER
- )
- .bindParameter(
- SlotMetadata.CHANGE.path,
- Arguments::durationChange,
- Arguments.Builder::setDurationChange,
- TypeConverters.DURATION_PARAM_VALUE_CONVERTER
- )
- .bindParameter(
- SlotMetadata.OPERATION.path,
- { SupportedOperationType.INCREMENT_OPERATION },
- { _, _ -> },
- TypeConverters.createEnumParamValueConverter(
- listOf(SupportedOperationType.INCREMENT_OPERATION)
- )
- )
- .bindParameter(
- SlotMetadata.FIELD_PATH.path,
- { FieldPath.REMAINING_DURATION },
- { _, _ -> },
- TypeConverters.createEnumParamValueConverter(
- listOf(FieldPath.REMAINING_DURATION)
- )
- )
- .bindOutput(
- "timer",
- Output::timer,
- ParamValueConverter.of(TIMER_TYPE_SPEC)
- )
- .bindOutput(
- "executionStatus",
- Output::executionStatus,
- ExecutionStatus.PARAM_VALUE_CONVERTER
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
- }
-
- class OverwriteRemainingDuration private constructor() {
- internal enum class SlotMetadata(val path: String) {
- TIMER("targetTimer"),
- OPERATION("operation.@type"),
- NEW_VALUE("operation.newValue"),
- FIELD_PATH("operation.fieldPath")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession
- >(ACTION_SPEC) {
- fun setTimerProperty(timer: Property<Timer>): CapabilityBuilder = setProperty(
- SlotMetadata.TIMER.path,
- timer,
- EntityConverter.of(TIMER_TYPE_SPEC)
- )
-
- fun setDurationProperty(duration: Property<Duration>): CapabilityBuilder =
- setProperty(
- SlotMetadata.NEW_VALUE.path,
- duration,
- TypeConverters.DURATION_ENTITY_CONVERTER
- )
-
- override fun build(): Capability {
- super.setProperty(
- SlotMetadata.OPERATION.path,
- Property<SupportedOperationType>(
- possibleValues = listOf(SupportedOperationType.OVERWRITE_OPERATION),
- isRequiredForExecution = true,
- shouldMatchPossibleValues = true
- ),
- TypeConverters.createEnumEntityConverter(
- listOf(SupportedOperationType.OVERWRITE_OPERATION)
- )
- )
- super.setProperty(
- SlotMetadata.FIELD_PATH.path,
- Property<FieldPath>(
- possibleValues = listOf(FieldPath.REMAINING_DURATION),
- isRequiredForExecution = true,
- shouldMatchPossibleValues = true
- ),
- TypeConverters.createEnumEntityConverter(
- listOf(FieldPath.REMAINING_DURATION)
- )
- )
- return super.build()
- }
- }
-
- class Arguments internal constructor(val timer: TimerReference?, val duration: Duration?) {
- override fun toString(): String {
- return "Arguments(timer=$timer,duration=$duration)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Arguments
-
- if (timer != other.timer) return false
- if (duration != other.duration) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = timer.hashCode()
- result += 31 * duration.hashCode()
- return result
- }
-
- class Builder {
- private var timer: TimerReference? = null
- private var duration: Duration? = null
-
- fun setTimer(timer: TimerReference): Builder = apply { this.timer = timer }
- fun setDuration(duration: Duration): Builder = apply { this.duration = duration }
-
- fun build(): Arguments = Arguments(timer, duration)
- }
- }
-
- class Output internal constructor(
- val executionStatus: ExecutionStatus?,
- val timer: Timer?
- ) {
- override fun toString(): String {
- return "Output(executionStatus=$executionStatus,timer=$timer)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Output
-
- if (executionStatus != other.executionStatus) return false
- if (timer != other.timer) return false
- return true
- }
-
- override fun hashCode(): Int {
- var result = executionStatus.hashCode()
- result += 31 * timer.hashCode()
- return result
- }
-
- class Builder {
- private var executionStatus: ExecutionStatus? = null
- private var timer: Timer? = null
-
- fun setExecutionStatus(executionStatus: ExecutionStatus): Builder = apply {
- this.executionStatus = executionStatus
- }
-
- fun setExecutionStatus(successStatus: SuccessStatus): Builder = apply {
- this.setExecutionStatus(ExecutionStatus(successStatus))
- }
-
- fun setExecutionStatus(genericErrorStatus: GenericErrorStatus): Builder = apply {
- this.setExecutionStatus(ExecutionStatus(genericErrorStatus))
- }
-
- fun setExecutionStatus(unsupportedOperationStatus: UnsupportedOperationStatus):
- Builder = apply {
- this.setExecutionStatus(ExecutionStatus(unsupportedOperationStatus))
- }
- fun setTimer(timer: Timer): Builder = apply { this.timer = timer }
-
- fun build(): Output = Output(executionStatus, timer)
- }
- }
-
- class ExecutionStatus {
- private var successStatus: SuccessStatus? = null
- private var genericErrorStatus: GenericErrorStatus? = null
- private var unsupportedOperationStatus: UnsupportedOperationStatus? = null
-
- constructor(successStatus: SuccessStatus) {
- this.successStatus = successStatus
- }
-
- constructor(genericErrorStatus: GenericErrorStatus) {
- this.genericErrorStatus = genericErrorStatus
- }
-
- constructor(unsupportedOperationStatus: UnsupportedOperationStatus) {
- this.unsupportedOperationStatus = unsupportedOperationStatus
- }
-
- companion object {
- private val TYPE_SPEC = UnionTypeSpec.Builder<ExecutionStatus>()
- .bindMemberType(
- memberGetter = ExecutionStatus::successStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = SUCCESS_STATUS_TYPE_SPEC
- ).bindMemberType(
- memberGetter = ExecutionStatus::genericErrorStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = GENERIC_ERROR_STATUS_TYPE_SPEC
- ).bindMemberType(
- memberGetter = ExecutionStatus::unsupportedOperationStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = UNSUPPORTED_OPERATION_STATUS_TYPE_SPEC
- ).build()
- internal val PARAM_VALUE_CONVERTER = ParamValueConverter.of(TYPE_SPEC)
- }
- }
-
- private class SupportedOperationType private constructor(val operationType: OperationType) {
-
- override fun toString(): String {
- return operationType.toString()
- }
-
- companion object {
- val OVERWRITE_OPERATION = SupportedOperationType(OperationType.OVERWRITE_OPERATION)
- }
- }
-
- private class FieldPath private constructor(val path: String) {
-
- override fun toString(): String {
- return path
- }
-
- companion object {
- val REMAINING_DURATION = FieldPath("remainingDuration")
- }
- }
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
- class Confirmation internal constructor()
-
- companion object {
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java,
- Arguments::Builder,
- Arguments.Builder::build
- )
- .setOutput(Output::class.java)
- .bindParameter(
- SlotMetadata.TIMER.path,
- Arguments::timer,
- Arguments.Builder::setTimer,
- TimerReference.PARAM_VALUE_CONVERTER
- )
- .bindParameter(
- SlotMetadata.NEW_VALUE.path,
- Arguments::duration,
- Arguments.Builder::setDuration,
- TypeConverters.DURATION_PARAM_VALUE_CONVERTER
- )
- .bindParameter(
- SlotMetadata.OPERATION.path,
- { SupportedOperationType.OVERWRITE_OPERATION },
- { _, _ -> },
- TypeConverters.createEnumParamValueConverter(
- listOf(SupportedOperationType.OVERWRITE_OPERATION)
- )
- )
- .bindParameter(
- SlotMetadata.FIELD_PATH.path,
- { FieldPath.REMAINING_DURATION },
- { _, _ -> },
- TypeConverters.createEnumParamValueConverter(
- listOf(FieldPath.REMAINING_DURATION)
- )
- )
- .bindOutput(
- "timer",
- Output::timer,
- ParamValueConverter.of(TIMER_TYPE_SPEC)
- )
- .bindOutput(
- "executionStatus",
- Output::executionStatus,
- ExecutionStatus.PARAM_VALUE_CONVERTER
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
- }
-
- class OverwriteName private constructor() {
- internal enum class SlotMetadata(val path: String) {
- TIMER("targetTimer"),
- OPERATION("operation.@type"),
- NEW_VALUE("operation.newValue"),
- FIELD_PATH("operation.fieldPath")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession
- >(ACTION_SPEC) {
- fun setTimerProperty(timer: Property<Timer>): CapabilityBuilder = setProperty(
- SlotMetadata.TIMER.path,
- timer,
- EntityConverter.of(TIMER_TYPE_SPEC)
- )
-
- fun setNameProperty(name: Property<StringValue>): CapabilityBuilder =
- setProperty(
- SlotMetadata.NEW_VALUE.path,
- name,
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
-
- override fun build(): Capability {
- super.setProperty(
- SlotMetadata.OPERATION.path,
- Property<SupportedOperationType>(
- possibleValues = listOf(SupportedOperationType.OVERWRITE_OPERATION),
- isRequiredForExecution = true,
- shouldMatchPossibleValues = true
- ),
- TypeConverters.createEnumEntityConverter(
- listOf(SupportedOperationType.OVERWRITE_OPERATION)
- )
- )
- super.setProperty(
- SlotMetadata.FIELD_PATH.path,
- Property<FieldPath>(
- possibleValues = listOf(FieldPath.NAME),
- isRequiredForExecution = true,
- shouldMatchPossibleValues = true
- ),
- TypeConverters.createEnumEntityConverter(listOf(FieldPath.NAME))
- )
- return super.build()
- }
- }
-
- class Arguments internal constructor(val timer: TimerReference?, val name: String?) {
- override fun toString(): String {
- return "Arguments(timer=$timer,name=$name)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Arguments
-
- if (timer != other.timer) return false
- if (name != other.name) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = timer.hashCode()
- result += 31 * name.hashCode()
- return result
- }
-
- class Builder {
- private var timer: TimerReference? = null
- private var name: String? = null
-
- fun setTimer(timer: TimerReference): Builder = apply { this.timer = timer }
- fun setName(name: String): Builder = apply { this.name = name }
-
- fun build(): Arguments = Arguments(timer, name)
- }
- }
-
- class Output internal constructor(
- val executionStatus: ExecutionStatus?,
- val timer: Timer?
- ) {
- override fun toString(): String {
- return "Output(executionStatus=$executionStatus,timer=$timer)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Output
-
- if (executionStatus != other.executionStatus) return false
- if (timer != other.timer) return false
- return true
- }
-
- override fun hashCode(): Int {
- var result = executionStatus.hashCode()
- result += 31 * timer.hashCode()
- return result
- }
-
- class Builder {
- private var executionStatus: ExecutionStatus? = null
- private var timer: Timer? = null
-
- fun setExecutionStatus(executionStatus: ExecutionStatus): Builder = apply {
- this.executionStatus = executionStatus
- }
-
- fun setExecutionStatus(successStatus: SuccessStatus): Builder = apply {
- this.setExecutionStatus(ExecutionStatus(successStatus))
- }
-
- fun setExecutionStatus(genericErrorStatus: GenericErrorStatus): Builder = apply {
- this.setExecutionStatus(ExecutionStatus(genericErrorStatus))
- }
-
- fun setExecutionStatus(unsupportedOperationStatus: UnsupportedOperationStatus):
- Builder = apply {
- this.setExecutionStatus(ExecutionStatus(unsupportedOperationStatus))
- }
- fun setTimer(timer: Timer): Builder = apply { this.timer = timer }
-
- fun build(): Output = Output(executionStatus, timer)
- }
- }
-
- class ExecutionStatus {
- private var successStatus: SuccessStatus? = null
- private var genericErrorStatus: GenericErrorStatus? = null
- private var unsupportedOperationStatus: UnsupportedOperationStatus? = null
-
- constructor(successStatus: SuccessStatus) {
- this.successStatus = successStatus
- }
-
- constructor(genericErrorStatus: GenericErrorStatus) {
- this.genericErrorStatus = genericErrorStatus
- }
-
- constructor(unsupportedOperationStatus: UnsupportedOperationStatus) {
- this.unsupportedOperationStatus = unsupportedOperationStatus
- }
-
- companion object {
- private val TYPE_SPEC = UnionTypeSpec.Builder<ExecutionStatus>()
- .bindMemberType(
- memberGetter = ExecutionStatus::successStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = SUCCESS_STATUS_TYPE_SPEC
- ).bindMemberType(
- memberGetter = ExecutionStatus::genericErrorStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = GENERIC_ERROR_STATUS_TYPE_SPEC
- ).bindMemberType(
- memberGetter = ExecutionStatus::unsupportedOperationStatus,
- ctor = { ExecutionStatus(it) },
- typeSpec = UNSUPPORTED_OPERATION_STATUS_TYPE_SPEC
- ).build()
- internal val PARAM_VALUE_CONVERTER = ParamValueConverter.of(TYPE_SPEC)
- }
- }
-
- private class SupportedOperationType private constructor(val operationType: OperationType) {
-
- override fun toString(): String {
- return operationType.toString()
- }
-
- companion object {
- val OVERWRITE_OPERATION = SupportedOperationType(OperationType.OVERWRITE_OPERATION)
- }
- }
-
- private class FieldPath private constructor(val path: String) {
-
- override fun toString(): String {
- return path
- }
-
- companion object {
- val NAME = FieldPath("name")
- }
- }
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
- class Confirmation internal constructor()
-
- companion object {
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java,
- Arguments::Builder,
- Arguments.Builder::build
- )
- .setOutput(Output::class.java)
- .bindParameter(
- SlotMetadata.TIMER.path,
- Arguments::timer,
- Arguments.Builder::setTimer,
- TimerReference.PARAM_VALUE_CONVERTER
- )
- .bindParameter(
- SlotMetadata.NEW_VALUE.path,
- Arguments::name,
- Arguments.Builder::setName,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .bindParameter(
- SlotMetadata.OPERATION.path,
- { SupportedOperationType.OVERWRITE_OPERATION },
- { _, _ -> },
- TypeConverters.createEnumParamValueConverter(
- listOf(SupportedOperationType.OVERWRITE_OPERATION)
- )
- )
- .bindParameter(
- SlotMetadata.FIELD_PATH.path,
- { FieldPath.NAME },
- { _, _ -> },
- TypeConverters.createEnumParamValueConverter(listOf(FieldPath.NAME))
- )
- .bindOutput(
- "timer",
- Output::timer,
- ParamValueConverter.of(TIMER_TYPE_SPEC)
- )
- .bindOutput(
- "executionStatus",
- Output::executionStatus,
- ExecutionStatus.PARAM_VALUE_CONVERTER
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
- }
-
- companion object {
- const val CAPABILITY_NAME = "actions.intent.UPDATE_TIMER"
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/package-info.java b/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/package-info.java
deleted file mode 100644
index 612634d..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/main/java/androidx/appactions/interaction/capabilities/productivity/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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.
- */
-
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-package androidx.appactions.interaction.capabilities.productivity;
-
-import androidx.annotation.RestrictTo;
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/CreateAlarmTest.kt b/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/CreateAlarmTest.kt
deleted file mode 100644
index 512fcba..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/CreateAlarmTest.kt
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import android.util.SizeF
-import androidx.appactions.builtintypes.properties.ByDay
-import androidx.appactions.builtintypes.properties.RepeatFrequency
-import androidx.appactions.builtintypes.types.DayOfWeek
-import androidx.appactions.builtintypes.types.Schedule
-import androidx.appactions.builtintypes.types.SuccessStatus
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.productivity.CreateAlarm.Arguments
-import androidx.appactions.interaction.capabilities.productivity.CreateAlarm.Output
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils
-import androidx.appactions.interaction.capabilities.testing.internal.FakeCallbackInternal
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.awaitSync
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter
-import androidx.appactions.interaction.proto.FulfillmentResponse
-import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput
-import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput.OutputValue
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.proto.TaskInfo
-import androidx.appactions.interaction.protobuf.ListValue
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-import com.google.common.truth.Truth.assertThat
-import java.time.Duration
-import java.time.LocalTime
-import kotlinx.coroutines.CompletableDeferred
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class CreateAlarmTest {
- private val hostProperties =
- HostProperties.Builder().setMaxHostSizeDp(SizeF(300f, 500f)).build()
- @Test
- fun createCapability_expectedResult() {
- val argsDeferred = CompletableDeferred<Arguments>()
- val capability =
- CreateAlarm.CapabilityBuilder()
- .setId("create alarm")
- .setScheduleProperty(Property<Schedule>())
- .setExecutionCallback(
- ExecutionCallback {
- argsDeferred.complete(it)
- ExecutionResult.Builder<Output>().setOutput(
- Output.Builder().setExecutionStatus(
- SuccessStatus.Builder().build()
- ).build()
- ).build()
- })
- .build()
- val capabilitySession = capability.createSession("fakeSessionId", hostProperties)
- val args: MutableMap<String, ParamValue> = mutableMapOf(
- "alarm.name" to ParamValue.newBuilder().setStringValue("wakeup").build(),
- "alarm.alarmSchedule" to ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("Schedule").build())
- .putFields("startTime", Value.newBuilder().setStringValue("08:30").build())
- .putFields(
- "repeatFrequency",
- Value.newBuilder().setStringValue("PT5M").build()
- )
- .putFields(
- "byDays",
- Value.newBuilder()
- .setListValue(
- ListValue.newBuilder()
- .addValues(
- Value.newBuilder()
- .setStringValue("http://schema.org/Monday")
- )
- .addValues(
- Value.newBuilder()
- .setStringValue("http://schema.org/Tuesday")
- )
- .build())
- .build()))
- .build()
- )
- val callback = FakeCallbackInternal()
- capabilitySession.execute(ArgumentUtils.buildArgs(args), callback)
-
- assertThat(capability.appAction)
- .isEqualTo(
- AppAction.newBuilder()
- .setIdentifier("create alarm")
- .setName("actions.intent.CREATE_ALARM")
- .addParams(IntentParameter.newBuilder().setName("alarm.alarmSchedule"))
- .setTaskInfo(TaskInfo.getDefaultInstance())
- .build()
- )
- assertThat(argsDeferred.awaitSync())
- .isEqualTo(
- Arguments.Builder()
- .setName("wakeup")
- .setSchedule(
- Schedule.Builder()
- .setStartTime(LocalTime.of(8, 30))
- .setRepeatFrequency(RepeatFrequency(Duration.ofMinutes(5)))
- .addByDay(ByDay(DayOfWeek.MONDAY))
- .addByDay(ByDay(DayOfWeek.TUESDAY))
- .build()
- )
- .build()
- )
- assertThat(callback.receiveResponse().fulfillmentResponse).isEqualTo(
- FulfillmentResponse.newBuilder().setExecutionOutput(
- StructuredOutput.newBuilder().addOutputValues(
- OutputValue.newBuilder().setName("executionStatus").addValues(
- ParamValue.newBuilder().setStructValue(
- Struct.newBuilder().putFields(
- "@type",
- Value.newBuilder().setStringValue("SuccessStatus").build()
- )
- )
- )
- )
- ).build()
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/DismissAlarmTest.kt b/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/DismissAlarmTest.kt
deleted file mode 100644
index 01315e6..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/DismissAlarmTest.kt
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import android.util.SizeF
-import androidx.appactions.builtintypes.types.Alarm
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.productivity.DismissAlarm.Arguments
-import androidx.appactions.interaction.capabilities.productivity.DismissAlarm.Output
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils
-import androidx.appactions.interaction.capabilities.testing.internal.FakeCallbackInternal
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.awaitSync
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.proto.TaskInfo
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CompletableDeferred
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class DismissAlarmTest {
- private val hostProperties =
- HostProperties.Builder().setMaxHostSizeDp(SizeF(300f, 500f)).build()
- @Test
- fun createCapability_expectedResult() {
- val argsDeferred = CompletableDeferred<Arguments>()
- val capability =
- DismissAlarm.CapabilityBuilder()
- .setId("dismiss alarm")
- .setAlarmProperty(Property<Alarm>(isRequiredForExecution = true))
- .setExecutionCallback(
- ExecutionCallback {
- argsDeferred.complete(it)
- ExecutionResult.Builder<Output>().build()
- })
- .build()
- val capabilitySession = capability.createSession("fakeSessionId", hostProperties)
- val args: MutableMap<String, ParamValue> = mutableMapOf(
- "alarm" to ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("Alarm").build())
- .putFields("identifier", Value.newBuilder().setStringValue("abc").build())
- )
- .build()
- )
- capabilitySession.execute(ArgumentUtils.buildArgs(args), FakeCallbackInternal())
-
- assertThat(capability.appAction)
- .isEqualTo(
- AppAction.newBuilder()
- .setIdentifier("dismiss alarm")
- .setName("actions.intent.DISMISS_ALARM")
- .addParams(IntentParameter.newBuilder().setName("alarm").setIsRequired(true))
- .setTaskInfo(TaskInfo.getDefaultInstance())
- .build()
- )
- assertThat(argsDeferred.awaitSync())
- .isEqualTo(
- Arguments.Builder()
- .setAlarm(AlarmReference(Alarm.Builder().setIdentifier("abc").build()))
- .build()
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/GetAlarmTest.kt b/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/GetAlarmTest.kt
deleted file mode 100644
index 6bd6cc3..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/GetAlarmTest.kt
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import android.util.SizeF
-import androidx.appactions.builtintypes.types.Alarm
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.productivity.GetAlarm.Arguments
-import androidx.appactions.interaction.capabilities.productivity.GetAlarm.Output
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils
-import androidx.appactions.interaction.capabilities.testing.internal.FakeCallbackInternal
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.awaitSync
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.proto.TaskInfo
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CompletableDeferred
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class GetAlarmTest {
- private val hostProperties =
- HostProperties.Builder().setMaxHostSizeDp(SizeF(300f, 500f)).build()
-
- @Test
- fun createCapability_expectedResult() {
- val argsDeferred = CompletableDeferred<Arguments>()
- val capability =
- GetAlarm.CapabilityBuilder()
- .setId("get alarm")
- .setAlarmProperty(Property<Alarm>(isRequiredForExecution = true))
- .setExecutionCallback(
- ExecutionCallback {
- argsDeferred.complete(it)
- ExecutionResult.Builder<Output>().build()
- }
- )
- .build()
- val capabilitySession = capability.createSession("fakeSessionId", hostProperties)
- val args: MutableMap<String, ParamValue> = mutableMapOf(
- "alarm" to ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("Alarm").build())
- .putFields("identifier", Value.newBuilder().setStringValue("abc").build())
- )
- .build()
- )
- capabilitySession.execute(ArgumentUtils.buildArgs(args), FakeCallbackInternal())
-
- assertThat(capability.appAction)
- .isEqualTo(
- AppAction.newBuilder()
- .setIdentifier("get alarm")
- .setName("actions.intent.GET_ALARM")
- .addParams(IntentParameter.newBuilder().setName("alarm").setIsRequired(true))
- .setTaskInfo(TaskInfo.getDefaultInstance())
- .build()
- )
- assertThat(argsDeferred.awaitSync())
- .isEqualTo(
- Arguments.Builder()
- .setAlarm(AlarmReference(Alarm.Builder().setIdentifier("abc").build()))
- .build()
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/PauseTimerTest.kt b/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/PauseTimerTest.kt
deleted file mode 100644
index 60302a5..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/PauseTimerTest.kt
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import android.util.SizeF
-import androidx.appactions.builtintypes.types.GenericErrorStatus
-import androidx.appactions.builtintypes.types.Timer
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.productivity.PauseTimer.Arguments
-import androidx.appactions.interaction.capabilities.productivity.PauseTimer.Output
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils
-import androidx.appactions.interaction.capabilities.testing.internal.FakeCallbackInternal
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.awaitSync
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter
-import androidx.appactions.interaction.proto.FulfillmentResponse
-import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput
-import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput.OutputValue
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.proto.TaskInfo
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CompletableDeferred
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class PauseTimerTest {
- private val hostProperties =
- HostProperties.Builder().setMaxHostSizeDp(SizeF(300f, 500f)).build()
-
- @Test
- fun createCapability_expectedResult() {
- val argsDeferred = CompletableDeferred<Arguments>()
- val capability = PauseTimer.CapabilityBuilder()
- .setId("pause timer")
- .setTimerProperty(Property<Timer>(isRequiredForExecution = true))
- .setExecutionCallback(
- ExecutionCallback {
- argsDeferred.complete(it)
- ExecutionResult.Builder<Output>().setOutput(
- Output.Builder().setExecutionStatus(
- GenericErrorStatus.Builder().build()
- ).build()
- ).build()
- })
- .build()
- val capabilitySession = capability.createSession("fakeSessionId", hostProperties)
- val args: MutableMap<String, ParamValue> = mutableMapOf(
- "timer" to ParamValue.newBuilder().setStructValue(
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("Timer").build())
- .putFields("identifier", Value.newBuilder().setStringValue("abc").build())
- )
- .build()
- )
- val callback = FakeCallbackInternal()
- capabilitySession.execute(ArgumentUtils.buildArgs(args), callback)
-
- assertThat(capability.appAction)
- .isEqualTo(
- AppAction.newBuilder()
- .setIdentifier("pause timer")
- .setName("actions.intent.PAUSE_TIMER")
- .addParams(IntentParameter.newBuilder().setName("timer").setIsRequired(true))
- .setTaskInfo(TaskInfo.getDefaultInstance())
- .build()
- )
- assertThat(argsDeferred.awaitSync())
- .isEqualTo(
- Arguments.Builder()
- .setTimerList(
- listOf(TimerReference(Timer.Builder().setIdentifier("abc").build()))
- )
- .build()
- )
- assertThat(callback.receiveResponse().fulfillmentResponse).isEqualTo(
- FulfillmentResponse.newBuilder().setExecutionOutput(
- StructuredOutput.newBuilder().addOutputValues(
- OutputValue.newBuilder().setName("executionStatus").addValues(
- ParamValue.newBuilder().setStructValue(
- Struct.newBuilder().putFields(
- "@type",
- Value.newBuilder().setStringValue("GenericErrorStatus").build()
- )
- )
- )
- )
- ).build()
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/ResetTimerTest.kt b/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/ResetTimerTest.kt
deleted file mode 100644
index 99764e7..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/ResetTimerTest.kt
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import android.util.SizeF
-import androidx.appactions.builtintypes.types.Timer
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.productivity.ResetTimer.Arguments
-import androidx.appactions.interaction.capabilities.productivity.ResetTimer.Output
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils
-import androidx.appactions.interaction.capabilities.testing.internal.FakeCallbackInternal
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.awaitSync
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.proto.TaskInfo
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CompletableDeferred
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class ResetTimerTest {
- private val hostProperties =
- HostProperties.Builder().setMaxHostSizeDp(SizeF(300f, 500f)).build()
-
- @Test
- fun createCapability_expectedResult() {
- val argsDeferred = CompletableDeferred<Arguments>()
- val capability = ResetTimer.CapabilityBuilder()
- .setId("reset timer")
- .setTimerProperty(Property<Timer>(isRequiredForExecution = true))
- .setExecutionCallback(
- ExecutionCallback {
- argsDeferred.complete(it)
- ExecutionResult.Builder<Output>().build()
- })
- .build()
- val capabilitySession = capability.createSession("fakeSessionId", hostProperties)
- val args: MutableMap<String, ParamValue> = mutableMapOf(
- "timer" to ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("Timer").build())
- .putFields("identifier", Value.newBuilder().setStringValue("abc").build())
- )
- .build()
- )
- capabilitySession.execute(ArgumentUtils.buildArgs(args), FakeCallbackInternal())
-
- assertThat(capability.appAction)
- .isEqualTo(
- AppAction.newBuilder()
- .setIdentifier("reset timer")
- .setName("actions.intent.RESET_TIMER")
- .addParams(IntentParameter.newBuilder().setName("timer").setIsRequired(true))
- .setTaskInfo(TaskInfo.getDefaultInstance())
- .build()
- )
- assertThat(argsDeferred.awaitSync())
- .isEqualTo(
- Arguments.Builder()
- .setTimerList(
- listOf(TimerReference(Timer.Builder().setIdentifier("abc").build()))
- )
- .build()
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/ResumeTimerTest.kt b/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/ResumeTimerTest.kt
deleted file mode 100644
index e9871ad..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/ResumeTimerTest.kt
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import android.util.SizeF
-import androidx.appactions.builtintypes.types.Timer
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.productivity.ResumeTimer.Arguments
-import androidx.appactions.interaction.capabilities.productivity.ResumeTimer.Output
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils
-import androidx.appactions.interaction.capabilities.testing.internal.FakeCallbackInternal
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.awaitSync
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.proto.TaskInfo
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CompletableDeferred
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class ResumeTimerTest {
- private val hostProperties =
- HostProperties.Builder().setMaxHostSizeDp(SizeF(300f, 500f)).build()
-
- @Test
- fun createCapability_expectedResult() {
- val argsDeferred = CompletableDeferred<Arguments>()
- val capability = ResumeTimer.CapabilityBuilder()
- .setId("resume timer")
- .setTimerProperty(Property<Timer>(isRequiredForExecution = true))
- .setExecutionCallback(
- ExecutionCallback {
- argsDeferred.complete(it)
- ExecutionResult.Builder<Output>().build()
- })
- .build()
- val capabilitySession = capability.createSession("fakeSessionId", hostProperties)
- val args: MutableMap<String, ParamValue> = mutableMapOf(
- "timer" to ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("Timer").build())
- .putFields("identifier", Value.newBuilder().setStringValue("abc").build())
- )
- .build()
- )
- capabilitySession.execute(ArgumentUtils.buildArgs(args), FakeCallbackInternal())
-
- assertThat(capability.appAction)
- .isEqualTo(
- AppAction.newBuilder()
- .setIdentifier("resume timer")
- .setName("actions.intent.RESUME_TIMER")
- .addParams(IntentParameter.newBuilder().setName("timer").setIsRequired(true))
- .setTaskInfo(TaskInfo.getDefaultInstance())
- .build()
- )
- assertThat(argsDeferred.awaitSync())
- .isEqualTo(
- Arguments.Builder()
- .setTimerList(
- listOf(TimerReference(Timer.Builder().setIdentifier("abc").build()))
- )
- .build()
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/SnoozeAlarmTest.kt b/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/SnoozeAlarmTest.kt
deleted file mode 100644
index 0097725..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/SnoozeAlarmTest.kt
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import android.util.SizeF
-import androidx.appactions.builtintypes.types.Alarm
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.productivity.SnoozeAlarm.Arguments
-import androidx.appactions.interaction.capabilities.productivity.SnoozeAlarm.Output
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils
-import androidx.appactions.interaction.capabilities.testing.internal.FakeCallbackInternal
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.awaitSync
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.proto.TaskInfo
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-import com.google.common.truth.Truth.assertThat
-import java.time.Duration
-import kotlinx.coroutines.CompletableDeferred
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-@RunWith(JUnit4::class)
-class SnoozeAlarmTest {
- private val hostProperties =
- HostProperties.Builder().setMaxHostSizeDp(SizeF(300f, 500f)).build()
- @Test
- fun createCapability_expectedResult() {
- val argsDeferred = CompletableDeferred<Arguments>()
- val capability =
- SnoozeAlarm.CapabilityBuilder()
- .setId("snooze alarm")
- .setSnoozeDurationProperty(Property<Duration>())
- .setTargetAlarmProperty(Property<Alarm>(isRequiredForExecution = true))
- .setExecutionCallback(
- ExecutionCallback {
- argsDeferred.complete(it)
- ExecutionResult.Builder<Output>().build()
- })
- .build()
- val capabilitySession = capability.createSession("fakeSessionId", hostProperties)
- val args: MutableMap<String, ParamValue> = mutableMapOf(
- "snoozeDuration" to ParamValue.newBuilder().setStringValue("PT5M").build(),
- "alarm" to ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("Alarm").build())
- .putFields("identifier", Value.newBuilder().setStringValue("abc").build())
- )
- .build()
- )
- capabilitySession.execute(ArgumentUtils.buildArgs(args), FakeCallbackInternal())
-
- assertThat(capability.appAction)
- .isEqualTo(
- AppAction.newBuilder()
- .setIdentifier("snooze alarm")
- .setName("actions.intent.SNOOZE_ALARM")
- .addParams(IntentParameter.newBuilder().setName("snoozeDuration"))
- .addParams(IntentParameter.newBuilder().setName("alarm").setIsRequired(true))
- .setTaskInfo(TaskInfo.getDefaultInstance())
- .build()
- )
- assertThat(argsDeferred.awaitSync())
- .isEqualTo(
- Arguments.Builder()
- .setSnoozeDuration(Duration.ofMinutes(5))
- .setTargetAlarm(AlarmReference(Alarm.Builder().setIdentifier("abc").build()))
- .build()
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/StartTimerTest.kt b/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/StartTimerTest.kt
deleted file mode 100644
index 8500e98..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/StartTimerTest.kt
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import android.util.SizeF
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.productivity.StartTimer.Arguments
-import androidx.appactions.interaction.capabilities.productivity.StartTimer.Output
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils
-import androidx.appactions.interaction.capabilities.testing.internal.FakeCallbackInternal
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.awaitSync
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.proto.TaskInfo
-import com.google.common.truth.Truth.assertThat
-import java.time.Duration
-import kotlinx.coroutines.CompletableDeferred
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class StartTimerTest {
- private val hostProperties =
- HostProperties.Builder().setMaxHostSizeDp(SizeF(300f, 500f)).build()
- @Test
- fun createCapability_expectedResult() {
- val argsDeferred = CompletableDeferred<Arguments>()
- val capability =
- StartTimer.CapabilityBuilder()
- .setId("start timer")
- .setDurationProperty(Property<Duration>())
- .setExecutionCallback(
- ExecutionCallback {
- argsDeferred.complete(it)
- ExecutionResult.Builder<Output>().build()
- })
- .build()
- val capabilitySession = capability.createSession("fakeSessionId", hostProperties)
- val args: MutableMap<String, ParamValue> = mutableMapOf(
- "timer.duration" to ParamValue.newBuilder().setStringValue("PT5M").build(),
- "timer.identifier" to ParamValue.newBuilder().setStringValue("abc123").build(),
- "timer.name" to ParamValue.newBuilder().setStringValue("cooking").build()
- )
- // "Start timer for 5 minutes"
- capabilitySession.execute(ArgumentUtils.buildArgs(args), FakeCallbackInternal())
-
- assertThat(capability.appAction)
- .isEqualTo(
- AppAction.newBuilder()
- .setIdentifier("start timer")
- .setName("actions.intent.START_TIMER")
- .addParams(IntentParameter.newBuilder().setName("timer.duration"))
- .setTaskInfo(TaskInfo.getDefaultInstance())
- .build()
- )
- assertThat(argsDeferred.awaitSync())
- .isEqualTo(
- Arguments.Builder()
- .setDuration(Duration.ofMinutes(5))
- .setIdentifier("abc123")
- .setName("cooking")
- .build()
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/StopTimerTest.kt b/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/StopTimerTest.kt
deleted file mode 100644
index ee0b6c2..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/StopTimerTest.kt
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import android.util.SizeF
-import androidx.appactions.builtintypes.types.Timer
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.productivity.StopTimer.Arguments
-import androidx.appactions.interaction.capabilities.productivity.StopTimer.Output
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils
-import androidx.appactions.interaction.capabilities.testing.internal.FakeCallbackInternal
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.awaitSync
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.proto.TaskInfo
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CompletableDeferred
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class StopTimerTest {
- private val hostProperties =
- HostProperties.Builder().setMaxHostSizeDp(SizeF(300f, 500f)).build()
-
- @Test
- fun createCapability_expectedResult() {
- val argsDeferred = CompletableDeferred<Arguments>()
- val capability = StopTimer.CapabilityBuilder()
- .setId("stop timer")
- .setTimerProperty(Property<Timer>(isRequiredForExecution = true))
- .setExecutionCallback(
- ExecutionCallback {
- argsDeferred.complete(it)
- ExecutionResult.Builder<Output>().build()
- })
- .build()
- val capabilitySession = capability.createSession("fakeSessionId", hostProperties)
- val args: MutableMap<String, ParamValue> = mutableMapOf(
- "timer" to ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("Timer").build())
- .putFields("identifier", Value.newBuilder().setStringValue("abc").build())
- )
- .build()
- )
- capabilitySession.execute(ArgumentUtils.buildArgs(args), FakeCallbackInternal())
-
- assertThat(capability.appAction)
- .isEqualTo(
- AppAction.newBuilder()
- .setIdentifier("stop timer")
- .setName("actions.intent.STOP_TIMER")
- .addParams(IntentParameter.newBuilder().setName("timer").setIsRequired(true))
- .setTaskInfo(TaskInfo.getDefaultInstance())
- .build()
- )
- assertThat(argsDeferred.awaitSync())
- .isEqualTo(
- Arguments.Builder()
- .setTimerList(
- listOf(TimerReference(Timer.Builder().setIdentifier("abc").build()))
- )
- .build()
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/UpdateAlarmOverwriteAlarmScheduleTest.kt b/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/UpdateAlarmOverwriteAlarmScheduleTest.kt
deleted file mode 100644
index 4bb9bc6..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/UpdateAlarmOverwriteAlarmScheduleTest.kt
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import android.util.SizeF
-import androidx.appactions.builtintypes.types.Alarm
-import androidx.appactions.builtintypes.types.DayOfWeek
-import androidx.appactions.builtintypes.types.Schedule
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.productivity.UpdateAlarm.OverwriteAlarmSchedule
-import androidx.appactions.interaction.capabilities.productivity.UpdateAlarm.OverwriteAlarmSchedule.Arguments
-import androidx.appactions.interaction.capabilities.productivity.UpdateAlarm.OverwriteAlarmSchedule.Output
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils
-import androidx.appactions.interaction.capabilities.testing.internal.FakeCallbackInternal
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.awaitSync
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter
-import androidx.appactions.interaction.proto.Entity
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.proto.TaskInfo
-import androidx.appactions.interaction.protobuf.ListValue
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-import com.google.common.truth.Truth.assertThat
-import java.time.Duration
-import java.time.LocalDate
-import java.time.LocalTime
-import kotlinx.coroutines.CompletableDeferred
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class UpdateAlarmOverwriteAlarmScheduleTest {
- private val hostProperties =
- HostProperties.Builder().setMaxHostSizeDp(SizeF(300f, 500f)).build()
-
- @Test
- fun createCapability_expectedResult() {
- val argsDeferred = CompletableDeferred<Arguments>()
- val capability = OverwriteAlarmSchedule.CapabilityBuilder()
- .setId("overwrite alarm schedule")
- .setAlarmProperty(Property<Alarm>(isRequiredForExecution = true))
- .setScheduleProperty(Property<Schedule>(isRequiredForExecution = true))
- .setExecutionCallback(
- ExecutionCallback {
- argsDeferred.complete(it)
- ExecutionResult.Builder<Output>().build()
- })
- .build()
- val capabilitySession = capability.createSession("fakeSessionId", hostProperties)
- val args: MutableMap<String, ParamValue> = mutableMapOf(
- "targetAlarm" to ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("Alarm").build())
- .putFields("identifier", Value.newBuilder().setStringValue("abc").build())
- ).build(),
- "operation.@type" to ParamValue.newBuilder()
- .setIdentifier("OverwriteOperation")
- .build(),
- "operation.newValue" to ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("Schedule").build())
- .putFields("identifier", Value.newBuilder().setStringValue("id").build())
- .putFields("startDate", Value.newBuilder()
- .setStringValue("2023-06-14").build())
- .putFields("startTime", Value.newBuilder().setStringValue("10:00").build())
- .putFields("repeatFrequency", Value.newBuilder()
- .setStringValue("PT5M").build())
- .putFields(
- "byDays",
- Value.newBuilder()
- .setListValue(
- ListValue.newBuilder()
- .addValues(
- Value.newBuilder()
- .setStringValue("http://schema.org/Sunday")
- .build())
- .addValues(
- Value.newBuilder()
- .setStringValue("http://schema.org/Monday")
- .build())
- .build())
- .build())
- .build())
- .build(),
- "operation.fieldPath" to ParamValue.newBuilder().setIdentifier("alarmSchedule").build()
- )
- capabilitySession.execute(ArgumentUtils.buildArgs(args), FakeCallbackInternal())
-
- assertThat(capability.appAction)
- .isEqualTo(
- AppAction.newBuilder()
- .setIdentifier("overwrite alarm schedule")
- .setName("actions.intent.UPDATE_ALARM")
- .addParams(IntentParameter.newBuilder()
- .setName("targetAlarm")
- .setIsRequired(true))
- .addParams(IntentParameter.newBuilder()
- .setName("operation.newValue")
- .setIsRequired(true))
- .addParams(
- IntentParameter.newBuilder()
- .setName("operation.@type")
- .addPossibleEntities(
- Entity.newBuilder().setIdentifier("OverwriteOperation").build())
- .setIsRequired(true)
- .setEntityMatchRequired(true))
- .addParams(
- IntentParameter.newBuilder()
- .setName("operation.fieldPath")
- .addPossibleEntities(
- Entity.newBuilder().setIdentifier("alarmSchedule").build())
- .setIsRequired(true)
- .setEntityMatchRequired(true))
- .setTaskInfo(TaskInfo.getDefaultInstance())
- .build()
- )
- assertThat(argsDeferred.awaitSync())
- .isEqualTo(
- Arguments.Builder()
- .setAlarm(AlarmReference(Alarm.Builder().setIdentifier("abc").build()))
- .setSchedule(
- Schedule.Builder()
- .setIdentifier("id")
- .setStartDate(LocalDate.of(2023, 6, 14))
- .setStartTime(LocalTime.of(10, 0))
- .setRepeatFrequency(Duration.ofMinutes(5))
- .addByDay(DayOfWeek.SUNDAY)
- .addByDay(DayOfWeek.MONDAY)
- .build())
- .build()
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/UpdateAlarmOverwriteNameTest.kt b/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/UpdateAlarmOverwriteNameTest.kt
deleted file mode 100644
index 6f8083b..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/UpdateAlarmOverwriteNameTest.kt
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import android.util.SizeF
-import androidx.appactions.builtintypes.types.Alarm
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.core.properties.StringValue
-import androidx.appactions.interaction.capabilities.productivity.UpdateAlarm.OverwriteName
-import androidx.appactions.interaction.capabilities.productivity.UpdateAlarm.OverwriteName.Arguments
-import androidx.appactions.interaction.capabilities.productivity.UpdateAlarm.OverwriteName.Output
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils
-import androidx.appactions.interaction.capabilities.testing.internal.FakeCallbackInternal
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.awaitSync
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter
-import androidx.appactions.interaction.proto.Entity
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.proto.TaskInfo
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CompletableDeferred
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class UpdateAlarmOverwriteNameTest {
- val hostProperties =
- HostProperties.Builder().setMaxHostSizeDp(SizeF(300f, 500f)).build()
-
- @Test
- fun createCapability_expectedResult() {
- val argsDeferred = CompletableDeferred<Arguments>()
- val capability = OverwriteName.CapabilityBuilder()
- .setId("overwrite name")
- .setAlarmProperty(Property<Alarm>(isRequiredForExecution = true))
- .setNameProperty(Property<StringValue>(isRequiredForExecution = true))
- .setExecutionCallback(
- ExecutionCallback {
- argsDeferred.complete(it)
- ExecutionResult.Builder<Output>().build()
- })
- .build()
- val capabilitySession = capability.createSession("fakeSessionId", hostProperties)
- val args: MutableMap<String, ParamValue> = mutableMapOf(
- "targetAlarm" to ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder().setStringValue("Alarm").build())
- .putFields("identifier", Value.newBuilder().setStringValue("abc").build()))
- .build(),
- "operation.@type" to ParamValue.newBuilder()
- .setIdentifier("OverwriteOperation")
- .build(),
- "operation.newValue" to ParamValue.newBuilder().setStringValue("chicken").build(),
- "operation.fieldPath" to ParamValue.newBuilder().setIdentifier("name").build()
- )
- capabilitySession.execute(ArgumentUtils.buildArgs(args), FakeCallbackInternal())
-
- assertThat(capability.appAction)
- .isEqualTo(
- AppAction.newBuilder()
- .setIdentifier("overwrite name")
- .setName("actions.intent.UPDATE_ALARM")
- .addParams(
- IntentParameter.newBuilder().setName("targetAlarm").setIsRequired(true))
- .addParams(
- IntentParameter.newBuilder()
- .setName("operation.newValue")
- .setIsRequired(true))
- .addParams(
- IntentParameter.newBuilder()
- .setName("operation.@type")
- .addPossibleEntities(
- Entity.newBuilder().setIdentifier("OverwriteOperation").build())
- .setIsRequired(true)
- .setEntityMatchRequired(true))
- .addParams(
- IntentParameter.newBuilder()
- .setName("operation.fieldPath")
- .addPossibleEntities(
- Entity.newBuilder().setIdentifier("name").build())
- .setIsRequired(true)
- .setEntityMatchRequired(true))
- .setTaskInfo(TaskInfo.getDefaultInstance())
- .build())
- assertThat(argsDeferred.awaitSync())
- .isEqualTo(
- Arguments.Builder()
- .setAlarm(AlarmReference(Alarm.Builder().setIdentifier("abc").build()))
- .setName("chicken")
- .build()
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/UpdateTimerIncrementRemainingDurationTest.kt b/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/UpdateTimerIncrementRemainingDurationTest.kt
deleted file mode 100644
index 59544fe..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/UpdateTimerIncrementRemainingDurationTest.kt
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import android.util.SizeF
-import androidx.appactions.builtintypes.types.Timer
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.productivity.UpdateTimer.IncrementRemainingDuration
-import androidx.appactions.interaction.capabilities.productivity.UpdateTimer.IncrementRemainingDuration.Arguments
-import androidx.appactions.interaction.capabilities.productivity.UpdateTimer.IncrementRemainingDuration.Output
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils
-import androidx.appactions.interaction.capabilities.testing.internal.FakeCallbackInternal
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.awaitSync
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter
-import androidx.appactions.interaction.proto.Entity
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.proto.TaskInfo
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-import com.google.common.truth.Truth.assertThat
-import java.time.Duration
-import kotlinx.coroutines.CompletableDeferred
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class UpdateTimerIncrementRemainingDurationTest {
- private val hostProperties =
- HostProperties.Builder().setMaxHostSizeDp(SizeF(300f, 500f)).build()
-
- @Test
- fun createCapability_expectedResult() {
- val argsDeferred = CompletableDeferred<Arguments>()
- val capability = IncrementRemainingDuration.CapabilityBuilder()
- .setId("increment remaining duration")
- .setTimerProperty(Property<Timer>(isRequiredForExecution = true))
- .setDurationProperty(Property<Duration>(isRequiredForExecution = true))
- .setExecutionCallback(
- ExecutionCallback {
- argsDeferred.complete(it)
- ExecutionResult.Builder<Output>().build()
- }
- )
- .build()
- val capabilitySession = capability.createSession("fakeSessionId", hostProperties)
- val args: MutableMap<String, ParamValue> = mutableMapOf(
- "targetTimer" to ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder()
- .setStringValue("Timer").build())
- .putFields("identifier", Value.newBuilder().setStringValue("abc").build())
- )
- .build(),
- "operation.@type" to ParamValue.newBuilder()
- .setIdentifier("IncrementOperation").build(),
- "operation.change" to ParamValue.newBuilder().setStringValue("PT5M").build(),
- "operation.fieldPath" to ParamValue.newBuilder()
- .setIdentifier("remainingDuration").build()
- )
- capabilitySession.execute(ArgumentUtils.buildArgs(args), FakeCallbackInternal())
-
- assertThat(capability.appAction)
- .isEqualTo(
- AppAction.newBuilder()
- .setIdentifier("increment remaining duration")
- .setName("actions.intent.UPDATE_TIMER")
- .addParams(IntentParameter.newBuilder()
- .setName("targetTimer")
- .setIsRequired(true))
- .addParams(
- IntentParameter.newBuilder()
- .setName("operation.change").setIsRequired(true)
- )
- .addParams(
- IntentParameter.newBuilder()
- .setName("operation.@type")
- .addPossibleEntities(
- Entity.newBuilder().setIdentifier("IncrementOperation").build())
- .setIsRequired(true).setEntityMatchRequired(true)
- )
- .addParams(
- IntentParameter.newBuilder()
- .setName("operation.fieldPath")
- .addPossibleEntities(
- Entity.newBuilder().setIdentifier("remainingDuration").build()
- )
- .setIsRequired(true)
- .setEntityMatchRequired(true)
- )
- .setTaskInfo(TaskInfo.getDefaultInstance())
- .build()
- )
- assertThat(argsDeferred.awaitSync())
- .isEqualTo(
- Arguments.Builder()
- .setTimer(TimerReference(Timer.Builder().setIdentifier("abc").build()))
- .setDurationChange(Duration.ofMinutes(5))
- .build()
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/UpdateTimerOverwriteNameTest.kt b/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/UpdateTimerOverwriteNameTest.kt
deleted file mode 100644
index 0e55c0c..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/UpdateTimerOverwriteNameTest.kt
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import android.util.SizeF
-import androidx.appactions.builtintypes.types.Timer
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.core.properties.StringValue
-import androidx.appactions.interaction.capabilities.productivity.UpdateTimer.OverwriteName
-import androidx.appactions.interaction.capabilities.productivity.UpdateTimer.OverwriteName.Arguments
-import androidx.appactions.interaction.capabilities.productivity.UpdateTimer.OverwriteName.Output
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils
-import androidx.appactions.interaction.capabilities.testing.internal.FakeCallbackInternal
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.awaitSync
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter
-import androidx.appactions.interaction.proto.Entity
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.proto.TaskInfo
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CompletableDeferred
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class UpdateTimerOverwriteNameTest {
- private val hostProperties =
- HostProperties.Builder().setMaxHostSizeDp(SizeF(300f, 500f)).build()
-
- @Test
- fun createCapability_expectedResult() {
- val argsDeferred = CompletableDeferred<Arguments>()
- val capability = OverwriteName.CapabilityBuilder()
- .setId("Overwrite name")
- .setTimerProperty(Property<Timer>(isRequiredForExecution = true))
- .setNameProperty(Property<StringValue>(isRequiredForExecution = true))
- .setExecutionCallback(
- ExecutionCallback {
- argsDeferred.complete(it)
- ExecutionResult.Builder<Output>().build()
- }
- )
- .build()
- val capabilitySession = capability.createSession("fakeSessionId", hostProperties)
- val args: MutableMap<String, ParamValue> = mutableMapOf(
- "targetTimer" to ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder()
- .setStringValue("Timer").build())
- .putFields("identifier", Value.newBuilder().setStringValue("abc").build())
- )
- .build(),
- "operation.@type" to ParamValue.newBuilder()
- .setIdentifier("OverwriteOperation").build(),
- "operation.newValue" to ParamValue.newBuilder().setStringValue("chicken").build(),
- "operation.fieldPath" to ParamValue.newBuilder()
- .setIdentifier("name").build()
- )
- capabilitySession.execute(ArgumentUtils.buildArgs(args), FakeCallbackInternal())
-
- assertThat(capability.appAction)
- .isEqualTo(
- AppAction.newBuilder()
- .setIdentifier("Overwrite name")
- .setName("actions.intent.UPDATE_TIMER")
- .addParams(IntentParameter.newBuilder()
- .setName("targetTimer")
- .setIsRequired(true))
- .addParams(
- IntentParameter.newBuilder()
- .setName("operation.newValue").setIsRequired(true)
- )
- .addParams(
- IntentParameter.newBuilder()
- .setName("operation.@type")
- .addPossibleEntities(
- Entity.newBuilder().setIdentifier("OverwriteOperation").build())
- .setIsRequired(true).setEntityMatchRequired(true)
- )
- .addParams(
- IntentParameter.newBuilder()
- .setName("operation.fieldPath")
- .addPossibleEntities(
- Entity.newBuilder().setIdentifier("name").build()
- )
- .setIsRequired(true)
- .setEntityMatchRequired(true)
- )
- .setTaskInfo(TaskInfo.getDefaultInstance())
- .build()
- )
- assertThat(argsDeferred.awaitSync())
- .isEqualTo(
- Arguments.Builder()
- .setTimer(TimerReference(Timer.Builder().setIdentifier("abc").build()))
- .setName("chicken")
- .build()
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/UpdateTimerOverwriteRemainingDurationTest.kt b/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/UpdateTimerOverwriteRemainingDurationTest.kt
deleted file mode 100644
index a94c361..0000000
--- a/appactions/interaction/interaction-capabilities-productivity/src/test/java/androidx/appactions/interaction/capabilities/productivity/UpdateTimerOverwriteRemainingDurationTest.kt
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.productivity
-
-import android.util.SizeF
-import androidx.appactions.builtintypes.types.Timer
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.productivity.UpdateTimer.OverwriteRemainingDuration
-import androidx.appactions.interaction.capabilities.productivity.UpdateTimer.OverwriteRemainingDuration.Arguments
-import androidx.appactions.interaction.capabilities.productivity.UpdateTimer.OverwriteRemainingDuration.Output
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils
-import androidx.appactions.interaction.capabilities.testing.internal.FakeCallbackInternal
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.awaitSync
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import androidx.appactions.interaction.proto.AppActionsContext.IntentParameter
-import androidx.appactions.interaction.proto.Entity
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.proto.TaskInfo
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-import com.google.common.truth.Truth.assertThat
-import java.time.Duration
-import kotlinx.coroutines.CompletableDeferred
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class UpdateTimerOverwriteRemainingDurationTest {
- private val hostProperties =
- HostProperties.Builder().setMaxHostSizeDp(SizeF(300f, 500f)).build()
-
- @Test
- fun createCapability_expectedResult() {
- val argsDeferred = CompletableDeferred<Arguments>()
- val capability = OverwriteRemainingDuration.CapabilityBuilder()
- .setId("Overwrite remaining duration")
- .setTimerProperty(Property<Timer>(isRequiredForExecution = true))
- .setDurationProperty(Property<Duration>(isRequiredForExecution = true))
- .setExecutionCallback(
- ExecutionCallback {
- argsDeferred.complete(it)
- ExecutionResult.Builder<Output>().build()
- }
- )
- .build()
- val capabilitySession = capability.createSession("fakeSessionId", hostProperties)
- val args: MutableMap<String, ParamValue> = mutableMapOf(
- "targetTimer" to ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields("@type", Value.newBuilder()
- .setStringValue("Timer").build())
- .putFields("identifier", Value.newBuilder().setStringValue("abc").build())
- )
- .build(),
- "operation.@type" to ParamValue.newBuilder()
- .setIdentifier("OverwriteOperation").build(),
- "operation.newValue" to ParamValue.newBuilder().setStringValue("PT5M").build(),
- "operation.fieldPath" to ParamValue.newBuilder()
- .setIdentifier("remainingDuration").build()
- )
- capabilitySession.execute(ArgumentUtils.buildArgs(args), FakeCallbackInternal())
-
- assertThat(capability.appAction)
- .isEqualTo(
- AppAction.newBuilder()
- .setIdentifier("Overwrite remaining duration")
- .setName("actions.intent.UPDATE_TIMER")
- .addParams(IntentParameter.newBuilder()
- .setName("targetTimer")
- .setIsRequired(true))
- .addParams(
- IntentParameter.newBuilder()
- .setName("operation.newValue").setIsRequired(true)
- )
- .addParams(
- IntentParameter.newBuilder()
- .setName("operation.@type")
- .addPossibleEntities(
- Entity.newBuilder().setIdentifier("OverwriteOperation").build())
- .setIsRequired(true).setEntityMatchRequired(true)
- )
- .addParams(
- IntentParameter.newBuilder()
- .setName("operation.fieldPath")
- .addPossibleEntities(
- Entity.newBuilder().setIdentifier("remainingDuration").build()
- )
- .setIsRequired(true)
- .setEntityMatchRequired(true)
- )
- .setTaskInfo(TaskInfo.getDefaultInstance())
- .build()
- )
- assertThat(argsDeferred.awaitSync())
- .isEqualTo(
- Arguments.Builder()
- .setTimer(TimerReference(Timer.Builder().setIdentifier("abc").build()))
- .setDuration(Duration.ofMinutes(5))
- .build()
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-safety/api/current.txt b/appactions/interaction/interaction-capabilities-safety/api/current.txt
deleted file mode 100644
index e6f50d0..0000000
--- a/appactions/interaction/interaction-capabilities-safety/api/current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 4.0
diff --git a/appactions/interaction/interaction-capabilities-safety/api/res-current.txt b/appactions/interaction/interaction-capabilities-safety/api/res-current.txt
deleted file mode 100644
index e69de29..0000000
--- a/appactions/interaction/interaction-capabilities-safety/api/res-current.txt
+++ /dev/null
diff --git a/appactions/interaction/interaction-capabilities-safety/api/restricted_current.txt b/appactions/interaction/interaction-capabilities-safety/api/restricted_current.txt
deleted file mode 100644
index e6f50d0..0000000
--- a/appactions/interaction/interaction-capabilities-safety/api/restricted_current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 4.0
diff --git a/appactions/interaction/interaction-capabilities-safety/build.gradle b/appactions/interaction/interaction-capabilities-safety/build.gradle
deleted file mode 100644
index a8a0230..0000000
--- a/appactions/interaction/interaction-capabilities-safety/build.gradle
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-/**
- * This file was created using the `create_project.py` script located in the
- * `<AndroidX root>/development/project-creator` directory.
- *
- * Please use that script when creating a new project, rather than copying an existing project and
- * modifying its settings.
- */
-import androidx.build.LibraryType
-
-plugins {
- id("AndroidXPlugin")
- id("com.android.library")
- id("org.jetbrains.kotlin.android")
-}
-
-dependencies {
- api(libs.autoValueAnnotations)
- api(libs.kotlinStdlib)
- annotationProcessor(libs.autoValue)
- implementation("androidx.annotation:annotation:1.1.0")
- implementation(project(":appactions:interaction:interaction-capabilities-core"))
-}
-
-android {
- namespace "androidx.appactions.interaction.capabilities.safety"
- defaultConfig {
- minSdkVersion 26
- }
-}
-
-androidx {
- name = "androidx.appactions.interaction:interaction-capabilities-safety"
- type = LibraryType.PUBLISHED_LIBRARY
- inceptionYear = "2023"
- description = "Capability APIs for Safety vertical."
- metalavaK2UastEnabled = true
-}
diff --git a/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/StartEmergencySharing.kt b/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/StartEmergencySharing.kt
deleted file mode 100644
index 05a4757..0000000
--- a/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/StartEmergencySharing.kt
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.safety
-
-import androidx.appactions.builtintypes.experimental.types.GenericErrorStatus
-import androidx.appactions.builtintypes.experimental.types.NoInternetConnection
-import androidx.appactions.builtintypes.experimental.types.SuccessStatus
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.safety.executionstatus.EmergencySharingInProgress
-import androidx.appactions.interaction.capabilities.safety.executionstatus.SafetyAccountNotLoggedIn
-import androidx.appactions.interaction.capabilities.safety.executionstatus.SafetyFeatureNotOnboarded
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-
-/** A capability corresponding to actions.intent.START_EMERGENCY_SHARING */
-@CapabilityFactory(name = StartEmergencySharing.CAPABILITY_NAME)
-class StartEmergencySharing private constructor() {
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder, Arguments, Output, Confirmation, ExecutionSession,
- >(ACTION_SPEC)
-
- class Arguments internal constructor() {
- class Builder {
- fun build(): Arguments = Arguments()
- }
- }
-
- class Output internal constructor(val executionStatus: ExecutionStatus?) {
- override fun toString(): String {
- return "Output(executionStatus=$executionStatus)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Output
-
- if (executionStatus != other.executionStatus) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- return executionStatus.hashCode()
- }
-
- class Builder {
- private var executionStatus: ExecutionStatus? = null
-
- fun setExecutionStatus(executionStatus: ExecutionStatus): Builder =
- apply { this.executionStatus = executionStatus }
-
- fun build(): Output = Output(executionStatus)
- }
- }
-
- class ExecutionStatus {
- private var successStatus: SuccessStatus? = null
- private var genericErrorStatus: GenericErrorStatus? = null
- private var emergencySharingInProgress: EmergencySharingInProgress? = null
- private var safetyAccountNotLoggedIn: SafetyAccountNotLoggedIn? = null
- private var safetyFeatureNotOnboarded: SafetyFeatureNotOnboarded? = null
- private var noInternetConnection: NoInternetConnection? = null
-
- constructor(successStatus: SuccessStatus) {
- this.successStatus = successStatus
- }
-
- constructor(genericErrorStatus: GenericErrorStatus) {
- this.genericErrorStatus = genericErrorStatus
- }
-
- constructor(emergencySharingInProgress: EmergencySharingInProgress) {
- this.emergencySharingInProgress = emergencySharingInProgress
- }
-
- constructor(safetyAccountNotLoggedIn: SafetyAccountNotLoggedIn) {
- this.safetyAccountNotLoggedIn = safetyAccountNotLoggedIn
- }
-
- constructor(safetyFeatureNotOnboarded: SafetyFeatureNotOnboarded) {
- this.safetyFeatureNotOnboarded = safetyFeatureNotOnboarded
- }
-
- constructor(noInternetConnection: NoInternetConnection) {
- this.noInternetConnection = noInternetConnection
- }
-
- internal fun toParamValue(): ParamValue {
- var status: String = ""
- if (successStatus != null) {
- status = successStatus.toString()
- }
- if (genericErrorStatus != null) {
- status = genericErrorStatus.toString()
- }
- if (emergencySharingInProgress != null) {
- status = emergencySharingInProgress.toString()
- }
- if (safetyAccountNotLoggedIn != null) {
- status = safetyAccountNotLoggedIn.toString()
- }
- if (safetyFeatureNotOnboarded != null) {
- status = safetyFeatureNotOnboarded.toString()
- }
- if (noInternetConnection != null) {
- status = noInternetConnection.toString()
- }
- val value: Value = Value.newBuilder().setStringValue(status).build()
- return ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields(TypeConverters.FIELD_NAME_TYPE, value)
- .build(),
- )
- .build()
- }
- }
-
- class Confirmation internal constructor()
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
-
- companion object {
- /** Canonical name for [StartEmergencySharing] capability */
- const val CAPABILITY_NAME = "actions.intent.START_EMERGENCY_SHARING"
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(
- Arguments::class.java,
- Arguments::Builder,
- Arguments.Builder::build
- )
- .setOutput(Output::class.java)
- .bindOutput(
- "executionStatus",
- Output::executionStatus,
- ExecutionStatus::toParamValue,
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/StartSafetyCheck.kt b/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/StartSafetyCheck.kt
deleted file mode 100644
index 4081fb3..0000000
--- a/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/StartSafetyCheck.kt
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.safety
-
-import androidx.appactions.builtintypes.experimental.types.ActionNotInProgress
-import androidx.appactions.builtintypes.experimental.types.GenericErrorStatus
-import androidx.appactions.builtintypes.experimental.types.NoInternetConnection
-import androidx.appactions.builtintypes.experimental.types.SafetyCheck
-import androidx.appactions.builtintypes.experimental.types.SuccessStatus
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.ParamValueConverter
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters.SAFETY_CHECK_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.safety.executionstatus.EmergencySharingInProgress
-import androidx.appactions.interaction.capabilities.safety.executionstatus.SafetyAccountNotLoggedIn
-import androidx.appactions.interaction.capabilities.safety.executionstatus.SafetyFeatureNotOnboarded
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-import java.time.Duration
-import java.time.ZonedDateTime
-
-/** A capability corresponding to actions.intent.START_SAFETY_CHECK */
-@CapabilityFactory(name = StartSafetyCheck.CAPABILITY_NAME)
-class StartSafetyCheck private constructor() {
- internal enum class SlotMetadata(val path: String) {
- DURATION("safetycheck.duration"),
- CHECK_IN_TIME("safetycheck.checkInTime")
- }
-
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder, Arguments, Output, Confirmation, ExecutionSession
- >(ACTION_SPEC) {
- fun setDurationProperty(duration: Property<Duration>): CapabilityBuilder = setProperty(
- SlotMetadata.DURATION.path,
- duration,
- TypeConverters.DURATION_ENTITY_CONVERTER
- )
-
- fun setCheckInTimeProperty(
- checkInTime: Property<ZonedDateTime>
- ): CapabilityBuilder = setProperty(
- SlotMetadata.CHECK_IN_TIME.path,
- checkInTime,
- TypeConverters.ZONED_DATE_TIME_ENTITY_CONVERTER
- )
- }
-
- class Arguments internal constructor(
- val duration: Duration?,
- val checkInTime: ZonedDateTime?
- ) {
- override fun toString(): String {
- return "Arguments(duration=$duration, checkInTime=$checkInTime)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Arguments
-
- if (duration != other.duration) return false
- if (checkInTime != other.checkInTime) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = duration.hashCode()
- result = 31 * result + checkInTime.hashCode()
- return result
- }
-
- class Builder {
- private var duration: Duration? = null
-
- private var checkInTime: ZonedDateTime? = null
-
- fun setDuration(duration: Duration): Builder =
- apply { this.duration = duration }
-
- fun setCheckInTime(checkInTime: ZonedDateTime): Builder =
- apply { this.checkInTime = checkInTime }
-
- fun build(): Arguments = Arguments(duration, checkInTime)
- }
- }
-
- class Output internal constructor(
- val safetyCheck: SafetyCheck?,
- val executionStatus: ExecutionStatus?
- ) {
- override fun toString(): String {
- return "Output(safetyCheck=$safetyCheck, executionStatus=$executionStatus)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Output
-
- if (safetyCheck != other.safetyCheck) return false
- if (executionStatus != other.executionStatus) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = safetyCheck.hashCode()
- result = 31 * result + executionStatus.hashCode()
- return result
- }
-
- class Builder {
- private var safetyCheck: SafetyCheck? = null
-
- private var executionStatus: ExecutionStatus? = null
-
- fun setSafetyCheck(safetyCheck: SafetyCheck): Builder =
- apply { this.safetyCheck = safetyCheck }
-
- fun setExecutionStatus(executionStatus: ExecutionStatus): Builder =
- apply { this.executionStatus = executionStatus }
-
- fun build(): Output = Output(safetyCheck, executionStatus)
- }
- }
-
- class ExecutionStatus {
- private var successStatus: SuccessStatus? = null
- private var genericErrorStatus: GenericErrorStatus? = null
- private var actionNotInProgress: ActionNotInProgress? = null
- private var emergencySharingInProgress: EmergencySharingInProgress? = null
- private var safetyAccountNotLoggedIn: SafetyAccountNotLoggedIn? = null
- private var safetyFeatureNotOnboarded: SafetyFeatureNotOnboarded? = null
- private var noInternetConnection: NoInternetConnection? = null
-
- constructor(successStatus: SuccessStatus) {
- this.successStatus = successStatus
- }
-
- constructor(genericErrorStatus: GenericErrorStatus) {
- this.genericErrorStatus = genericErrorStatus
- }
-
- constructor(actionNotInProgress: ActionNotInProgress) {
- this.actionNotInProgress = actionNotInProgress
- }
-
- constructor(emergencySharingInProgress: EmergencySharingInProgress) {
- this.emergencySharingInProgress = emergencySharingInProgress
- }
-
- constructor(safetyAccountNotLoggedIn: SafetyAccountNotLoggedIn) {
- this.safetyAccountNotLoggedIn = safetyAccountNotLoggedIn
- }
-
- constructor(safetyFeatureNotOnboarded: SafetyFeatureNotOnboarded) {
- this.safetyFeatureNotOnboarded = safetyFeatureNotOnboarded
- }
-
- constructor(noInternetConnection: NoInternetConnection) {
- this.noInternetConnection = noInternetConnection
- }
-
- internal fun toParamValue(): ParamValue {
- var status: String = ""
- if (successStatus != null) {
- status = successStatus.toString()
- }
- if (genericErrorStatus != null) {
- status = genericErrorStatus.toString()
- }
- if (actionNotInProgress != null) {
- status = actionNotInProgress.toString()
- }
- if (emergencySharingInProgress != null) {
- status = emergencySharingInProgress.toString()
- }
- if (safetyAccountNotLoggedIn != null) {
- status = safetyAccountNotLoggedIn.toString()
- }
- if (safetyFeatureNotOnboarded != null) {
- status = safetyFeatureNotOnboarded.toString()
- }
- if (noInternetConnection != null) {
- status = noInternetConnection.toString()
- }
- val value: Value = Value.newBuilder().setStringValue(status).build()
- return ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields(TypeConverters.FIELD_NAME_TYPE, value)
- .build()
- )
- .build()
- }
- }
-
- class Confirmation internal constructor()
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
-
- companion object {
- /** Canonical name for [StartSafetyCheck] capability */
- const val CAPABILITY_NAME = "actions.intent.START_SAFETY_CHECK"
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindParameter(
- SlotMetadata.DURATION.path,
- Arguments::duration,
- Arguments.Builder::setDuration,
- TypeConverters.DURATION_PARAM_VALUE_CONVERTER
- )
- .bindParameter(
- SlotMetadata.CHECK_IN_TIME.path,
- Arguments::checkInTime,
- Arguments.Builder::setCheckInTime,
- TypeConverters.ZONED_DATE_TIME_PARAM_VALUE_CONVERTER
- )
- .bindOutput(
- "safetyCheck",
- Output::safetyCheck,
- ParamValueConverter.of(SAFETY_CHECK_TYPE_SPEC)::toParamValue
- )
- .bindOutput(
- "executionStatus",
- Output::executionStatus,
- ExecutionStatus::toParamValue
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/StopEmergencySharing.kt b/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/StopEmergencySharing.kt
deleted file mode 100644
index b2cf5d4..0000000
--- a/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/StopEmergencySharing.kt
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.safety
-
-import androidx.appactions.builtintypes.experimental.types.ActionNotInProgress
-import androidx.appactions.builtintypes.experimental.types.GenericErrorStatus
-import androidx.appactions.builtintypes.experimental.types.NoInternetConnection
-import androidx.appactions.builtintypes.experimental.types.SuccessStatus
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.safety.executionstatus.SafetyAccountNotLoggedIn
-import androidx.appactions.interaction.capabilities.safety.executionstatus.SafetyFeatureNotOnboarded
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-
-/** A capability corresponding to actions.intent.STOP_EMERGENCY_SHARING */
-@CapabilityFactory(name = StopEmergencySharing.CAPABILITY_NAME)
-class StopEmergencySharing private constructor() {
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder, Arguments, Output, Confirmation, ExecutionSession,
- >(ACTION_SPEC)
-
- class Arguments internal constructor() {
- class Builder {
- fun build(): Arguments = Arguments()
- }
- }
-
- class Output internal constructor(val executionStatus: ExecutionStatus?) {
- override fun toString(): String {
- return "Output(executionStatus=$executionStatus)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Output
-
- if (executionStatus != other.executionStatus) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- return executionStatus.hashCode()
- }
-
- class Builder {
- private var executionStatus: ExecutionStatus? = null
-
- fun setExecutionStatus(executionStatus: ExecutionStatus): Builder =
- apply { this.executionStatus = executionStatus }
-
- fun build(): Output = Output(executionStatus)
- }
- }
-
- class ExecutionStatus {
- private var successStatus: SuccessStatus? = null
- private var genericErrorStatus: GenericErrorStatus? = null
- private var actionNotInProgress: ActionNotInProgress? = null
- private var safetyAccountNotLoggedIn: SafetyAccountNotLoggedIn? = null
- private var safetyFeatureNotOnboarded: SafetyFeatureNotOnboarded? = null
- private var noInternetConnection: NoInternetConnection? = null
-
- constructor(successStatus: SuccessStatus) {
- this.successStatus = successStatus
- }
-
- constructor(genericErrorStatus: GenericErrorStatus) {
- this.genericErrorStatus = genericErrorStatus
- }
-
- constructor(actionNotInProgress: ActionNotInProgress) {
- this.actionNotInProgress = actionNotInProgress
- }
-
- constructor(safetyAccountNotLoggedIn: SafetyAccountNotLoggedIn) {
- this.safetyAccountNotLoggedIn = safetyAccountNotLoggedIn
- }
-
- constructor(safetyFeatureNotOnboarded: SafetyFeatureNotOnboarded) {
- this.safetyFeatureNotOnboarded = safetyFeatureNotOnboarded
- }
-
- constructor(noInternetConnection: NoInternetConnection) {
- this.noInternetConnection = noInternetConnection
- }
-
- internal fun toParamValue(): ParamValue {
- var status: String = ""
- if (successStatus != null) {
- status = successStatus.toString()
- }
- if (genericErrorStatus != null) {
- status = genericErrorStatus.toString()
- }
- if (actionNotInProgress != null) {
- status = actionNotInProgress.toString()
- }
- if (safetyAccountNotLoggedIn != null) {
- status = safetyAccountNotLoggedIn.toString()
- }
- if (safetyFeatureNotOnboarded != null) {
- status = safetyFeatureNotOnboarded.toString()
- }
- if (noInternetConnection != null) {
- status = noInternetConnection.toString()
- }
- val value: Value = Value.newBuilder().setStringValue(status).build()
- return ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields(TypeConverters.FIELD_NAME_TYPE, value)
- .build(),
- )
- .build()
- }
- }
-
- class Confirmation internal constructor()
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
-
- companion object {
- /** Canonical name for [StopEmergencySharing] capability */
- const val CAPABILITY_NAME = "actions.intent.STOP_EMERGENCY_SHARING"
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(
- Arguments::class.java,
- Arguments::Builder,
- Arguments.Builder::build
- )
- .setOutput(Output::class.java)
- .bindOutput(
- "executionStatus",
- Output::executionStatus,
- ExecutionStatus::toParamValue,
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/StopSafetyCheck.kt b/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/StopSafetyCheck.kt
deleted file mode 100644
index bd4795e..0000000
--- a/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/StopSafetyCheck.kt
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.safety
-
-import androidx.appactions.builtintypes.experimental.types.ActionNotInProgress
-import androidx.appactions.builtintypes.experimental.types.GenericErrorStatus
-import androidx.appactions.builtintypes.experimental.types.NoInternetConnection
-import androidx.appactions.builtintypes.experimental.types.SuccessStatus
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.CapabilityFactory
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.capabilities.safety.executionstatus.SafetyAccountNotLoggedIn
-import androidx.appactions.interaction.capabilities.safety.executionstatus.SafetyFeatureNotOnboarded
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-
-/** A capability corresponding to actions.intent.STOP_SAFETY_CHECK */
-@CapabilityFactory(name = StopSafetyCheck.CAPABILITY_NAME)
-class StopSafetyCheck private constructor() {
- class CapabilityBuilder :
- Capability.Builder<
- CapabilityBuilder, Arguments, Output, Confirmation, ExecutionSession
- >(ACTION_SPEC)
-
- class Arguments internal constructor() {
- class Builder {
- fun build(): Arguments = Arguments()
- }
- }
-
- class Output internal constructor(val executionStatus: ExecutionStatus?) {
- override fun toString(): String {
- return "Output(executionStatus=$executionStatus)"
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Output
-
- if (executionStatus != other.executionStatus) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- return executionStatus.hashCode()
- }
-
- class Builder {
- private var executionStatus: ExecutionStatus? = null
-
- fun setExecutionStatus(executionStatus: ExecutionStatus): Builder =
- apply { this.executionStatus = executionStatus }
-
- fun build(): Output = Output(executionStatus)
- }
- }
-
- class ExecutionStatus {
- private var successStatus: SuccessStatus? = null
- private var genericErrorStatus: GenericErrorStatus? = null
- private var actionNotInProgress: ActionNotInProgress? = null
- private var safetyAccountNotLoggedIn: SafetyAccountNotLoggedIn? = null
- private var safetyFeatureNotOnboarded: SafetyFeatureNotOnboarded? = null
- private var noInternetConnection: NoInternetConnection? = null
-
- constructor(successStatus: SuccessStatus) {
- this.successStatus = successStatus
- }
-
- constructor(genericErrorStatus: GenericErrorStatus) {
- this.genericErrorStatus = genericErrorStatus
- }
-
- constructor(actionNotInProgress: ActionNotInProgress) {
- this.actionNotInProgress = actionNotInProgress
- }
-
- constructor(safetyAccountNotLoggedIn: SafetyAccountNotLoggedIn) {
- this.safetyAccountNotLoggedIn = safetyAccountNotLoggedIn
- }
-
- constructor(safetyFeatureNotOnboarded: SafetyFeatureNotOnboarded) {
- this.safetyFeatureNotOnboarded = safetyFeatureNotOnboarded
- }
-
- constructor(noInternetConnection: NoInternetConnection) {
- this.noInternetConnection = noInternetConnection
- }
-
- internal fun toParamValue(): ParamValue {
- var status: String = ""
- if (successStatus != null) {
- status = successStatus.toString()
- }
- if (genericErrorStatus != null) {
- status = genericErrorStatus.toString()
- }
- if (actionNotInProgress != null) {
- status = actionNotInProgress.toString()
- }
- if (safetyAccountNotLoggedIn != null) {
- status = safetyAccountNotLoggedIn.toString()
- }
- if (safetyFeatureNotOnboarded != null) {
- status = safetyFeatureNotOnboarded.toString()
- }
- if (noInternetConnection != null) {
- status = noInternetConnection.toString()
- }
- val value: Value = Value.newBuilder().setStringValue(status).build()
- return ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields(TypeConverters.FIELD_NAME_TYPE, value)
- .build(),
- )
- .build()
- }
- }
-
- class Confirmation internal constructor()
-
- sealed interface ExecutionSession : BaseExecutionSession<Arguments, Output>
-
- companion object {
- /** Canonical name for [StopSafetyCheck] capability */
- const val CAPABILITY_NAME = "actions.intent.STOP_SAFETY_CHECK"
- private val ACTION_SPEC =
- ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindOutput(
- "executionStatus",
- Output::executionStatus,
- ExecutionStatus::toParamValue
- )
- .build()
- init {
- ActionSpecRegistry.registerActionSpec(Arguments::class, Output::class, ACTION_SPEC)
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/executionstatus/EmergencySharingInProgress.kt b/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/executionstatus/EmergencySharingInProgress.kt
deleted file mode 100644
index 0062e26..0000000
--- a/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/executionstatus/EmergencySharingInProgress.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.safety.executionstatus
-
-import androidx.appactions.builtintypes.experimental.properties.Name
-import androidx.appactions.builtintypes.experimental.types.Thing
-
-interface EmergencySharingInProgress : Thing {
- override fun toBuilder(): Builder<*>
-
- companion object {
- @JvmStatic
- fun Builder(): Builder<*> = EmergencySharingInProgressBuilderImpl()
- }
-
- interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
- override fun build(): EmergencySharingInProgress
- }
-}
-
-private class EmergencySharingInProgressBuilderImpl :
- EmergencySharingInProgress.Builder<EmergencySharingInProgressBuilderImpl> {
-
- private var identifier: String? = null
- private var name: Name? = null
-
- override fun build() = EmergencySharingInProgressImpl(identifier, name)
-
- override fun setIdentifier(text: String?): EmergencySharingInProgressBuilderImpl =
- apply { identifier = text }
-
- override fun setName(text: String): EmergencySharingInProgressBuilderImpl =
- apply { name = Name(text) }
-
- override fun setName(name: Name?): EmergencySharingInProgressBuilderImpl =
- apply { this.name = name }
-
- override fun clearName(): EmergencySharingInProgressBuilderImpl = apply { name = null }
-}
-
-private class EmergencySharingInProgressImpl(
- override val identifier: String?,
- override val name: Name?
-) :
- EmergencySharingInProgress {
- override fun toBuilder(): EmergencySharingInProgress.Builder<*> =
- EmergencySharingInProgressBuilderImpl().setIdentifier(identifier).setName(name)
-
- override fun toString(): String = "EmergencySharingInProgress"
-}
diff --git a/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/executionstatus/SafetyAccountNotLoggedIn.kt b/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/executionstatus/SafetyAccountNotLoggedIn.kt
deleted file mode 100644
index 048f0e4..0000000
--- a/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/executionstatus/SafetyAccountNotLoggedIn.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.safety.executionstatus
-
-import androidx.appactions.builtintypes.experimental.properties.Name
-import androidx.appactions.builtintypes.experimental.types.Thing
-
-interface SafetyAccountNotLoggedIn : Thing {
- override fun toBuilder(): Builder<*>
-
- companion object {
- @JvmStatic
- fun Builder(): Builder<*> = SafetyAccountNotLoggedInBuilderImpl()
- }
-
- interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
- override fun build(): SafetyAccountNotLoggedIn
- }
-}
-
-private class SafetyAccountNotLoggedInBuilderImpl :
- SafetyAccountNotLoggedIn.Builder<SafetyAccountNotLoggedInBuilderImpl> {
-
- private var identifier: String? = null
- private var name: Name? = null
-
- override fun build() = SafetyAccountNotLoggedInImpl(identifier, name)
-
- override fun setIdentifier(text: String?): SafetyAccountNotLoggedInBuilderImpl =
- apply { identifier = text }
-
- override fun setName(text: String): SafetyAccountNotLoggedInBuilderImpl =
- apply { name = Name(text) }
-
- override fun setName(name: Name?): SafetyAccountNotLoggedInBuilderImpl =
- apply { this.name = name }
-
- override fun clearName(): SafetyAccountNotLoggedInBuilderImpl = apply { name = null }
-}
-
-private class SafetyAccountNotLoggedInImpl(
- override val identifier: String?,
- override val name: Name?
-) :
- SafetyAccountNotLoggedIn {
- override fun toBuilder(): SafetyAccountNotLoggedIn.Builder<*> =
- SafetyAccountNotLoggedInBuilderImpl().setIdentifier(identifier).setName(name)
-
- override fun toString(): String = "SafetyAccountNotLoggedIn"
-}
diff --git a/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/executionstatus/SafetyFeatureNotOnboarded.kt b/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/executionstatus/SafetyFeatureNotOnboarded.kt
deleted file mode 100644
index 8c3474d..0000000
--- a/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/executionstatus/SafetyFeatureNotOnboarded.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.safety.executionstatus
-
-import androidx.appactions.builtintypes.experimental.properties.Name
-import androidx.appactions.builtintypes.experimental.types.Thing
-
-interface SafetyFeatureNotOnboarded : Thing {
- override fun toBuilder(): Builder<*>
-
- companion object {
- @JvmStatic
- fun Builder(): Builder<*> = SafetyFeatureNotOnboardedBuilderImpl()
- }
-
- interface Builder<Self : Builder<Self>> : Thing.Builder<Self> {
- override fun build(): SafetyFeatureNotOnboarded
- }
-}
-
-private class SafetyFeatureNotOnboardedBuilderImpl :
- SafetyFeatureNotOnboarded.Builder<SafetyFeatureNotOnboardedBuilderImpl> {
-
- private var identifier: String? = null
- private var name: Name? = null
-
- override fun build() = SafetyFeatureNotOnboardedImpl(identifier, name)
-
- override fun setIdentifier(text: String?): SafetyFeatureNotOnboardedBuilderImpl =
- apply { identifier = text }
-
- override fun setName(text: String): SafetyFeatureNotOnboardedBuilderImpl =
- apply { name = Name(text) }
-
- override fun setName(name: Name?): SafetyFeatureNotOnboardedBuilderImpl =
- apply { this.name = name }
-
- override fun clearName(): SafetyFeatureNotOnboardedBuilderImpl = apply { name = null }
-}
-
-private class SafetyFeatureNotOnboardedImpl(
- override val identifier: String?,
- override val name: Name?
-) :
- SafetyFeatureNotOnboarded {
- override fun toBuilder(): SafetyFeatureNotOnboarded.Builder<*> =
- SafetyFeatureNotOnboardedBuilderImpl().setIdentifier(identifier).setName(name)
-
- override fun toString(): String = "SafetyFeatureNotOnboarded"
-}
diff --git a/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/package-info.java b/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/package-info.java
deleted file mode 100644
index 01a762e..0000000
--- a/appactions/interaction/interaction-capabilities-safety/src/main/java/androidx/appactions/interaction/capabilities/safety/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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.
- */
-
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-package androidx.appactions.interaction.capabilities.safety;
-
-import androidx.annotation.RestrictTo;
diff --git a/appactions/interaction/interaction-capabilities-testing/api/current.txt b/appactions/interaction/interaction-capabilities-testing/api/current.txt
deleted file mode 100644
index e6f50d0..0000000
--- a/appactions/interaction/interaction-capabilities-testing/api/current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 4.0
diff --git a/appactions/interaction/interaction-capabilities-testing/api/res-current.txt b/appactions/interaction/interaction-capabilities-testing/api/res-current.txt
deleted file mode 100644
index e69de29..0000000
--- a/appactions/interaction/interaction-capabilities-testing/api/res-current.txt
+++ /dev/null
diff --git a/appactions/interaction/interaction-capabilities-testing/api/restricted_current.txt b/appactions/interaction/interaction-capabilities-testing/api/restricted_current.txt
deleted file mode 100644
index e6f50d0..0000000
--- a/appactions/interaction/interaction-capabilities-testing/api/restricted_current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 4.0
diff --git a/appactions/interaction/interaction-capabilities-testing/build.gradle b/appactions/interaction/interaction-capabilities-testing/build.gradle
deleted file mode 100644
index 6185156..0000000
--- a/appactions/interaction/interaction-capabilities-testing/build.gradle
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-/**
- * This file was created using the `create_project.py` script located in the
- * `<AndroidX root>/development/project-creator` directory.
- *
- * Please use that script when creating a new project, rather than copying an existing project and
- * modifying its settings.
- */
-import androidx.build.LibraryType
-
-plugins {
- id("AndroidXPlugin")
- id("com.android.library")
- id("org.jetbrains.kotlin.android")
-}
-
-dependencies {
- implementation(libs.guavaListenableFuture)
- implementation(libs.kotlinCoroutinesCore)
- implementation(libs.kotlinStdlib)
- implementation("androidx.annotation:annotation:1.1.0")
- implementation("androidx.concurrent:concurrent-futures:1.1.0")
- implementation(project(":appactions:interaction:interaction-capabilities-core"))
-
- // depending on productivity (any vertical works) capability artifact for writing unit tests
- // for this library
- testImplementation(project(":appactions:interaction:interaction-capabilities-productivity"))
- testImplementation(libs.junit)
- testImplementation(libs.truth)
-}
-
-android {
- defaultConfig {
- minSdkVersion 26
- }
- namespace "androidx.appactions.interaction.capabilities.testing.internal"
-}
-
-androidx {
- name = "androidx.appactions.interaction:interaction-capabilities-testing"
- type = LibraryType.PUBLISHED_TEST_LIBRARY
- inceptionYear = "2023"
- description = "Test integrations with App Actions Interactions capabilities libraries."
- metalavaK2UastEnabled = true
-}
diff --git a/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/CapabilityRequest.kt b/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/CapabilityRequest.kt
deleted file mode 100644
index 16e276d..0000000
--- a/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/CapabilityRequest.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.testing
-
-import androidx.annotation.RestrictTo
-import androidx.annotation.VisibleForTesting
-import androidx.appactions.interaction.proto.FulfillmentRequest
-
-/**
- * Represents a request which can be sent to some capability session for unit testing.
- */
-@VisibleForTesting
-class CapabilityRequest @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-constructor(
- @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- val fulfillmentRequest: FulfillmentRequest
-) {
- /**
- * Returns a new CapabilityRequest that sets an identifier to the first Fulfillment in this
- * request.
- * Fulfillments after the first are dropped.
- */
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- fun addCapabilityIdentifier(capabilityIdentifier: String): CapabilityRequest {
- val fulfillment = fulfillmentRequest.getFulfillments(0)
- return CapabilityRequest(
- FulfillmentRequest.newBuilder().addFulfillments(
- fulfillment.toBuilder().setIdentifier(capabilityIdentifier).build()
- ).build()
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/CapabilityResponse.kt b/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/CapabilityResponse.kt
deleted file mode 100644
index 36a0a88..0000000
--- a/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/CapabilityResponse.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.testing
-
-import androidx.annotation.RestrictTo
-import androidx.annotation.VisibleForTesting
-import androidx.appactions.interaction.proto.FulfillmentResponse
-
-/**
- * Represents a request which can be sent to some capability session for unit testing.
- */
-@VisibleForTesting
-class CapabilityResponse @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-constructor(
- @get:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- val fulfillmentResponse: FulfillmentResponse
-)
diff --git a/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/CapabilityTestUtils.kt b/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/CapabilityTestUtils.kt
deleted file mode 100644
index c2e01c7..0000000
--- a/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/CapabilityTestUtils.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.testing
-
-import androidx.annotation.VisibleForTesting
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecRegistry
-import androidx.appactions.interaction.proto.FulfillmentRequest
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.FulfillmentParam
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.FulfillmentValue
-
-/**
- * Contains utility methods and classes for testing any BII capability built with the
- * AppInteraction Capabilities library.
- */
-@VisibleForTesting
-object CapabilityTestUtils {
- /**
- * Create a CapabilityRequest for executing a capability with some Argument instance.
- * @param args an Arguments instance for some AppInteraction capability.
- * @throws [IllegalArgumentException] if [args] is not an instance of a supported Arguments
- * class.
- * Example Usage:
- * ```
- * val arguments = CreateMessage.Arguments.Builder().setMessageText("Hello").build()
- * val capabilityRequest = createCapabilityRequest(arguments)
- * ```
- */
- fun createCapabilityRequest(args: Any): CapabilityRequest {
- val actionSpec = ActionSpecRegistry.getActionSpecForArguments(args)
- if (actionSpec == null) {
- throw IllegalArgumentException(
- "Failed to find associated capability class for arguments of class ${args.javaClass}."
- )
- }
- val fulfillmentParams = actionSpec.serializeArguments(args).map {
- (slotName, paramValues) ->
- FulfillmentParam.newBuilder().setName(slotName).addAllFulfillmentValues(
- paramValues.map { FulfillmentValue.newBuilder().setValue(it).build() }
- ).build()
- }
- return CapabilityRequest(
- FulfillmentRequest.newBuilder().addFulfillments(
- Fulfillment.newBuilder()
- .setName(actionSpec.capabilityName)
- .addAllParams(fulfillmentParams)
- .build()
- ).build()
- )
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/internal/ArgumentUtils.kt b/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/internal/ArgumentUtils.kt
deleted file mode 100644
index a452ee0..0000000
--- a/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/internal/ArgumentUtils.kt
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.testing.internal
-
-import androidx.appactions.interaction.capabilities.core.impl.ArgumentsWrapper
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.FulfillmentParam
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.FulfillmentValue
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.protobuf.Struct
-import androidx.appactions.interaction.protobuf.Value
-
-object ArgumentUtils {
- /**
- * Useful for one-shot BIIs where the task data is not needed and the ParamValues are singular.
- */
- fun buildArgs(args: Map<String, ParamValue>): ArgumentsWrapper {
- return buildListArgs(args.mapValues { listOf(it.value) })
- }
-
- /** Useful for one-shot BIIs where the task data is not needed. */
- fun buildListArgs(args: Map<String, List<ParamValue>>): ArgumentsWrapper {
- val builder = Fulfillment.newBuilder()
- for ((key, valueList) in args) {
- val paramBuilder = FulfillmentParam.newBuilder().setName(key)
- for (value in valueList) {
- builder.addParams(
- paramBuilder.addFulfillmentValues(
- FulfillmentValue.newBuilder().setValue(value).build()
- )
- )
- }
- }
- return ArgumentsWrapper.create(builder.build())
- }
-
- private fun toParamValue(argVal: Any): ParamValue {
- when (argVal) {
- is Int -> {
- return ParamValue.newBuilder().setNumberValue(argVal.toDouble()).build()
- }
-
- is Double -> {
- return ParamValue.newBuilder().setNumberValue(argVal).build()
- }
-
- is String -> {
- return ParamValue.newBuilder().setStringValue(argVal).build()
- }
-
- is Enum<*> -> {
- return ParamValue.newBuilder().setIdentifier(argVal.toString()).build()
- }
-
- is ParamValue -> {
- return argVal
- }
-
- else -> throw IllegalArgumentException("invalid argument type.")
- }
- }
-
- fun buildSearchActionParamValue(query: String): ParamValue {
- return ParamValue.newBuilder()
- .setStructValue(
- Struct.newBuilder()
- .putFields(
- "@type",
- Value.newBuilder().setStringValue("SearchAction").build()
- )
- .putFields(
- "query",
- Value.newBuilder().setStringValue(query).build()
- )
- .build()
- )
- .build()
- }
-
- /**
- * Convenience method to build ArgumentsWrapper based on plain java types. Input args should be
- * even in length, where each String argName is followed by any type of argVal. This method
- * will use SLOTS_COMPLETE as the default value for the SyncStatus
- */
- fun buildRequestArgs(
- type: Fulfillment.Type,
- vararg args: Any,
- ): ArgumentsWrapper {
- return buildRequestArgs(type, Fulfillment.SyncStatus.SLOTS_COMPLETE, *args)
- }
-
- /**
- * Convenience method to build ArgumentsWrapper based on plain java types and
- * also sets the SyncStatus. Input args should be even in length, where each String
- * argName is followed by any type of argVal.
- */
- fun buildRequestArgs(
- type: Fulfillment.Type,
- syncStatus: Fulfillment.SyncStatus,
- vararg args: Any,
- ): ArgumentsWrapper {
- val builder = Fulfillment.newBuilder().addAllParams(buildFulfillmentParams(*args))
- if (type != Fulfillment.Type.UNRECOGNIZED) {
- builder.type = type
- if (type == Fulfillment.Type.SYNC &&
- syncStatus != Fulfillment.SyncStatus.UNRECOGNIZED) {
- builder.syncStatus = syncStatus
- }
- }
- return ArgumentsWrapper.create(builder.build())
- }
-
- private fun buildFulfillmentParams(vararg args: Any): List<FulfillmentParam> {
- if (args.isEmpty()) {
- return emptyList()
- }
- val fulfillmentParams = mutableListOf<FulfillmentParam>()
- require(args.size % 2 == 0) { "Must call function with even number of args" }
- val argsMap: MutableMap<String, MutableList<ParamValue>> = LinkedHashMap()
- var argNamePos = 0
- var argValPos = 1
- while (argValPos < args.size) {
- require(args[argNamePos] is String) {
- ("Argument must be instance of String but got: ${args[argNamePos].javaClass}")
- }
- val argName = args[argNamePos] as String
- val paramValue: ParamValue = toParamValue(
- args[argValPos]
- )
- argsMap.computeIfAbsent(
- argName
- ) { ArrayList() }
- argsMap[argName]?.add(paramValue)
- argNamePos += 2
- argValPos += 2
- }
- for ((key, valueList) in argsMap.entries) {
- val paramBuilder = FulfillmentParam.newBuilder().setName(key)
- for (value in valueList) {
- fulfillmentParams.add(
- paramBuilder.addFulfillmentValues(
- FulfillmentValue.newBuilder().setValue(value).build()
- ).build()
- )
- }
- }
- return fulfillmentParams.toList()
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/internal/FakeCallbackInternal.kt b/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/internal/FakeCallbackInternal.kt
deleted file mode 100644
index 960f8d0..0000000
--- a/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/internal/FakeCallbackInternal.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.testing.internal
-
-import androidx.appactions.interaction.capabilities.core.impl.CallbackInternal
-import androidx.appactions.interaction.capabilities.core.impl.ErrorStatusInternal
-import androidx.appactions.interaction.capabilities.core.impl.FulfillmentResult
-import androidx.appactions.interaction.proto.FulfillmentResponse
-import kotlinx.coroutines.CompletableDeferred
-
-/**
- * A fake CallbackInternal instance being used for testing to receive the [FulfillmentResult]
- * containing either [FulfillmentResponse] or [ErrorStatusInternal]
- */
-class FakeCallbackInternal constructor(
- private val timeoutMs: Long = TestingUtils.CB_TIMEOUT,
-) : CallbackInternal {
-
- private val completer = CompletableDeferred<FulfillmentResult>()
-
- override fun onSuccess(fulfillmentResponse: FulfillmentResponse) {
- completer.complete(FulfillmentResult(fulfillmentResponse))
- }
-
- override fun onError(errorStatus: ErrorStatusInternal) {
- completer.complete(FulfillmentResult(errorStatus))
- }
-
- fun receiveResponse(): FulfillmentResult = with(TestingUtils) {
- completer.awaitSync(timeoutMs)
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/internal/TestingUtils.kt b/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/internal/TestingUtils.kt
deleted file mode 100644
index 39c7d77..0000000
--- a/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/internal/TestingUtils.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.testing.internal
-
-import androidx.appactions.interaction.capabilities.core.ExecutionCallbackAsync
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures
-import kotlinx.coroutines.Deferred
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.withTimeout
-
-object TestingUtils {
- // use this timeout for things that should take negligible time.
- const val CB_TIMEOUT = 1000L
-
- // use this timeout for waiting an arbitrary period of time.
- const val BLOCKING_TIMEOUT = 300L
-
- fun <ArgumentsT, OutputT> createFakeExecutionCallback():
- ExecutionCallbackAsync<ArgumentsT, OutputT> {
- return ExecutionCallbackAsync { _: ArgumentsT ->
- Futures.immediateFuture(
- ExecutionResult.Builder<OutputT>().build()
- )
- }
- }
-
- /** Blocks the current thread until the Deferred is completed, or times out. */
- fun <T> Deferred<T>.awaitSync(timeoutMs: Long = CB_TIMEOUT): T =
- runBlocking {
- withTimeout(timeoutMs) {
- [email protected]()
- }
- }
-}
diff --git a/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/internal/package-info.java b/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/internal/package-info.java
deleted file mode 100644
index c5871f6..0000000
--- a/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/internal/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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.
- */
-
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-package androidx.appactions.interaction.capabilities.testing.internal;
-
-import androidx.annotation.RestrictTo;
diff --git a/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/package-info.java b/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/package-info.java
deleted file mode 100644
index fd06784..0000000
--- a/appactions/interaction/interaction-capabilities-testing/src/main/java/androidx/appactions/interaction/capabilities/testing/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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.
- */
-
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-package androidx.appactions.interaction.capabilities.testing;
-
-import androidx.annotation.RestrictTo;
diff --git a/appactions/interaction/interaction-capabilities-testing/src/test/java/androidx/appactions/interaction/capabilities/testing/CapabilityTestUtilsTest.kt b/appactions/interaction/interaction-capabilities-testing/src/test/java/androidx/appactions/interaction/capabilities/testing/CapabilityTestUtilsTest.kt
deleted file mode 100644
index 1efb0e3..0000000
--- a/appactions/interaction/interaction-capabilities-testing/src/test/java/androidx/appactions/interaction/capabilities/testing/CapabilityTestUtilsTest.kt
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.appactions.interaction.capabilities.testing
-
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.productivity.StartTimer
-import androidx.appactions.interaction.proto.FulfillmentRequest
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.FulfillmentParam
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.FulfillmentValue
-import androidx.appactions.interaction.proto.ParamValue
-import com.google.common.truth.Truth.assertThat
-import java.time.Duration
-import org.junit.Assert.assertThrows
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class CapabilityTestUtilsTest {
- // triggers StartTimer companion object init
- val unusedCapability = StartTimer.CapabilityBuilder()
- .setId("unusedStartTimer")
- .setExecutionCallback(ExecutionCallback {
- ExecutionResult.Builder<StartTimer.Output>().build()
- })
- .build()
-
- @Test
- fun invalidArgs_throwsException() {
- val thrown = assertThrows(IllegalArgumentException::class.java, {
- CapabilityTestUtils.createCapabilityRequest(Any())
- })
- assertThat(thrown).hasMessageThat().isEqualTo(
- "Failed to find associated capability class for arguments of class class java.lang.Object."
- )
- }
-
- @Test
- fun startTimerArgs_serializesArgs() {
- val startTimerArgs = StartTimer.Arguments.Builder()
- .setIdentifier("timerId")
- .setName("my timer")
- .setDuration(Duration.ofDays(3))
- .build()
-
- val fulfillmentRequest = CapabilityTestUtils.createCapabilityRequest(
- startTimerArgs
- ).addCapabilityIdentifier("unusedStartTimer").fulfillmentRequest
-
- assertThat(fulfillmentRequest).isEqualTo(
- FulfillmentRequest.newBuilder()
- .addFulfillments(
- Fulfillment.newBuilder()
- .setName(StartTimer.CAPABILITY_NAME)
- .setIdentifier("unusedStartTimer")
- .addParams(
- FulfillmentParam.newBuilder().setName("timer.identifier").addFulfillmentValues(
- FulfillmentValue.newBuilder().setValue(
- ParamValue.newBuilder().setStringValue("timerId")
- )
- )
- )
- .addParams(
- FulfillmentParam.newBuilder().setName("timer.name").addFulfillmentValues(
- FulfillmentValue.newBuilder().setValue(
- ParamValue.newBuilder().setStringValue("my timer")
- )
- )
- )
- .addParams(
- FulfillmentParam.newBuilder().setName("timer.duration").addFulfillmentValues(
- FulfillmentValue.newBuilder().setValue(
- ParamValue.newBuilder().setStringValue("PT72H")
- )
- )
- )
- )
- .build()
- )
- }
-}
diff --git a/appactions/interaction/interaction-proto/api/current.txt b/appactions/interaction/interaction-proto/api/current.txt
deleted file mode 100644
index e6f50d0..0000000
--- a/appactions/interaction/interaction-proto/api/current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 4.0
diff --git a/appactions/interaction/interaction-proto/api/res-current.txt b/appactions/interaction/interaction-proto/api/res-current.txt
deleted file mode 100644
index e69de29..0000000
--- a/appactions/interaction/interaction-proto/api/res-current.txt
+++ /dev/null
diff --git a/appactions/interaction/interaction-proto/api/restricted_current.txt b/appactions/interaction/interaction-proto/api/restricted_current.txt
deleted file mode 100644
index e6f50d0..0000000
--- a/appactions/interaction/interaction-proto/api/restricted_current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 4.0
diff --git a/appactions/interaction/interaction-proto/build.gradle b/appactions/interaction/interaction-proto/build.gradle
deleted file mode 100644
index 72ed0dc..0000000
--- a/appactions/interaction/interaction-proto/build.gradle
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2022 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.LibraryType
-
-plugins {
- id("AndroidXPlugin")
- id("com.android.library")
- id("com.github.johnrengelman.shadow")
- id("com.google.protobuf")
-}
-
-configurations {
- shadowed
- compileOnly.extendsFrom(shadowed)
- testCompile.extendsFrom(shadowed)
- shadowJar // configuration containing Jar built by shadow plugin
- protoJar // configuration containing compiled proto and source
-}
-
-dependencies {
- shadowed(libs.protobufLite)
-
- implementation("androidx.annotation:annotation:1.1.0")
-}
-
-task protoLiteJar(type: com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
- archiveClassifier = 'proto-lite-jar'
- dependsOn(":appactions:interaction:interaction-proto:syncReleaseLibJars")
- from("${buildDir}/intermediates/aar_main_jar/release")
-}
-assemble.dependsOn(protoLiteJar)
-
-task shadowJar(type: com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
- archiveClassifier = 'shadow-jar'
- configurations = [project.configurations.shadowed]
- dependsOn(protoLiteJar)
- from(protoLiteJar.archiveFile)
- relocate "com.google.protobuf", "androidx.appactions.interaction.protobuf"
- exclude("**/*.proto")
-}
-assemble.dependsOn(shadowJar)
-
-artifacts {
- // Specifies the output files for the shadowJar and protoJar configurations
- shadowJar shadowJar.archiveFile
- protoJar protoLiteJar.archiveFile
-}
-
-protobuf {
- protoc {
- artifact = libs.protobufCompiler.get()
- }
- generateProtoTasks {
- all().each { task ->
- task.builtins {
- java {
- option "lite"
- }
- }
- }
- }
-}
-
-android {
- namespace "androidx.appactions.interaction.proto"
- defaultConfig {
- }
- libraryVariants.all { variant ->
- // Replace the default jar with the shadow jar in the AAR.
- def packageLib = variant.getPackageLibraryProvider().get()
- packageLib.exclude('classes.jar')
- packageLib.into('') {
- from(project.tasks.getByName("shadowJar").outputs)
- rename { "classes.jar" }
- }
- }
- lintOptions {
- // protobuf generates unannotated methods
- disable("UnknownNullness")
- }
-}
-
-androidx {
- name = "androidx.appactions.interaction:interaction-proto"
- type = LibraryType.PUBLISHED_LIBRARY
- inceptionYear = "2022"
- description = "Protos for use with App Action interaction libraries."
- metalavaK2UastEnabled = true
- doNotDocumentReason = "No public API"
-}
diff --git a/appactions/interaction/interaction-proto/src/main/java/androidx/appactions/interaction/proto/package-info.java b/appactions/interaction/interaction-proto/src/main/java/androidx/appactions/interaction/proto/package-info.java
deleted file mode 100644
index 7de97d8..0000000
--- a/appactions/interaction/interaction-proto/src/main/java/androidx/appactions/interaction/proto/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2022 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.
- */
-
-@RestrictTo(RestrictTo.Scope.LIBRARY)
-package androidx.appactions.interaction.proto;
-
-import androidx.annotation.RestrictTo;
\ No newline at end of file
diff --git a/appactions/interaction/interaction-proto/src/main/proto/app_actions_data.proto b/appactions/interaction/interaction-proto/src/main/proto/app_actions_data.proto
deleted file mode 100644
index 4e2e9dd..0000000
--- a/appactions/interaction/interaction-proto/src/main/proto/app_actions_data.proto
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * Copyright (C) 2022 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.
- */
-syntax = "proto3";
-
-package androidx.appactions.interaction.proto;
-
-import "google/protobuf/struct.proto";
-
-option java_package = "androidx.appactions.interaction.proto";
-option java_outer_classname = "AppActionsDataProto";
-option java_multiple_files = true;
-
-message ParamValue {
- // If this parameter matched an Entity, `identifier` of that Entity.
- optional string identifier = 1;
-
- oneof value {
- string string_value = 2;
- bool bool_value = 3;
- double number_value = 4;
- google.protobuf.Struct struct_value = 6;
- }
- reserved 5; // Deleted DateTime value.
-}
-
-message Entity {
- // A unique identifier of the entity.
- optional string identifier = 1;
-
- // Name of the entity
- string name = 2;
-
- // Alternate names for the entity.
- repeated string alternate_names = 3;
-
- oneof entity_value {
- // Structured entity value.
- google.protobuf.Struct struct_value = 4;
- string string_value = 5;
- bool bool_value = 6;
- double number_value = 7;
- }
-}
-
-// Data for disambiguation of the parameter value.
-message DisambiguationData {
- // Entities used to disambiguate the parameter value.
- repeated Entity entities = 1;
-}
-
-// Current value from the app for the associated param.
-// Next ID: 4
-message CurrentValue {
- // Current value of the associated parameter. Must have an entity identifier
- // if the status == ACCEPTED.
- ParamValue value = 1;
-
- enum Status {
- UNKNOWN = 0;
- // The value has been set for the associated parameter, but the app hasn't
- // validated it yet. This usually happens when the app is prompting other
- // parameter and want to handle this one later.
- PENDING = 1;
- // This value needs to be disambiguated through assistant.
- DISAMBIG = 4;
- // This value is accepted for this parameter during this dialogue.
- ACCEPTED = 2;
- // This value is rejected by this dialogue.
- REJECTED = 3;
- }
-
- // Data for disambiguate this value. Only be filled if status == DISAMBIG.
- DisambiguationData disambiguation_data = 3;
-
- // The state of the parameter value, which can be pending, accepted or
- // rejected.
- Status status = 2;
-}
-
-// Represents the data to describe app actions.
-// Next ID: 5
-message AppActionsContext {
-
- message AppAction {
- // Name of the intent. For example: actions.intent.UPDATE_FORM_FIELD
- string name = 1;
-
- // One intent can be registered multiple times. Use this field to identify
- // the intents. Developers can set this field via `fulfillmentId` in both shortcuts.xml and the
- // Capability library of the AppInteractionSDK.
- string identifier = 2;
-
- repeated IntentParameter params = 4;
-
- // The importance of this App Action, ranging from -10 to 10. The higher the
- // number, the higher its priority. If there are multiple App Actions with
- // the same name, and different identifier, then the action with the higher
- // priority will be selected.
- optional int32 priority = 5;
-
- // Describes the dialog status for this action. If does not exist, app
- // action must be fulfilled as one-shot action.
- optional TaskInfo task_info = 6;
-
- // Set to true if the capability requires confirmation OR if the capability
- // has optional confirmation and the developer has provided a confirmation
- // callback.
- bool needs_confirmation = 7;
-
- // Describes the restrictions needed to execute this action.
- // It would be set by the app and checked by the assistant to ensure the
- // restrictions can be supported.
- repeated Restriction restrictions = 8;
- }
-
- // Next ID: 9
- message IntentParameter {
- // The built-in-intent parameter name. For example: "textField.name".
- string name = 1;
-
- // Current values of the associated parameter.
- repeated CurrentValue current_value = 7 [deprecated = true];
-
- // List of possible values for this parameter.
- repeated Entity possible_entities = 3;
-
- // Whether this parameter is required for the intent.
- //
- // If true, Assistant won't send the fulfillment request to the app when
- // the parameter is absent from the user query.
- bool is_required = 4;
-
- // Whether the entity matched is required for this intent.
- //
- // If true, Assistant will skip this parameter if the argument from the user
- // query doesn't match any of the possible entities.
- bool entity_match_required = 5;
-
- // If true, Assistant will reject this capability if this param is set in
- // argument.
- //
- // Note: when an intent parameter is prohibited, it cannot be required, nor
- // can it require entity match; therefore, even if |is_required| or
- // |entity_match_required| is set to true, they would be simply ignored.
- bool is_prohibited = 6;
-
- // Whether or not this parameter field is focused right now.
- // If yes, it usually suggests that Assistant will prompt the value for this
- // argument.
- bool is_focused = 8 [deprecated = true];
-
- reserved 2;
- }
-
- message AppDialogState {
- // Each App capability can be associated with multiple dialogs. Use this
- // field to identify the dialog instance.
- string session_identifier = 1;
-
- // Identifier of the corresponding capability that this dialog state maps
- // to. This field maps to AppActionsContext.AppAction.identifier.
- string fulfillment_identifier = 2;
-
- // List of BII intent parameters of this dialog.
- repeated DialogParameter params = 3;
-
- // Validation errors of this dialog, including both slot-level and
- // task-level validation errors. Leave empty if validation is successful.
- repeated ValidationError validation_errors = 4;
- }
-
- message DialogParameter {
- // The built-in-intent parameter name. For example: "textField.name".
- string name = 1;
-
- // Current values of the associated parameter.
- repeated CurrentValue current_value = 2;
-
- bool is_focused = 3 [deprecated = true];
- }
-
- message ValidationError {
- message Slot {
- // Name of this slot, e.g. "timer.duration".
- string name = 1;
- }
-
- // The list of slots that are affected by this error.
- repeated Slot slots = 1;
-
- // TODO(b/269659830): Add link to below description.
- // The validation error status with parameters (if any), where all parameter
- // values should use the string type. These will correspond to the supported
- // validation errors defined in BII definitions (link), and transformed
- // as described in (link). For example, DurationTooShort with parameter min
- // duration 1 second can be represented as such:
- //
- // fields {
- // key: "@type"
- // value: { string_value: "DurationTooShort" }
- // }
- // fields {
- // key: "minDuration"
- // value: { string_value: "PT1S" }
- // }
- google.protobuf.Struct error = 2;
- }
-
-
- // Current version of the protocol. Populated with from the interaction-capabiliites-core library.
- optional Version version = 4;
-
- // Represents the dynamic capabilities declared by an App. Capabilities
- // declare the types of actions a developer can take to launch an app and jump
- // directly to performing a specific task. Dynamic capabilities are not
- // declared in shortcuts.xml, but are added during runtime.
- repeated AppAction actions = 1;
-
- // Represents the current dialog state, which is a list of built-in-intent
- // parameters and corresponding values from users. App
- // Dialog is a transaction session of intent and intent parameters.
- repeated AppDialogState dialog_states = 3;
-
- // This field contains the info for current focused text input.
- TextInputState text_input_state = 2;
-}
-
-// Next ID: 3
-message TaskInfo {
- reserved 2;
-
- // Whether the app supports partial fulfillment with multi-turn dialog.
- bool supports_partial_fulfillment = 1;
-}
-
-// Represents the data used to perform an intent.
-// Next ID: 7
-message FulfillmentRequest {
- message Fulfillment {
- // Name of the intent. For example: actions.intent.UPDATE_FORM_FIELD
- string name = 1;
-
- // The identifier of the intent. This field is corresponding to the
- // |identifier| field with in `AppActionsContext.AppAction`.
- string identifier = 2;
-
- message FulfillmentValue {
- // The resolved value for the parameter.
- ParamValue value = 1;
-
- // Contains a list of disambig entities for the param.
- // If not empty, this indicates to render the disambiguation options for
- // this value.
- DisambiguationData disambig_data = 2;
- }
-
- message FulfillmentParam {
- // The alias for the built-in-intent parameter. For example:
- // "textField.name".
- string name = 1;
-
- // The updated values for this parameter.
- repeated ParamValue values = 2 [deprecated = true];
-
- // The values and disambig data for this parameter.
- repeated FulfillmentValue fulfillment_values = 3;
- }
-
- repeated FulfillmentParam params = 3;
-
- enum Type {
- UNKNOWN_TYPE = 0;
- // Assistant is asking to sync the current state with the app. The intent
- // will be executed if:
- // - App-side checks have passed:
- // - no validation failures
- // - no intent (value) suggestions
- // - no confirmation suggestions or user has confirmed intent
- // - Assistant-side checks have passed
- SYNC = 1;
- // Assistant confirms an ongoing task with the app.
- // Deprecated: set SyncStatus = INTENT_CONFIRMED instead.
- CONFIRM = 2 [deprecated = true];
- // Assistant cancels an ongoing task of the app.
- CANCEL = 3;
- // Deprecated: Delete this enum value after cleaning up references
- TERMINATE = 4 [deprecated = true];
- }
-
- enum SyncStatus {
- UNKNOWN_SYNC_STATUS = 0;
- // Assistant-side checks have not passed and the App should not execute
- // yet even if App-side checks pass.
- SLOTS_INCOMPLETE = 1;
- // Assistant-side checks have passed. The App may execute or suggest
- // confirmation if App-side validation succeeds.
- SLOTS_COMPLETE = 2;
- // User confirmed the intent and the App should execute. This indicates
- // that the App has requested confirmation so it should not request
- // confirmation again.
- INTENT_CONFIRMED = 3;
- }
-
- // The Type of this Fulfillment. Not applicable for one-shot Fulfillment.
- optional Type type = 5;
-
- // The status of the SYNC request. Only set when fulfillment type == SYNC.
- optional SyncStatus sync_status = 6;
-
- reserved 4;
- }
-
- // This field should be treated as an optional field. Only the first
- // fulfilment will be respected if multiple fulfillment exists.
- repeated Fulfillment fulfillments = 1;
-}
-
-message FulfillmentResponse {
- SpeechResponse speech_response = 1;
-
- // Whether Assistant should start dictation as a result of performing this
- // direct action.
- bool start_dictation = 2;
-
- message StructuredOutput {
- message OutputValue {
- // The name of the output parameter.
- string name = 1;
-
- // The value of the output.
- repeated ParamValue values = 2;
- }
-
- // The output values.
- repeated OutputValue output_values = 1;
- }
-
- oneof output {
- // The output of the execution returned to Assistant.
- StructuredOutput execution_output = 3;
- // The output for confirmation returned to Assistant.
- StructuredOutput confirmation_data = 4;
- }
-
- message SpeechResponse {
- oneof response {
- // On receipt, assistant will see whether this is an SSML response
- // or plain text for TTS generation.
- string text_to_speech = 1;
- }
- // The language of the response in IETF BCP 47 format. e.g. "en-US".
- // This will be used to generate TTS with the correct language.
- string language = 2;
- }
-}
-
-// Represents the data related to input field state. It includes the app action
-// info associated to focusable text inputs, and also focus and content state of
-// the text input field.
-message TextInputState {
- // Contains the app action info used to look up the app action and entity name
- // for the focusable input state.
- repeated ActionBinding action_binding = 1;
-
- message ActionBinding {
- // The id of app action which the focusable property belong to.
- string action_identifier = 1;
-
- // The id of entity associated with the input field.
- string focusable_property_identifier = 2;
-
- // Whether the text input related to this action is focused.
- bool is_focused = 3;
-
- // Current state of input content.
- ContentState content_state = 4;
- }
-
- enum ContentState {
- UNKNOWN = 0;
- // Current input has no content.
- NO_CONTENT = 1;
- // Current input has content
- HAS_CONTENT = 2;
- }
-}
-
-// Versioning to maintain compatibility
-message Version {
- // The major version.
- optional uint64 major = 1;
-
- // The minor version.
- optional uint64 minor = 2;
-
- // The patch version.
- optional uint64 patch = 3;
-
- // The prerelease version suffix.
- optional string prerelease_id = 4;
-}
-
-// Restrictions to run a specific AppAction.
-message Restriction {
- oneof requirement {
- // If true, the corresponding AppAction requires assistant to
- // start dictation.
- bool text_input = 1;
- }
-}
-
-// Represents the result of sending an execution request to a capability.
-// NEXT_ID: 2
-message AppInteractionMetadata {
-
- // The error status of capability execution.
- // NEXT_ID: 10
- enum ErrorStatus {
- // Unexpected error occurred.
- UNKNOWN_ERROR_STATUS = 0;
- // The current capability session was cancelled, likely because a new request was sent to the
- // capability before the first had time to complete.
- CANCELED = 1;
- // Developer provided callback has timed out. Note, there might be a transport level timeout in
- // addition to the capability specific one, which may be less than the capability timeout. In
- // such cases, the capability should receive a fulfillment request with CANCEL status.
- TIMEOUT = 2;
- // Invalid data was sent to the capability. This could be a nonsensical request Type or
- // malformed arguments (e.g. wrong data format for a BII argument).
- INVALID_REQUEST = 3;
- // An exception was thrown from a developer-provided callback.
- EXTERNAL_EXCEPTION = 7;
- // Tried to send request to a particular capability session, but that session has not been
- // started or has already ended.
- SESSION_NOT_FOUND = 8;
- // Tried to start up a session for a particular capability ID but the capability was not found.
- CAPABILITY_NOT_FOUND = 9;
- // UI was requested but there is no UI currently set.
- NO_UI_ELEMENTS = 10;
- // Internal error occurred.
- INTERNAL = 11;
- }
-
- // ErrorStatus of capability execution. Can be logged to a dashboard to
- ErrorStatus error_status = 1;
-}
diff --git a/appactions/interaction/interaction-proto/src/main/proto/grounding.proto b/appactions/interaction/interaction-proto/src/main/proto/grounding.proto
deleted file mode 100644
index dd894b1..0000000
--- a/appactions/interaction/interaction-proto/src/main/proto/grounding.proto
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2022 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.
- */
-syntax = "proto3";
-
-package androidx.appactions.interaction.proto;
-
-import "app_actions_data.proto";
-
-option java_package = "androidx.appactions.interaction.proto";
-option java_outer_classname = "GroundingProto";
-option java_multiple_files = true;
-
-message GroundingRequest {
- message Request {
- // SearchAction retrieved from the descriptor.
- optional .androidx.appactions.interaction.proto.ParamValue search_action = 1;
-
- // Max number of the results to return, API may return less results.
- // If this is not set, default will be ${fixed number we defined}.
- optional int32 page_size = 2;
-
- // Token to get the subsequent page, it’s retrieved by the last API call.
- optional bytes page_token = 3;
-
- // Identifier of the expected EntityProvider.
- optional string entity_provider_id = 4;
- }
-
- optional Request request = 1;
-}
-
-message GroundingResponse {
- enum Status {
- DEFAULT_UNKNOWN = 0;
- SUCCESS = 1;
- TIMEOUT = 2; // Entity lookup timeout.
- CANCELED = 3; // Entity lookup canceled, e.g. caller cancels the RPC.
- INVALID_PAGE_TOKEN =
- 4; // Invalid the token when querying the following pages.
- INVALID_ENTITY_ARGUMENT = 5; // Entity cannot be parsed correctly.
- INVALID_ENTITY_PROVIDER = 6; // EntityProvider cannot be found.
- }
-
- message Candidate {
- // Information for the grounded entity.
- optional .androidx.appactions.interaction.proto.Entity grounded_entity = 1;
- }
-
- message Response {
- // Whether the request succeeds or the reason of the failure.
- optional Status status = 1;
-
- repeated Candidate candidates = 2;
-
- // The token to retrieve candidates from the next page, will not be omitted
- // if there are no more candidates.
- optional bytes next_page_token = 3;
- }
-
- optional Response response = 1;
-}
diff --git a/appactions/interaction/interaction-proto/src/main/proto/handover.proto b/appactions/interaction/interaction-proto/src/main/proto/handover.proto
deleted file mode 100644
index b48c3d5..0000000
--- a/appactions/interaction/interaction-proto/src/main/proto/handover.proto
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2022 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.
- */
-syntax = "proto3";
-
-package androidx.appactions.interaction.proto;
-
-import "app_actions_data.proto";
-
-option java_package = "androidx.appactions.interaction.proto";
-option java_outer_classname = "HandoverProto";
-option java_multiple_files = true;
-
-// Result of the App Control Handover intent execution.
-// Next ID: 4
-message HandoverResult {
- // The identifier of the executed `FulfillmentRequest.Fulfillment`. This field
- // corresponds to the |identifier| field in `AppActionsContext.AppAction`.
- string fulfillment_identifier = 1;
-
- // The intent name of the executed `FulfillmentRequest.Fulfillment`.
- // For example: actions.intent.UPDATE_ITEM_LIST.
- string fulfillment_name = 2;
-
- // Result of the executed `FulfillmentRequest`.
- FulfillmentResponse fulfillment_response = 3;
-}
diff --git a/appactions/interaction/interaction-proto/src/main/proto/touch_event.proto b/appactions/interaction/interaction-proto/src/main/proto/touch_event.proto
deleted file mode 100644
index b7bad70..0000000
--- a/appactions/interaction/interaction-proto/src/main/proto/touch_event.proto
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2022 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.
- */
-syntax = "proto3";
-
-package androidx.appactions.interaction.proto;
-
-option java_package = "androidx.appactions.interaction.proto";
-option java_outer_classname = "TouchEventProto";
-option java_multiple_files = true;
-
-// Additional metadata that was generated from the developer manually setting
-// some BII args. Note: context updates are reflected in AppActionsContext, and
-// single-turn data like BII outputs should be in FulfillmentResponse.
-message TouchEventMetadata {}
diff --git a/appactions/interaction/interaction-service-proto/build.gradle b/appactions/interaction/interaction-service-proto/build.gradle
deleted file mode 100644
index ca8bcc1..0000000
--- a/appactions/interaction/interaction-service-proto/build.gradle
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-/**
- * This file was created using the `create_project.py` script located in the
- * `<AndroidX root>/development/project-creator` directory.
- *
- * Please use that script when creating a new project, rather than copying an existing project and
- * modifying its settings.
- */
-import androidx.build.Publish
-import androidx.build.RunApiTasks
-
-plugins {
- id("AndroidXPlugin")
- id("java-library")
- id("com.google.protobuf")
-}
-
-dependencies {
- implementation(libs.grpcProtobufLite) {
- // Ensure we only bundle grpc-protobuf-lite. Any of its dependencies should be added
- // as `compileOnly` dependencies below.
- exclude group: 'com.google.protobuf'
- exclude group: 'com.google.guava'
- exclude group: 'io.grpc'
- exclude group: 'com.google.code.findbugs'
- }
-
- // We need to use the non-shadow configurations at compile time to pick up the protos at the
- // original package location (before renaming) since that's what the compiled service protos
- // expect. The final AAR (interaction-service) will have the renamed/shadowed configurations.
- compileOnly(project(path:":appactions:interaction:interaction-proto", configuration:"protoJar"))
-
- // These are the compile-time dependencies needed to build the interaction-service-proto
- // with the grpc-protobuf-lite dependencies bundled. They need to be added as dependencies in
- // any library that bundles interaction-service-proto.
- compileOnly(libs.protobufLite)
- compileOnly(libs.grpcStub)
- compileOnly(libs.jsr250)
- compileOnly("androidx.annotation:annotation:1.1.0")
-}
-
-protobuf {
- protoc {
- artifact = libs.protobufCompiler.get()
- }
- // Configure the codegen plugins for GRPC.
- plugins {
- grpc {
- artifact = libs.grpcProtobufCompiler.get()
- }
- }
-
- generateProtoTasks {
- // Add any additional directories specified in the "main" source set to the Java
- // source directories of the main source set.
- ofSourceSet("main").each { task ->
- project.sourceSets.main.java.srcDir(task)
- }
- all().each { task ->
- task.builtins {
- java {
- option "lite"
- }
- }
- task.plugins {
- grpc {
- option 'lite'
- }
- }
- }
- }
-}
-
-afterEvaluate {
- lint {
- lintOptions {
- // protobuf generates unannotated methods
- disable("UnknownNullness")
- abortOnError(false)
- checkReleaseBuilds(false)
- }
- }
-}
-
-androidx {
- name = "androidx.appactions.interaction:interaction-service-proto"
- publish = Publish.NONE
- inceptionYear = "2023"
- description = "Internal protos for Interaction Service"
- runApiTasks = new RunApiTasks.No("No public API required for internal use with app widgets.")
-}
diff --git a/appactions/interaction/interaction-service-proto/src/main/proto/app_interaction_service.proto b/appactions/interaction/interaction-service-proto/src/main/proto/app_interaction_service.proto
deleted file mode 100644
index e4cbeb2..0000000
--- a/appactions/interaction/interaction-service-proto/src/main/proto/app_interaction_service.proto
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-syntax = "proto3";
-
-package androidx.appactions.interaction.service.proto;
-
-import "app_actions_data.proto";
-import "grounding.proto";
-import "touch_event.proto";
-
-option java_package = "androidx.appactions.interaction.service.proto";
-option java_outer_classname = "AppInteractionServiceProto";
-
-// Request from host client (Assistant) to service provider (app) as part of the
-// RequestFulfillment streaming call. Throughout a dialog facilitated by the
-// provider, host might send multiple Request every time the
-// user issues a query. This proto contains user's query (parsed into BII).
-// NEXT_ID: 3
-message Request {
- // This session id corresponds to the one in [AppDialogState]. Session id is used to identify the
- // hosts. When there are multiple hosts connecting to the provider at the same time for different
- // requests, provider can use the session_ids to distinguish sessions, thus providing different
- // responses to different hosts.
- string session_identifier = 1;
- // FulfillmentRequest contains the request data sent from Assistant, such as
- // new values of BII arguments.
- .androidx.appactions.interaction.proto.FulfillmentRequest fulfillment_request = 2;
-}
-
-// Response from service provider (app) to host client (Assistant) as part of
-// the RequestFulfillment streaming call. While the RequestFulfillment streaming
-// call is not completed, provider can stream Response when
-// there is new TTS to play or new UI to display.
-// NEXT_ID: 7
-message Response {
- // Response of the capability invocation. Contains single-turn information
- // (such as structured data for TTS). State updates (e.g. slot value changes)
- // are reflected in the app_actions_context).
- .androidx.appactions.interaction.proto.FulfillmentResponse fulfillment_response = 1;
- // Context from the app. This should invalidate the Assistant app cache.
- .androidx.appactions.interaction.proto.AppActionsContext app_actions_context = 2;
- // Signal to the host that there is a new UI (RemoteViews or Tiles) ready to
- // be requested.
- UiUpdate ui_update = 3;
- // Signal to the host that there is a new UI (RemoteViews or Tiles) ready to
- // be requested, specifically for a list view.
- CollectionUpdate collection_update = 4;
- Status ending_status = 5;
- // Additional single-turn response data (in addition to
- // 'fulfillment_response') when the capability processing was triggered via
- // manual input.
- .androidx.appactions.interaction.proto.TouchEventMetadata touch_event_metadata = 6;
-}
-
-// The ending status of the dialog.
-// NEXT_ID: 3
-message Status {
- string message = 1;
- Code status_code = 2;
-
- enum Code {
- CODE_UNSPECIFIED = 0;
- COMPLETE = 1;
- USER_CANCELED = 2;
- ERROR = 3;
- TIMEOUT = 4;
- }
-}
-// NEXT_ID: 1
-message UiUpdate {}
-
-// NEXT_ID: 2
-message CollectionUpdate {
- repeated int32 view_ids = 1;
-}
-
-// Host request to fetch UI
-// NEXT_ID: 3
-message UiRequest {
- int32 session_id = 1 [deprecated = true];
- // This session id corresponds to the one in [AppDialogState]. Indicates the UiResponse should
- // contain only the responses for this particular session.
- string session_identifier = 2;
-}
-
-// A wrapper for weartile Layout and Resources
-// NEXT_ID: 3
-message TileLayout {
- // bytes for androidx.wear.tiles.proto.Layout
- bytes layout = 1;
- // bytes for androidx.wear.tiles.proto.Resources
- bytes resources = 2;
-}
-
-// Information about the RemoteViews.
-// NEXT_ID: 5
-message RemoteViewsInfo {
- oneof width {
- // Fixed width in dp. Won't resize when host width changes.
- float width_dp = 1;
- // Take up as much horizontal space as possible, automatically resizes when
- // host width changes
- bool width_match_parent = 2;
- }
- oneof height {
- // Fixed height in dp. Won't resize when host height changes.
- float height_dp = 3;
- // Take up as much vertical space as possible, automatically resizes when
- // host height changes
- bool height_match_parent = 4;
- }
-}
-
-// Provider response to return UI. If the UI is RemoteViews, it will be attached
-// as trailer metadata of the response.
-// NEXT_ID: 3
-message UiResponse {
- oneof ui_type {
- TileLayout tile_layout = 1;
- RemoteViewsInfo remote_views_info = 2;
- }
-}
-
-// NEXT_ID: 5
-message HostProperties {
- // The width of the host area (in dp) where the app content can be displayed.
- float host_view_width_dp = 1;
-
- // The height of the host area (in dp) where the app content can be displayed.
- float host_view_height_dp = 2;
-
- DeviceType device_type = 3;
-
- bool requires_ui = 4;
-
- enum ResponseType {
- // default
- TYPE_UNSPECIFIED = 0;
-
- // The host supports displaying UI, text, and speech.
- SPEECH_AND_UI = 1;
-
- // The host supports playing TTS and receiving user voice query.
- SPEECH_ONLY = 2;
-
- // The host supports displaying a string text
- UI_ONLY = 3;
- }
-
- enum DeviceType {
- UNSPECIFIED = 0; // default
- MOBILE = 1; // the host is an Android phone or tablet.
- ANDROID_AUTO = 2; // the host is an Android Auto device.
- WEAR_OS = 3; // The host is a WearOS device.
- SPEAKER = 4; // The host is a smart speaker.
- }
-}
-
-// Request containing the specification of the host to prepare the session.
-// NEXT_ID: 5
-message StartSessionRequest {
- HostProperties host_properties = 1;
- // Name of the BII e.g. "actions.intent.CREATE_TIMER"
- string intent_name = 2;
- // Fulfillment identifier associated with this BII. The developer sets this
- // field in their shortcuts.xml e.g. "create-timer-1"
- string identifier = 3;
- // Unique session ID generated by Assistant. The server (app) should create a
- // new Session for the given identifiers above and assign this field to it.
- string session_identifier = 4;
-}
-
-// Response providing a session_id. Session_id works like a cookie in browser.
-// It is used to identify a session.
-// NEXT_ID: 2
-message StartSessionResponse {
- int32 session_id = 1 [deprecated = true];
-}
-
-// Request and response corresponding to methods on IRemoteViewsFactory.aidl
-// frameworks/base/core/java/com/android/internal/widget/IRemoteViewsFactory.aidl
-// NEXT_ID: 11
-message CollectionRequest {
- int32 session_id = 1 [deprecated = true];
- // This session id corresponds to the one in [AppDialogState]. Indicates the CollectionResponse
- // should contain only the responses for this particular session.
- string session_identifier = 10;
- int32 view_id = 2;
- oneof request_data {
- OnDestroy on_destroy = 3;
- GetCount get_count = 4;
- GetViewAt get_view_at = 5;
- GetLoadingView get_loading_view = 6;
- GetViewTypeCount get_view_type_count = 7;
- GetItemId get_item_id = 8;
- HasStableIds has_stable_ids = 9;
- }
-
- message OnDestroy {}
- message GetCount {}
- message GetViewAt {
- int32 position = 1;
- }
- message GetLoadingView {}
- message GetViewTypeCount {}
- message GetItemId {
- int32 position = 1;
- }
- message HasStableIds {}
-}
-
-// NEXT_ID: 5
-message CollectionResponse {
- oneof response_data {
- GetCount get_count = 1;
- GetViewTypeCount get_view_type_count = 2;
- GetItemId get_item_id = 3;
- HasStableIds has_stable_ids = 4;
- }
-
- message GetCount {
- int32 count = 1;
- }
- message GetViewTypeCount {
- int32 view_type_count = 1;
- }
- message GetItemId {
- int64 item_id = 1;
- }
- message HasStableIds {
- bool has_stable_ids = 1;
- }
-}
-
-// Service between Assistant app and 3P app. The 3P app acts as the server and the Assistant app is
-// the client that binds to it. This GRPC service facilitates the communication with the 3P app.
-service AppInteractionService {
- // Start up a session.
- rpc StartUpSession(stream StartSessionRequest)
- returns (stream StartSessionResponse);
-
- // Send request fulfillment.
- rpc SendRequestFulfillment(Request) returns (Response);
-
- // Request RemoteViews or TileLayout. This method is called after the
- // AppInteractionService SDK returns a signal in the Response of
- // RequestFulfillment. The Response.ui_update signal indicates that the app
- // provider has requested to send UI to Assistant. RemoteViews are not
- // directly sent in the response of this method, but passed in the gRPC
- // 'metadata'
- // (https://grpc.io/docs/what-is-grpc/core-concepts/#metadata).
- // TileLayout is sent directly as protos in the UiResponse.
- rpc RequestUi(UiRequest) returns (UiResponse);
-
- // Request RemoteViews specifically regarding a collection view / list items.
- // Similar to the RequestUI RPC, the response might contain RemoteViews in
- // gRPC 'metadata'.
- rpc RequestCollection(CollectionRequest) returns (CollectionResponse);
-
- // Request grounded candidates from the app
- rpc RequestGrounding(.androidx.appactions.interaction.proto.GroundingRequest)
- returns (.androidx.appactions.interaction.proto.GroundingResponse);
-}
\ No newline at end of file
diff --git a/appactions/interaction/interaction-service-testing/api/current.txt b/appactions/interaction/interaction-service-testing/api/current.txt
deleted file mode 100644
index e6f50d0..0000000
--- a/appactions/interaction/interaction-service-testing/api/current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 4.0
diff --git a/appactions/interaction/interaction-service-testing/api/res-current.txt b/appactions/interaction/interaction-service-testing/api/res-current.txt
deleted file mode 100644
index e69de29..0000000
--- a/appactions/interaction/interaction-service-testing/api/res-current.txt
+++ /dev/null
diff --git a/appactions/interaction/interaction-service-testing/api/restricted_current.txt b/appactions/interaction/interaction-service-testing/api/restricted_current.txt
deleted file mode 100644
index e6f50d0..0000000
--- a/appactions/interaction/interaction-service-testing/api/restricted_current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 4.0
diff --git a/appactions/interaction/interaction-service-testing/build.gradle b/appactions/interaction/interaction-service-testing/build.gradle
deleted file mode 100644
index e024c97..0000000
--- a/appactions/interaction/interaction-service-testing/build.gradle
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-/**
- * This file was created using the `create_project.py` script located in the
- * `<AndroidX root>/development/project-creator` directory.
- *
- * Please use that script when creating a new project, rather than copying an existing project and
- * modifying its settings.
- */
-import androidx.build.LibraryType
-
-plugins {
- id("AndroidXPlugin")
- id("com.android.library")
- id("org.jetbrains.kotlin.android")
-}
-
-dependencies {
- api(libs.kotlinStdlib)
- // Add dependencies here
-}
-
-android {
- namespace "androidx.appactions.interaction.service.testing"
-}
-
-androidx {
- name = "androidx.appactions.interaction:interaction-service-testing"
- type = LibraryType.PUBLISHED_TEST_LIBRARY
- inceptionYear = "2023"
- description = "Test integrations with App Actions Interactions service libraries"
- metalavaK2UastEnabled = true
-}
diff --git a/appactions/interaction/interaction-service-wear/api/current.txt b/appactions/interaction/interaction-service-wear/api/current.txt
deleted file mode 100644
index e6f50d0..0000000
--- a/appactions/interaction/interaction-service-wear/api/current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 4.0
diff --git a/appactions/interaction/interaction-service-wear/api/res-current.txt b/appactions/interaction/interaction-service-wear/api/res-current.txt
deleted file mode 100644
index e69de29..0000000
--- a/appactions/interaction/interaction-service-wear/api/res-current.txt
+++ /dev/null
diff --git a/appactions/interaction/interaction-service-wear/api/restricted_current.txt b/appactions/interaction/interaction-service-wear/api/restricted_current.txt
deleted file mode 100644
index e6f50d0..0000000
--- a/appactions/interaction/interaction-service-wear/api/restricted_current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 4.0
diff --git a/appactions/interaction/interaction-service-wear/build.gradle b/appactions/interaction/interaction-service-wear/build.gradle
deleted file mode 100644
index 4865eda..0000000
--- a/appactions/interaction/interaction-service-wear/build.gradle
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-/**
- * This file was created using the `create_project.py` script located in the
- * `<AndroidX root>/development/project-creator` directory.
- *
- * Please use that script when creating a new project, rather than copying an existing project and
- * modifying its settings.
- */
-import androidx.build.LibraryType
-
-plugins {
- id("AndroidXPlugin")
- id("com.android.library")
- id("org.jetbrains.kotlin.android")
-}
-
-dependencies {
- api(libs.kotlinStdlib)
- api(project(":appactions:interaction:interaction-service"))
- implementation(project(":wear:protolayout:protolayout"))
-}
-
-android {
- namespace "androidx.appactions.interaction.service.wear"
- defaultConfig {
- minSdkVersion 26
- }
-}
-
-androidx {
- name = "App Actions Interaction Service Wear"
- type = LibraryType.PUBLISHED_LIBRARY
- inceptionYear = "2023"
- description = "Support App Actions Interactions with apps on Wear."
- metalavaK2UastEnabled = true
-}
diff --git a/appactions/interaction/interaction-service-wear/src/main/java/androidx/appactions/interaction/service/wear/TileLayoutBuilder.kt b/appactions/interaction/interaction-service-wear/src/main/java/androidx/appactions/interaction/service/wear/TileLayoutBuilder.kt
deleted file mode 100644
index c165926..0000000
--- a/appactions/interaction/interaction-service-wear/src/main/java/androidx/appactions/interaction/service/wear/TileLayoutBuilder.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.appactions.interaction.service.wear
-
-import androidx.appactions.interaction.service.TileLayoutInternal
-import androidx.appactions.interaction.service.UiResponse
-
-/**
- * Holder for TileLayout response.
- */
-@Suppress("UnsafeOptInUsageError") // toByteArray() is still experimental in protolayout library.
-internal class TileLayoutBuilder(
- val layout: androidx.wear.protolayout.LayoutElementBuilders.Layout
-) {
-
- fun build(): UiResponse = UiResponse(TileLayoutInternal(layout.toByteArray()))
-}
diff --git a/appactions/interaction/interaction-service/api/current.txt b/appactions/interaction/interaction-service/api/current.txt
deleted file mode 100644
index a16d96a..0000000
--- a/appactions/interaction/interaction-service/api/current.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-// Signature format: 4.0
-package androidx.appactions.interaction.service {
-
- public abstract class AppInteractionService extends android.app.Service {
- ctor public AppInteractionService();
- method protected abstract java.util.List<androidx.appactions.interaction.service.AppVerificationInfo> getAllowedApps();
- method public abstract java.util.List<androidx.appactions.interaction.capabilities.core.Capability> getRegisteredCapabilities();
- method protected io.grpc.binder.SecurityPolicy getSecurityPolicy();
- method public android.os.IBinder onBind(android.content.Intent? intent);
- property protected abstract java.util.List<androidx.appactions.interaction.service.AppVerificationInfo> allowedApps;
- property public abstract java.util.List<androidx.appactions.interaction.capabilities.core.Capability> registeredCapabilities;
- property protected io.grpc.binder.SecurityPolicy securityPolicy;
- }
-
- public final class AppVerificationInfo {
- method public String getPackageName();
- method public java.util.List<byte[]> getSignatures();
- property public final String packageName;
- property public final java.util.List<byte[]> signatures;
- }
-
- public static final class AppVerificationInfo.Builder {
- ctor public AppVerificationInfo.Builder();
- method public androidx.appactions.interaction.service.AppVerificationInfo.Builder addSignature(byte[] signatures);
- method public androidx.appactions.interaction.service.AppVerificationInfo build();
- method public androidx.appactions.interaction.service.AppVerificationInfo.Builder setPackageName(String packageName);
- }
-
-}
-
diff --git a/appactions/interaction/interaction-service/api/res-current.txt b/appactions/interaction/interaction-service/api/res-current.txt
deleted file mode 100644
index e69de29..0000000
--- a/appactions/interaction/interaction-service/api/res-current.txt
+++ /dev/null
diff --git a/appactions/interaction/interaction-service/api/restricted_current.txt b/appactions/interaction/interaction-service/api/restricted_current.txt
deleted file mode 100644
index a16d96a..0000000
--- a/appactions/interaction/interaction-service/api/restricted_current.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-// Signature format: 4.0
-package androidx.appactions.interaction.service {
-
- public abstract class AppInteractionService extends android.app.Service {
- ctor public AppInteractionService();
- method protected abstract java.util.List<androidx.appactions.interaction.service.AppVerificationInfo> getAllowedApps();
- method public abstract java.util.List<androidx.appactions.interaction.capabilities.core.Capability> getRegisteredCapabilities();
- method protected io.grpc.binder.SecurityPolicy getSecurityPolicy();
- method public android.os.IBinder onBind(android.content.Intent? intent);
- property protected abstract java.util.List<androidx.appactions.interaction.service.AppVerificationInfo> allowedApps;
- property public abstract java.util.List<androidx.appactions.interaction.capabilities.core.Capability> registeredCapabilities;
- property protected io.grpc.binder.SecurityPolicy securityPolicy;
- }
-
- public final class AppVerificationInfo {
- method public String getPackageName();
- method public java.util.List<byte[]> getSignatures();
- property public final String packageName;
- property public final java.util.List<byte[]> signatures;
- }
-
- public static final class AppVerificationInfo.Builder {
- ctor public AppVerificationInfo.Builder();
- method public androidx.appactions.interaction.service.AppVerificationInfo.Builder addSignature(byte[] signatures);
- method public androidx.appactions.interaction.service.AppVerificationInfo build();
- method public androidx.appactions.interaction.service.AppVerificationInfo.Builder setPackageName(String packageName);
- }
-
-}
-
diff --git a/appactions/interaction/interaction-service/build.gradle b/appactions/interaction/interaction-service/build.gradle
deleted file mode 100644
index 24af205..0000000
--- a/appactions/interaction/interaction-service/build.gradle
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 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.BundleInsideHelper
-import androidx.build.LibraryType
-
-plugins {
- id("AndroidXPlugin")
- id("com.android.library")
- id("org.jetbrains.kotlin.android")
-}
-
-BundleInsideHelper.forInsideAar(
- project,
- [
- new BundleInsideHelper.Relocation(
- /* from = */ "io.grpc.protobuf",
- /* to = */ "androidx.appactions.interaction.grpc.protobuf"),
- new BundleInsideHelper.Relocation(
- /* from = */ "com.google.protobuf",
- /* to = */ "androidx.appactions.interaction.protobuf")
- ],
- // proto-lite dependency includes .proto files, which are not used and would clash if
- // users also use proto library directly
- /* dropResourcesWithSuffix = */ ".proto"
-)
-
-dependencies {
- bundleInside(project(":appactions:interaction:interaction-service-proto"))
-
- implementation(project(":appactions:interaction:interaction-capabilities-core"))
- implementation("androidx.annotation:annotation:1.1.0")
- implementation("androidx.concurrent:concurrent-futures:1.1.0")
- implementation(libs.grpcAndroid)
- implementation(libs.grpcBinder)
- implementation(libs.grpcStub)
- implementation(libs.kotlinCoroutinesCore)
- implementation(libs.kotlinStdlib)
- implementation(libs.jsr250)
-
- // Force upgrade since 1.2.0 is not compatible with latest lint.
- implementation("androidx.annotation:annotation-experimental:1.4.0")
-
- testImplementation(project(":appactions:interaction:interaction-capabilities-core"))
- testImplementation(project(":appactions:interaction:interaction-capabilities-testing"))
- testImplementation(project(":appactions:interaction:interaction-service-proto"))
- testImplementation(libs.grpcTesting)
- testImplementation(libs.junit)
- testImplementation(libs.kotlinCoroutinesTest)
- testImplementation(libs.kotlinStdlib)
- testImplementation(libs.kotlinTest)
- testImplementation(libs.mockitoKotlin)
- testImplementation(libs.protobufLite)
- testImplementation(libs.robolectric)
- testImplementation(libs.testExtJunit)
- testImplementation(libs.testExtTruth)
- testImplementation(libs.testCore)
- testImplementation(libs.testRunner)
- testImplementation(libs.truth)
- testImplementation("androidx.concurrent:concurrent-futures-ktx:1.1.0")
-}
-
-android {
- namespace "androidx.appactions.interaction.service"
- defaultConfig {
- minSdkVersion 26
- }
- defaultConfig {
- testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
- }
- testOptions {
- unitTests {
- includeAndroidResources = true
- }
- }
-}
-
-androidx {
- name = "androidx.appactions.interaction:interaction-service"
- type = LibraryType.PUBLISHED_LIBRARY
- inceptionYear = "2023"
- description = "Library for integrating with Google Assistant via GRPC binder channel."
- metalavaK2UastEnabled = true
-}
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionGrpcMetadata.kt b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionGrpcMetadata.kt
deleted file mode 100644
index 6bdcb10..0000000
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionGrpcMetadata.kt
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.appactions.interaction.service
-
-import androidx.appactions.interaction.capabilities.core.impl.ErrorStatusInternal
-import androidx.appactions.interaction.proto.AppInteractionMetadata
-import androidx.appactions.interaction.proto.AppInteractionMetadata.ErrorStatus
-import androidx.appactions.interaction.protobuf.InvalidProtocolBufferException
-import io.grpc.Metadata
-
-/**
- * Utilities to attach App Interaction specific metadata to any gRPC response
- * (via StatusRuntimeException).
- */
-internal object AppInteractionGrpcMetadata {
-
- /** [Metadata.Key] used on gRPC trailers to pass [AppInteractionMetadata]. */
- val INTERACTION_SERVICE_STATUS_KEY: Metadata.Key<AppInteractionMetadata> = Metadata.Key.of(
- "interaction-service-metadata-bin",
- object : Metadata.BinaryMarshaller<AppInteractionMetadata> {
-
- override fun toBytes(value: AppInteractionMetadata): ByteArray {
- return value.toByteArray()
- }
-
- override fun parseBytes(serialized: ByteArray): AppInteractionMetadata {
- return try {
- AppInteractionMetadata.parseFrom(serialized)
- } catch (e: InvalidProtocolBufferException) {
- throw IllegalArgumentException(e)
- }
- }
- })
-
- private fun buildAppInteractionMetadata(
- errorStatusInternal: ErrorStatusInternal
- ): AppInteractionMetadata {
- val errorStatus = when (errorStatusInternal) {
- ErrorStatusInternal.UNKNOWN_ERROR_STATUS,
- -> ErrorStatus.UNKNOWN_ERROR_STATUS
- ErrorStatusInternal.INTERNAL -> ErrorStatus.INTERNAL
- ErrorStatusInternal.CANCELED -> ErrorStatus.CANCELED
- ErrorStatusInternal.TIMEOUT -> ErrorStatus.TIMEOUT
- ErrorStatusInternal.INVALID_REQUEST -> ErrorStatus.INVALID_REQUEST
- ErrorStatusInternal.SESSION_NOT_FOUND,
- -> ErrorStatus.SESSION_NOT_FOUND
- ErrorStatusInternal.EXTERNAL_EXCEPTION -> ErrorStatus.EXTERNAL_EXCEPTION
- }
- return AppInteractionMetadata.newBuilder()
- .setErrorStatus(errorStatus)
- .build()
- }
-
- /**
- * Supply errors directly from the service library. For example, sometimes we need to return an
- * error before we invoked any capability.
- */
- fun metadataOf(errorStatus: ErrorStatus): Metadata {
- val metadata = Metadata()
- metadata.put(
- INTERACTION_SERVICE_STATUS_KEY,
- AppInteractionMetadata.newBuilder()
- .setErrorStatus(errorStatus)
- .build()
- )
- return metadata
- }
-
- /** Supply errors by converting from errors in the Capability library. */
- fun metadataOf(errorStatusInternal: ErrorStatusInternal): Metadata {
- val metadata = Metadata()
- metadata.put(
- INTERACTION_SERVICE_STATUS_KEY,
- buildAppInteractionMetadata(errorStatusInternal)
- )
- return metadata
- }
-}
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionService.kt b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionService.kt
deleted file mode 100644
index 87c769e..0000000
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionService.kt
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * 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.appactions.interaction.service
-
-import android.app.Service
-import android.content.Intent
-import android.os.IBinder
-import android.util.Log
-import androidx.annotation.CallSuper
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.entity.EntityProvider
-import androidx.appactions.interaction.service.proto.AppInteractionServiceGrpc
-import io.grpc.Server
-import io.grpc.binder.AndroidComponentAddress
-import io.grpc.binder.BinderServerBuilder
-import io.grpc.binder.IBinderReceiver
-import io.grpc.binder.SecurityPolicies
-import io.grpc.binder.SecurityPolicy
-import io.grpc.binder.ServerSecurityPolicy
-import java.io.IOException
-
-/**
- * Base service class for the AppInteractionService SDK. This sets up the GRPC on-device server for
- * communication with Assistant.
- */
-abstract class AppInteractionService : Service() {
- private var binderSupplier: ServerLifecycle? = null
-
- /**
- * Called by the system once after the Assistant binds to the service.
- *
- * @return the list of capabilities that this service supports.
- */
- abstract val registeredCapabilities: List<Capability>
-
- /**
- * Called by the system once after the Assistant binds to the service.
- *
- * @return the list of EntityProvider that this service supports.
- */
- // TODO(b/284057017): Open up Grounding API (remove internal).
- internal open val registeredEntityProviders: List<EntityProvider<*>> = listOf()
-
- /**
- * A list of [AppVerificationInfo] which define who is allowed to interact with the app's bound
- * service. This gives control over which clients are allowed to communicate with the service.
- *
- * This is the default method for enforcing security and must be overridden. Developers should
- * return an empty list should they choose to define their own security by way of overriding
- * [.getSecurityPolicyFromAllowedList].
- */
- protected abstract val allowedApps: List<AppVerificationInfo>
-
- /**
- * Sets a custom [SecurityPolicy] for the gRPC service. This gives control over which clients
- * are allowed to bind to your service.
- *
- * Overriding this property is **not** the preferred method for security enforcement. We
- * recommend developers override [allowedApps] for security needs. Implementing your own
- * security policy requires significant care, and an understanding of the details and pitfalls
- * of Android security. If you choose to do so, we **strongly** recommend you get such a change
- * reviewed by Android security experts.
- */
- protected open val securityPolicy: SecurityPolicy
- get() =
- SecurityPolicies.anyOf(*getSecurityPolicyFromAllowedList(allowedApps).toTypedArray())
-
- /**
- * Sets a custom [SecurityPolicy] for the gRPC service given the client's allowed pairs of
- * package names with corresponding Sha256 signatures. This gives control over which clients are
- * allowed to bind to your service.
- *
- * A SecurityPolicy is returned per supported Assistant. Such as "Google Assistant", "Bixby",
- * etc.
- */
- private fun getSecurityPolicyFromAllowedList(
- verificationInfoList: List<AppVerificationInfo>
- ): List<SecurityPolicy> {
- val policies: MutableList<SecurityPolicy> = ArrayList()
- if (verificationInfoList.isEmpty()) {
- policies.add(SecurityPolicies.internalOnly())
- return policies
- }
- for (verificationInfo in verificationInfoList) {
- policies.add(
- SecurityPolicies.oneOfSignatureSha256Hash(
- this.packageManager,
- verificationInfo.packageName,
- verificationInfo.signatures
- )
- )
- }
- return policies
- }
-
- @CallSuper
- override fun onCreate() {
- super.onCreate()
- val binderReceiver = IBinderReceiver()
- val serverSecurityPolicy =
- ServerSecurityPolicy.newBuilder()
- .servicePolicy(AppInteractionServiceGrpc.SERVICE_NAME, securityPolicy)
- .build()
- val server =
- BinderServerBuilder.forAddress(AndroidComponentAddress.forContext(this), binderReceiver)
- .securityPolicy(serverSecurityPolicy)
- .intercept(RemoteViewsOverMetadataInterceptor())
- .addService(AppInteractionServiceFactory.create(this))
- .build()
- binderSupplier = ServerLifecycle(server, binderReceiver)
- }
-
- override fun onBind(intent: Intent?): IBinder {
- return binderSupplier!!.get()!!
- }
-
- @CallSuper
- override fun onDestroy() {
- if (binderSupplier != null) {
- binderSupplier!!.shutdown()
- }
- super.onDestroy()
- }
-
- internal class ServerLifecycle(
- private val server: Server,
- private val receiver: IBinderReceiver
- ) {
- private var isServerStarted = false
-
- fun get(): IBinder? {
- synchronized(this) {
- if (!isServerStarted) {
- try {
- isServerStarted = true
- server.start()
- } catch (ioe: IOException) {
- Log.e(TAG, "Unable to start server $server", ioe)
- }
- }
- return receiver.get()
- }
- }
-
- fun shutdown() {
- synchronized(this) {
- if (isServerStarted) {
- server.shutdownNow()
- isServerStarted = false
- }
- }
- }
- }
-
- internal companion object {
- private const val TAG = "AppInteractionService"
- }
-}
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionServiceFactory.kt b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionServiceFactory.kt
deleted file mode 100644
index f35c045..0000000
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionServiceFactory.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.appactions.interaction.service
-
-import androidx.annotation.RestrictTo
-import io.grpc.BindableService
-
-/**
- * Factory for returning a [BindableService] from an [AppInteractionService].
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-object AppInteractionServiceFactory {
- /**
- * Creates a new instance of the gRPC service from the developer's [AppInteractionService]
- * (android service).
- */
- fun create(appInteractionService: AppInteractionService): BindableService {
- return AppInteractionServiceGrpcImpl(appInteractionService)
- }
-}
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
deleted file mode 100644
index e8ffe9a..0000000
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionServiceGrpcImpl.kt
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- * 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.appactions.interaction.service
-
-import android.util.Log
-import android.util.SizeF
-import android.widget.RemoteViewsService.RemoteViewsFactory
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.core.LibInfo
-import androidx.appactions.interaction.capabilities.core.impl.ArgumentsWrapper
-import androidx.appactions.interaction.capabilities.core.impl.CapabilitySession
-import androidx.appactions.interaction.capabilities.core.impl.ErrorStatusInternal
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.FutureCallback
-import androidx.appactions.interaction.capabilities.core.impl.concurrent.Futures
-import androidx.appactions.interaction.capabilities.core.impl.utils.CapabilityLogger
-import androidx.appactions.interaction.capabilities.core.impl.utils.CapabilityLogger.LogLevel
-import androidx.appactions.interaction.capabilities.core.impl.utils.LoggerInternal
-import androidx.appactions.interaction.proto.AppActionsContext
-import androidx.appactions.interaction.proto.AppInteractionMetadata.ErrorStatus
-import androidx.appactions.interaction.proto.FulfillmentRequest
-import androidx.appactions.interaction.proto.FulfillmentResponse
-import androidx.appactions.interaction.proto.GroundingRequest
-import androidx.appactions.interaction.proto.GroundingResponse
-import androidx.appactions.interaction.proto.Version
-import androidx.appactions.interaction.service.proto.AppInteractionServiceGrpc.AppInteractionServiceImplBase
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto.CollectionRequest
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto.CollectionRequest.RequestDataCase
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto.CollectionResponse
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto.RemoteViewsInfo
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto.Request
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto.Response
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto.StartSessionRequest
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto.StartSessionResponse
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto.Status.Code
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto.UiUpdate
-import androidx.concurrent.futures.CallbackToFutureAdapter
-import com.google.common.util.concurrent.ListenableFuture
-import io.grpc.Status
-import io.grpc.StatusException
-import io.grpc.StatusRuntimeException
-import io.grpc.stub.StreamObserver
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-
-/**
- * Implementation of [AppInteractionServiceImplBase] generated from the GRPC proto file. This
- * class delegates the requests to the appropriate capability session.
- */
-internal class AppInteractionServiceGrpcImpl(
- private val appInteractionService: AppInteractionService,
-) : AppInteractionServiceImplBase() {
-
- var registeredCapabilities = listOf<Capability>()
-
- companion object {
- private const val TAG = "ActionsServiceGrpcImpl"
- private const val ERROR_NO_COLLECTION_SUPPORT = "Session doesn't support collection view"
- private const val ERROR_NO_UI = "No UI set"
- const val ERROR_NO_SESSION = "Session not available"
- const val ERROR_NO_FULFILLMENT_REQUEST = "Fulfillment request missing"
- const val ERROR_NO_ACTION_CAPABILITY = "Capability was not found"
- const val ERROR_SESSION_ENDED = "Session already ended"
-
- fun <T> respondAndComplete(response: T, responseObserver: StreamObserver<T>) {
- synchronized(responseObserver) {
- responseObserver.onNext(response)
- responseObserver.onCompleted()
- }
- }
-
- fun respondWithError(t: Throwable, responseObserver: StreamObserver<*>) {
- synchronized(responseObserver) {
- responseObserver.onError(t)
- }
- }
-
- init {
- LoggerInternal.setLogger(
- object : CapabilityLogger {
- override fun log(
- logLevel: LogLevel,
- logTag: String,
- message: String,
- ) {
- when (logLevel) {
- LogLevel.ERROR -> Log.e(logTag, message)
- LogLevel.WARN -> Log.w(logTag, message)
- LogLevel.INFO -> Log.i(logTag, message)
- LogLevel.DEBUG -> Log.d(logTag, message)
- }
- }
-
- override fun log(
- logLevel: LogLevel,
- logTag: String,
- message: String,
- throwable: Throwable,
- ) {
- when (logLevel) {
- LogLevel.ERROR -> Log.e(logTag, message, throwable)
- LogLevel.WARN -> Log.w(logTag, message, throwable)
- LogLevel.INFO -> Log.i(logTag, message, throwable)
- LogLevel.DEBUG -> Log.d(logTag, message, throwable)
- }
- }
- },
- )
- }
- }
-
- override fun startUpSession(
- responseObserver: StreamObserver<StartSessionResponse>,
- ): StreamObserver<StartSessionRequest> = StartSessionRequestObserver(responseObserver)
-
- private inner class StartSessionRequestObserver internal constructor(
- private val startSessionResponseObserver: StreamObserver<StartSessionResponse>,
- ) : StreamObserver<StartSessionRequest> {
-
- // Every AppInteractionService connection is defined by this streaming RPC connection.
- // There should only be one session tied to each gRPC impl instance.
- private var currentSessionId: String? = null
-
- override fun onNext(request: StartSessionRequest) {
- if (currentSessionId != null) {
- return
- }
- val sessionId = request.sessionIdentifier!!
- currentSessionId = sessionId
- if (registeredCapabilities.isEmpty()) {
- registeredCapabilities = appInteractionService.registeredCapabilities
- }
- val targetCapability =
- registeredCapabilities.firstOrNull { request.identifier == it.id }
- if (targetCapability == null) {
- return respondWithError(
- StatusRuntimeException(
- Status.FAILED_PRECONDITION.withDescription(
- ERROR_NO_ACTION_CAPABILITY,
- ),
- AppInteractionGrpcMetadata.metadataOf(ErrorStatus.CAPABILITY_NOT_FOUND)
- ),
- startSessionResponseObserver,
- )
- }
- val hostProperties = HostProperties.Builder()
- .setMaxHostSizeDp(
- SizeF(
- request.hostProperties.hostViewHeightDp,
- request.hostProperties.hostViewWidthDp,
- ),
- ).build()
- val session = targetCapability.createSession(
- sessionId,
- hostProperties,
- )
- SessionManager.putSession(sessionId, session)
- startSessionResponseObserver.onNext(StartSessionResponse.getDefaultInstance())
- }
-
- override fun onError(t: Throwable) {
- respondWithError(t, startSessionResponseObserver)
- currentSessionId?.let {
- destroyAndRemoveSession(it)
- UiSessions.removeUiCache(it)
- }
- }
-
- override fun onCompleted() {
- synchronized(startSessionResponseObserver) {
- startSessionResponseObserver.onCompleted()
- }
- currentSessionId?.let {
- destroyAndRemoveSession(it)
- UiSessions.removeUiCache(it)
- }
- }
- }
-
- override fun sendRequestFulfillment(
- request: Request,
- responseObserver: StreamObserver<Response>,
- ) {
- if (request.fulfillmentRequest.fulfillmentsList.isEmpty()) {
- return respondWithError(
- StatusRuntimeException(
- Status.FAILED_PRECONDITION.withDescription(
- ERROR_NO_FULFILLMENT_REQUEST,
- ),
- AppInteractionGrpcMetadata.metadataOf(ErrorStatus.INVALID_REQUEST)
- ),
- responseObserver,
- )
- }
- val selectedFulfillment = request.fulfillmentRequest.getFulfillments(0)
- val capability =
- registeredCapabilities.firstOrNull { selectedFulfillment.identifier == it.id }
- if (capability == null) {
- return respondWithError(
- StatusRuntimeException(
- Status.FAILED_PRECONDITION.withDescription(
- ERROR_NO_ACTION_CAPABILITY,
- ),
- AppInteractionGrpcMetadata.metadataOf(ErrorStatus.CAPABILITY_NOT_FOUND)
- ),
- responseObserver,
- )
- }
- val sessionId = request.sessionIdentifier!!
- val currentSession = SessionManager.getSession(sessionId)
- if (currentSession == null) {
- return respondWithError(
- StatusRuntimeException(
- Status.FAILED_PRECONDITION.withDescription(ERROR_NO_SESSION),
- AppInteractionGrpcMetadata.metadataOf(ErrorStatus.SESSION_NOT_FOUND)
- ),
- responseObserver,
- )
- }
- if (!currentSession.isActive) {
- return respondWithError(
- StatusRuntimeException(
- Status.FAILED_PRECONDITION.withDescription(ERROR_SESSION_ENDED),
- AppInteractionGrpcMetadata.metadataOf(ErrorStatus.SESSION_NOT_FOUND)
- ),
- responseObserver,
- )
- }
- Futures.addCallback(
- executeFulfillmentRequest(currentSession, selectedFulfillment),
- object : FutureCallback<FulfillmentResponse> {
- override fun onSuccess(result: FulfillmentResponse) {
- val responseBuilder =
- convertFulfillmentResponse(result, capability, currentSession)
- .toBuilder()
- val uiCache = UiSessions.getUiCacheOrNull(sessionId)
- if (uiCache != null && uiCache.hasUnreadUiResponse) {
- val cachedRemoteViewsInternal = uiCache.cachedRemoteViewsInternal
- responseBuilder.uiUpdate = UiUpdate.getDefaultInstance()
- if (cachedRemoteViewsInternal != null &&
- cachedRemoteViewsInternal.collectionViewFactories.keys.isNotEmpty()
- ) {
- responseBuilder.setCollectionUpdate(
- AppInteractionServiceProto.CollectionUpdate.newBuilder()
- .addAllViewIds(
- cachedRemoteViewsInternal.collectionViewFactories.keys
- ),
- )
- }
- uiCache.resetUnreadUiResponse()
- }
- respondAndComplete(responseBuilder.build(), responseObserver)
- }
-
- override fun onFailure(t: Throwable) {
- respondWithError(
- when (t) {
- is CapabilityExecutionException -> convertToGrpcException(t)
- is StatusRuntimeException, is StatusException -> t
- else -> StatusRuntimeException(
- Status.INTERNAL.withDescription(t.message).withCause(t),
- AppInteractionGrpcMetadata.metadataOf(
- ErrorStatus.UNKNOWN_ERROR_STATUS)
- )
- },
- responseObserver,
- )
- // Assistant will terminate the connection, which will reach
- // startUpSession.onError(t) / onCompleted()
- }
- },
- Runnable::run,
- )
- }
-
- override fun requestUi(
- req: AppInteractionServiceProto.UiRequest,
- responseObserver: StreamObserver<AppInteractionServiceProto.UiResponse>,
- ) {
- val sessionId = req.sessionIdentifier!!
- if (SessionManager.getSession(sessionId) == null) {
- return respondWithError(
- StatusRuntimeException(
- Status.FAILED_PRECONDITION.withDescription(ERROR_NO_SESSION),
- AppInteractionGrpcMetadata.metadataOf(ErrorStatus.SESSION_NOT_FOUND)
- ),
- responseObserver,
- )
- }
- val uiCache = UiSessions.getUiCacheOrNull(sessionId)
- if (uiCache == null) {
- return respondWithError(
- StatusRuntimeException(Status.INTERNAL.withDescription(ERROR_NO_UI),
- AppInteractionGrpcMetadata.metadataOf(ErrorStatus.NO_UI_ELEMENTS)),
- responseObserver,
- )
- }
- val tileLayoutInternal = uiCache.cachedTileLayoutInternal
- val remoteViewsInternal = uiCache.cachedRemoteViewsInternal
-
- if (tileLayoutInternal == null && remoteViewsInternal == null) {
- UiSessions.removeUiCache(sessionId)
- return respondWithError(
- StatusRuntimeException(Status.INTERNAL.withDescription(ERROR_NO_UI),
- AppInteractionGrpcMetadata.metadataOf(ErrorStatus.NO_UI_ELEMENTS)),
- responseObserver
- )
- }
- val uiResponseBuilder = AppInteractionServiceProto.UiResponse.newBuilder()
- tileLayoutInternal?.let { uiResponseBuilder.tileLayout = it.toProto() }
- if (remoteViewsInternal != null) {
- RemoteViewsOverMetadataInterceptor.setRemoteViews(remoteViewsInternal.remoteViews)
- uiResponseBuilder
- .setRemoteViewsInfo(
- RemoteViewsInfo.newBuilder()
- .setWidthDp(remoteViewsInternal.size.width)
- .setHeightDp(remoteViewsInternal.size.height)
- )
- .build()
- }
- respondAndComplete(uiResponseBuilder.build(), responseObserver)
- }
-
- override fun requestCollection(
- req: CollectionRequest,
- responseObserver: StreamObserver<CollectionResponse>,
- ) {
- val sessionId = req.sessionIdentifier!!
- if (SessionManager.getSession(sessionId) == null) {
- return respondWithError(
- StatusRuntimeException(
- Status.FAILED_PRECONDITION.withDescription(ERROR_NO_SESSION),
- AppInteractionGrpcMetadata.metadataOf(ErrorStatus.SESSION_NOT_FOUND)
- ),
- responseObserver,
- )
- }
- val uiCache = UiSessions.getUiCacheOrNull(sessionId)
- if (uiCache == null) {
- return respondWithError(
- StatusRuntimeException(
- Status.INTERNAL.withDescription(ERROR_NO_UI),
- AppInteractionGrpcMetadata.metadataOf(ErrorStatus.NO_UI_ELEMENTS)
- ),
- responseObserver,
- )
- }
- val factory = uiCache.cachedRemoteViewsInternal?.collectionViewFactories?.get(req.viewId)
- if (factory == null) {
- return respondWithError(
- StatusRuntimeException(
- Status.INTERNAL.withDescription(ERROR_NO_COLLECTION_SUPPORT),
- AppInteractionGrpcMetadata.metadataOf(ErrorStatus.UNKNOWN_ERROR_STATUS),
- ),
- responseObserver,
- )
- }
- when (req.requestDataCase) {
- RequestDataCase.ON_DESTROY -> {
- requestCollectionOnDestroy(factory, responseObserver)
- }
- RequestDataCase.GET_COUNT -> {
- requestCollectionGetCount(factory, responseObserver)
- }
- RequestDataCase.GET_VIEW_AT -> {
- requestCollectionGetViewAt(
- factory,
- responseObserver,
- req.getViewAt.position,
- )
- }
- RequestDataCase.GET_LOADING_VIEW -> {
- requestCollectionGetLoadingView(factory, responseObserver)
- }
- RequestDataCase.GET_VIEW_TYPE_COUNT -> {
- requestCollectionGetViewTypeCount(factory, responseObserver)
- }
- RequestDataCase.GET_ITEM_ID -> {
- requestCollectionGetItemId(
- factory,
- responseObserver,
- req.getItemId.position,
- )
- }
- RequestDataCase.HAS_STABLE_IDS -> {
- requestCollectionHasStableIds(factory, responseObserver)
- }
- else -> {
- // ignore it
- Log.d(TAG, "received CollectionRequest with unknown RequestData case.")
- responseObserver.onCompleted()
- }
- }
- }
-
- override fun requestGrounding(
- request: GroundingRequest,
- responseObserver: StreamObserver<GroundingResponse>,
- ) {
- val entityProvider = appInteractionService.registeredEntityProviders.firstOrNull {
- it.id == request.request.entityProviderId
- }
- if (entityProvider == null) {
- return respondAndComplete(
- GroundingResponse.newBuilder()
- .setResponse(
- GroundingResponse.Response.newBuilder().setStatus(
- GroundingResponse.Status.INVALID_ENTITY_PROVIDER,
- ),
- ).build(),
- responseObserver,
- )
- }
- CoroutineScope(Dispatchers.Unconfined).launch {
- try {
- respondAndComplete(
- entityProvider.lookupInternal(request),
- responseObserver,
- )
- } catch (t: Throwable) {
- respondWithError(
- when (t) {
- is StatusRuntimeException, is StatusException -> t
- else -> StatusRuntimeException(
- Status.INTERNAL.withDescription(t.message,).withCause(t),
- AppInteractionGrpcMetadata.metadataOf(ErrorStatus.UNKNOWN_ERROR_STATUS)
- )
- },
- responseObserver,
- )
- }
- }
- }
-
- private fun requestCollectionOnDestroy(
- factory: RemoteViewsFactory,
- observer: StreamObserver<CollectionResponse>,
- ) {
- factory.onDestroy()
- respondAndComplete(CollectionResponse.getDefaultInstance(), observer)
- }
-
- private fun requestCollectionGetCount(
- factory: RemoteViewsFactory,
- observer: StreamObserver<CollectionResponse>,
- ) {
- respondAndComplete(
- CollectionResponse.newBuilder()
- .setGetCount(
- CollectionResponse.GetCount.newBuilder()
- .setCount(factory.count),
- )
- .build(),
- observer,
- )
- }
-
- private fun requestCollectionGetViewAt(
- factory: RemoteViewsFactory,
- observer: StreamObserver<CollectionResponse>,
- position: Int,
- ) {
- factory.getViewAt(position)?.let(RemoteViewsOverMetadataInterceptor::setRemoteViews)
- respondAndComplete(CollectionResponse.getDefaultInstance(), observer)
- }
-
- private fun requestCollectionGetLoadingView(
- factory: RemoteViewsFactory,
- observer: StreamObserver<CollectionResponse>,
- ) {
- factory.loadingView?.let(RemoteViewsOverMetadataInterceptor::setRemoteViews)
- respondAndComplete(CollectionResponse.getDefaultInstance(), observer)
- }
-
- private fun requestCollectionGetViewTypeCount(
- factory: RemoteViewsFactory,
- observer: StreamObserver<CollectionResponse>,
- ) {
- respondAndComplete(
- CollectionResponse.newBuilder()
- .setGetViewTypeCount(
- CollectionResponse.GetViewTypeCount.newBuilder()
- .setViewTypeCount(factory.viewTypeCount),
- )
- .build(),
- observer,
- )
- }
-
- private fun requestCollectionGetItemId(
- factory: RemoteViewsFactory,
- observer: StreamObserver<CollectionResponse>,
- position: Int,
- ) {
- respondAndComplete(
- CollectionResponse.newBuilder()
- .setGetItemId(
- CollectionResponse.GetItemId.newBuilder()
- .setItemId(factory.getItemId(position)),
- )
- .build(),
- observer,
- )
- }
-
- private fun requestCollectionHasStableIds(
- factory: RemoteViewsFactory,
- observer: StreamObserver<CollectionResponse>,
- ) {
- respondAndComplete(
- CollectionResponse.newBuilder()
- .setHasStableIds(
- CollectionResponse.HasStableIds.newBuilder()
- .setHasStableIds(factory.hasStableIds()),
- )
- .build(),
- observer,
- )
- }
-
- private fun convertToAppActionsContextVersion(
- libInfoVersion: LibInfo.Version,
- ): Version {
- val builder = Version.newBuilder()
- .setMajor(libInfoVersion.major.toLong())
- .setMinor(libInfoVersion.minor.toLong())
- .setPatch(libInfoVersion.patch.toLong())
- libInfoVersion.preReleaseId?.let(builder::setPrereleaseId)
- return builder.build()
- }
-
- /**
- * Calls destroy on the session if it's found in SessionManager.
- * Also removes the session from map.
- */
- internal fun destroyAndRemoveSession(sessionId: String) {
- SessionManager.getSession(sessionId)?.destroy()
- SessionManager.removeSession(sessionId)
- }
-
- internal fun convertToGrpcException(e: CapabilityExecutionException): StatusRuntimeException {
- val rpcStatus = when (e.errorStatus) {
- ErrorStatusInternal.UNKNOWN_ERROR_STATUS -> Status.UNKNOWN
- ErrorStatusInternal.CANCELED -> Status.CANCELLED
- ErrorStatusInternal.TIMEOUT -> Status.DEADLINE_EXCEEDED
- ErrorStatusInternal.INVALID_REQUEST -> Status.INVALID_ARGUMENT
- ErrorStatusInternal.SESSION_NOT_FOUND -> Status.FAILED_PRECONDITION
- ErrorStatusInternal.INTERNAL,
- ErrorStatusInternal.EXTERNAL_EXCEPTION,
- -> Status.INTERNAL
- }
- return StatusRuntimeException(
- rpcStatus.withDescription(e.message).withCause(e),
- AppInteractionGrpcMetadata.metadataOf(e.errorStatus)
- )
- }
-
- internal fun convertFulfillmentResponse(
- fulfillmentResponse: FulfillmentResponse,
- capability: Capability,
- currentSession: CapabilitySession
- ): Response {
- val appAction = capability.appAction
- val isDialogSession = appAction.taskInfo.supportsPartialFulfillment
- val version = convertToAppActionsContextVersion(
- LibInfo(appInteractionService.applicationContext).getVersion(),
- )
- val appActionsContextBuilder = AppActionsContext.newBuilder()
- .addActions(appAction)
- .setVersion(version)
- currentSession.state?.let(appActionsContextBuilder::addDialogStates)
- val responseBuilder: Response.Builder =
- Response.newBuilder()
- .setFulfillmentResponse(fulfillmentResponse)
- .setAppActionsContext(appActionsContextBuilder.build())
- if (!isDialogSession) {
- responseBuilder.endingStatus = AppInteractionServiceProto.Status.newBuilder()
- .setStatusCode(Code.COMPLETE)
- .build()
- }
- return responseBuilder.build()
- }
-
- private fun executeFulfillmentRequest(
- session: CapabilitySession,
- fulfillmentRequest: FulfillmentRequest.Fulfillment,
- ): ListenableFuture<FulfillmentResponse> = CallbackToFutureAdapter.getFuture { completer ->
- session.execute(
- ArgumentsWrapper.create(fulfillmentRequest),
- CapabilityCallback(completer),
- )
- "executing action capability"
- }
-}
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppVerificationInfo.kt b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppVerificationInfo.kt
deleted file mode 100644
index 5f14f32..0000000
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppVerificationInfo.kt
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.appactions.interaction.service
-
-import java.util.Objects
-
-/**
- * Representation of a client's verified package with a corresponding list of Sha256 signatures.
- * [AppVerificationInfo] provides a convenient way to build a valid {@link SecurityPolicy} for the
- * grpc service.
- */
-class AppVerificationInfo
-internal constructor(val packageName: String, val signatures: List<ByteArray>) {
-
- override fun toString() =
- "AppVerificationInfo(packageName=$packageName, signaturesSize=$signatures.size)"
-
- override fun equals(other: Any?): Boolean {
- return other is AppVerificationInfo &&
- packageName == other.packageName &&
- signatures == other.signatures
- }
-
- override fun hashCode() = Objects.hash(packageName, signatures)
-
- /** Builder for constructing an AppVerificationInfo instance. */
- class Builder {
- private var packageName: String? = null
- private var signatures: List<ByteArray> = mutableListOf()
-
- /** Set the packageName that will be part of the [AppVerificationInfo] */
- fun setPackageName(packageName: String) = apply { this.packageName = packageName }
-
- /** Set the packageName that will be part of the [AppVerificationInfo] */
- fun addSignature(signatures: ByteArray) = apply { this.signatures = listOf(signatures) }
-
- /**
- * Creates a new instance of [AppVerificationInfo]
- *
- * @Throws IllegalArgumentException if packageName is null or signatures are empty.
- */
- fun build(): AppVerificationInfo {
- if (packageName == null) {
- throw IllegalArgumentException("App verification info packageName is missing.")
- }
- if (signatures.isEmpty()) {
- throw IllegalArgumentException("App verification info signatures are missing.")
- }
- return AppVerificationInfo(packageName!!, signatures)
- }
- }
-}
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/CapabilityCallback.java b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/CapabilityCallback.java
deleted file mode 100644
index b66015e9f..0000000
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/CapabilityCallback.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.appactions.interaction.service;
-
-import androidx.annotation.NonNull;
-import androidx.appactions.interaction.capabilities.core.impl.CallbackInternal;
-import androidx.appactions.interaction.capabilities.core.impl.ErrorStatusInternal;
-import androidx.appactions.interaction.proto.FulfillmentResponse;
-import androidx.concurrent.futures.CallbackToFutureAdapter.Completer;
-
-/** Service implementation of the capability library execution callback. */
-final class CapabilityCallback implements CallbackInternal {
-
- private final Completer<FulfillmentResponse> mCompleter;
-
- CapabilityCallback(@NonNull Completer<FulfillmentResponse> mCompleter) {
- this.mCompleter = mCompleter;
- }
-
- @Override
- public void onSuccess(@NonNull FulfillmentResponse fulfillmentResponse) {
- mCompleter.set(fulfillmentResponse);
- }
-
- @Override
- public void onError(@NonNull ErrorStatusInternal errorStatus) {
- mCompleter.setException(
- new CapabilityExecutionException(errorStatus, "Error executing action capability"));
- }
-}
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/CapabilityExecutionException.kt b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/CapabilityExecutionException.kt
deleted file mode 100644
index 6f7b5ff..0000000
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/CapabilityExecutionException.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.appactions.interaction.service
-
-import androidx.appactions.interaction.capabilities.core.impl.ErrorStatusInternal
-
-/** Exception that occurs from failure to execute capability when sending fulfillment request. */
-internal class CapabilityExecutionException(
- val errorStatus: ErrorStatusInternal,
- message: String?
-) : RuntimeException(message)
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/RemoteViewsInternal.kt b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/RemoteViewsInternal.kt
deleted file mode 100644
index 7d300c3..0000000
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/RemoteViewsInternal.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.appactions.interaction.service
-
-import android.util.SizeF
-import android.widget.RemoteViews
-import android.widget.RemoteViewsService.RemoteViewsFactory
-import androidx.annotation.RestrictTo
-
-/**
- * Holder for RemoteViews UI response.
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY)
-data class RemoteViewsInternal(
- val remoteViews: RemoteViews,
- val size: SizeF,
- val collectionViewFactories: Map<Int, RemoteViewsFactory> = mapOf()
-)
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/RemoteViewsOverMetadataInterceptor.java b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/RemoteViewsOverMetadataInterceptor.java
deleted file mode 100644
index 013936f..0000000
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/RemoteViewsOverMetadataInterceptor.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.appactions.interaction.service;
-
-import static io.grpc.binder.ParcelableUtils.metadataKey;
-
-import android.widget.RemoteViews;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RestrictTo;
-
-import java.util.concurrent.atomic.AtomicReference;
-
-import io.grpc.Context;
-import io.grpc.Contexts;
-import io.grpc.ForwardingServerCall.SimpleForwardingServerCall;
-import io.grpc.Metadata;
-import io.grpc.ServerCall;
-import io.grpc.ServerCall.Listener;
-import io.grpc.ServerCallHandler;
-import io.grpc.ServerInterceptor;
-import io.grpc.Status;
-
-/**
- * Server interceptor that copies the RemoteViews provided in context to metadata.
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-public final class RemoteViewsOverMetadataInterceptor implements ServerInterceptor {
-
- private static final String KEY = "RemoteViews-bin";
- public static final Metadata.Key<RemoteViews> METADATA_KEY = metadataKey(KEY,
- RemoteViews.CREATOR);
- static final Context.Key<AtomicReference<RemoteViews>> RESPONSE = Context.key("RES-" + KEY);
-
- static void setRemoteViews(@NonNull RemoteViews remoteViews) {
- RESPONSE.get().set(remoteViews);
- }
-
- @Override
- @NonNull
- public <ReqT, RespT> Listener<ReqT> interceptCall(
- @NonNull ServerCall<ReqT, RespT> call,
- @NonNull Metadata headers,
- @NonNull ServerCallHandler<ReqT, RespT> next) {
- Context context = Context.current().withValue(RESPONSE, new AtomicReference<>());
-
- return Contexts.interceptCall(
- context,
- new SimpleForwardingServerCall<ReqT, RespT>(call) {
- @Override
- public void close(Status status, Metadata trailers) {
- RemoteViews value = RESPONSE.get(context).get();
- if (value != null) {
- trailers.put(METADATA_KEY, value);
- }
- super.close(status, trailers);
- }
- },
- headers,
- next);
- }
-}
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/SessionManager.kt b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/SessionManager.kt
deleted file mode 100644
index 7852a42..0000000
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/SessionManager.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.appactions.interaction.service
-
-import androidx.annotation.GuardedBy
-import androidx.appactions.interaction.capabilities.core.impl.CapabilitySession
-import javax.annotation.concurrent.ThreadSafe
-
-/** Global object for managing capability sessions. */
-@ThreadSafe
-internal object SessionManager {
-
- private val lock = Any()
-
- @GuardedBy("lock")
- private val sessions = mutableMapOf<String, CapabilitySession>()
-
- fun putSession(sessionId: String, session: CapabilitySession) {
- synchronized(lock) {
- sessions[sessionId] = session
- }
- }
-
- fun getSession(sessionId: String): CapabilitySession? {
- synchronized(lock) {
- return sessions[sessionId]
- }
- }
-
- fun removeSession(sessionId: String) {
- synchronized(lock) {
- sessions.remove(sessionId)
- }
- }
-}
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/TileLayoutInternal.kt b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/TileLayoutInternal.kt
deleted file mode 100644
index 70279ad..0000000
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/TileLayoutInternal.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.appactions.interaction.service
-
-import androidx.annotation.RestrictTo
-import androidx.appactions.interaction.protobuf.ByteString
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto
-
-/**
- * Holder for TileLayout response.
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-class TileLayoutInternal(val byteArray: ByteArray) {
-
- fun toProto(): AppInteractionServiceProto.TileLayout {
- return AppInteractionServiceProto.TileLayout.newBuilder()
- .setLayout(ByteString.copyFrom(byteArray))
- .build()
- }
-}
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiCache.kt b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiCache.kt
deleted file mode 100644
index ec9809f..0000000
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiCache.kt
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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.appactions.interaction.service
-
-import androidx.annotation.GuardedBy
-import javax.annotation.concurrent.ThreadSafe
-
-/**
- * Cache for different types of supported UI (RemoteViews for general Android and TileLayout for
- * Wear).
- * <p>
- * When developers call our APIs to update UI, we don't immediately respect that and send it over
- * the service. Instead, we cache it here and wait for the GRPC impl to decide on an appropriate
- * time to return UI.
- */
-@ThreadSafe
-internal class UiCache {
-
- private val lock = Any()
-
- @GuardedBy("lock")
- var cachedRemoteViewsInternal: RemoteViewsInternal? = null
- get() {
- synchronized(lock) {
- return field
- }
- }
- private set
-
- @GuardedBy("lock")
- var cachedTileLayoutInternal: TileLayoutInternal? = null
- get() {
- synchronized(lock) {
- return field
- }
- }
- private set
-
- // Needs to be reset after the UiUpdate signal has been sent to assistant. When assistant receives
- // the signal, it should send rpc requests to fetch these cached UiResponse(s).
- @GuardedBy("lock")
- var hasUnreadUiResponse: Boolean = false
- get() {
- synchronized(lock) {
- return field
- }
- }
- private set
-
- /**
- * Caches a UiResponse for this particular {@link BaseExecutionSession}.
- */
- fun updateUiInternal(uiResponse: UiResponse) {
- synchronized(lock) {
- hasUnreadUiResponse = true
- if (uiResponse.remoteViewsInternal != null) {
- cachedRemoteViewsInternal = uiResponse.remoteViewsInternal
- }
- if (uiResponse.tileLayoutInternal != null) {
- cachedTileLayoutInternal = uiResponse.tileLayoutInternal
- }
- }
- }
-
- fun resetUnreadUiResponse() {
- synchronized(lock) {
- hasUnreadUiResponse = false
- }
- }
-}
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
deleted file mode 100644
index ec2dded..0000000
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiResponse.kt
+++ /dev/null
@@ -1,86 +0,0 @@
-
-/*
- * 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.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.
- */
-// TODO(b/284056880): Open up UI related APIs.
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-class UiResponse {
-
- internal val remoteViewsInternal: RemoteViewsInternal?
- internal val tileLayoutInternal: TileLayoutInternal?
-
- internal constructor(remoteViewsInternal: RemoteViewsInternal) {
- this.remoteViewsInternal = remoteViewsInternal
- this.tileLayoutInternal = null
- }
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
- constructor(tileLayout: TileLayoutInternal) {
- this.remoteViewsInternal = null
- this.tileLayoutInternal = tileLayout
- }
-
- /** 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.
- *
- * @param remoteViews the `RemoteViews` to be displayed
- * @param size the size, in dp, of the RemoteViews being displayed
- */
- @SuppressLint("MissingGetterMatchingBuilder")
- fun setRemoteViews(remoteViews: RemoteViews, size: SizeF?): RemoteViewsUiBuilder {
- this.remoteViews = remoteViews
- 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
- * [RemoteViewsFactory] is cached by `viewId` and will be cleared when the session exits.
- *
- * @param viewId the id of the collection view
- * @param factory a RemoteViewsFactory associated with the collection view
- */
- @SuppressLint("MissingGetterMatchingBuilder")
- fun addRemoteViewsFactory(
- @IdRes viewId: Int,
- factory: RemoteViewsFactory
- ): RemoteViewsUiBuilder {
- collectionViewFactories[viewId] = factory
- return this
- }
- /** Builds the UiResponse. */
- fun build() =
- UiResponse(
- RemoteViewsInternal(remoteViews!!, size!!, collectionViewFactories)
- )
- }
-}
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiSessions.kt b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiSessions.kt
deleted file mode 100644
index b4d2405..0000000
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiSessions.kt
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.
- */
-@file:JvmName("UiUpdater")
-
-package androidx.appactions.interaction.service
-
-import androidx.annotation.GuardedBy
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.impl.UiHandleRegistry
-import androidx.appactions.interaction.service.UiSessions.removeUiCache
-import javax.annotation.concurrent.ThreadSafe
-
-/**
- * A singleton object used to maintain UiCache objects per capability session.
- *
- * When the developer first calls `updateUi`, create a new [UiCache] for it. The Ui from the
- * developer is cached until the GRPC impl reads it. It's up to the GRPC impl to clean up the
- * UiCache (by calling [removeUiCache] before destroying the session.
- */
-@ThreadSafe
-internal object UiSessions {
- private val lock = Any()
- @GuardedBy("lock")
- private val sessionIdToUiCache = mutableMapOf<String, UiCache>()
-
- fun removeUiCache(sessionId: String): Boolean {
- synchronized(lock) {
- return sessionIdToUiCache.remove(sessionId) != null
- }
- }
-
- fun getOrCreateUiCache(sessionId: String): UiCache {
- synchronized(lock) {
- return sessionIdToUiCache[sessionId] ?: createUiCache(sessionId)
- }
- }
-
- fun getUiCacheOrNull(sessionId: String): UiCache? {
- synchronized(lock) {
- return sessionIdToUiCache[sessionId]
- }
- }
-
- private fun createUiCache(sessionId: String): UiCache {
- val uiCache = UiCache()
- synchronized(lock) {
- sessionIdToUiCache[sessionId] = uiCache
- }
- return uiCache
- }
-}
-
-// TODO(b/284056880): Open up UI related APIs (remove internal)
-/** Return a UI associated with this [BaseExecutionSession]. */
-internal fun BaseExecutionSession<*, *>.updateUi(uiResponse: UiResponse) =
- UiSessions.getOrCreateUiCache(
- UiHandleRegistry.getSessionIdFromUiHandle(this)!!
- ).updateUiInternal(uiResponse)
-
-// TODO(b/284056880): Open up UI related APIs (remove internal)
-/** Return a UI associated with this [ExecutionCallback]. */
-internal fun ExecutionCallback<*, *>.updateUi(uiResponse: UiResponse) =
- UiSessions.getOrCreateUiCache(
- UiHandleRegistry.getSessionIdFromUiHandle(this)!!
- ).updateUiInternal(uiResponse)
diff --git a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/AppInteractionServiceEntityProviderTest.kt b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/AppInteractionServiceEntityProviderTest.kt
deleted file mode 100644
index c955f86..0000000
--- a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/AppInteractionServiceEntityProviderTest.kt
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * 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.appactions.interaction.service
-
-import androidx.appactions.builtintypes.types.Alarm
-import androidx.appactions.interaction.capabilities.core.impl.converters.EntityConverter
-import androidx.appactions.interaction.capabilities.serializers.types.ALARM_TYPE_SPEC
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils.buildSearchActionParamValue
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.awaitSync
-import androidx.appactions.interaction.proto.GroundingRequest
-import androidx.appactions.interaction.proto.GroundingRequest.Request
-import androidx.appactions.interaction.proto.GroundingResponse
-import androidx.appactions.interaction.proto.GroundingResponse.Candidate
-import androidx.appactions.interaction.proto.GroundingResponse.Response
-import androidx.appactions.interaction.proto.GroundingResponse.Status
-import androidx.appactions.interaction.service.proto.AppInteractionServiceGrpc
-import androidx.appactions.interaction.service.testing.internal.FakeAlarmEntityProvider
-import androidx.appactions.interaction.service.testing.internal.FakeAppInteractionService
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.google.common.truth.Truth.assertThat
-import io.grpc.BindableService
-import io.grpc.ManagedChannel
-import io.grpc.Server
-import io.grpc.inprocess.InProcessChannelBuilder
-import io.grpc.inprocess.InProcessServerBuilder
-import io.grpc.stub.StreamObserver
-import io.grpc.testing.GrpcCleanupRule
-import kotlinx.coroutines.CompletableDeferred
-import kotlinx.coroutines.runBlocking
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.robolectric.Robolectric
-
-@RunWith(AndroidJUnit4::class)
-class AppInteractionServiceEntityProviderTest {
- val testServerName = "testServer"
-
- @get:Rule val grpcCleanup = GrpcCleanupRule()
-
- private lateinit var appInteractionService: FakeAppInteractionService
-
- @Before
- fun before() {
- appInteractionService = Robolectric.buildService(
- FakeAppInteractionService::class.java
- ).get()
- }
-
- @Test
- fun alarmProvider_incorrectProviderId(): Unit = runBlocking {
- val morningAlarm = Alarm.Builder().setIdentifier("alarm1").setName("Morning Alarm").build()
- val alarmProvider = FakeAlarmEntityProvider(
- "alarmProvider",
- listOf(morningAlarm)
- )
- appInteractionService.registeredEntityProviders = listOf(alarmProvider)
- val server =
- createInProcessServer(
- AppInteractionServiceGrpcImpl(appInteractionService)
- )
-
- val channel = createInProcessChannel()
- val stub = AppInteractionServiceGrpc.newStub(channel)
-
- val groundingRequest = GroundingRequest
- .newBuilder()
- .setRequest(
- Request.newBuilder()
- .setEntityProviderId("randomIncorrectId")
- .setSearchAction(
- buildSearchActionParamValue(
- "alarm search query"
- )
- )
- )
- .build()
-
- val responseObserver = TestStreamObserver<GroundingResponse>()
- stub.requestGrounding(groundingRequest, responseObserver)
- val groundingResponse = responseObserver.firstResultDeferred.awaitSync()
- assertThat(groundingResponse).isEqualTo(
- GroundingResponse.newBuilder()
- .setResponse(
- GroundingResponse.Response.newBuilder().setStatus(
- GroundingResponse.Status.INVALID_ENTITY_PROVIDER,
- ),
- ).build()
- )
-
- server.shutdownNow()
- }
-
- @Test
- fun alarmProvider_success(): Unit = runBlocking {
- val morningAlarm = Alarm.Builder().setIdentifier("alarm1").setName("Morning Alarm").build()
- val alarmProvider = FakeAlarmEntityProvider(
- "alarmProvider",
- listOf(morningAlarm)
- )
- appInteractionService.registeredEntityProviders = listOf(alarmProvider)
- val server =
- createInProcessServer(
- AppInteractionServiceGrpcImpl(appInteractionService)
- )
-
- val channel = createInProcessChannel()
- val stub = AppInteractionServiceGrpc.newStub(channel)
-
- val groundingRequest = GroundingRequest
- .newBuilder()
- .setRequest(
- Request.newBuilder()
- .setEntityProviderId("alarmProvider")
- .setSearchAction(
- buildSearchActionParamValue(
- "alarm search query"
- )
- )
- )
- .build()
-
- val responseObserver = TestStreamObserver<GroundingResponse>()
- stub.requestGrounding(groundingRequest, responseObserver)
- val groundingResponse = responseObserver.firstResultDeferred.awaitSync()
- assertThat(groundingResponse).isEqualTo(
- GroundingResponse.newBuilder().setResponse(
- Response.newBuilder()
- .setStatus(Status.SUCCESS)
- .addCandidates(
- Candidate.newBuilder().setGroundedEntity(
- EntityConverter.of(ALARM_TYPE_SPEC).convert(morningAlarm)
- )
- )
- ).build()
- )
-
- server.shutdownNow()
- }
-
- private fun createInProcessServer(
- service: BindableService
- ): Server {
- return grpcCleanup.register(
- InProcessServerBuilder.forName(testServerName)
- .directExecutor()
- .addService(service)
- .build()
- .start()
- )
- }
-
- private fun createInProcessChannel(): ManagedChannel {
- return grpcCleanup.register(
- InProcessChannelBuilder.forName(testServerName).directExecutor().build()
- )
- }
-
- /** Captures the first error or value received by the stream observer */
- private class TestStreamObserver<T> : StreamObserver<T> {
- val firstResultDeferred = CompletableDeferred<T>()
-
- override fun onNext(value: T) {
- firstResultDeferred.complete(value)
- }
-
- override fun onError(t: Throwable) {
- firstResultDeferred.completeExceptionally(t)
- }
-
- override fun onCompleted() {
- firstResultDeferred.cancel()
- }
- }
-}
diff --git a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/AppInteractionServiceGrpcImplTest.kt b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/AppInteractionServiceGrpcImplTest.kt
deleted file mode 100644
index a6c6a05..0000000
--- a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/AppInteractionServiceGrpcImplTest.kt
+++ /dev/null
@@ -1,989 +0,0 @@
-/*
- * 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.appactions.interaction.service
-
-import android.content.Context
-import android.util.SizeF
-import android.widget.RemoteViews
-import android.widget.RemoteViewsService.RemoteViewsFactory
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.impl.CallbackInternal
-import androidx.appactions.interaction.capabilities.core.impl.CapabilitySession
-import androidx.appactions.interaction.capabilities.core.impl.ErrorStatusInternal
-import androidx.appactions.interaction.proto.AppActionsContext
-import androidx.appactions.interaction.proto.AppActionsContext.AppAction
-import androidx.appactions.interaction.proto.AppActionsContext.AppDialogState
-import androidx.appactions.interaction.proto.AppInteractionMetadata.ErrorStatus
-import androidx.appactions.interaction.proto.CurrentValue
-import androidx.appactions.interaction.proto.FulfillmentRequest
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.FulfillmentParam
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.FulfillmentValue
-import androidx.appactions.interaction.proto.FulfillmentResponse
-import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput
-import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput.OutputValue
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.service.AppInteractionServiceGrpcImpl.Companion.ERROR_NO_ACTION_CAPABILITY
-import androidx.appactions.interaction.service.AppInteractionServiceGrpcImpl.Companion.ERROR_NO_FULFILLMENT_REQUEST
-import androidx.appactions.interaction.service.AppInteractionServiceGrpcImpl.Companion.ERROR_NO_SESSION
-import androidx.appactions.interaction.service.AppInteractionServiceGrpcImpl.Companion.ERROR_SESSION_ENDED
-import androidx.appactions.interaction.service.proto.AppInteractionServiceGrpc
-import androidx.appactions.interaction.service.proto.AppInteractionServiceGrpc.AppInteractionServiceStub
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto.CollectionRequest.GetCount
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto.CollectionRequest.GetItemId
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto.CollectionRequest.GetLoadingView
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto.CollectionRequest.GetViewAt
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto.CollectionRequest.GetViewTypeCount
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto.CollectionRequest.HasStableIds
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto.CollectionRequest.OnDestroy
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto.Request
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto.StartSessionRequest
-import androidx.appactions.interaction.service.proto.AppInteractionServiceProto.StartSessionResponse
-import androidx.appactions.interaction.service.test.R
-import androidx.appactions.interaction.service.testing.internal.FakeAppInteractionService
-import androidx.appactions.interaction.service.testing.internal.FakeCapability
-import androidx.concurrent.futures.await
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.google.common.truth.Truth.assertThat
-import io.grpc.BindableService
-import io.grpc.ManagedChannel
-import io.grpc.Server
-import io.grpc.ServerInterceptor
-import io.grpc.ServerInterceptors
-import io.grpc.Status
-import io.grpc.StatusRuntimeException
-import io.grpc.inprocess.InProcessChannelBuilder
-import io.grpc.inprocess.InProcessServerBuilder
-import io.grpc.stub.StreamObserver
-import io.grpc.testing.GrpcCleanupRule
-import java.io.IOException
-import kotlin.test.assertFailsWith
-import kotlinx.coroutines.CompletableDeferred
-import kotlinx.coroutines.runBlocking
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.kotlin.any
-import org.mockito.kotlin.argumentCaptor
-import org.mockito.kotlin.doAnswer
-import org.mockito.kotlin.doReturn
-import org.mockito.kotlin.mock
-import org.mockito.kotlin.never
-import org.mockito.kotlin.times
-import org.mockito.kotlin.verify
-import org.mockito.kotlin.whenever
-import org.robolectric.Robolectric
-
-// TODO(b/271929200) Implement tests for the 2 UI related RPCs
-@RunWith(AndroidJUnit4::class)
-class AppInteractionServiceGrpcImplTest {
-
- @get:Rule val grpcCleanup = GrpcCleanupRule()
-
- private val remoteViewsInterceptor: ServerInterceptor = RemoteViewsOverMetadataInterceptor()
- private val testServerName = InProcessServerBuilder.generateName()
- private val testBiiName = "actions.intent.SAMPLE_BII_NAME"
- private val sessionId = "session-123"
- private val capabilityId = "capability-123"
- private val defaultStartSessionRequest =
- StartSessionRequest.newBuilder()
- .setIntentName(testBiiName)
- .setIdentifier(capabilityId)
- .setSessionIdentifier(sessionId)
- .build()
- private val testFulfillmentRequest =
- FulfillmentRequest.newBuilder()
- .addFulfillments(
- Fulfillment.newBuilder().setName(testBiiName).setIdentifier(capabilityId).build()
- )
- .build()
- private val testFulfillmentResponse =
- FulfillmentResponse.newBuilder()
- .setExecutionOutput(
- StructuredOutput.newBuilder()
- .addOutputValues(OutputValue.newBuilder().setName("bio_arg1")),
- )
- .build()
- private val testFulfillmentRequestUi =
- FulfillmentRequest.newBuilder()
- .addFulfillments(
- Fulfillment.newBuilder()
- .setName(testBiiName)
- .setIdentifier(capabilityId)
- .addParams(
- FulfillmentParam.newBuilder()
- .setName("fieldOne")
- .addFulfillmentValues(
- FulfillmentValue.newBuilder()
- .setValue(
- ParamValue.newBuilder().setStringValue("hello").build())
- .build())
- .build())
- .setType(Fulfillment.Type.SYNC)
- .setSyncStatus(Fulfillment.SyncStatus.SLOTS_COMPLETE)
- .build()
- )
- .build()
- private val testAppDialogState = AppDialogState.newBuilder().setFulfillmentIdentifier("id")
- .addParams(
- AppActionsContext.DialogParameter.newBuilder()
- .setName("Sample dialog")
- .addCurrentValue(
- CurrentValue.newBuilder().setValue(
- ParamValue.newBuilder().setStringValue("Sample Test").build()
- )
- )
- ).build()
- private lateinit var capability1: Capability
- private lateinit var appInteractionService: FakeAppInteractionService
-
- private val context: Context = ApplicationProvider.getApplicationContext()
- private val remoteViewsFactoryId = 123
- private val remoteViews = RemoteViews(context.packageName, R.layout.remote_view)
-
- private fun createFakeCapability(vararg uiResponses: UiResponse):
- Capability {
- return FakeCapability.CapabilityBuilder()
- .setId(capabilityId)
- .setExecutionSessionFactory { _ ->
- object : FakeCapability.ExecutionSession {
- override suspend fun onExecute(
- arguments: FakeCapability.Arguments,
- ): ExecutionResult<FakeCapability.Output> {
- for (uiResponse in uiResponses) {
- this.updateUi(uiResponse)
- }
- return ExecutionResult.Builder<FakeCapability.Output>().build()
- }
- }
- }
- .build()
- }
-
- @Before
- fun setup() {
- capability1 = mock()
- whenever(capability1.id).thenReturn(capabilityId)
- whenever(capability1.appAction).thenReturn(AppAction.getDefaultInstance())
- val mockCapabilitySession = createMockSession()
- whenever(capability1.createSession(any(), any())).thenReturn(mockCapabilitySession)
- appInteractionService = Robolectric.buildService(
- FakeAppInteractionService::class.java
- ).get()
- appInteractionService.registeredCapabilities = listOf(capability1)
- }
-
- @After
- fun cleanup() {
- UiSessions.removeUiCache(sessionId)
- }
-
- @Test
- fun startUpSession_validRequest_success(): Unit = runBlocking {
- val server =
- createInProcessServer(
- AppInteractionServiceGrpcImpl(appInteractionService),
- remoteViewsInterceptor,
- )
-
- val channel = createInProcessChannel()
- val stub = AppInteractionServiceGrpc.newStub(channel)
-
- // Set up gRPC response capture
- val startUpSessionCallback = CompletableDeferred<Unit>()
- val startSessionResponseObserver = mock<StreamObserver<StartSessionResponse>>()
- whenever(startSessionResponseObserver.onNext(any())) doAnswer
- {
- startUpSessionCallback.complete(Unit)
- Unit
- }
-
- // Send startup request
- val startSessionRequestObserver = stub.startUpSession(startSessionResponseObserver)
- startSessionRequestObserver.onNext(defaultStartSessionRequest)
-
- // Assert startup response
- startUpSessionCallback.await()
- val responseCaptor = argumentCaptor<StartSessionResponse>()
- verify(startSessionResponseObserver).onNext(responseCaptor.capture())
- val startSessionResponse = responseCaptor.firstValue
- assertThat(startSessionResponse).isEqualTo(StartSessionResponse.getDefaultInstance())
- verify(startSessionResponseObserver, times(1)).onNext(any())
- assertThat(SessionManager.getSession(sessionId)).isNotNull()
-
- // end startSession stream
- startSessionRequestObserver.onCompleted()
- assertThat(SessionManager.getSession(sessionId)).isNull()
-
- server.shutdownNow()
- }
-
- @Test
- fun requestUi_respondWithRemoteViewsInMetadata(): Unit = runBlocking {
-
- val remoteViewsUiResponse =
- UiResponse.RemoteViewsUiBuilder()
- .setRemoteViews(remoteViews, SizeF(10f, 15f))
- .addRemoteViewsFactory(remoteViewsFactoryId, FakeRemoteViewsFactory())
- .build()
-
- appInteractionService.registeredCapabilities = listOf(
- createFakeCapability(remoteViewsUiResponse)
- )
- val server =
- createInProcessServer(
- AppInteractionServiceGrpcImpl(appInteractionService),
- remoteViewsInterceptor
- )
- val channel = createInProcessChannel()
- val stub = AppInteractionServiceGrpc.newStub(channel)
- val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
-
- assertStartupSession(stub)
-
- // Send fulfillment request
- val request =
- Request.newBuilder()
- .setSessionIdentifier(sessionId)
- .setFulfillmentRequest(testFulfillmentRequestUi)
- .build()
-
- val responseFuture = futureStub.sendRequestFulfillment(request)
- responseFuture.await()
-
- val responseObserver = mock<StreamObserver<AppInteractionServiceProto.UiResponse>>()
- stub.requestUi(
- AppInteractionServiceProto.UiRequest.newBuilder()
- .setSessionIdentifier(sessionId).build(),
- responseObserver
- )
- val responseCaptor = argumentCaptor<AppInteractionServiceProto.UiResponse>()
- verify(responseObserver).onNext(responseCaptor.capture())
- assertThat(responseCaptor.firstValue).isEqualTo(
- AppInteractionServiceProto.UiResponse.newBuilder().setRemoteViewsInfo(
- AppInteractionServiceProto.RemoteViewsInfo.newBuilder()
- .setWidthDp(10f)
- .setHeightDp(15f)
- .build()
- ).build()
- )
-
- server.shutdownNow()
- }
-
- @Test
- fun requestUi_noUi_failWithStatusRuntimeException(): Unit = runBlocking {
-
- appInteractionService.registeredCapabilities = listOf(
- createFakeCapability() // Not setting any Ui response
- )
- val server =
- createInProcessServer(
- AppInteractionServiceGrpcImpl(appInteractionService),
- remoteViewsInterceptor
- )
- val channel = createInProcessChannel()
- val stub = AppInteractionServiceGrpc.newStub(channel)
- val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
-
- assertStartupSession(stub)
- // Send fulfillment request
- val request =
- Request.newBuilder()
- .setSessionIdentifier(sessionId)
- .setFulfillmentRequest(testFulfillmentRequestUi)
- .build()
-
- val responseFuture = futureStub.sendRequestFulfillment(request)
- responseFuture.await()
-
- val responseObserver = mock<StreamObserver<AppInteractionServiceProto.UiResponse>>()
- stub.requestUi(
- AppInteractionServiceProto.UiRequest.newBuilder()
- .setSessionIdentifier(sessionId).build(),
- responseObserver
- )
-
- val errorCaptor = argumentCaptor<StatusRuntimeException>()
- verify(responseObserver).onError(errorCaptor.capture())
- assertThat(errorCaptor.firstValue.status.code).isEqualTo(
- Status.INTERNAL.code
- )
- assertThat(errorCaptor.firstValue.status.description).isEqualTo("No UI set")
-
- server.shutdownNow()
- }
-
- @Test
- fun collectionRequestTriggersRemoteViewFactory(): Unit = runBlocking {
-
- val mockedRemoteViewFactory = mock<RemoteViewsFactory>()
- val remoteViewsUiResponse = UiResponse.RemoteViewsUiBuilder()
- .setRemoteViews(remoteViews, SizeF(10f, 15f))
- .addRemoteViewsFactory(remoteViewsFactoryId, mockedRemoteViewFactory)
- .build()
-
- appInteractionService.registeredCapabilities = listOf(
- createFakeCapability(remoteViewsUiResponse)
- )
- val server =
- createInProcessServer(
- AppInteractionServiceGrpcImpl(appInteractionService),
- remoteViewsInterceptor
- )
- val channel = createInProcessChannel()
- val stub = AppInteractionServiceGrpc.newStub(channel)
- val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
-
- assertStartupSession(stub)
- // Send fulfillment request
- val request =
- Request.newBuilder()
- .setSessionIdentifier(sessionId)
- .setFulfillmentRequest(testFulfillmentRequestUi)
- .build()
-
- val responseFuture = futureStub.sendRequestFulfillment(request)
- responseFuture.await()
-
- val collectionRequest = AppInteractionServiceProto.CollectionRequest.newBuilder()
- .setSessionIdentifier(sessionId)
- .setViewId(123)
- .setGetViewTypeCount(GetViewTypeCount.newBuilder().build()).build()
- futureStub.requestCollection(collectionRequest)
- verify(mockedRemoteViewFactory, times(1)).viewTypeCount
-
- server.shutdownNow()
- }
-
- @Test
- fun collectionRequestTriggersGetCount(): Unit = runBlocking {
-
- val mockedRemoteViewFactory = mock<RemoteViewsFactory>()
- whenever(mockedRemoteViewFactory.count) doReturn (3)
- val remoteViewsUiResponse = UiResponse.RemoteViewsUiBuilder()
- .setRemoteViews(remoteViews, SizeF(10f, 15f))
- .addRemoteViewsFactory(remoteViewsFactoryId, mockedRemoteViewFactory)
- .build()
-
- appInteractionService.registeredCapabilities = listOf(
- createFakeCapability(remoteViewsUiResponse)
- )
- val server =
- createInProcessServer(
- AppInteractionServiceGrpcImpl(appInteractionService),
- remoteViewsInterceptor
- )
- val channel = createInProcessChannel()
- val stub = AppInteractionServiceGrpc.newStub(channel)
- val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
-
- assertStartupSession(stub)
- // Send fulfillment request
- val request =
- Request.newBuilder()
- .setSessionIdentifier(sessionId)
- .setFulfillmentRequest(testFulfillmentRequestUi)
- .build()
-
- val responseFuture = futureStub.sendRequestFulfillment(request)
- responseFuture.await()
-
- val collectionRequest = AppInteractionServiceProto.CollectionRequest.newBuilder()
- .setSessionIdentifier(sessionId)
- .setViewId(123)
- .setGetCount(GetCount.newBuilder().build())
- .build()
- val collectionResponse = futureStub.requestCollection(collectionRequest).await()
- verify(mockedRemoteViewFactory).count
- assertThat(collectionResponse.getCount.count).isEqualTo(3)
-
- server.shutdownNow()
- }
-
- @Test
- fun collectionRequestTriggersOnDestroy(): Unit = runBlocking {
-
- val mockedRemoteViewFactory = mock<RemoteViewsFactory>()
- val remoteViewsUiResponse = UiResponse.RemoteViewsUiBuilder()
- .setRemoteViews(remoteViews, SizeF(10f, 15f))
- .addRemoteViewsFactory(remoteViewsFactoryId, mockedRemoteViewFactory)
- .build()
-
- appInteractionService.registeredCapabilities = listOf(
- createFakeCapability(remoteViewsUiResponse)
- )
- val server =
- createInProcessServer(
- AppInteractionServiceGrpcImpl(appInteractionService),
- remoteViewsInterceptor
- )
- val channel = createInProcessChannel()
- val stub = AppInteractionServiceGrpc.newStub(channel)
- val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
-
- assertStartupSession(stub)
- // Send fulfillment request
- val request =
- Request.newBuilder()
- .setSessionIdentifier(sessionId)
- .setFulfillmentRequest(testFulfillmentRequestUi)
- .build()
-
- val responseFuture = futureStub.sendRequestFulfillment(request)
- responseFuture.await()
-
- val collectionRequest = AppInteractionServiceProto.CollectionRequest.newBuilder()
- .setSessionIdentifier(sessionId)
- .setViewId(123)
- .setOnDestroy(OnDestroy.newBuilder().build()).build()
- futureStub.requestCollection(collectionRequest).await()
- verify(mockedRemoteViewFactory, times(1)).onDestroy()
-
- server.shutdownNow()
- }
-
- @Test
- fun collectionRequestTriggersGetViewAt(): Unit = runBlocking {
-
- val mockedRemoteViewFactory = mock<RemoteViewsFactory>()
- val remoteViewsUiResponse = UiResponse.RemoteViewsUiBuilder()
- .setRemoteViews(remoteViews, SizeF(10f, 15f))
- .addRemoteViewsFactory(remoteViewsFactoryId, mockedRemoteViewFactory)
- .build()
-
- appInteractionService.registeredCapabilities = listOf(
- createFakeCapability(remoteViewsUiResponse)
- )
- val server =
- createInProcessServer(
- AppInteractionServiceGrpcImpl(appInteractionService),
- remoteViewsInterceptor
- )
- val channel = createInProcessChannel()
- val stub = AppInteractionServiceGrpc.newStub(channel)
- val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
-
- assertStartupSession(stub)
- // Send fulfillment request
- val request =
- Request.newBuilder()
- .setSessionIdentifier(sessionId)
- .setFulfillmentRequest(testFulfillmentRequestUi)
- .build()
-
- val responseFuture = futureStub.sendRequestFulfillment(request)
- responseFuture.await()
-
- val collectionRequest = AppInteractionServiceProto.CollectionRequest.newBuilder()
- .setSessionIdentifier(sessionId)
- .setViewId(123)
- .setGetViewAt(GetViewAt.newBuilder().setPosition(1).build()).build()
- futureStub.requestCollection(collectionRequest).await()
- verify(mockedRemoteViewFactory, times(1)).getViewAt(1)
-
- server.shutdownNow()
- }
-
- @Test
- fun collectionRequestTriggersGetLoadingView(): Unit = runBlocking {
-
- val mockedRemoteViewFactory = mock<RemoteViewsFactory>()
- val remoteViewsUiResponse = UiResponse.RemoteViewsUiBuilder()
- .setRemoteViews(remoteViews, SizeF(10f, 15f))
- .addRemoteViewsFactory(remoteViewsFactoryId, mockedRemoteViewFactory)
- .build()
-
- appInteractionService.registeredCapabilities = listOf(
- createFakeCapability(remoteViewsUiResponse)
- )
- val server =
- createInProcessServer(
- AppInteractionServiceGrpcImpl(appInteractionService),
- remoteViewsInterceptor
- )
- val channel = createInProcessChannel()
- val stub = AppInteractionServiceGrpc.newStub(channel)
- val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
-
- assertStartupSession(stub)
- // Send fulfillment request
- val request =
- Request.newBuilder()
- .setSessionIdentifier(sessionId)
- .setFulfillmentRequest(testFulfillmentRequestUi)
- .build()
-
- val responseFuture = futureStub.sendRequestFulfillment(request)
- responseFuture.await()
-
- val collectionRequest = AppInteractionServiceProto.CollectionRequest.newBuilder()
- .setSessionIdentifier(sessionId)
- .setViewId(123)
- .setGetLoadingView(GetLoadingView.newBuilder().build()).build()
- futureStub.requestCollection(collectionRequest).await()
- verify(mockedRemoteViewFactory, times(1)).loadingView
-
- server.shutdownNow()
- }
-
- @Test
- fun collectionRequestTriggersGetViewTypeCount(): Unit = runBlocking {
-
- val mockedRemoteViewFactory = mock<RemoteViewsFactory>()
- whenever(mockedRemoteViewFactory.viewTypeCount) doReturn (1)
- val remoteViewsUiResponse = UiResponse.RemoteViewsUiBuilder()
- .setRemoteViews(remoteViews, SizeF(10f, 15f))
- .addRemoteViewsFactory(remoteViewsFactoryId, mockedRemoteViewFactory)
- .build()
-
- appInteractionService.registeredCapabilities = listOf(
- createFakeCapability(remoteViewsUiResponse)
- )
- val server =
- createInProcessServer(
- AppInteractionServiceGrpcImpl(appInteractionService),
- remoteViewsInterceptor
- )
- val channel = createInProcessChannel()
- val stub = AppInteractionServiceGrpc.newStub(channel)
- val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
-
- assertStartupSession(stub)
- // Send fulfillment request
- val request =
- Request.newBuilder()
- .setSessionIdentifier(sessionId)
- .setFulfillmentRequest(testFulfillmentRequestUi)
- .build()
-
- val responseFuture = futureStub.sendRequestFulfillment(request)
- responseFuture.await()
-
- val collectionRequest = AppInteractionServiceProto.CollectionRequest.newBuilder()
- .setSessionIdentifier(sessionId)
- .setViewId(123)
- .setGetViewTypeCount(GetViewTypeCount.newBuilder().build())
- .build()
- val collectionResponse = futureStub.requestCollection(collectionRequest).await()
- verify(mockedRemoteViewFactory).viewTypeCount
- assertThat(collectionResponse.getViewTypeCount.viewTypeCount).isEqualTo(1)
-
- server.shutdownNow()
- }
-
- @Test
- fun collectionRequestTriggersGetItemId(): Unit = runBlocking {
-
- val mockedRemoteViewFactory = mock<RemoteViewsFactory>()
- whenever(mockedRemoteViewFactory.getItemId(any())) doReturn (2)
- val remoteViewsUiResponse = UiResponse.RemoteViewsUiBuilder()
- .setRemoteViews(remoteViews, SizeF(10f, 15f))
- .addRemoteViewsFactory(remoteViewsFactoryId, mockedRemoteViewFactory)
- .build()
-
- appInteractionService.registeredCapabilities = listOf(
- createFakeCapability(remoteViewsUiResponse)
- )
- val server =
- createInProcessServer(
- AppInteractionServiceGrpcImpl(appInteractionService),
- remoteViewsInterceptor
- )
- val channel = createInProcessChannel()
- val stub = AppInteractionServiceGrpc.newStub(channel)
- val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
-
- assertStartupSession(stub)
- // Send fulfillment request
- val request =
- Request.newBuilder()
- .setSessionIdentifier(sessionId)
- .setFulfillmentRequest(testFulfillmentRequestUi)
- .build()
-
- val responseFuture = futureStub.sendRequestFulfillment(request)
- responseFuture.await()
-
- val collectionRequest = AppInteractionServiceProto.CollectionRequest.newBuilder()
- .setSessionIdentifier(sessionId)
- .setViewId(123)
- .setGetItemId(GetItemId.newBuilder().setPosition(2).build())
- .build()
- val collectionResponse = futureStub.requestCollection(collectionRequest).await()
- verify(mockedRemoteViewFactory).getItemId(2)
- assertThat(collectionResponse.getItemId.itemId).isEqualTo(2)
-
- server.shutdownNow()
- }
-
- @Test
- fun collectionRequestTriggersHasStableIds(): Unit = runBlocking {
-
- val mockedRemoteViewFactory = mock<RemoteViewsFactory>()
- whenever(mockedRemoteViewFactory.hasStableIds()) doReturn (true)
- val remoteViewsUiResponse = UiResponse.RemoteViewsUiBuilder()
- .setRemoteViews(remoteViews, SizeF(10f, 15f))
- .addRemoteViewsFactory(remoteViewsFactoryId, mockedRemoteViewFactory)
- .build()
-
- appInteractionService.registeredCapabilities = listOf(
- createFakeCapability(remoteViewsUiResponse)
- )
- val server =
- createInProcessServer(
- AppInteractionServiceGrpcImpl(appInteractionService),
- remoteViewsInterceptor
- )
- val channel = createInProcessChannel()
- val stub = AppInteractionServiceGrpc.newStub(channel)
- val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
-
- assertStartupSession(stub)
- // Send fulfillment request
- val request =
- Request.newBuilder()
- .setSessionIdentifier(sessionId)
- .setFulfillmentRequest(testFulfillmentRequestUi)
- .build()
-
- val responseFuture = futureStub.sendRequestFulfillment(request)
- responseFuture.await()
-
- val collectionRequest = AppInteractionServiceProto.CollectionRequest.newBuilder()
- .setSessionIdentifier(sessionId)
- .setViewId(123)
- .setHasStableIds(HasStableIds.newBuilder().build())
- .build()
- val collectionResponse = futureStub.requestCollection(collectionRequest).await()
- verify(mockedRemoteViewFactory).hasStableIds()
- assertThat(collectionResponse.hasStableIds.hasStableIds).isEqualTo(true)
-
- server.shutdownNow()
- }
-
- @Test
- fun startUpSession_shouldFailWhenNoStaticCapability(): Unit = runBlocking {
- val server =
- createInProcessServer(
- AppInteractionServiceGrpcImpl(appInteractionService),
- remoteViewsInterceptor,
- )
-
- val channel = createInProcessChannel()
- val stub = AppInteractionServiceGrpc.newStub(channel)
- val startSessionResponseObserver = mock<StreamObserver<StartSessionResponse>>()
-
- // Send startup request
- val invalidStartSessionRequest =
- StartSessionRequest.newBuilder()
- .setIntentName(testBiiName)
- .setIdentifier("UNKNOWN_FULFILLMENT_ID")
- .setSessionIdentifier(sessionId)
- .build()
- val startSessionRequestObserver = stub.startUpSession(startSessionResponseObserver)
- startSessionRequestObserver.onNext(invalidStartSessionRequest)
-
- // Assert.
- val exceptionCaptor = argumentCaptor<StatusRuntimeException>()
- verify(startSessionResponseObserver).onError(exceptionCaptor.capture())
- assertThat(Status.fromThrowable(exceptionCaptor.firstValue).code)
- .isEqualTo(Status.Code.FAILED_PRECONDITION)
- assertThat(Status.fromThrowable(exceptionCaptor.firstValue).description)
- .isEqualTo(ERROR_NO_ACTION_CAPABILITY)
- val metadataErrorStatus = assertAndGetErrorStatus(exceptionCaptor.firstValue)
- assertThat(metadataErrorStatus).isEqualTo(ErrorStatus.CAPABILITY_NOT_FOUND)
- verify(capability1, never()).createSession(any(), any())
-
- server.shutdownNow()
- }
-
- @Test
- fun sendRequestFulfillment_shouldGetValidResponse(): Unit = runBlocking {
- val server =
- createInProcessServer(
- AppInteractionServiceGrpcImpl(appInteractionService),
- remoteViewsInterceptor,
- )
- val channel = createInProcessChannel()
- val stub = AppInteractionServiceGrpc.newStub(channel)
- val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
- assertStartupSession(stub)
- verify(capability1, times(1)).createSession(any(), any())
-
- // Send fulfillment request
- val request =
- Request.newBuilder()
- .setSessionIdentifier(sessionId)
- .setFulfillmentRequest(testFulfillmentRequest)
- .build()
- val responseFuture = futureStub.sendRequestFulfillment(request)
-
- val response = responseFuture.await()
- assertThat(response).isNotNull()
- assertThat(response.fulfillmentResponse).isEqualTo(testFulfillmentResponse)
-
- assertThat(response.appActionsContext.dialogStatesList).containsExactly(testAppDialogState)
- server.shutdownNow()
- }
-
- @Test
- fun sendRequestFulfillment_errorFromCallback_errorPassedInGrpcMetadata(): Unit = runBlocking {
- val mockCapabilitySession = createMockSession()
- whenever(mockCapabilitySession.execute(any(), any())).thenAnswer { invocation ->
- (invocation.arguments[1] as CallbackInternal)
- .onError(ErrorStatusInternal.EXTERNAL_EXCEPTION)
- }
- whenever(capability1.createSession(any(), any())).thenReturn(mockCapabilitySession)
-
- val server =
- createInProcessServer(
- AppInteractionServiceGrpcImpl(appInteractionService),
- remoteViewsInterceptor,
- )
- val channel = createInProcessChannel()
- val stub = AppInteractionServiceGrpc.newStub(channel)
- val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
- assertStartupSession(stub)
- verify(capability1, times(1)).createSession(any(), any())
-
- // Send fulfillment request
- val request =
- Request.newBuilder()
- .setSessionIdentifier(sessionId)
- .setFulfillmentRequest(testFulfillmentRequest)
- .build()
- val exception =
- assertFailsWith<StatusRuntimeException> {
- futureStub.sendRequestFulfillment(request).await()
- }
- assertThat(Status.fromThrowable(exception).code).isEqualTo(Status.Code.INTERNAL)
- assertThat(Status.fromThrowable(exception).description)
- .isEqualTo("Error executing action capability")
- val metadataErrorStatus = assertAndGetErrorStatus(exception)
- assertThat(metadataErrorStatus).isEqualTo(ErrorStatus.EXTERNAL_EXCEPTION)
-
- server.shutdownNow()
- }
-
- @Test
- fun sendRequestFulfillment_shouldFailWhenNoFulfillment(): Unit = runBlocking {
- val server =
- createInProcessServer(
- AppInteractionServiceGrpcImpl(appInteractionService),
- remoteViewsInterceptor,
- )
-
- val channel = createInProcessChannel()
- val stub = AppInteractionServiceGrpc.newStub(channel)
- val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
- assertStartupSession(stub)
- verify(capability1, times(1)).createSession(any(), any())
-
- // Ensure a failed future is returned when missing fulfillment
- val requestWithMissingFulfillment =
- Request.newBuilder()
- .setFulfillmentRequest(FulfillmentRequest.getDefaultInstance())
- .build()
- val exception =
- assertFailsWith<StatusRuntimeException> {
- futureStub.sendRequestFulfillment(requestWithMissingFulfillment).await()
- }
- assertThat(Status.fromThrowable(exception).code).isEqualTo(Status.Code.FAILED_PRECONDITION)
- assertThat(Status.fromThrowable(exception).description)
- .isEqualTo(ERROR_NO_FULFILLMENT_REQUEST)
- val metadataErrorStatus = assertAndGetErrorStatus(exception)
- assertThat(metadataErrorStatus).isEqualTo(ErrorStatus.INVALID_REQUEST)
-
- server.shutdownNow()
- }
-
- @Test
- fun sendRequestFulfillment_shouldFailWhenNoStaticCapability(): Unit = runBlocking {
- val server =
- createInProcessServer(
- AppInteractionServiceGrpcImpl(appInteractionService),
- remoteViewsInterceptor,
- )
-
- val channel = createInProcessChannel()
- val stub = AppInteractionServiceGrpc.newStub(channel)
- val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
- assertStartupSession(stub)
- verify(capability1, times(1)).createSession(any(), any())
-
- val requestWithUnknownFulfillmentId =
- Request.newBuilder()
- .setSessionIdentifier(sessionId)
- .setFulfillmentRequest(
- FulfillmentRequest.newBuilder()
- .addFulfillments(
- Fulfillment.newBuilder().setIdentifier("UNKNOWN_FULFILLMENT_ID")
- ),
- )
- .build()
- val exception =
- assertFailsWith<StatusRuntimeException> {
- futureStub.sendRequestFulfillment(requestWithUnknownFulfillmentId).await()
- }
- assertThat(Status.fromThrowable(exception).code).isEqualTo(Status.Code.FAILED_PRECONDITION)
- assertThat(Status.fromThrowable(exception).description)
- .isEqualTo(ERROR_NO_ACTION_CAPABILITY)
- val metadataErrorStatus = assertAndGetErrorStatus(exception)
- assertThat(metadataErrorStatus).isEqualTo(ErrorStatus.CAPABILITY_NOT_FOUND)
-
- server.shutdownNow()
- }
-
- @Test
- fun sendRequestFulfillment_shouldFailWhenNoSession(): Unit = runBlocking {
- val server =
- createInProcessServer(
- AppInteractionServiceGrpcImpl(appInteractionService),
- remoteViewsInterceptor,
- )
-
- val channel = createInProcessChannel()
- val stub = AppInteractionServiceGrpc.newStub(channel)
- val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
- assertStartupSession(stub)
- verify(capability1, times(1)).createSession(any(), any())
-
- val requestWithUnknownFulfillmentId =
- Request.newBuilder()
- .setSessionIdentifier("UNKNOWN_SESSION_ID")
- .setFulfillmentRequest(
- FulfillmentRequest.newBuilder()
- .addFulfillments(Fulfillment.newBuilder().setIdentifier(capabilityId)),
- )
- .build()
- val exception =
- assertFailsWith<StatusRuntimeException> {
- futureStub.sendRequestFulfillment(requestWithUnknownFulfillmentId).await()
- }
- assertThat(Status.fromThrowable(exception).code).isEqualTo(Status.Code.FAILED_PRECONDITION)
- assertThat(Status.fromThrowable(exception).description).isEqualTo(ERROR_NO_SESSION)
- val metadataErrorStatus = assertAndGetErrorStatus(exception)
- assertThat(metadataErrorStatus).isEqualTo(ErrorStatus.SESSION_NOT_FOUND)
-
- server.shutdownNow()
- }
-
- @Test
- fun sendRequestFulfillment_shouldFailWhenSessionEnded(): Unit = runBlocking {
- val server =
- createInProcessServer(
- AppInteractionServiceGrpcImpl(appInteractionService),
- remoteViewsInterceptor,
- )
-
- val channel = createInProcessChannel()
- val stub = AppInteractionServiceGrpc.newStub(channel)
- val futureStub = AppInteractionServiceGrpc.newFutureStub(channel)
-
- // Verify capability session is created
- val mockSession = createMockSession()
- whenever(mockSession.isActive).thenReturn(false)
- whenever(capability1.createSession(any(), any())).thenReturn(mockSession)
- assertStartupSession(stub)
- verify(capability1, times(1)).createSession(any(), any())
-
- // Send request to completed session.
- val requestToEndedSession =
- Request.newBuilder()
- .setSessionIdentifier(sessionId)
- .setFulfillmentRequest(testFulfillmentRequest)
- .build()
- val exception =
- assertFailsWith<StatusRuntimeException> {
- futureStub.sendRequestFulfillment(requestToEndedSession).await()
- }
- assertThat(Status.fromThrowable(exception).code).isEqualTo(Status.Code.FAILED_PRECONDITION)
- assertThat(Status.fromThrowable(exception).description).isEqualTo(ERROR_SESSION_ENDED)
- val metadataErrorStatus = assertAndGetErrorStatus(exception)
- assertThat(metadataErrorStatus).isEqualTo(ErrorStatus.SESSION_NOT_FOUND)
-
- server.shutdownNow()
- }
-
- private suspend fun assertStartupSession(stub: AppInteractionServiceStub) {
- // Set up gRPC response capture
- val startUpSession = CompletableDeferred<Unit>()
- val startSessionResponseObserver = mock<StreamObserver<StartSessionResponse>>()
- whenever(startSessionResponseObserver.onNext(any())) doAnswer
- {
- startUpSession.complete(Unit)
- Unit
- }
-
- // Send startup request
- val startSessionRequestObserver = stub.startUpSession(startSessionResponseObserver)
- startSessionRequestObserver.onNext(defaultStartSessionRequest)
-
- // Assert startup response
- startUpSession.await()
- val responseCaptor = argumentCaptor<StartSessionResponse>()
- verify(startSessionResponseObserver).onNext(responseCaptor.capture())
- val startSessionResponse = responseCaptor.firstValue
- assertThat(startSessionResponse).isEqualTo(StartSessionResponse.getDefaultInstance())
- verify(startSessionResponseObserver, times(1)).onNext(any())
- }
-
- @Throws(IOException::class)
- private fun createInProcessServer(
- service: BindableService,
- vararg interceptors: ServerInterceptor,
- ): Server {
- return grpcCleanup.register(
- InProcessServerBuilder.forName(testServerName)
- .directExecutor()
- .addService(ServerInterceptors.intercept(service, *interceptors))
- .build()
- .start(),
- )
- }
-
- private fun createInProcessChannel(): ManagedChannel {
- return grpcCleanup.register(
- InProcessChannelBuilder.forName(testServerName).directExecutor().build(),
- )
- }
-
- private fun createMockSession(): CapabilitySession {
- val mockSession = mock<CapabilitySession>()
- whenever(mockSession.execute(any(), any())).thenAnswer { invocation ->
- (invocation.arguments[1] as CallbackInternal).onSuccess(testFulfillmentResponse)
- }
- whenever(mockSession.sessionId).thenReturn(sessionId)
- whenever(mockSession.state).thenReturn(testAppDialogState)
- whenever(mockSession.isActive).thenReturn(true)
- whenever(mockSession.uiHandle).thenReturn(Any())
- return mockSession
- }
-
- private fun assertAndGetErrorStatus(ex: StatusRuntimeException): ErrorStatus {
- val appInteractionMetadata =
- ex.trailers?.get(AppInteractionGrpcMetadata.INTERACTION_SERVICE_STATUS_KEY)
- assertThat(appInteractionMetadata).isNotNull()
- return appInteractionMetadata!!.errorStatus
- }
-}
diff --git a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/AppVerificationInfoTest.kt b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/AppVerificationInfoTest.kt
deleted file mode 100644
index 6a97a1d..0000000
--- a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/AppVerificationInfoTest.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.appactions.interaction.service
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-class AppVerificationInfoTest {
-
- @Test
- fun builderPattern() {
- val verificationInfo: AppVerificationInfo =
- AppVerificationInfo.Builder()
- .setPackageName("packageName")
- .addSignature(ByteArray(5))
- .build()
-
- assertThat(verificationInfo.packageName).isEqualTo("packageName")
- assertThat(verificationInfo.signatures).hasSize(1)
- }
-}
diff --git a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/CapabilityCallbackTest.java b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/CapabilityCallbackTest.java
deleted file mode 100644
index cb7155a..0000000
--- a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/CapabilityCallbackTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.appactions.interaction.service;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.assertThrows;
-
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-
-import androidx.appactions.interaction.capabilities.core.impl.ErrorStatusInternal;
-import androidx.appactions.interaction.proto.FulfillmentResponse;
-import androidx.appactions.interaction.proto.FulfillmentResponse.StructuredOutput;
-import androidx.appactions.interaction.proto.ParamValue;
-import androidx.concurrent.futures.CallbackToFutureAdapter;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.concurrent.ExecutionException;
-
-@RunWith(AndroidJUnit4.class)
-public class CapabilityCallbackTest {
-
- private static final long CB_TIMEOUT = 1000L;
- private static final FulfillmentResponse RESPONSE =
- FulfillmentResponse.newBuilder()
- .setExecutionOutput(
- FulfillmentResponse.StructuredOutput.newBuilder()
- .addOutputValues(
- StructuredOutput.OutputValue.newBuilder()
- .addValues(
- ParamValue.newBuilder()
- .setStringValue("abcd"))))
- .build();
-
- @Test
- public void callbackImpl_callbackSuccess_forwardsToCompleter() throws Exception {
- ListenableFuture<FulfillmentResponse> future =
- CallbackToFutureAdapter.getFuture(
- completer -> {
- CapabilityCallback cb = new CapabilityCallback(completer);
- cb.onSuccess(RESPONSE);
- return "test future";
- });
-
- assertThat(future.get(CB_TIMEOUT, MILLISECONDS)).isEqualTo(RESPONSE);
- }
-
- @Test
- public void callbackImpl_callbackError_failsCompleter() throws Exception {
- ListenableFuture<FulfillmentResponse> future =
- CallbackToFutureAdapter.getFuture(
- completer -> {
- CapabilityCallback cb = new CapabilityCallback(completer);
- cb.onError(ErrorStatusInternal.CANCELED);
- return "test future";
- });
-
- assertThat(future.isDone()).isTrue();
- ExecutionException e =
- assertThrows(ExecutionException.class, () -> future.get(CB_TIMEOUT, MILLISECONDS));
- assertThat(e.getCause().getMessage()).isEqualTo("Error executing action capability");
- }
-}
diff --git a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/FakeRemoteViewsFactory.kt b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/FakeRemoteViewsFactory.kt
deleted file mode 100644
index 16b5778..0000000
--- a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/FakeRemoteViewsFactory.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.appactions.interaction.service
-
-import android.os.Build.VERSION
-import android.os.Build.VERSION_CODES
-import android.widget.RemoteViews
-import android.widget.RemoteViewsService.RemoteViewsFactory
-import androidx.appactions.interaction.service.test.R
-
-/** Fake implementation of a RemoteViewsFactory. */
-internal class FakeRemoteViewsFactory : RemoteViewsFactory {
-
- private val collectionCount = 3
- private val viewTypeCount = 1
- private val hasStableIds = true
- private val packageName = "androidx.appactions.interaction.service"
-
- override fun onCreate() {
- // do nothing
- }
-
- override fun onDataSetChanged() {
- // do nothing
- }
-
- override fun onDestroy() {
- // do nothing
- }
-
- override fun getCount(): Int {
- return collectionCount
- }
-
- override fun getViewAt(i: Int): RemoteViews {
- // here we use the position as the view Id, which is the id given to the root of the
- // RemoteViews. This is just so that we can use getViewId in test to verify that RemoteViews
- // received is correct.
- return if (VERSION.SDK_INT >= VERSION_CODES.S) {
- RemoteViews(packageName, R.layout.remote_view, i)
- } else RemoteViews(packageName, R.layout.remote_view)
- }
-
- override fun getLoadingView(): RemoteViews {
- return if (VERSION.SDK_INT >= VERSION_CODES.S) {
- RemoteViews(packageName, R.layout.loading_view)
- } else RemoteViews(packageName, R.layout.loading_view)
- }
-
- override fun getViewTypeCount(): Int {
- return viewTypeCount
- }
-
- override fun getItemId(i: Int): Long {
- return i.toLong()
- }
-
- override fun hasStableIds(): Boolean {
- return hasStableIds
- }
-}
diff --git a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/SessionManagerTest.kt b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/SessionManagerTest.kt
deleted file mode 100644
index ebc1d73..0000000
--- a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/SessionManagerTest.kt
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.appactions.interaction.service
-
-import androidx.appactions.interaction.capabilities.core.impl.ArgumentsWrapper
-import androidx.appactions.interaction.capabilities.core.impl.CallbackInternal
-import androidx.appactions.interaction.capabilities.core.impl.CapabilitySession
-import androidx.appactions.interaction.capabilities.core.impl.TouchEventCallback
-import androidx.appactions.interaction.proto.AppActionsContext
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-class SessionManagerTest {
-
- private val fakeSessionId = "12345"
- private val session1 =
- object : CapabilitySession {
- override val sessionId: String = fakeSessionId
-
- override val uiHandle: Any
- get() = this
-
- override fun execute(argumentsWrapper: ArgumentsWrapper, callback: CallbackInternal) {}
-
- override fun setTouchEventCallback(callback: TouchEventCallback) {}
-
- override val state: AppActionsContext.AppDialogState
- get() = AppActionsContext.AppDialogState.getDefaultInstance()
-
- override val isActive: Boolean = true
-
- override fun destroy() {}
- }
-
- private val session2 =
- object : CapabilitySession {
- override val sessionId: String = fakeSessionId
-
- override val uiHandle: Any
- get() = this
-
- override fun execute(argumentsWrapper: ArgumentsWrapper, callback: CallbackInternal) {}
-
- override fun setTouchEventCallback(callback: TouchEventCallback) {}
-
- override val state: AppActionsContext.AppDialogState
- get() = AppActionsContext.AppDialogState.getDefaultInstance()
-
- override val isActive: Boolean = true
-
- override fun destroy() {}
- }
-
- @Test
- fun sessionManager_putGetRemoveLifecycle() {
- SessionManager.putSession(fakeSessionId, session1)
- assertThat(SessionManager.getSession(fakeSessionId)).isEqualTo(session1)
-
- SessionManager.removeSession(fakeSessionId)
- assertThat(SessionManager.getSession(fakeSessionId)).isNull()
- }
-
- @Test
- fun sessionManager_multipleOverwrites_returnsLatestWrite() {
- SessionManager.putSession(fakeSessionId, session1)
- SessionManager.putSession(fakeSessionId, session2)
- assertThat(SessionManager.getSession(fakeSessionId)).isEqualTo(session2)
- }
-
- @Test
- fun sessionManager_getSession_returnsNullWhenNotFound() {
- val session2 = fakeSessionId + "test"
- SessionManager.putSession(fakeSessionId, session1)
-
- assertThat(SessionManager.getSession(session2)).isNull()
- }
-}
diff --git a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiCacheTest.kt b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiCacheTest.kt
deleted file mode 100644
index f89ff0b..0000000
--- a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiCacheTest.kt
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.appactions.interaction.service
-
-import android.content.Context
-import android.util.SizeF
-import android.widget.RemoteViews
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.service.test.R
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-class UiCacheTest {
- private val capabilitySession = object : BaseExecutionSession<String, String> {}
- private val context: Context = ApplicationProvider.getApplicationContext()
- private val remoteViewsFactoryId = 123
- private val changeViewId = 111
- private val remoteViews = RemoteViews(context.packageName, R.layout.remote_view)
- private val remoteViewsUiResponse =
- UiResponse.RemoteViewsUiBuilder().setRemoteViews(remoteViews, SizeF(10f, 15f)).build()
- private val remoteViewsUiResponseWithFactory =
- UiResponse.RemoteViewsUiBuilder()
- .setRemoteViews(remoteViews, SizeF(10f, 15f))
- .addRemoteViewsFactory(remoteViewsFactoryId, FakeRemoteViewsFactory())
- .build()
-
- private fun assertEmptyCache(uiCache: UiCache) {
- assertThat(uiCache.cachedRemoteViewsInternal).isNull()
- assertThat(uiCache.cachedTileLayoutInternal).isNull()
- }
-
- @Test
- fun unreadUiResponseFlag_lifecycle() {
- val uiCache = UiCache()
- assertThat(uiCache.hasUnreadUiResponse).isFalse()
-
- // Test set unread flag.
- uiCache.updateUiInternal(remoteViewsUiResponse)
- assertThat(uiCache.hasUnreadUiResponse).isTrue()
-
- // Test reset.
- uiCache.resetUnreadUiResponse()
- assertThat(uiCache.hasUnreadUiResponse).isFalse()
- }
-
- @Test
- fun remoteViewsUiResponse_noFactory() {
- val uiCache = UiCache()
- assertEmptyCache(uiCache)
-
- uiCache.updateUiInternal(remoteViewsUiResponse)
-
- assertThat(uiCache.cachedRemoteViewsInternal?.remoteViews).isEqualTo(remoteViews)
- assertThat(uiCache.cachedRemoteViewsInternal?.size).isEqualTo(SizeF(10f, 15f))
- assertThat(
- uiCache.cachedRemoteViewsInternal?.collectionViewFactories?.get(remoteViewsFactoryId)
- ).isNull()
- }
-
- @Test
- fun remoteViewsUiResponse_withFactory() {
- val uiCache = UiCache()
- assertEmptyCache(uiCache)
-
- uiCache.updateUiInternal(remoteViewsUiResponseWithFactory)
-
- assertThat(uiCache.cachedRemoteViewsInternal?.remoteViews).isEqualTo(remoteViews)
- assertThat(uiCache.cachedRemoteViewsInternal?.size).isEqualTo(SizeF(10f, 15f))
- assertThat(
- uiCache.cachedRemoteViewsInternal?.collectionViewFactories?.get(remoteViewsFactoryId)
- ).isNotNull()
- }
-}
diff --git a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiResponseTest.kt b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiResponseTest.kt
deleted file mode 100644
index 66cdafd..0000000
--- a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiResponseTest.kt
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.appactions.interaction.service
-
-import android.content.Context
-import android.util.SizeF
-import android.widget.RemoteViews
-import androidx.appactions.interaction.service.test.R
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.google.common.truth.Truth.assertThat
-import org.junit.Assert.assertThrows
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-class UiResponseTest {
- private val context: Context = ApplicationProvider.getApplicationContext()
- private val remoteViewsFactoryId = 123
-
- @Test
- fun uiResponse_remoteViewsBuilder_withFactory_success() {
- val views = RemoteViews(context.packageName, R.layout.remote_view)
- val uiResponse: UiResponse =
- UiResponse.RemoteViewsUiBuilder()
- .setRemoteViews(views, SizeF(10f, 15f))
- .addRemoteViewsFactory(remoteViewsFactoryId, FakeRemoteViewsFactory())
- .build()
-
- assertThat(uiResponse.tileLayoutInternal).isNull()
- assertThat(uiResponse.remoteViewsInternal?.size?.width).isEqualTo(10)
- assertThat(uiResponse.remoteViewsInternal?.size?.height).isEqualTo(15)
- assertThat(uiResponse.remoteViewsInternal?.remoteViews?.`package`)
- .isEqualTo(context.packageName)
- assertThat(uiResponse.remoteViewsInternal?.collectionViewFactories)
- .containsKey(remoteViewsFactoryId)
- }
-
- @Test
- fun uiResponse_remoteViewsBuilder_withoutFactory_success() {
- val views = RemoteViews(context.packageName, R.layout.remote_view)
- val uiResponse: UiResponse =
- UiResponse.RemoteViewsUiBuilder().setRemoteViews(views, SizeF(10f, 15f)).build()
-
- assertThat(uiResponse.tileLayoutInternal).isNull()
- assertThat(uiResponse.remoteViewsInternal?.size?.width).isEqualTo(10)
- assertThat(uiResponse.remoteViewsInternal?.size?.height).isEqualTo(15)
- assertThat(uiResponse.remoteViewsInternal?.remoteViews?.`package`)
- .isEqualTo(context.packageName)
- }
-
- @Test
- fun uiResponse_remoteViewsBuilder_failure() {
- assertThrows(NullPointerException::class.java) { UiResponse.RemoteViewsUiBuilder().build() }
-
- // No remote views.
- assertThrows(NullPointerException::class.java) {
- UiResponse.RemoteViewsUiBuilder()
- .addRemoteViewsFactory(remoteViewsFactoryId, FakeRemoteViewsFactory())
- .build()
- }
- }
-}
diff --git a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiSessionsTest.kt b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiSessionsTest.kt
deleted file mode 100644
index dbdbcab..0000000
--- a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/UiSessionsTest.kt
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * 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.appactions.interaction.service
-
-import android.content.Context
-import android.util.SizeF
-import android.widget.RemoteViews
-import androidx.appactions.interaction.capabilities.core.ExecutionCallback
-import androidx.appactions.interaction.capabilities.core.ExecutionResult
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils.buildArgs
-import androidx.appactions.interaction.capabilities.testing.internal.ArgumentUtils.buildRequestArgs
-import androidx.appactions.interaction.capabilities.testing.internal.FakeCallbackInternal
-import androidx.appactions.interaction.capabilities.testing.internal.TestingUtils.CB_TIMEOUT
-import androidx.appactions.interaction.proto.FulfillmentRequest.Fulfillment.Type.SYNC
-import androidx.appactions.interaction.proto.ParamValue
-import androidx.appactions.interaction.service.test.R
-import androidx.appactions.interaction.service.testing.internal.FakeCapability
-import androidx.appactions.interaction.service.testing.internal.FakeCapability.Arguments
-import androidx.appactions.interaction.service.testing.internal.FakeCapability.ExecutionSession
-import androidx.appactions.interaction.service.testing.internal.FakeCapability.Output
-import androidx.test.core.app.ApplicationProvider
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.google.common.truth.Truth.assertThat
-import org.junit.After
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-@Suppress("deprecation") // For backwards compatibility.
-class UiSessionsTest {
- private class SessionList {
- private val sessions = mutableListOf<ExecutionSession>()
- private var index = 0
- val sessionFactory: (hostProperties: HostProperties?) -> ExecutionSession =
- { _ -> sessions[index++] }
-
- fun addExecutionSessions(vararg session: ExecutionSession) {
- sessions.addAll(session)
- }
-
- fun reset() {
- sessions.clear()
- index = 0
- }
- }
- private val sessionList = SessionList()
- private val sessionId = "fakeSessionId"
- private val hostProperties =
- HostProperties.Builder().setMaxHostSizeDp(SizeF(300f, 500f)).build()
- private val multiTurnCapability = FakeCapability.CapabilityBuilder()
- .setId("multiTurnCapability")
- .setExecutionSessionFactory(sessionList.sessionFactory).build()
-
- private val context: Context = ApplicationProvider.getApplicationContext()
- private val remoteViewsFactoryId = 123
- private val remoteViews = RemoteViews(context.packageName, R.layout.remote_view)
- private val remoteViewsUiResponse =
- UiResponse.RemoteViewsUiBuilder()
- .setRemoteViews(remoteViews, SizeF(10f, 15f))
- .addRemoteViewsFactory(remoteViewsFactoryId, FakeRemoteViewsFactory())
- .build()
-
- @After
- fun cleanup() {
- sessionList.reset()
- UiSessions.removeUiCache(sessionId)
- }
-
- private fun createFakeSessionWithUiResponses(vararg uiResponses: UiResponse): ExecutionSession {
- return object : ExecutionSession {
- override suspend fun onExecute(
- arguments: Arguments,
- ): ExecutionResult<Output> {
- for (uiResponse in uiResponses) {
- this.updateUi(uiResponse)
- }
- return ExecutionResult.Builder<Output>().build()
- }
- }
- }
-
- @Test
- fun sessionExtensionMethod_createCache_removeCache() {
- assertThat(UiSessions.getUiCacheOrNull(sessionId)).isNull()
-
- sessionList.addExecutionSessions(
- createFakeSessionWithUiResponses(remoteViewsUiResponse),
- )
- val session = multiTurnCapability.createSession(sessionId, hostProperties)
- val callback = FakeCallbackInternal(CB_TIMEOUT)
- session.execute(
- buildRequestArgs(
- SYNC,
- "fieldOne",
- "hello",
- ),
- callback,
- )
- callback.receiveResponse()
- val uiCache = UiSessions.getUiCacheOrNull(sessionId)
- assertThat(uiCache).isNotNull()
- assertThat(uiCache?.hasUnreadUiResponse).isTrue()
- assertThat(uiCache?.cachedRemoteViewsInternal?.size).isEqualTo(SizeF(10f, 15f))
- assertThat(uiCache?.cachedRemoteViewsInternal?.remoteViews).isEqualTo(remoteViews)
-
- // Test removing.
- assertThat(UiSessions.removeUiCache(sessionId)).isTrue()
- assertThat(UiSessions.getUiCacheOrNull(sessionId)).isNull()
- }
-
- @Test
- fun multipleUpdate_sharesCache() {
- assertThat(UiSessions.getUiCacheOrNull(sessionId)).isNull()
- sessionList.addExecutionSessions(object : ExecutionSession {
- override suspend fun onExecute(
- arguments: Arguments,
- ): ExecutionResult<Output> {
- this.updateUi(remoteViewsUiResponse)
-
- return ExecutionResult.Builder<Output>().build()
- }
- })
- val session = multiTurnCapability.createSession(sessionId, hostProperties)
- val callback = FakeCallbackInternal(CB_TIMEOUT)
- session.execute(
- buildRequestArgs(
- SYNC,
- "fieldOne",
- "hello",
- ),
- callback,
- )
- callback.receiveResponse()
- val uiCache = UiSessions.getUiCacheOrNull(sessionId)
- assertThat(uiCache).isNotNull()
- assertThat(uiCache?.hasUnreadUiResponse).isTrue()
- assertThat(uiCache?.cachedRemoteViewsInternal?.size).isEqualTo(SizeF(10f, 15f))
- assertThat(uiCache?.cachedRemoteViewsInternal?.remoteViews).isEqualTo(remoteViews)
- }
-
- @Test
- fun multipleSession_haveTheirOwnCache() {
- val sessionId1 = "fakeSessionId1"
- val sessionId2 = "fakeSessionId2"
- sessionList.addExecutionSessions(
- object : ExecutionSession {
- override suspend fun onExecute(
- arguments: Arguments,
- ): ExecutionResult<Output> {
- this.updateUi(remoteViewsUiResponse)
- return ExecutionResult.Builder<Output>().build()
- }
- },
- object : ExecutionSession {
- override suspend fun onExecute(
- arguments: Arguments,
- ): ExecutionResult<Output> {
- this.updateUi(remoteViewsUiResponse)
- return ExecutionResult.Builder<Output>().build()
- }
- },
- )
- val session1 = multiTurnCapability.createSession(sessionId1, hostProperties)
- val session2 = multiTurnCapability.createSession(sessionId2, hostProperties)
-
- val callback1 = FakeCallbackInternal(CB_TIMEOUT)
- val callback2 = FakeCallbackInternal(CB_TIMEOUT)
-
- session1.execute(
- buildRequestArgs(
- SYNC,
- "fieldOne",
- "hello",
- ),
- callback1,
- )
- session2.execute(
- buildRequestArgs(
- SYNC,
- "fieldOne",
- "hello",
- ),
- callback2,
- )
- callback1.receiveResponse()
- callback2.receiveResponse()
-
- val uiCache1 = UiSessions.getUiCacheOrNull(sessionId1)
- assertThat(uiCache1).isNotNull()
- assertThat(uiCache1?.hasUnreadUiResponse).isTrue()
- assertThat(uiCache1?.cachedRemoteViewsInternal?.remoteViews).isEqualTo(remoteViews)
-
- val uiCache2 = UiSessions.getUiCacheOrNull(sessionId2)
- assertThat(uiCache2).isNotNull()
- assertThat(uiCache2?.hasUnreadUiResponse).isTrue()
- assertThat(uiCache2?.cachedRemoteViewsInternal?.remoteViews).isEqualTo(remoteViews)
-
- // Assert that UiCache2 response still marked unread.
- uiCache1?.resetUnreadUiResponse()
- assertThat(uiCache2?.hasUnreadUiResponse).isTrue()
-
- UiSessions.removeUiCache(sessionId1)
- UiSessions.removeUiCache(sessionId2)
- }
-
- @Test
- fun executionCallback_hasUpdateUiExtension() {
- assertThat(UiSessions.getUiCacheOrNull(sessionId)).isNull()
- val oneShotCapability = FakeCapability.CapabilityBuilder().setId(
- "oneShotCapability",
- ).setExecutionCallback(object : ExecutionCallback<Arguments, Output> {
- override suspend fun onExecute(arguments: Arguments): ExecutionResult<Output> {
- this.updateUi(remoteViewsUiResponse)
- return ExecutionResult.Builder<Output>().build()
- }
- }).build()
- val session = oneShotCapability.createSession(
- sessionId,
- hostProperties,
- )
- val callback = FakeCallbackInternal(CB_TIMEOUT)
- session.execute(
- buildArgs(
- mapOf(
- "fieldOne" to ParamValue.newBuilder().setStringValue("hello").build(),
- ),
- ),
- callback,
- )
- callback.receiveResponse()
- val uiCache = UiSessions.getUiCacheOrNull(sessionId)
- assertThat(uiCache).isNotNull()
- assertThat(uiCache?.hasUnreadUiResponse).isTrue()
- assertThat(uiCache?.cachedRemoteViewsInternal?.size).isEqualTo(SizeF(10f, 15f))
- assertThat(uiCache?.cachedRemoteViewsInternal?.remoteViews).isEqualTo(remoteViews)
- }
-}
diff --git a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/testing/internal/FakeAlarmEntityProvider.kt b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/testing/internal/FakeAlarmEntityProvider.kt
deleted file mode 100644
index 4e15652..0000000
--- a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/testing/internal/FakeAlarmEntityProvider.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.appactions.interaction.service.testing.internal
-
-import androidx.appactions.builtintypes.types.Alarm
-import androidx.appactions.interaction.capabilities.core.entity.EntityLookupCandidate
-import androidx.appactions.interaction.capabilities.core.entity.EntityLookupRequest
-import androidx.appactions.interaction.capabilities.core.entity.EntityLookupResponse
-import androidx.appactions.interaction.capabilities.core.entity.EntityProvider
-import androidx.appactions.interaction.capabilities.serializers.types.ALARM_TYPE_SPEC
-
-class FakeAlarmEntityProvider(
- override val id: String,
- private val alarms: List<Alarm> = listOf()
-) : EntityProvider<Alarm>(
- ALARM_TYPE_SPEC
-) {
- override suspend fun lookup(
- request: EntityLookupRequest<Alarm>
- ): EntityLookupResponse<Alarm> {
- return EntityLookupResponse.Builder<Alarm>().setCandidateList(
- alarms.map { EntityLookupCandidate.Builder<Alarm>().setCandidate(it).build() }
- ).setStatus(
- EntityLookupResponse.SUCCESS
- ).build()
- }
-}
diff --git a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/testing/internal/FakeAppInteractionService.kt b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/testing/internal/FakeAppInteractionService.kt
deleted file mode 100644
index 64f145f..0000000
--- a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/testing/internal/FakeAppInteractionService.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.appactions.interaction.service.testing.internal
-
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.entity.EntityProvider
-import androidx.appactions.interaction.service.AppInteractionService
-import androidx.appactions.interaction.service.AppVerificationInfo
-import io.grpc.binder.SecurityPolicies
-import io.grpc.binder.SecurityPolicy
-
-class FakeAppInteractionService() : AppInteractionService() {
- override var registeredCapabilities: List<Capability> = listOf()
- override var registeredEntityProviders: List<EntityProvider<*>> = listOf()
- override val securityPolicy: SecurityPolicy = SecurityPolicies.internalOnly()
- override val allowedApps: List<AppVerificationInfo> = listOf()
-}
diff --git a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/testing/internal/FakeCapability.kt b/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/testing/internal/FakeCapability.kt
deleted file mode 100644
index 6e9f4b1..0000000
--- a/appactions/interaction/interaction-service/src/test/java/androidx/appactions/interaction/service/testing/internal/FakeCapability.kt
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.appactions.interaction.service.testing.internal
-
-import androidx.appactions.interaction.capabilities.core.BaseExecutionSession
-import androidx.appactions.interaction.capabilities.core.Capability
-import androidx.appactions.interaction.capabilities.core.HostProperties
-import androidx.appactions.interaction.capabilities.core.ValueListener
-import androidx.appactions.interaction.capabilities.core.impl.converters.TypeConverters
-import androidx.appactions.interaction.capabilities.core.impl.spec.ActionSpecBuilder
-import androidx.appactions.interaction.capabilities.core.impl.task.SessionBridge
-import androidx.appactions.interaction.capabilities.core.impl.task.TaskHandler
-import androidx.appactions.interaction.capabilities.core.properties.Property
-import androidx.appactions.interaction.capabilities.core.properties.StringValue
-
-private const val CAPABILITY_NAME = "actions.intent.FAKE_CAPABILITY"
-
-class FakeCapability private constructor() {
- class Arguments internal constructor(
- val fieldOne: String?,
- ) {
- class Builder {
- private var fieldOne: String? = null
- fun setFieldOne(value: String) = apply {
- fieldOne = value
- }
- fun build() = Arguments(fieldOne)
- }
- }
-
- class Output internal constructor()
-
- class Confirmation internal constructor()
-
- interface ExecutionSession : BaseExecutionSession<Arguments, Output> {
- val fieldOneListener: ValueListener<String>?
- get() = null
- }
-
- class CapabilityBuilder : Capability.Builder<
- CapabilityBuilder,
- Arguments,
- Output,
- Confirmation,
- ExecutionSession,
- >(ACTION_SPEC) {
- override val sessionBridge = SessionBridge<ExecutionSession, Arguments, Confirmation> {
- session ->
- val builder = TaskHandler.Builder<Arguments, Confirmation>()
- session.fieldOneListener?.let {
- builder.registerValueTaskParam(
- "fieldOne",
- it,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER,
- )
- }
- builder.build()
- }
-
- public override fun setExecutionSessionFactory(
- sessionFactory: (hostProperties: HostProperties?) -> ExecutionSession
- ) = super.setExecutionSessionFactory(sessionFactory)
-
- fun setFieldOne(fieldOne: Property<StringValue>) = setProperty(
- "fieldOne",
- fieldOne,
- TypeConverters.STRING_VALUE_ENTITY_CONVERTER
- )
- }
-
- companion object {
- private val ACTION_SPEC = ActionSpecBuilder.ofCapabilityNamed(CAPABILITY_NAME)
- .setArguments(Arguments::class.java, Arguments::Builder, Arguments.Builder::build)
- .setOutput(Output::class.java)
- .bindParameter(
- "fieldOne",
- Arguments::fieldOne,
- Arguments.Builder::setFieldOne,
- TypeConverters.STRING_PARAM_VALUE_CONVERTER
- )
- .build()
- }
-}
diff --git a/appactions/interaction/interaction-service/src/test/res/layout/loading_view.xml b/appactions/interaction/interaction-service/src/test/res/layout/loading_view.xml
deleted file mode 100644
index 306ad28..0000000
--- a/appactions/interaction/interaction-service/src/test/res/layout/loading_view.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
- -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
\ No newline at end of file
diff --git a/appactions/interaction/interaction-service/src/test/res/layout/remote_view.xml b/appactions/interaction/interaction-service/src/test/res/layout/remote_view.xml
deleted file mode 100644
index 4591475..0000000
--- a/appactions/interaction/interaction-service/src/test/res/layout/remote_view.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
- -->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <TextView
- android:id="@+id/title"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_gravity="center"
- android:text="000"
- android:textSize="30sp"
- android:textStyle="bold" />
-</FrameLayout>
\ No newline at end of file
diff --git a/appactions/interaction/interaction-service/src/test/resources/robolectric.properties b/appactions/interaction/interaction-service/src/test/resources/robolectric.properties
deleted file mode 100644
index 80e2a6f..0000000
--- a/appactions/interaction/interaction-service/src/test/resources/robolectric.properties
+++ /dev/null
@@ -1 +0,0 @@
-# robolectric properties
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/Macrobenchmark.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/Macrobenchmark.kt
index a16bfd5..7e80279 100644
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/Macrobenchmark.kt
+++ b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/Macrobenchmark.kt
@@ -22,7 +22,6 @@
import android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP
import android.content.pm.PackageManager
import android.os.Build
-import android.util.Log
import androidx.annotation.RestrictTo
import androidx.benchmark.Arguments
import androidx.benchmark.ConfigurationError
@@ -38,15 +37,9 @@
import androidx.benchmark.perfetto.ExperimentalPerfettoCaptureApi
import androidx.benchmark.perfetto.PerfettoCapture.PerfettoSdkConfig
import androidx.benchmark.perfetto.PerfettoCapture.PerfettoSdkConfig.InitialProcessState
-import androidx.benchmark.perfetto.PerfettoCaptureWrapper
import androidx.benchmark.perfetto.PerfettoConfig
-import androidx.benchmark.perfetto.PerfettoTrace
import androidx.benchmark.perfetto.PerfettoTraceProcessor
-import androidx.benchmark.perfetto.UiState
-import androidx.benchmark.perfetto.appendUiState
import androidx.test.platform.app.InstrumentationRegistry
-import androidx.tracing.trace
-import java.io.File
/**
* Get package ApplicationInfo, throw if not found.
@@ -250,170 +243,110 @@
// package name for macrobench process, so it's captured as well
val macrobenchPackageName = InstrumentationRegistry.getInstrumentation().context.packageName
+ val outputs = mutableListOf<PhaseResult>()
- // Perfetto collector is separate from metrics, so we can control file
- // output, and give it different (test-wide) lifecycle
- val perfettoCollector = PerfettoCaptureWrapper()
- val tracePaths = mutableListOf<String>()
- val methodTracingResultFiles = mutableListOf<Profiler.ResultFile>()
- try {
- metrics.forEach {
- it.configure(packageName)
- }
- val measurements = PerfettoTraceProcessor.runServer {
- val runIterations = if (Arguments.dryRunMode) 1 else iterations
- List(runIterations) { iteration ->
- // Wake the device to ensure it stays awake with large iteration count
- inMemoryTrace("wake device") {
- scope.device.wakeUp()
- }
-
- scope.iteration = iteration
-
- inMemoryTrace("setupBlock") {
- setupBlock(scope)
- }
-
- val iterString = iteration.toString().padStart(3, '0')
- scope.fileLabel = "${uniqueName}_iter$iterString"
- val tracePath = perfettoCollector.record(
- fileLabel = scope.fileLabel,
- config = perfettoConfig ?: PerfettoConfig.Benchmark(
- /**
- * Prior to API 24, every package name was joined into a single setprop
- * which can overflow, and disable *ALL* app level tracing.
- *
- * For safety here, we only trace the macrobench package on newer platforms,
- * and use reflection in the macrobench test process to trace important
- * sections
- *
- * @see androidx.benchmark.macro.perfetto.ForceTracing
- */
- appTagPackages = if (Build.VERSION.SDK_INT >= 24) {
- listOf(packageName, macrobenchPackageName)
- } else {
- listOf(packageName)
- },
- useStackSamplingConfig = true
- ),
- perfettoSdkConfig = perfettoSdkConfig,
- inMemoryTracingLabel = "Macrobenchmark"
- ) {
- try {
- trace("start metrics") {
- metrics.forEach {
- it.start()
- }
- }
- if (requestMethodTracing) {
- scope.startMethodTracing()
- }
- trace("measureBlock") {
- measureBlock(scope)
- }
- } finally {
- trace("stop metrics") {
- metrics.forEach {
- it.stop()
- }
- if (requestMethodTracing) {
- methodTracingResultFiles += scope.stopMethodTracing()
- }
- }
- }
- }!!
-
- tracePaths.add(tracePath)
-
- val measurementList = loadTrace(PerfettoTrace(tracePath)) {
- // Extracts the metrics using the perfetto trace processor
- inMemoryTrace("extract metrics") {
- metrics
- // capture list of Measurements
- .map {
- it.getMeasurements(
- Metric.CaptureInfo(
- targetPackageName = packageName,
- testPackageName = macrobenchPackageName,
- startupMode = startupModeMetricHint,
- apiLevel = Build.VERSION.SDK_INT
- ),
- this
- )
- }
- // merge together
- .reduce { sum, element -> sum.merge(element) }
- }
- }
-
- // append UI state to trace, so tools opening trace will highlight relevant part in UI
- val uiState = UiState(
- highlightPackage = packageName
- )
- File(tracePath).apply {
- appendUiState(uiState)
- }
- Log.d(TAG, "Iteration $iteration captured $uiState")
- // report just the metrics
- measurementList
- }.mergeMultiIterResults()
- }
-
- require(measurements.isNotEmpty()) {
- """
- Unable to read any metrics during benchmark (metric list: $metrics).
- Check that you're performing the operations to be measured. For example, if
- using StartupTimingMetric, are you starting an activity for the specified package
- in the measure block?
- """.trimIndent()
- }
-
- InstrumentationResults.instrumentationReport {
- reportSummaryToIde(
- warningMessage = warningMessage,
- testName = uniqueName,
- measurements = measurements,
- iterationTracePaths = tracePaths,
- profilerResults = methodTracingResultFiles
- )
-
- warningMessage = "" // warning only printed once
- measurements.singleMetrics.forEach {
- it.putInBundle(bundle, suppressionState?.prefix ?: "")
- }
- measurements.sampledMetrics.forEach {
- it.putPercentilesInBundle(bundle, suppressionState?.prefix ?: "")
- }
- }
-
- val warmupIterations = when (compilationMode) {
- is CompilationMode.Partial -> compilationMode.warmupIterations
- else -> 0
- }
-
- val mergedProfilerOutputs = (tracePaths.mapIndexed { index, it ->
- Profiler.ResultFile.ofPerfettoTrace(
- label = "Trace Iteration $index",
- absolutePath = it
- )
- } + methodTracingResultFiles).map {
- BenchmarkData.TestResult.ProfilerOutput(it)
- }
- val testResult = BenchmarkData.TestResult(
- className = className,
- name = testName,
- totalRunTimeNs = System.nanoTime() - startTime,
- metrics = measurements.singleMetrics + measurements.sampledMetrics,
- repeatIterations = iterations,
- thermalThrottleSleepSeconds = 0,
- warmupIterations = warmupIterations,
- profilerOutputs = mergedProfilerOutputs
+ PerfettoTraceProcessor.runServer {
+ // Measurement Phase
+ outputs += runPhase(
+ uniqueName = uniqueName,
+ packageName = packageName,
+ macrobenchmarkPackageName = macrobenchPackageName,
+ iterations = if (Arguments.dryRunMode) 1 else iterations,
+ startupMode = startupModeMetricHint,
+ scope = scope,
+ profiler = null, // Don't profile when measuring
+ metrics = metrics,
+ perfettoConfig = perfettoConfig,
+ perfettoSdkConfig = perfettoSdkConfig,
+ setupBlock = setupBlock,
+ measureBlock = measureBlock
)
- ResultWriter.appendTestResult(testResult)
- return testResult
- } finally {
- scope.killProcess()
+ // Profiling Phase
+ if (requestMethodTracing) {
+ outputs += runPhase(
+ uniqueName = uniqueName,
+ packageName = packageName,
+ macrobenchmarkPackageName = macrobenchPackageName,
+ // We should open up an API to control the number of iterations here.
+ // Run profiling for 1 additional iteration.
+ iterations = 1,
+ startupMode = startupModeMetricHint,
+ scope = scope,
+ profiler = MethodTracingProfiler(scope),
+ metrics = emptyList(), // Nothing to measure
+ perfettoConfig = perfettoConfig,
+ perfettoSdkConfig = perfettoSdkConfig,
+ setupBlock = setupBlock,
+ measureBlock = measureBlock
+ )
+ }
}
+
+ val tracePaths = mutableListOf<String>()
+ val profilerResults = mutableListOf<Profiler.ResultFile>()
+ val measurementsList = mutableListOf<List<Metric.Measurement>>()
+
+ outputs.forEach {
+ tracePaths += it.tracePaths
+ profilerResults += it.profilerResults
+ measurementsList += it.measurements
+ }
+
+ // Merge measurements
+ val measurements = measurementsList.mergeMultiIterResults()
+ require(measurements.isNotEmpty()) {
+ """
+ Unable to read any metrics during benchmark (metric list: $metrics).
+ Check that you're performing the operations to be measured. For example, if
+ using StartupTimingMetric, are you starting an activity for the specified package
+ in the measure block?
+ """.trimIndent()
+ }
+
+ InstrumentationResults.instrumentationReport {
+ reportSummaryToIde(
+ warningMessage = warningMessage,
+ testName = uniqueName,
+ measurements = measurements,
+ iterationTracePaths = tracePaths,
+ profilerResults = profilerResults
+ )
+
+ warningMessage = "" // warning only printed once
+ measurements.singleMetrics.forEach {
+ it.putInBundle(bundle, suppressionState?.prefix ?: "")
+ }
+ measurements.sampledMetrics.forEach {
+ it.putPercentilesInBundle(bundle, suppressionState?.prefix ?: "")
+ }
+ }
+
+ val warmupIterations = when (compilationMode) {
+ is CompilationMode.Partial -> compilationMode.warmupIterations
+ else -> 0
+ }
+
+ val mergedProfilerOutputs = (tracePaths.mapIndexed { index, it ->
+ Profiler.ResultFile.ofPerfettoTrace(
+ label = "Trace Iteration $index",
+ absolutePath = it
+ )
+ } + profilerResults).map {
+ BenchmarkData.TestResult.ProfilerOutput(it)
+ }
+
+ val testResult = BenchmarkData.TestResult(
+ className = className,
+ name = testName,
+ totalRunTimeNs = System.nanoTime() - startTime,
+ metrics = measurements.singleMetrics + measurements.sampledMetrics,
+ repeatIterations = iterations,
+ thermalThrottleSleepSeconds = 0,
+ warmupIterations = warmupIterations,
+ profilerOutputs = mergedProfilerOutputs
+ )
+ ResultWriter.appendTestResult(testResult)
+ return testResult
}
/**
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/MacrobenchmarkPhase.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/MacrobenchmarkPhase.kt
new file mode 100644
index 0000000..1bad1d6
--- /dev/null
+++ b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/MacrobenchmarkPhase.kt
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2024 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.benchmark.macro
+
+import android.os.Build
+import android.util.Log
+import androidx.benchmark.Profiler
+import androidx.benchmark.inMemoryTrace
+import androidx.benchmark.perfetto.ExperimentalPerfettoCaptureApi
+import androidx.benchmark.perfetto.PerfettoCapture
+import androidx.benchmark.perfetto.PerfettoCaptureWrapper
+import androidx.benchmark.perfetto.PerfettoConfig
+import androidx.benchmark.perfetto.PerfettoTrace
+import androidx.benchmark.perfetto.PerfettoTraceProcessor
+import androidx.benchmark.perfetto.UiState
+import androidx.benchmark.perfetto.appendUiState
+import androidx.tracing.trace
+import java.io.File
+
+/**
+ * A Profiler being used during a Macro Benchmark Phase.
+ */
+internal interface PhaseProfiler {
+ /**
+ * Starts a Phase profiler.
+ */
+ fun start()
+
+ /**
+ * Stops a Phase profiler.
+ */
+ fun stop(): List<Profiler.ResultFile>
+}
+
+/**
+ * A [PhaseProfiler] that performs method tracing.
+ */
+internal class MethodTracingProfiler(
+ private val scope: MacrobenchmarkScope
+) : PhaseProfiler {
+ override fun start() {
+ scope.startMethodTracing()
+ }
+
+ override fun stop(): List<Profiler.ResultFile> {
+ return scope.stopMethodTracing()
+ }
+}
+
+/**
+ * Results obtained from running a Macrobenchmark Phase.
+ */
+internal data class PhaseResult(
+ /**
+ * A list of Perfetto trace paths obtained. Typically a single trace in this list represents
+ * one iteration of a Macrobenchmark Phase.
+ */
+ val tracePaths: List<String> = emptyList(),
+ /**
+ * A list of profiler results obtained during a Macrobenchmark Phase.
+ */
+ val profilerResults: List<Profiler.ResultFile> = emptyList(),
+ /**
+ * The list of measurements obtained per-iteration from the Macrobenchmark Phase.
+ */
+ val measurements: List<List<Metric.Measurement>> = emptyList()
+)
+
+/**
+ * Run a Macrobenchmark Phase and collect the [PhaseResult].
+ */
+@ExperimentalPerfettoCaptureApi
+internal fun PerfettoTraceProcessor.runPhase(
+ uniqueName: String,
+ packageName: String,
+ macrobenchmarkPackageName: String,
+ iterations: Int,
+ startupMode: StartupMode?,
+ scope: MacrobenchmarkScope,
+ profiler: PhaseProfiler?,
+ metrics: List<Metric>,
+ perfettoConfig: PerfettoConfig?,
+ perfettoSdkConfig: PerfettoCapture.PerfettoSdkConfig?,
+ setupBlock: MacrobenchmarkScope.() -> Unit,
+ measureBlock: MacrobenchmarkScope.() -> Unit
+): PhaseResult {
+ // Perfetto collector is separate from metrics, so we can control file
+ // output, and give it different (test-wide) lifecycle
+ val perfettoCollector = PerfettoCaptureWrapper()
+ val tracePaths = mutableListOf<String>()
+ val measurements = mutableListOf<List<Metric.Measurement>>()
+ val profilerResultFiles = mutableListOf<Profiler.ResultFile>()
+ try {
+ // Configure metrics in the Phase.
+ metrics.forEach {
+ it.configure(packageName)
+ }
+ List(iterations) { iteration ->
+ // Wake the device to ensure it stays awake with large iteration count
+ inMemoryTrace("wake device") {
+ scope.device.wakeUp()
+ }
+
+ scope.iteration = iteration
+
+ inMemoryTrace("setupBlock") {
+ setupBlock(scope)
+ }
+
+ // Setup file labels.
+ val iterString = iteration.toString().padStart(3, '0')
+ scope.fileLabel = "${uniqueName}_iter$iterString"
+
+ val tracePath = perfettoCollector.record(
+ fileLabel = scope.fileLabel,
+ config = perfettoConfig ?: PerfettoConfig.Benchmark(
+ /**
+ * Prior to API 24, every package name was joined into a single setprop
+ * which can overflow, and disable *ALL* app level tracing.
+ *
+ * For safety here, we only trace the macrobench package on newer platforms,
+ * and use reflection in the macrobench test process to trace important
+ * sections
+ *
+ * @see androidx.benchmark.macro.perfetto.ForceTracing
+ */
+ appTagPackages = if (Build.VERSION.SDK_INT >= 24) {
+ listOf(packageName, macrobenchmarkPackageName)
+ } else {
+ listOf(packageName)
+ },
+ useStackSamplingConfig = true
+ ),
+ perfettoSdkConfig = perfettoSdkConfig,
+ inMemoryTracingLabel = "Macrobenchmark"
+ ) {
+ try {
+ trace("start metrics") {
+ metrics.forEach {
+ it.start()
+ }
+ profiler?.start()
+ trace("measureBlock") {
+ measureBlock(scope)
+ }
+ }
+ } finally {
+ trace("stop metrics") {
+ metrics.forEach {
+ it.stop()
+ }
+ // Keep track of Profiler Results.
+ profilerResultFiles += profiler?.stop() ?: emptyList()
+ }
+ }
+ }!!
+
+ // Accumulate Trace Paths
+ tracePaths.add(tracePath)
+
+ // Append UI state to trace, so tools opening trace will highlight relevant
+ // parts in UI.
+ val uiState = UiState(
+ highlightPackage = packageName
+ )
+
+ Log.d(TAG, "Iteration $iteration captured $uiState")
+ File(tracePath).apply {
+ appendUiState(uiState)
+ }
+
+ // Accumulate measurements
+ measurements += loadTrace(PerfettoTrace(tracePath)) {
+ // Extracts the metrics using the perfetto trace processor
+ inMemoryTrace("extract metrics") {
+ metrics
+ // capture list of Measurements
+ .map {
+ it.getMeasurements(
+ Metric.CaptureInfo(
+ targetPackageName = packageName,
+ testPackageName = macrobenchmarkPackageName,
+ startupMode = startupMode,
+ apiLevel = Build.VERSION.SDK_INT
+ ),
+ this
+ )
+ }
+ // merge together
+ .reduceOrNull() { sum, element -> sum.merge(element) } ?: emptyList()
+ }
+ }
+ }
+ } finally {
+ scope.killProcess()
+ }
+ return PhaseResult(
+ tracePaths = tracePaths,
+ profilerResults = profilerResultFiles,
+ measurements = measurements
+ )
+}
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/perfetto/PerfettoTraceProcessor.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/perfetto/PerfettoTraceProcessor.kt
index d2324a7..63135c4 100644
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/perfetto/PerfettoTraceProcessor.kt
+++ b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/perfetto/PerfettoTraceProcessor.kt
@@ -81,7 +81,7 @@
@ExperimentalPerfettoTraceProcessorApi
class PerfettoTraceProcessor {
companion object {
- private val SERVER_START_TIMEOUT_MS = 5.seconds
+ private val SERVER_START_TIMEOUT_MS = 60.seconds
internal const val PORT = 9001
/**
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXRootImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXRootImplPlugin.kt
index 1e8f047..196d5fd 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXRootImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXRootImplPlugin.kt
@@ -37,7 +37,6 @@
import org.gradle.api.Project
import org.gradle.api.artifacts.component.ModuleComponentSelector
import org.gradle.api.file.RelativePath
-import org.gradle.api.plugins.JvmEcosystemPlugin
import org.gradle.api.tasks.Copy
import org.gradle.api.tasks.bundling.Zip
import org.gradle.api.tasks.bundling.ZipEntryCompression
@@ -50,10 +49,6 @@
if (!project.isRoot) {
throw Exception("This plugin should only be applied to root project")
}
- // workaround for https://github.com/gradle/gradle/issues/20145
- // note that a future KMP plugin(1.8+) will apply this and then we can remove the following
- // line.
- project.plugins.apply(JvmEcosystemPlugin::class.java)
project.configureRootProject()
}
diff --git a/appactions/interaction/interaction-capabilities-fitness/api/current.txt b/camera/camera-feature-combination-query-play-services/api/current.txt
similarity index 100%
rename from appactions/interaction/interaction-capabilities-fitness/api/current.txt
rename to camera/camera-feature-combination-query-play-services/api/current.txt
diff --git a/appactions/builtintypes/builtintypes/api/res-current.txt b/camera/camera-feature-combination-query-play-services/api/res-current.txt
similarity index 100%
rename from appactions/builtintypes/builtintypes/api/res-current.txt
rename to camera/camera-feature-combination-query-play-services/api/res-current.txt
diff --git a/appactions/interaction/interaction-capabilities-fitness/api/restricted_current.txt b/camera/camera-feature-combination-query-play-services/api/restricted_current.txt
similarity index 100%
rename from appactions/interaction/interaction-capabilities-fitness/api/restricted_current.txt
rename to camera/camera-feature-combination-query-play-services/api/restricted_current.txt
diff --git a/camera/camera-feature-combination-query-play-services/build.gradle b/camera/camera-feature-combination-query-play-services/build.gradle
new file mode 100644
index 0000000..ba423b1d
--- /dev/null
+++ b/camera/camera-feature-combination-query-play-services/build.gradle
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2024 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
+import androidx.build.RunApiTasks
+
+plugins {
+ id("AndroidXPlugin")
+ id("com.android.library")
+ id("kotlin-android")
+}
+
+dependencies {
+ api(libs.androidx.annotation)
+ implementation(project(":camera:camera-feature-combination-query"))
+
+ testImplementation(libs.testRunner)
+ testImplementation(libs.robolectric)
+ testImplementation(libs.kotlinStdlib)
+ testImplementation(libs.truth)
+ testImplementation(libs.testRules)
+ testImplementation(libs.testCore)
+}
+
+android {
+ defaultConfig {
+ multiDexEnabled = true
+ }
+
+ lintOptions {
+ enable 'CameraXQuirksClassDetector'
+ }
+
+ testOptions.unitTests.includeAndroidResources = true
+
+ namespace "androidx.camera.featurecombinationquery.playservices"
+}
+
+androidx {
+ name = "Jetpack Camera Feature Combination Play Services Library"
+ publish = Publish.NONE
+ inceptionYear = "2024"
+ runApiTasks = new RunApiTasks.Yes()
+ description = "Camera feature combination components for the Jetpack Camera Library, a " +
+ "library providing camera feature combination with Google Play Services dependencies."
+ metalavaK2UastEnabled = true
+}
\ No newline at end of file
diff --git a/camera/camera-feature-combination-query-play-services/src/main/AndroidManifest.xml b/camera/camera-feature-combination-query-play-services/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..a5918e6
--- /dev/null
+++ b/camera/camera-feature-combination-query-play-services/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+
+</manifest>
\ No newline at end of file
diff --git a/appactions/interaction/interaction-capabilities-fitness/api/current.txt b/camera/camera-feature-combination-query/api/current.txt
similarity index 100%
copy from appactions/interaction/interaction-capabilities-fitness/api/current.txt
copy to camera/camera-feature-combination-query/api/current.txt
diff --git a/appactions/builtintypes/builtintypes/api/res-current.txt b/camera/camera-feature-combination-query/api/res-current.txt
similarity index 100%
copy from appactions/builtintypes/builtintypes/api/res-current.txt
copy to camera/camera-feature-combination-query/api/res-current.txt
diff --git a/appactions/interaction/interaction-capabilities-fitness/api/restricted_current.txt b/camera/camera-feature-combination-query/api/restricted_current.txt
similarity index 100%
copy from appactions/interaction/interaction-capabilities-fitness/api/restricted_current.txt
copy to camera/camera-feature-combination-query/api/restricted_current.txt
diff --git a/camera/camera-feature-combination-query/build.gradle b/camera/camera-feature-combination-query/build.gradle
new file mode 100644
index 0000000..fb716df
--- /dev/null
+++ b/camera/camera-feature-combination-query/build.gradle
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2024 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
+import androidx.build.RunApiTasks
+
+plugins {
+ id("AndroidXPlugin")
+ id("com.android.library")
+ id("kotlin-android")
+}
+
+dependencies {
+ api(libs.androidx.annotation)
+
+ testImplementation(libs.testRunner)
+ testImplementation(libs.robolectric)
+ testImplementation(libs.kotlinStdlib)
+ testImplementation(libs.truth)
+ testImplementation(libs.testRules)
+ testImplementation(libs.testCore)
+}
+
+android {
+ defaultConfig {
+ multiDexEnabled = true
+ }
+
+ lintOptions {
+ enable 'CameraXQuirksClassDetector'
+ }
+
+ testOptions.unitTests.includeAndroidResources = true
+ namespace "androidx.camera.featurecombinationquery"
+}
+
+androidx {
+ name = "Jetpack Camera Feature Combination Library"
+ publish = Publish.NONE
+ inceptionYear = "2024"
+ runApiTasks = new RunApiTasks.Yes()
+ description = "Camera feature combination components for the Jetpack Camera Library, a library " +
+ "providing a seamless experience for querying camera features across all of Android."
+ metalavaK2UastEnabled = true
+}
\ No newline at end of file
diff --git a/camera/camera-feature-combination-query/src/main/AndroidManifest.xml b/camera/camera-feature-combination-query/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..a5918e6
--- /dev/null
+++ b/camera/camera-feature-combination-query/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+
+</manifest>
\ No newline at end of file
diff --git a/camera/camera-viewfinder-compose/api/current.txt b/camera/camera-viewfinder-compose/api/current.txt
index 518164d..527874e 100644
--- a/camera/camera-viewfinder-compose/api/current.txt
+++ b/camera/camera-viewfinder-compose/api/current.txt
@@ -1,7 +1,7 @@
// Signature format: 4.0
package androidx.camera.viewfinder.compose {
- @androidx.compose.runtime.Stable public interface CoordinateTransformer {
+ public interface CoordinateTransformer {
method public float[] getTransformMatrix();
method public long transform(long);
property public float[] transformMatrix;
diff --git a/camera/camera-viewfinder-compose/api/restricted_current.txt b/camera/camera-viewfinder-compose/api/restricted_current.txt
index 518164d..527874e 100644
--- a/camera/camera-viewfinder-compose/api/restricted_current.txt
+++ b/camera/camera-viewfinder-compose/api/restricted_current.txt
@@ -1,7 +1,7 @@
// Signature format: 4.0
package androidx.camera.viewfinder.compose {
- @androidx.compose.runtime.Stable public interface CoordinateTransformer {
+ public interface CoordinateTransformer {
method public float[] getTransformMatrix();
method public long transform(long);
property public float[] transformMatrix;
diff --git a/camera/camera-viewfinder-compose/src/main/java/androidx/camera/viewfinder/compose/CoordinateTransformer.kt b/camera/camera-viewfinder-compose/src/main/java/androidx/camera/viewfinder/compose/CoordinateTransformer.kt
index 93d589d..204aa56 100644
--- a/camera/camera-viewfinder-compose/src/main/java/androidx/camera/viewfinder/compose/CoordinateTransformer.kt
+++ b/camera/camera-viewfinder-compose/src/main/java/androidx/camera/viewfinder/compose/CoordinateTransformer.kt
@@ -16,7 +16,6 @@
package androidx.camera.viewfinder.compose
-import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
@@ -31,7 +30,6 @@
* will set this transform matrix.
*
*/
-@Stable
interface CoordinateTransformer {
/**
* Matrix that's used for coordinate transformations.
diff --git a/car/app/app/src/main/java/androidx/car/app/ScreenManager.java b/car/app/app/src/main/java/androidx/car/app/ScreenManager.java
index 26372f5..fc21474 100644
--- a/car/app/app/src/main/java/androidx/car/app/ScreenManager.java
+++ b/car/app/app/src/main/java/androidx/car/app/ScreenManager.java
@@ -43,6 +43,7 @@
import java.util.Collections;
import java.util.Deque;
import java.util.List;
+import java.util.Locale;
/**
* Manages the stack of {@link Screen}s and their respective {@link Lifecycle}s.
@@ -88,6 +89,13 @@
}
return;
}
+ if (screen.getLifecycle().getCurrentState().equals(State.DESTROYED)) {
+ throw new IllegalStateException(String.format(Locale.US,
+ "Failed to push screen (%s), because it has already been destroyed. Please "
+ + "note that screens are single-use, so a fresh instance is required "
+ + "every time you call screenManager.push().",
+ screen));
+ }
pushInternal(requireNonNull(screen));
}
diff --git a/car/app/app/src/test/java/androidx/car/app/ScreenManagerTest.java b/car/app/app/src/test/java/androidx/car/app/ScreenManagerTest.java
index 0439ab3..e5d70da 100644
--- a/car/app/app/src/test/java/androidx/car/app/ScreenManagerTest.java
+++ b/car/app/app/src/test/java/androidx/car/app/ScreenManagerTest.java
@@ -341,6 +341,16 @@
}
@Test
+ public void push_sameScreenMultipleTimes_fails() {
+ mScreenManager.push(mScreen1);
+ mScreenManager.push(mScreen2);
+ mScreenManager.pop(); // Screen 2 moves to DESTROYED state
+
+ // Pushing DESTROYED screen should fail.
+ assertThrows(IllegalStateException.class, () -> mScreenManager.push(mScreen2));
+ }
+
+ @Test
public void pushScreen_afterDestroyed_noop() {
mLifecycleOwner.mRegistry.handleLifecycleEvent(Event.ON_DESTROY);
mScreenManager.push(mScreen1);
diff --git a/compose/animation/animation/src/commonMain/kotlin/androidx/compose/animation/SharedElement.kt b/compose/animation/animation/src/commonMain/kotlin/androidx/compose/animation/SharedElement.kt
index 2a9aafd..edf6a19 100644
--- a/compose/animation/animation/src/commonMain/kotlin/androidx/compose/animation/SharedElement.kt
+++ b/compose/animation/animation/src/commonMain/kotlin/androidx/compose/animation/SharedElement.kt
@@ -24,7 +24,6 @@
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
-import androidx.compose.runtime.snapshots.SnapshotStateObserver
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.Size
@@ -43,9 +42,6 @@
internal class SharedElement(val key: Any, val scope: SharedTransitionScope) {
fun isAnimating(): Boolean = states.fastAny { it.boundsAnimation.isRunning } && foundMatch
- // observation is stopped when no states are in the list, started when new state is added
- private val observer = SnapshotStateObserver { it() }
-
private var _targetBounds: Rect? by mutableStateOf(null)
/**
@@ -76,7 +72,7 @@
foundMatch = false
}
if (states.isNotEmpty()) {
- observer.observeReads(this, updateMatch, observingVisibilityChange)
+ SharedTransitionObserver.observeReads(this, updateMatch, observingVisibilityChange)
}
}
@@ -155,21 +151,17 @@
}
fun addState(sharedElementState: SharedElementInternalState) {
- val wasEmpty = states.isEmpty()
states.add(sharedElementState)
- if (wasEmpty) {
- observer.start()
- }
- observer.observeReads(this, updateMatch, observingVisibilityChange)
+ SharedTransitionObserver.observeReads(this, updateMatch, observingVisibilityChange)
}
fun removeState(sharedElementState: SharedElementInternalState) {
states.remove(sharedElementState)
if (states.isEmpty()) {
updateMatch()
- observer.stop()
+ SharedTransitionObserver.clear(this)
} else {
- observer.observeReads(this, updateMatch, observingVisibilityChange)
+ SharedTransitionObserver.observeReads(this, updateMatch, observingVisibilityChange)
}
}
}
diff --git a/compose/animation/animation/src/commonMain/kotlin/androidx/compose/animation/SharedTransitionScope.kt b/compose/animation/animation/src/commonMain/kotlin/androidx/compose/animation/SharedTransitionScope.kt
index 74cef36..82d39f6 100644
--- a/compose/animation/animation/src/commonMain/kotlin/androidx/compose/animation/SharedTransitionScope.kt
+++ b/compose/animation/animation/src/commonMain/kotlin/androidx/compose/animation/SharedTransitionScope.kt
@@ -34,6 +34,7 @@
import androidx.compose.animation.core.spring
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.key
@@ -143,6 +144,11 @@
sharedScope.drawInOverlay(this)
}
)
+ DisposableEffect(Unit) {
+ onDispose {
+ SharedTransitionObserver.clear(sharedScope)
+ }
+ }
}
}
@@ -835,11 +841,13 @@
sharedElements.forEach { _, element ->
element.updateMatch()
}
- observer.observeReads(this, updateTransitionActiveness, observeAnimatingBlock)
+ SharedTransitionObserver.observeReads(
+ this@SharedTransitionScope,
+ updateTransitionActiveness,
+ observeAnimatingBlock
+ )
}
- private val observer = SnapshotStateObserver { it() }.also { it.start() }
-
/**
* sharedBoundsImpl is the implementation for creating animations for shared element
* or shared bounds transition. [parentTransition] defines the parent Transition that
@@ -975,7 +983,11 @@
with(sharedElementState.sharedElement) {
removeState(sharedElementState)
updateTransitionActiveness.invoke(this@SharedTransitionScope)
- observer.observeReads(scope, updateTransitionActiveness, observeAnimatingBlock)
+ SharedTransitionObserver.observeReads(
+ scope,
+ updateTransitionActiveness,
+ observeAnimatingBlock
+ )
renderers.remove(sharedElementState)
if (states.isEmpty()) {
scope.coroutineScope.launch {
@@ -991,7 +1003,11 @@
with(sharedElementState.sharedElement) {
addState(sharedElementState)
updateTransitionActiveness.invoke(this@SharedTransitionScope)
- observer.observeReads(scope, updateTransitionActiveness, observeAnimatingBlock)
+ SharedTransitionObserver.observeReads(
+ scope,
+ updateTransitionActiveness,
+ observeAnimatingBlock
+ )
val id = renderers.indexOfFirst {
(it as? SharedElementInternalState)?.sharedElement ==
sharedElementState.sharedElement
@@ -1158,3 +1174,7 @@
private val DefaultBoundsTransform = BoundsTransform { _, _ -> DefaultSpring }
internal const val VisualDebugging = false
+
+internal val SharedTransitionObserver by lazy(LazyThreadSafetyMode.NONE) {
+ SnapshotStateObserver { it() }.also { it.start() }
+}
diff --git a/compose/foundation/foundation/api/current.txt b/compose/foundation/foundation/api/current.txt
index 9a75490..8373973 100644
--- a/compose/foundation/foundation/api/current.txt
+++ b/compose/foundation/foundation/api/current.txt
@@ -478,7 +478,8 @@
public final class Draggable2DKt {
method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi public static androidx.compose.foundation.gestures.Draggable2DState Draggable2DState(kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Offset,kotlin.Unit> onDelta);
- method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier draggable2D(androidx.compose.ui.Modifier, androidx.compose.foundation.gestures.Draggable2DState state, optional boolean enabled, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional boolean startDragImmediately, optional kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.ui.geometry.Offset,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> onDragStarted, optional kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.ui.unit.Velocity,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> onDragStopped, optional boolean reverseDirection);
+ method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier draggable2D(androidx.compose.ui.Modifier, androidx.compose.foundation.gestures.Draggable2DState state, optional boolean enabled, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional boolean startDragImmediately, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Offset,kotlin.Unit> onDragStarted, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Velocity,kotlin.Unit> onDragStopped, optional boolean reverseDirection);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier draggable2D(androidx.compose.ui.Modifier, androidx.compose.foundation.gestures.Draggable2DState state, optional boolean enabled, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional boolean startDragImmediately, optional kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.ui.geometry.Offset,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> onDragStarted, optional kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.ui.unit.Velocity,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> onDragStopped, optional boolean reverseDirection);
method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static androidx.compose.foundation.gestures.Draggable2DState rememberDraggable2DState(kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Offset,kotlin.Unit> onDelta);
}
diff --git a/compose/foundation/foundation/api/restricted_current.txt b/compose/foundation/foundation/api/restricted_current.txt
index e6fa4da3..393f809 100644
--- a/compose/foundation/foundation/api/restricted_current.txt
+++ b/compose/foundation/foundation/api/restricted_current.txt
@@ -480,7 +480,8 @@
public final class Draggable2DKt {
method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi public static androidx.compose.foundation.gestures.Draggable2DState Draggable2DState(kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Offset,kotlin.Unit> onDelta);
- method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier draggable2D(androidx.compose.ui.Modifier, androidx.compose.foundation.gestures.Draggable2DState state, optional boolean enabled, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional boolean startDragImmediately, optional kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.ui.geometry.Offset,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> onDragStarted, optional kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.ui.unit.Velocity,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> onDragStopped, optional boolean reverseDirection);
+ method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier draggable2D(androidx.compose.ui.Modifier, androidx.compose.foundation.gestures.Draggable2DState state, optional boolean enabled, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional boolean startDragImmediately, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Offset,kotlin.Unit> onDragStarted, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.unit.Velocity,kotlin.Unit> onDragStopped, optional boolean reverseDirection);
+ method @Deprecated @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier draggable2D(androidx.compose.ui.Modifier, androidx.compose.foundation.gestures.Draggable2DState state, optional boolean enabled, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource, optional boolean startDragImmediately, optional kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.ui.geometry.Offset,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> onDragStarted, optional kotlin.jvm.functions.Function3<? super kotlinx.coroutines.CoroutineScope,? super androidx.compose.ui.unit.Velocity,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> onDragStopped, optional boolean reverseDirection);
method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static androidx.compose.foundation.gestures.Draggable2DState rememberDraggable2DState(kotlin.jvm.functions.Function1<? super androidx.compose.ui.geometry.Offset,kotlin.Unit> onDelta);
}
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/ComposeTextAccessibility.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/ComposeTextAccessibility.kt
index b049faf..b9274b1 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/ComposeTextAccessibility.kt
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/ComposeTextAccessibility.kt
@@ -18,9 +18,8 @@
import androidx.compose.foundation.layout.Column
import androidx.compose.material.Text
-import androidx.compose.material.TextDefaults
import androidx.compose.runtime.Composable
-import androidx.compose.ui.text.ExperimentalTextApi
+import androidx.compose.ui.text.LinkAnnotation
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.VerbatimTtsAnnotation
@@ -29,7 +28,6 @@
import androidx.compose.ui.text.withLink
import androidx.compose.ui.tooling.preview.Preview
-@OptIn(ExperimentalTextApi::class)
@Preview
@Composable
fun TextAccessibilityDemo() {
@@ -75,7 +73,7 @@
Text(
text = buildAnnotatedString {
append("This word is a link: ")
- withLink(TextDefaults.Url("https://google.com")) {
+ withLink(LinkAnnotation.Url("https://google.com")) {
append("Google")
}
append("\nThis word is not a link: google.com")
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/Hyperlinks.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/Hyperlinks.kt
index b9721f3..3b74519 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/Hyperlinks.kt
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/text/Hyperlinks.kt
@@ -29,12 +29,12 @@
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.text.BasicText
import androidx.compose.foundation.text.InlineTextContent
import androidx.compose.foundation.text.appendInlineContent
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Text
-import androidx.compose.material.TextDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.Saver
@@ -64,7 +64,7 @@
import androidx.compose.ui.unit.sp
import androidx.compose.ui.util.fastForEach
-private const val WebLink = "https://google.com"
+private const val WebLink = "https://developer.android.com"
private const val LongWebLink =
"https://developer.android.com/design/ui/mobile/guides/foundations/system-bars"
private const val PhoneUri = "tel:+123456789"
@@ -80,15 +80,12 @@
.padding(10.dp),
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
-
- val dac = "https://developer.android.com/develop/ui/compose/"
-
Sample("State-based styling through builder") {
- Text(buildAnnotatedString {
+ BasicText(buildAnnotatedString {
append("Text and a ")
withLink(
LinkAnnotation.Url(
- url = "$dac/accessibility",
+ url = "https://developer.android.com",
style = SpanStyle(color = Color.Magenta),
focusedStyle = SpanStyle(background = Color.Yellow.copy(alpha = 0.3f)),
hoveredStyle = SpanStyle(textDecoration = TextDecoration.Underline),
@@ -103,16 +100,15 @@
}
Sample("State-based styling from Html-tagged string") {
val htmlString = """
- This is a <span style=\"color:red\"><a href=$dac/animation>link</a></span>
- here. Another <a href=$dac/semantics>link</a> follows.
+ This is a <span style="color:red"><a href="https://developer.android.com">link</a></span> here.
+ Another <a href="https://developer.android.com">link</a> follows.
""".trimIndent()
val annotatedString = AnnotatedString.fromHtml(
htmlString,
- linkStyle = SpanStyle(color = Color.Magenta),
linkFocusedStyle = SpanStyle(background = Color.Yellow.copy(alpha = 0.3f)),
linkHoveredStyle = SpanStyle(textDecoration = TextDecoration.Underline)
)
- Text(annotatedString)
+ BasicText(annotatedString)
}
Sample("Single link styling with SpanStyle") {
val stringWithLink = buildAnnotatedString {
@@ -124,25 +120,26 @@
withStyle(
SpanStyle(
fontWeight = FontWeight.Bold,
- textDecoration = TextDecoration.None
+ textDecoration = TextDecoration.Underline
)
) {
withLink(LinkAnnotation.Url(PhoneUri)) { append("+1 (234) 567890") }
}
append(" with a custom style.")
}
- Text(text = stringWithLink)
+ BasicText(text = stringWithLink)
}
Sample("Material colors for links from builder") {
Text(buildAnnotatedString {
append("Text and ")
- withLink(TextDefaults.Url(url = WebLink)) { append("developer.android.com") }
+ withLink(LinkAnnotation.Url(WebLink)) { append("developer.android.com") }
append(" link.")
})
}
Sample("Material colors for links from html") {
- val htmlString = "Text and <a href=https://google.com>developer.android.com</a> link"
- Text(TextDefaults.fromHtml(htmlString = htmlString))
+ val htmlString =
+ "Text and <a href=\"https://developer.android.com\">developer.android.com</a> link"
+ Text(AnnotatedString.fromHtml(htmlString))
}
Sample("Long links") {
val text = buildAnnotatedString {
@@ -209,7 +206,8 @@
}
}
append(" is invalid and won't be opened.")
- }
+ },
+ color = Color.Red
)
}
Sample("RTL text") {
@@ -243,7 +241,7 @@
Sample("Custom Saver with link listener restoration") {
val listener = LinkInteractionListener { /* do something */ }
val text = buildAnnotatedString {
- withLink(TextDefaults.Clickable("tag", linkInteractionListener = listener)) {
+ withLink(LinkAnnotation.Clickable("tag", linkInteractionListener = listener)) {
append("Click me")
}
}
@@ -257,11 +255,11 @@
val listener = LinkInteractionListener { localUriHandler.openUri(WebLink) }
val text = buildAnnotatedString {
append("Click ")
- withLink(TextDefaults.Clickable("tag", linkInteractionListener = listener)) {
+ withLink(LinkAnnotation.Clickable("tag", linkInteractionListener = listener)) {
append("the first link")
}
append(" or ")
- withLink(TextDefaults.Url(WebLink, linkInteractionListener = listener)) {
+ withLink(LinkAnnotation.Url(WebLink, linkInteractionListener = listener)) {
append("the second link")
}
}
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/BackgroundTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/BackgroundTest.kt
index 56dc5a4..4e1ab73 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/BackgroundTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/BackgroundTest.kt
@@ -33,9 +33,12 @@
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Outline
+import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.graphics.addOutline
import androidx.compose.ui.platform.InspectableValue
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLayoutDirection
@@ -231,6 +234,136 @@
}
@Test
+ fun background_changeOutline_differentPaths_observableShape() {
+ var roundCorners by mutableStateOf(false)
+
+ val shape = object : Shape {
+ override fun createOutline(
+ size: Size,
+ layoutDirection: LayoutDirection,
+ density: Density
+ ): Outline {
+ return if (roundCorners) {
+ RoundedCornerShape(50f).createOutline(size, layoutDirection, density)
+ } else {
+ RectangleShape.createOutline(size, layoutDirection, density)
+ }
+ }
+ }
+
+ rule.setContent {
+ SemanticParent {
+ Box(
+ Modifier
+ .size(40f.toDp())
+ .background(Color.Magenta)
+ .background(color = Color.White, shape = shape)
+ )
+ }
+ }
+
+ val bitmap = rule.onNodeWithTag(contentTag).captureToImage()
+ bitmap.assertShape(
+ density = rule.density,
+ backgroundColor = Color.Magenta,
+ shape = RectangleShape,
+ shapeColor = Color.White,
+ shapeOverlapPixelCount = 2.0f
+ )
+
+ roundCorners = true
+ rule.waitForIdle()
+
+ val bitmap2 = rule.onNodeWithTag(contentTag).captureToImage()
+ bitmap2.assertShape(
+ density = rule.density,
+ backgroundColor = Color.Magenta,
+ shape = RoundedCornerShape(50f),
+ shapeColor = Color.White,
+ shapeOverlapPixelCount = 2.0f
+ )
+
+ roundCorners = false
+ rule.waitForIdle()
+
+ val bitmap3 = rule.onNodeWithTag(contentTag).captureToImage()
+ bitmap3.assertShape(
+ density = rule.density,
+ backgroundColor = Color.Magenta,
+ shape = RectangleShape,
+ shapeColor = Color.White,
+ shapeOverlapPixelCount = 2.0f
+ )
+ }
+
+ @Test
+ fun background_changeOutline_samePath_observableShape() {
+ var roundCorners by mutableStateOf(false)
+
+ val path = Path()
+ val shape = object : Shape {
+ override fun createOutline(
+ size: Size,
+ layoutDirection: LayoutDirection,
+ density: Density
+ ): Outline {
+ val outlineToAdd = if (roundCorners) {
+ RoundedCornerShape(50f).createOutline(size, layoutDirection, density)
+ } else {
+ RectangleShape.createOutline(size, layoutDirection, density)
+ }
+ path.reset()
+ path.addOutline(outlineToAdd)
+ return Outline.Generic(path)
+ }
+ }
+
+ rule.setContent {
+ SemanticParent {
+ Box(
+ Modifier
+ .size(40f.toDp())
+ .background(Color.Magenta)
+ .background(color = Color.White, shape = shape)
+ )
+ }
+ }
+
+ val bitmap = rule.onNodeWithTag(contentTag).captureToImage()
+ bitmap.assertShape(
+ density = rule.density,
+ backgroundColor = Color.Magenta,
+ shape = RectangleShape,
+ shapeColor = Color.White,
+ shapeOverlapPixelCount = 2.0f
+ )
+
+ roundCorners = true
+ rule.waitForIdle()
+
+ val bitmap2 = rule.onNodeWithTag(contentTag).captureToImage()
+ bitmap2.assertShape(
+ density = rule.density,
+ backgroundColor = Color.Magenta,
+ shape = RoundedCornerShape(50f),
+ shapeColor = Color.White,
+ shapeOverlapPixelCount = 2.0f
+ )
+
+ roundCorners = false
+ rule.waitForIdle()
+
+ val bitmap3 = rule.onNodeWithTag(contentTag).captureToImage()
+ bitmap3.assertShape(
+ density = rule.density,
+ backgroundColor = Color.Magenta,
+ shape = RectangleShape,
+ shapeColor = Color.White,
+ shapeOverlapPixelCount = 2.0f
+ )
+ }
+
+ @Test
fun background_rtl_initially() {
rule.setContent {
SemanticParent {
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/BorderTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/BorderTest.kt
index 084cd3e..e0950ce 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/BorderTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/BorderTest.kt
@@ -26,10 +26,13 @@
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
import androidx.compose.testutils.assertModifierIsPure
import androidx.compose.testutils.assertShape
import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.RoundRect
@@ -406,7 +409,7 @@
val testTag = "testTag"
val borderStrokeDp = 5.dp
var borderStrokePx = 0f
- var toggle = mutableStateOf(false)
+ val toggle = mutableStateOf(false)
rule.setContent {
val testShape = GenericShape { size, _ ->
addRect(Rect(0f, 0f, size.width, size.height))
@@ -597,6 +600,173 @@
}
@Test
+ fun border_changeShape() {
+ var roundedCorners by mutableStateOf(false)
+
+ rule.setContent {
+ SemanticParent {
+ Box(
+ Modifier
+ .size(40.0f.toDp(), 40.0f.toDp())
+ .background(color = Color.Blue)
+ .border(
+ BorderStroke(1f.toDp(), Color.Red),
+ if (roundedCorners) RoundedCornerShape(5f) else RectangleShape
+ )
+ ) {}
+ }
+ }
+
+ rule.onNodeWithTag(testTag).captureToImage().run {
+ val map = toPixelMap()
+ // We should not be rounded, so left edge should be fully red
+ assertEquals(Color.Red, map[0, 0])
+ assertEquals(Color.Red, map[0, (height - 1) / 2])
+ assertEquals(Color.Red, map[0, height - 1])
+ }
+
+ rule.runOnIdle {
+ roundedCorners = true
+ }
+
+ rule.onNodeWithTag(testTag).captureToImage().run {
+ val map = toPixelMap()
+ // We should now be rounded, so the top and bottom of the left edge will be blue, but
+ // the center will still be red
+ assertEquals(Color.Blue, map[0, 0])
+ assertEquals(Color.Red, map[0, (height - 1) / 2])
+ assertEquals(Color.Blue, map[0, height - 1])
+ }
+ }
+
+ @Test
+ fun border_changeOutline_outlineRounded_observableShape() {
+ var roundedCorners by mutableStateOf(false)
+ val roundedCornersShape = object : Shape {
+ override fun createOutline(
+ size: Size,
+ layoutDirection: LayoutDirection,
+ density: Density
+ ): Outline {
+ val roundRect = if (roundedCorners) {
+ RoundRect(
+ Rect(Offset.Zero, size),
+ cornerRadius = CornerRadius(5f)
+ )
+ } else {
+ RoundRect(
+ Rect(Offset.Zero, size),
+ cornerRadius = CornerRadius.Zero
+ )
+ }
+ return Outline.Rounded(roundRect)
+ }
+ }
+
+ rule.setContent {
+ SemanticParent {
+ Box(
+ Modifier
+ .size(40.0f.toDp(), 40.0f.toDp())
+ .background(color = Color.Blue)
+ .border(
+ BorderStroke(1f.toDp(), Color.Red),
+ roundedCornersShape
+ )
+ ) {}
+ }
+ }
+
+ rule.onNodeWithTag(testTag).captureToImage().run {
+ val map = toPixelMap()
+ // We should not be rounded, so left edge should be fully red
+ assertEquals(Color.Red, map[0, 0])
+ assertEquals(Color.Red, map[0, (height - 1) / 2])
+ assertEquals(Color.Red, map[0, height - 1])
+ }
+
+ rule.runOnIdle {
+ roundedCorners = true
+ }
+
+ rule.onNodeWithTag(testTag).captureToImage().run {
+ val map = toPixelMap()
+ // We should now be rounded, so the top and bottom of the left edge will be blue, but
+ // the center will still be red
+ assertEquals(Color.Blue, map[0, 0])
+ assertEquals(Color.Red, map[0, (height - 1) / 2])
+ assertEquals(Color.Blue, map[0, height - 1])
+ }
+ }
+
+ @Test
+ fun border_changeOutline_outlineGeneric_samePath_observableShape() {
+ var roundedCorners by mutableStateOf(false)
+ val roundedCornersShape = object : Shape {
+ val path = Path()
+ override fun createOutline(
+ size: Size,
+ layoutDirection: LayoutDirection,
+ density: Density
+ ): Outline {
+ val roundRect = if (roundedCorners) {
+ RoundRect(
+ Rect(Offset.Zero, size),
+ cornerRadius = CornerRadius(50f)
+ )
+ } else {
+ RoundRect(
+ Rect(Offset.Zero, size),
+ cornerRadius = CornerRadius.Zero
+ )
+ }
+ path.reset()
+ path.addRoundRect(roundRect)
+ return Outline.Generic(path)
+ }
+ }
+
+ rule.setContent {
+ SemanticParent {
+ Box(
+ Modifier
+ .size(400.0f.toDp(), 400.0f.toDp())
+ .background(color = Color.Blue)
+ .border(
+ BorderStroke(1f.toDp(), Color.Red),
+ roundedCornersShape
+ )
+ ) {}
+ }
+ }
+
+ rule.onNodeWithTag(testTag).captureToImage().run {
+ val map = toPixelMap()
+ // We should not be rounded, so left edge should be fully red
+ assertEquals(Color.Red, map[0, 0])
+ assertEquals(Color.Red, map[0, (height - 1) / 2])
+ // The last pixel fails to render properly on some emulators, so just assert the one
+ // before instead - b/267371353
+ assertEquals(Color.Red, map[0, height - 2])
+ }
+
+ rule.runOnIdle {
+ roundedCorners = true
+ }
+
+ rule.onNodeWithTag(testTag).captureToImage().run {
+ val map = toPixelMap()
+ // We should now be rounded, so the top and bottom of the left edge will be blue, but
+ // the center will still be red
+ assertEquals(Color.Blue, map[0, 0])
+ assertEquals(Color.Red, map[0, (height - 1) / 2])
+ // The last pixel fails to render properly on some emulators, so just assert the one
+ // before instead - b/267371353
+ assertEquals(Color.Blue, map[0, height - 2])
+ }
+ }
+
+ @Test
fun equalInputs_shouldResolveToEquals_withColor() {
assertModifierIsPure { toggleInput ->
if (toggleInput) {
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/Draggable2DTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/Draggable2DTest.kt
index b813eef..ef283ac 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/Draggable2DTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/Draggable2DTest.kt
@@ -850,6 +850,7 @@
val enabled = mutableStateOf(true)
lateinit var runningJob: Job
rule.setContent {
+ val scope = rememberCoroutineScope()
Box(
modifier = Modifier
.testTag(draggable2DBoxTag)
@@ -858,7 +859,7 @@
enabled = enabled.value,
state = rememberDraggable2DState { },
onDragStopped = { _ ->
- runningJob = launch { delay(10_000L) } // long running operation
+ runningJob = scope.launch { delay(10_000L) } // long running operation
}
)
)
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/BasicTextLinkTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/BasicTextLinkTest.kt
index f65b5c2..09857ac 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/BasicTextLinkTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/BasicTextLinkTest.kt
@@ -505,7 +505,7 @@
}
rule.onNode(hasClickAction(), useUnmergedTree = true)
- .performMouseInput { enter(this.center) }
+ .performMouseInput { moveTo(this.center) }
.captureToImage()
.assertContainsColor(Color.Green)
.assertDoesNotContainColor(Color.Red)
@@ -531,7 +531,7 @@
}
rule.onNode(hasClickAction(), useUnmergedTree = true)
- .performMouseInput { enter(this.center) }
+ .performMouseInput { moveTo(this.center) }
.captureToImage()
.assertContainsColor(Color.Green)
.assertDoesNotContainColor(Color.Red)
@@ -555,7 +555,7 @@
}
rule.onNode(hasClickAction(), useUnmergedTree = true)
- .performMouseInput { enter(this.center) }
+ .performMouseInput { moveTo(this.center) }
.captureToImage()
.assertContainsColor(Color.Green)
.assertContainsColor(Color.Red)
@@ -649,7 +649,7 @@
rule.onNode(hasClickAction(), useUnmergedTree = true)
.requestFocus()
- .performMouseInput { enter(this.center) }
+ .performMouseInput { moveTo(this.center) }
.captureToImage()
.assertContainsColor(Color.Green)
.assertDoesNotContainColor(Color.Blue)
@@ -672,7 +672,7 @@
}
rule.onNode(hasClickAction(), useUnmergedTree = true)
- .performMouseInput { enter(this.center) }
+ .performMouseInput { moveTo(this.center) }
.requestFocus()
.captureToImage()
.assertContainsColor(Color.Green)
@@ -696,7 +696,7 @@
}
rule.onNode(hasClickAction(), useUnmergedTree = true)
- .performMouseInput { enter(this.center) }
+ .performMouseInput { moveTo(this.center) }
.requestFocus()
.captureToImage()
.assertContainsColor(Color.Green)
@@ -766,7 +766,7 @@
rule.onNode(hasClickAction(), useUnmergedTree = true)
.requestFocus()
- .performMouseInput { enter(this.center) }
+ .performMouseInput { moveTo(this.center) }
.performTouchInput { longPress(this.center) }
.captureToImage()
.assertContainsColor(Color.Blue)
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/input/BasicTextFieldTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/input/BasicTextFieldTest.kt
index 4400ec6..8ec2e92 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/input/BasicTextFieldTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/input/BasicTextFieldTest.kt
@@ -440,12 +440,10 @@
}
@Test
- fun hideKeyboardWhenFocusCleared() {
- val keyboardHelper = KeyboardHelper(rule)
+ fun disposeSessionWhenFocusCleared() {
val state = TextFieldState("initial text")
lateinit var focusManager: FocusManager
- rule.setContent {
- keyboardHelper.initialize()
+ inputMethodInterceptor.setContent {
focusManager = LocalFocusManager.current
Row {
// Extra focusable that takes initial focus when focus is cleared.
@@ -461,15 +459,14 @@
}
rule.onNodeWithTag("TextField").requestFocus()
- keyboardHelper.waitForKeyboardVisibility(true)
- assertTrue(keyboardHelper.isSoftwareKeyboardShown())
+
+ inputMethodInterceptor.assertSessionActive()
rule.runOnIdle {
focusManager.clearFocus()
}
- keyboardHelper.waitForKeyboardVisibility(false)
- assertFalse(keyboardHelper.isSoftwareKeyboardShown())
+ inputMethodInterceptor.assertNoSessionActive()
}
@Test
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/input/internal/AndroidTextInputSessionTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/input/internal/AndroidTextInputSessionTest.kt
index 46bd2d9..333c607 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/input/internal/AndroidTextInputSessionTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/input/internal/AndroidTextInputSessionTest.kt
@@ -23,7 +23,9 @@
import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.text.input.FakeInputMethodManager
import androidx.compose.foundation.text.input.TextFieldState
+import androidx.compose.foundation.text.input.TextHighlightType
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.node.ModifierNodeElement
@@ -188,6 +190,19 @@
}
@Test
+ fun onlyChangingHighlight_doesNotFireUpdateSelectionOrRestartInput() {
+ val state = TextFieldState("abc def ghi")
+ val composeImm = FakeInputMethodManager()
+ launchInputSessionWithDefaultsForTest(state = state, composeImm = composeImm)
+
+ state.editAsUser(inputTransformation = null) {
+ setHighlight(TextHighlightType.HandwritingSelectPreview, 0, 3)
+ }
+
+ composeImm.expectNoMoreCalls()
+ }
+
+ @Test
fun debugMode_isDisabled() {
// run this in presubmit to check that we are not accidentally enabling logs on prod
assertFalse(
@@ -200,15 +215,25 @@
private fun launchInputSessionWithDefaultsForTest(
state: TextFieldState = TextFieldState(),
imeOptions: ImeOptions = ImeOptions.Default,
- onImeAction: (ImeAction) -> Unit = {}
+ onImeAction: (ImeAction) -> Unit = {},
+ composeImm: ComposeInputMethodManager? = null
) {
coroutineScope.launch {
textInputNode.establishTextInputSession {
- inputSessionWithDefaultsForTest(
- state,
- imeOptions,
- onImeAction
- )
+ if (composeImm != null) {
+ inputSessionWithDefaultsForTest(
+ state,
+ imeOptions,
+ onImeAction,
+ composeImm = composeImm
+ )
+ } else {
+ inputSessionWithDefaultsForTest(
+ state,
+ imeOptions,
+ onImeAction
+ )
+ }
}
}
}
@@ -217,7 +242,8 @@
state: TextFieldState = TextFieldState(),
imeOptions: ImeOptions = ImeOptions.Default,
onImeAction: (ImeAction) -> Unit = {},
- receiveContentConfiguration: ReceiveContentConfiguration? = null
+ receiveContentConfiguration: ReceiveContentConfiguration? = null,
+ composeImm: ComposeInputMethodManager = ComposeInputMethodManager(view)
): Nothing = platformSpecificTextInputSession(
state = TransformedTextFieldState(
textFieldState = state,
@@ -226,8 +252,11 @@
),
layoutState = TextLayoutState(),
imeOptions = imeOptions,
+ composeImm = composeImm,
receiveContentConfiguration = receiveContentConfiguration,
onImeAction = onImeAction,
+ stylusHandwritingTrigger = null,
+ viewConfiguration = null
)
private inner class TestTextElement : ModifierNodeElement<TestTextNode>() {
diff --git a/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/input/TextFieldStateTest.kt b/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/input/TextFieldStateTest.kt
index d0a1c57..2a4f9b2 100644
--- a/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/input/TextFieldStateTest.kt
+++ b/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/input/TextFieldStateTest.kt
@@ -683,6 +683,22 @@
assertThat(isRead).isEqualTo(false)
}
+ @Test
+ fun onlyHighlightChange_doesNotTriggerInputTransformation() {
+ val state = TextFieldState("abc def ghi")
+ var transformationCalled = 0
+ val inputTransformation = InputTransformation {
+ transformationCalled++
+ }
+ state.editAsUser(inputTransformation) {
+ setHighlight(TextHighlightType.HandwritingSelectPreview, 0, 3)
+ }
+ state.editAsUser(inputTransformation) {
+ setHighlight(TextHighlightType.HandwritingDeletePreview, 4, 7)
+ }
+ assertThat(transformationCalled).isEqualTo(0)
+ }
+
private fun runTestWithSnapshotsThenCancelChildren(testBody: suspend TestScope.() -> Unit) {
val globalWriteObserverHandle = Snapshot.registerGlobalWriteObserver {
// This is normally done by the compose runtime.
diff --git a/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/input/internal/TextFieldStateInternalBufferTest.kt b/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/input/internal/TextFieldStateInternalBufferTest.kt
index 12207b6..85c4c8c 100644
--- a/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/input/internal/TextFieldStateInternalBufferTest.kt
+++ b/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/input/internal/TextFieldStateInternalBufferTest.kt
@@ -18,6 +18,7 @@
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.text.input.InputTransformation
+import androidx.compose.foundation.text.input.TextFieldBuffer
import androidx.compose.foundation.text.input.TextFieldCharSequence
import androidx.compose.foundation.text.input.TextFieldState
import androidx.compose.ui.text.TextRange
@@ -94,13 +95,13 @@
}
val initialBuffer = state.mainBuffer
- state.resetStateAndNotifyIme(
+ state.syncMainBufferToTemporaryBuffer(
TextFieldCharSequence("qwerty", TextRange.Zero, TextRange.Zero)
)
assertThat(state.mainBuffer).isNotSameInstanceAs(initialBuffer)
val updatedBuffer = state.mainBuffer
- state.resetStateAndNotifyIme(
+ state.syncMainBufferToTemporaryBuffer(
TextFieldCharSequence("qwerty", TextRange.Zero, TextRange.Zero)
)
assertThat(state.mainBuffer).isSameInstanceAs(updatedBuffer)
@@ -120,11 +121,11 @@
}
val textFieldValue = TextFieldCharSequence("qwerty", TextRange.Zero, TextRange.Zero)
- state.resetStateAndNotifyIme(textFieldValue)
+ state.syncMainBufferToTemporaryBuffer(textFieldValue)
val initialBuffer = state.mainBuffer
val newTextFieldValue = TextFieldCharSequence("abc")
- state.resetStateAndNotifyIme(newTextFieldValue)
+ state.syncMainBufferToTemporaryBuffer(newTextFieldValue)
assertThat(state.mainBuffer).isNotSameInstanceAs(initialBuffer)
assertThat(resetCalled).isEqualTo(2)
@@ -142,11 +143,11 @@
}
val textFieldValue = TextFieldCharSequence("qwerty", TextRange.Zero, TextRange.Zero)
- state.resetStateAndNotifyIme(textFieldValue)
+ state.syncMainBufferToTemporaryBuffer(textFieldValue)
val initialBuffer = state.mainBuffer
val newTextFieldValue = TextFieldCharSequence(textFieldValue, selection = TextRange(1))
- state.resetStateAndNotifyIme(newTextFieldValue)
+ state.syncMainBufferToTemporaryBuffer(newTextFieldValue)
assertThat(state.mainBuffer).isSameInstanceAs(initialBuffer)
assertThat(newTextFieldValue.selection.start)
@@ -169,7 +170,7 @@
}
val textFieldValue = TextFieldCharSequence("qwerty", TextRange.Zero, TextRange(1))
- state.resetStateAndNotifyIme(textFieldValue)
+ state.syncMainBufferToTemporaryBuffer(textFieldValue)
val initialBuffer = state.mainBuffer
// composition can not be set from app, IME owns it.
@@ -181,7 +182,7 @@
textFieldValue.selection,
composition = null
)
- state.resetStateAndNotifyIme(newTextFieldValue)
+ state.syncMainBufferToTemporaryBuffer(newTextFieldValue)
assertThat(state.mainBuffer).isSameInstanceAs(initialBuffer)
assertThat(EditingBuffer.NOWHERE).isEqualTo(state.mainBuffer.compositionStart)
@@ -210,7 +211,7 @@
val updatedSelection = TextRange(3, 0)
val newTextFieldValue = TextFieldCharSequence(textFieldValue, selection = updatedSelection)
// set the new selection
- state.resetStateAndNotifyIme(newTextFieldValue)
+ state.syncMainBufferToTemporaryBuffer(newTextFieldValue)
assertThat(state.mainBuffer).isSameInstanceAs(initialBuffer)
assertThat(updatedSelection.start).isEqualTo(initialBuffer.selectionStart)
@@ -244,7 +245,7 @@
state.selection,
state.composition
)
- state.resetStateAndNotifyIme(newValue)
+ state.syncMainBufferToTemporaryBuffer(newValue)
assertThat(state.text.toString()).isEqualTo(newValue.toString())
assertThat(state.composition).isNull()
@@ -270,7 +271,7 @@
state.selection,
state.composition
)
- state.resetStateAndNotifyIme(newValue)
+ state.syncMainBufferToTemporaryBuffer(newValue)
assertThat(state.text.toString()).isEqualTo(newValue.toString())
assertThat(state.composition).isEqualTo(composition)
@@ -293,7 +294,7 @@
state.selection,
composition = TextRange(0, 2)
)
- state.resetStateAndNotifyIme(newValue)
+ state.syncMainBufferToTemporaryBuffer(newValue)
assertThat(state.text.toString()).isEqualTo(newValue.toString())
assertThat(state.composition).isNull()
@@ -315,7 +316,7 @@
state.selection,
composition = TextRange(0, 1)
)
- state.resetStateAndNotifyIme(newValue)
+ state.syncMainBufferToTemporaryBuffer(newValue)
assertThat(state.text.toString()).isEqualTo(newValue.toString())
assertThat(state.composition).isNull()
@@ -342,7 +343,7 @@
selection = newSelection,
composition = state.composition
)
- state.resetStateAndNotifyIme(newValue)
+ state.syncMainBufferToTemporaryBuffer(newValue)
assertThat(state.text.toString()).isEqualTo(newValue.toString())
assertThat(state.composition).isEqualTo(composition)
@@ -580,4 +581,15 @@
)
}
}
+
+ private fun TextFieldState.syncMainBufferToTemporaryBuffer(
+ textFieldCharSequence: TextFieldCharSequence
+ ) {
+ syncMainBufferToTemporaryBuffer(
+ textFieldBuffer = TextFieldBuffer(textFieldCharSequence),
+ newComposition = textFieldCharSequence.composition,
+ textChanged = !textFieldCharSequence.contentEquals(mainBuffer.toString()),
+ selectionChanged = textFieldCharSequence.selection != mainBuffer.selection,
+ )
+ }
}
diff --git a/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/input/internal/undo/TextUndoTest.kt b/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/input/internal/undo/TextUndoTest.kt
index ea0d8d1..abd1cb7 100644
--- a/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/input/internal/undo/TextUndoTest.kt
+++ b/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/input/internal/undo/TextUndoTest.kt
@@ -291,7 +291,7 @@
}
@Test
- fun directEditsClearTheUndoHistory() {
+ fun directEdits_clearTheUndoHistory() {
val state = TextFieldState("abc")
state.typeAtEnd("d")
state.typeAtStart("e")
@@ -303,6 +303,39 @@
assertThat(state.undoState.canRedo).isEqualTo(false)
}
+ @Test
+ fun directEdit_onlySelectionChange_doesNotClearUndoHistory() {
+ val state = TextFieldState("abc")
+ state.typeAtEnd("d")
+ state.typeAtStart("e")
+ state.typeAtEnd("f")
+
+ state.edit {
+ selection = TextRange(0)
+ }
+
+ assertThat(state.undoState.canUndo).isEqualTo(true)
+ }
+
+ @Test
+ fun directEdit_replaceButNoContentChange_clearsUndoHistory() {
+ val state = TextFieldState("abc")
+ state.typeAtEnd("d")
+ state.typeAtStart("e")
+ state.typeAtEnd("f")
+
+ val before = state.text.toString()
+
+ state.edit {
+ replace(0, 6, "eabcdf")
+ }
+
+ val after = state.text.toString()
+
+ assertThat(before).isEqualTo(after)
+ assertThat(state.undoState.canUndo).isEqualTo(false)
+ }
+
companion object {
private fun TextFieldState.typeAtEnd(text: String) {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Background.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Background.kt
index 622afb5..c9ce2c9 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Background.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Background.kt
@@ -29,6 +29,9 @@
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
import androidx.compose.ui.node.DrawModifierNode
import androidx.compose.ui.node.ModifierNodeElement
+import androidx.compose.ui.node.ObserverModifierNode
+import androidx.compose.ui.node.invalidateDraw
+import androidx.compose.ui.node.observeReads
import androidx.compose.ui.platform.InspectorInfo
import androidx.compose.ui.platform.debugInspectorInfo
import androidx.compose.ui.unit.LayoutDirection
@@ -141,10 +144,11 @@
var brush: Brush?,
var alpha: Float,
var shape: Shape,
-) : DrawModifierNode, Modifier.Node() {
+) : DrawModifierNode, Modifier.Node(), ObserverModifierNode {
- // naive cache outline calculation if size is the same
- private var lastSize: Size? = null
+ // Naively cache outline calculation if input parameters are the same, we manually observe
+ // reads inside shape#createOutline separately
+ private var lastSize: Size = Size.Unspecified
private var lastLayoutDirection: LayoutDirection? = null
private var lastOutline: Outline? = null
private var lastShape: Shape? = null
@@ -159,23 +163,42 @@
drawContent()
}
+ override fun onObservedReadsChanged() {
+ // Reset cached properties
+ lastSize = Size.Unspecified
+ lastLayoutDirection = null
+ lastOutline = null
+ lastShape = null
+ // Invalidate draw so we build the cache again - this is needed because observeReads within
+ // the draw scope obscures the state reads from the draw scope's observer
+ invalidateDraw()
+ }
+
private fun ContentDrawScope.drawRect() {
if (color != Color.Unspecified) drawRect(color = color)
brush?.let { drawRect(brush = it, alpha = alpha) }
}
private fun ContentDrawScope.drawOutline() {
- val outline =
- if (size == lastSize && layoutDirection == lastLayoutDirection && lastShape == shape) {
- lastOutline!!
- } else {
- shape.createOutline(size, layoutDirection, this)
- }
+ val outline = getOutline()
if (color != Color.Unspecified) drawOutline(outline, color = color)
brush?.let { drawOutline(outline, brush = it, alpha = alpha) }
+ }
+
+ private fun ContentDrawScope.getOutline(): Outline {
+ var outline: Outline? = null
+ if (size == lastSize && layoutDirection == lastLayoutDirection && lastShape == shape) {
+ outline = lastOutline!!
+ } else {
+ // Manually observe reads so we can directly invalidate the outline when it changes
+ observeReads {
+ outline = shape.createOutline(size, layoutDirection, this)
+ }
+ }
lastOutline = outline
lastSize = size
lastLayoutDirection = layoutDirection
lastShape = shape
+ return outline!!
}
}
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/AnchoredDraggable.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/AnchoredDraggable.kt
index aaf6abe..44e9b90 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/AnchoredDraggable.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/AnchoredDraggable.kt
@@ -374,7 +374,8 @@
) : DragGestureNode(
canDrag = AlwaysDrag,
enabled = enabled,
- interactionSource = interactionSource
+ interactionSource = interactionSource,
+ orientationLock = orientation
) {
open suspend fun AnchoredDragScope.anchoredDrag(
@@ -389,9 +390,6 @@
state.anchoredDrag(MutatePriority.Default) { anchoredDrag(forEachDelta) }
}
- override val pointerDirectionConfig: PointerDirectionConfig
- get() = orientation.toPointerDirectionConfig()
-
override suspend fun CoroutineScope.onDragStarted(startedPosition: Offset) {}
override suspend fun CoroutineScope.onDragStopped(velocity: Velocity) {
@@ -429,7 +427,8 @@
update(
enabled = enabled,
interactionSource = interactionSource,
- isResetPointerInputHandling = resetPointerInputHandling,
+ shouldResetPointerInputHandling = resetPointerInputHandling,
+ orientationLock = orientation
)
}
@@ -742,7 +741,8 @@
@Deprecated(
message = "Use the progress function to query the progress between two specified " +
"anchors.",
- replaceWith = ReplaceWith("progress(state.settledValue, state.targetValue)"))
+ replaceWith = ReplaceWith("progress(state.settledValue, state.targetValue)")
+ )
@get:FloatRange(from = 0.0, to = 1.0)
val progress: Float by derivedStateOf(structuralEqualityPolicy()) {
val a = anchors.positionOf(settledValue)
@@ -1296,7 +1296,7 @@
}
}
-private fun<K> ObjectFloatMap<K>.minValueOrNaN(): Float {
+private fun <K> ObjectFloatMap<K>.minValueOrNaN(): Float {
if (size == 1) return Float.NaN
var minValue = Float.POSITIVE_INFINITY
forEachValue { value ->
@@ -1307,7 +1307,7 @@
return minValue
}
-private fun<K> ObjectFloatMap<K>.maxValueOrNaN(): Float {
+private fun <K> ObjectFloatMap<K>.maxValueOrNaN(): Float {
if (size == 1) return Float.NaN
var maxValue = Float.NEGATIVE_INFINITY
forEachValue { value ->
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/DragGestureDetector.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/DragGestureDetector.kt
index 4d7c7fc..86835e4 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/DragGestureDetector.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/DragGestureDetector.kt
@@ -45,7 +45,7 @@
import androidx.compose.ui.util.fastAny
import androidx.compose.ui.util.fastFirstOrNull
import androidx.compose.ui.util.fastForEach
-import kotlin.math.abs
+import kotlin.math.absoluteValue
import kotlin.math.sign
import kotlinx.coroutines.CancellationException
@@ -79,7 +79,7 @@
pointerId,
PointerType.Touch,
onPointerSlopReached = onTouchSlopReached,
- pointerDirectionConfig = BidirectionalPointerDirectionConfig,
+ orientation = null,
)
}
@@ -170,33 +170,113 @@
onDragEnd: () -> Unit = { },
onDragCancel: () -> Unit = { },
onDrag: (change: PointerInputChange, dragAmount: Offset) -> Unit
+) = detectDragGestures(
+ onDragStart = { _, offset -> onDragStart(offset) },
+ onDragEnd = { onDragEnd.invoke() },
+ onDragCancel = onDragCancel,
+ shouldAwaitTouchSlop = { true },
+ orientationLock = null,
+ onDrag = onDrag
+)
+
+/**
+ * A Gesture detector that waits for pointer down and touch slop in the direction specified by
+ * [orientationLock] and then calls [onDrag] for each drag event.
+ * It follows the touch slop detection of [awaitTouchSlopOrCancellation] but will consume the
+ * position change automatically once the touch slop has been crossed, the amount of drag over
+ * the touch slop is reported as the first drag event [onDrag] after the slop is crossed.
+ * If [shouldAwaitTouchSlop] returns true the touch slop recognition phase will be ignored
+ * and the drag gesture will be recognized immediately.The first [onDrag] in this case will report
+ * an [Offset.Zero].
+ *
+ * [onDragStart] is called when the touch slop has been passed and includes an [Offset] representing
+ * the last known pointer position relative to the containing element as well as the initial
+ * down event that triggered this gesture detection cycle. The [Offset] can be outside
+ * the actual bounds of the element itself meaning the numbers can be negative or larger than the
+ * element bounds if the touch target is smaller than the
+ * [ViewConfiguration.minimumTouchTargetSize].
+ *
+ * [onDragEnd] is called after all pointers are up with the event change of the up event
+ * and [onDragCancel] is called if another gesture has consumed pointer input,
+ * canceling this gesture.
+ *
+ * @param onDragStart A lambda to be called when the drag gesture starts, it contains information
+ * about the triggering [PointerInputChange] and post slop delta.
+ * @param onDragEnd A lambda to be called when the gesture ends. It contains information about the
+ * up [PointerInputChange] that finished the gesture.
+ * @param onDragCancel A lambda to be called when the gesture is cancelled either by an error or
+ * when it was consumed.
+ * @param shouldAwaitTouchSlop Indicates if touch slop detection should be skipped.
+ * @param orientationLock Optionally locks detection to this orientation, this means, when this is
+ * provided, touch slop detection and drag event detection will be conditioned to the given
+ * orientation axis. [onDrag] will still dispatch events on with information in both axis, but
+ * if orientation lock is provided, only events that happen on the given orientation will be
+ * considered. If no value is provided (i.e. null) touch slop and drag detection will happen on
+ * an "any" orientation basis, that is, touch slop will be detected if crossed in either direction
+ * and drag events will be dispatched if present in either direction.
+ * @param onDrag A lambda to be called for each delta event in the gesture. It contains information
+ * about the [PointerInputChange] and the movement offset.
+ *
+ * Example Usage:
+ * @sample androidx.compose.foundation.samples.DetectDragGesturesSample
+ *
+ * @see detectVerticalDragGestures
+ * @see detectHorizontalDragGestures
+ * @see detectDragGesturesAfterLongPress to detect gestures after long press
+ */
+internal suspend fun PointerInputScope.detectDragGestures(
+ onDragStart: (change: PointerInputChange, initialDelta: Offset) -> Unit,
+ onDragEnd: (change: PointerInputChange) -> Unit,
+ onDragCancel: () -> Unit,
+ shouldAwaitTouchSlop: () -> Boolean,
+ orientationLock: Orientation?,
+ onDrag: (change: PointerInputChange, dragAmount: Offset) -> Unit
) {
awaitEachGesture {
+ val initialDown =
+ awaitFirstDown(requireUnconsumed = false, pass = PointerEventPass.Initial)
+ val awaitTouchSlop = shouldAwaitTouchSlop()
+
+ if (!awaitTouchSlop) {
+ initialDown.consume()
+ }
val down = awaitFirstDown(requireUnconsumed = false)
var drag: PointerInputChange?
var overSlop = Offset.Zero
- do {
- drag = awaitPointerSlopOrCancellation(
- down.id,
- down.type,
- pointerDirectionConfig = BidirectionalPointerDirectionConfig
- ) { change, over ->
- change.consume()
- overSlop = over
- }
- } while (drag != null && !drag.isConsumed)
- if (drag != null) {
- onDragStart.invoke(drag.position)
- onDrag(drag, overSlop)
- if (
- !drag(drag.id) {
- onDrag(it, it.positionChange())
- it.consume()
+ var initialDelta = Offset.Zero
+
+ if (awaitTouchSlop) {
+ do {
+ drag = awaitPointerSlopOrCancellation(
+ down.id,
+ down.type,
+ orientation = orientationLock
+ ) { change, over ->
+ change.consume()
+ overSlop = over
}
- ) {
+ } while (drag != null && !drag.isConsumed)
+ initialDelta = drag?.position ?: Offset.Zero
+ } else {
+ drag = initialDown
+ }
+
+ if (drag != null) {
+ onDragStart.invoke(initialDown, initialDelta)
+ onDrag(drag, overSlop)
+ val upEvent = drag(
+ pointerId = drag.id,
+ onDrag = {
+ onDrag(it, it.positionChange())
+ },
+ orientation = orientationLock,
+ motionConsumed = {
+ it.isConsumed
+ })
+ if (upEvent == null) {
onDragCancel()
} else {
- onDragEnd()
+ onDragEnd(upEvent)
}
}
}
@@ -288,7 +368,7 @@
pointerId = pointerId,
pointerType = PointerType.Touch,
onPointerSlopReached = { change, overSlop -> onTouchSlopReached(change, overSlop.y) },
- pointerDirectionConfig = VerticalPointerDirectionConfig
+ orientation = Orientation.Vertical
)
internal suspend fun AwaitPointerEventScope.awaitVerticalPointerSlopOrCancellation(
@@ -299,7 +379,7 @@
pointerId = pointerId,
pointerType = pointerType,
onPointerSlopReached = { change, overSlop -> onTouchSlopReached(change, overSlop.y) },
- pointerDirectionConfig = VerticalPointerDirectionConfig
+ orientation = Orientation.Vertical
)
/**
@@ -324,7 +404,7 @@
): Boolean = drag(
pointerId = pointerId,
onDrag = onDrag,
- hasDragged = { it.positionChangeIgnoreConsumed().y != 0f },
+ orientation = Orientation.Vertical,
motionConsumed = { it.isConsumed }
) != null
@@ -439,7 +519,7 @@
pointerId = pointerId,
pointerType = PointerType.Touch,
onPointerSlopReached = { change, overSlop -> onTouchSlopReached(change, overSlop.x) },
- pointerDirectionConfig = HorizontalPointerDirectionConfig
+ orientation = Orientation.Horizontal
)
internal suspend fun AwaitPointerEventScope.awaitHorizontalPointerSlopOrCancellation(
@@ -450,7 +530,7 @@
pointerId = pointerId,
pointerType = pointerType,
onPointerSlopReached = { change, overSlop -> onPointerSlopReached(change, overSlop.x) },
- pointerDirectionConfig = HorizontalPointerDirectionConfig
+ orientation = Orientation.Horizontal
)
/**
@@ -472,7 +552,7 @@
): Boolean = drag(
pointerId = pointerId,
onDrag = onDrag,
- hasDragged = { it.positionChangeIgnoreConsumed().x != 0f },
+ orientation = Orientation.Horizontal,
motionConsumed = { it.isConsumed }
) != null
@@ -563,9 +643,12 @@
/**
* Continues to read drag events until all pointers are up or the drag event is canceled.
- * The initial pointer to use for driving the drag is [pointerId]. [hasDragged]
- * passes the result whether a change was detected from the drag function or not. [onDrag] is called
- * whenever the pointer moves and [hasDragged] returns non-zero.
+ * The initial pointer to use for driving the drag is [pointerId]. [onDrag] is called
+ * whenever the pointer moves. The up event is returned at the end of the drag gesture.
+ *
+ * @param pointerId The pointer where that is driving the gesture.
+ * @param onDrag Callback for every new drag event.
+ * @param motionConsumed If the PointerInputChange should be considered as consumed.
*
* @return The last pointer input event change when gesture ended with all pointers up
* and null when the gesture was canceled.
@@ -573,7 +656,7 @@
internal suspend inline fun AwaitPointerEventScope.drag(
pointerId: PointerId,
onDrag: (PointerInputChange) -> Unit,
- hasDragged: (PointerInputChange) -> Boolean,
+ orientation: Orientation?,
motionConsumed: (PointerInputChange) -> Boolean
): PointerInputChange? {
if (currentEvent.isPointerUp(pointerId)) {
@@ -581,7 +664,15 @@
}
var pointer = pointerId
while (true) {
- val change = awaitDragOrUp(pointer, hasDragged) ?: return null
+ val change = awaitDragOrUp(pointer) {
+ val positionChange = it.positionChangeIgnoreConsumed()
+ val motionChange = if (orientation == null) {
+ positionChange.getDistance()
+ } else {
+ if (orientation == Orientation.Vertical) positionChange.y else positionChange.x
+ }
+ motionChange != 0.0f
+ } ?: return null
if (motionConsumed(change)) {
return null
@@ -629,16 +720,14 @@
}
/**
- * Waits for drag motion along one axis when [pointerDirectionConfig] is
- * [HorizontalPointerDirectionConfig] or [VerticalPointerDirectionConfig], and drag motion along
- * any axis when using [BidirectionalPointerDirectionConfig]. It passes [pointerId] as the pointer
- * to examine. If [pointerId] is raised, another pointer from those that are down will be chosen to
+ * Waits for drag motion and uses [orientation] to detect the direction of touch slop detection.
+ * It passes [pointerId] as the pointer to examine. If [pointerId] is raised, another pointer from
+ * those that are down will be chosen to
* lead the gesture, and if none are down, `null` is returned. If [pointerId] is not down when
* [awaitPointerSlopOrCancellation] is called, then `null` is returned.
*
* When pointer slop is detected, [onPointerSlopReached] is called with the change and the distance
- * beyond the pointer slop. [PointerDirectionConfig.calculateDeltaChange] should return the position
- * change in the direction of the drag axis. If [onPointerSlopReached] does not consume the
+ * beyond the pointer slop. If [onPointerSlopReached] does not consume the
* position change, pointer slop will not have been considered detected and the detection will
* continue or, if it is consumed, the [PointerInputChange] that was consumed will be returned.
*
@@ -650,10 +739,10 @@
* `null` if all pointers are raised or the position change was consumed by another gesture
* detector.
*/
-internal suspend inline fun AwaitPointerEventScope.awaitPointerSlopOrCancellation(
+private suspend inline fun AwaitPointerEventScope.awaitPointerSlopOrCancellation(
pointerId: PointerId,
pointerType: PointerType,
- pointerDirectionConfig: PointerDirectionConfig,
+ orientation: Orientation?,
onPointerSlopReached: (PointerInputChange, Offset) -> Unit,
): PointerInputChange? {
if (currentEvent.isPointerUp(pointerId)) {
@@ -661,8 +750,7 @@
}
val touchSlop = viewConfiguration.pointerSlop(pointerType)
var pointer: PointerId = pointerId
- var totalPositionChange = Offset.Zero
-
+ val touchSlopDetector = TouchSlopDetector(orientation)
while (true) {
val event = awaitPointerEvent()
val dragEvent = event.changes.fastFirstOrNull { it.id == pointer } ?: return null
@@ -677,29 +765,8 @@
pointer = otherDown.id
}
} else {
- val currentPosition = dragEvent.position
- val previousPosition = dragEvent.previousPosition
-
- val positionChange = currentPosition - previousPosition
-
- totalPositionChange += positionChange
-
- val inDirection = pointerDirectionConfig.calculateDeltaChange(
- totalPositionChange
- )
-
- if (inDirection < touchSlop) {
- // verify that nothing else consumed the drag event
- awaitPointerEvent(PointerEventPass.Final)
- if (dragEvent.isConsumed) {
- return null
- }
- } else {
- val postSlopOffset = pointerDirectionConfig.calculatePostSlopOffset(
- totalPositionChange,
- touchSlop
- )
-
+ val postSlopOffset = touchSlopDetector.addPointerInputChange(dragEvent, touchSlop)
+ if (postSlopOffset != null) {
onPointerSlopReached(
dragEvent,
postSlopOffset
@@ -707,7 +774,13 @@
if (dragEvent.isConsumed) {
return dragEvent
} else {
- totalPositionChange = Offset.Zero
+ touchSlopDetector.reset()
+ }
+ } else {
+ // verify that nothing else consumed the drag event
+ awaitPointerEvent(PointerEventPass.Final)
+ if (dragEvent.isConsumed) {
+ return null
}
}
}
@@ -715,70 +788,77 @@
}
/**
- * Configures the calculations to get the change amount depending on the dragging type.
- * [calculatePostSlopOffset] will return the post offset slop when the touchSlop is reached.
+ * Detects if touch slop has been crossed after adding a series of [PointerInputChange].
+ * For every new [PointerInputChange] one should add it to this detector using
+ * [addPointerInputChange]. If the position change causes the touch slop to be crossed,
+ * [addPointerInputChange] will return true.
*/
-internal interface PointerDirectionConfig {
- fun calculateDeltaChange(offset: Offset): Float
- fun calculatePostSlopOffset(
- totalPositionChange: Offset,
- touchSlop: Float
- ): Offset
-}
+private class TouchSlopDetector(val orientation: Orientation? = null) {
-/**
- * Used for monitoring changes on X axis.
- */
-internal val HorizontalPointerDirectionConfig = object : PointerDirectionConfig {
- override fun calculateDeltaChange(offset: Offset): Float = abs(offset.x)
+ fun Offset.mainAxis() = if (orientation == Orientation.Horizontal) x else y
+ fun Offset.crossAxis() = if (orientation == Orientation.Horizontal) y else x
- override fun calculatePostSlopOffset(
- totalPositionChange: Offset,
+ /**
+ * The accumulation of drag deltas in this detector.
+ */
+ private var totalPositionChange: Offset = Offset.Zero
+
+ /**
+ * Adds [dragEvent] to this detector. If the accumulated position changes crosses the touch
+ * slop provided by [touchSlop], this method will return the post slop offset, that is the
+ * total accumulated delta change minus the touch slop value, otherwise this should return null.
+ */
+ fun addPointerInputChange(
+ dragEvent: PointerInputChange,
touchSlop: Float
- ): Offset {
- val finalMainPositionChange = totalPositionChange.x -
- (sign(totalPositionChange.x) * touchSlop)
- return Offset(finalMainPositionChange, totalPositionChange.y)
+ ): Offset? {
+ val currentPosition = dragEvent.position
+ val previousPosition = dragEvent.previousPosition
+ val positionChange = currentPosition - previousPosition
+ totalPositionChange += positionChange
+
+ val inDirection = if (orientation == null) {
+ totalPositionChange.getDistance()
+ } else {
+ totalPositionChange.mainAxis().absoluteValue
+ }
+
+ val hasCrossedSlop = inDirection >= touchSlop
+
+ return if (hasCrossedSlop) {
+ calculatePostSlopOffset(touchSlop)
+ } else {
+ null
+ }
+ }
+
+ /**
+ * Resets the accumulator associated with this detector.
+ */
+ fun reset() {
+ totalPositionChange = Offset.Zero
+ }
+
+ private fun calculatePostSlopOffset(touchSlop: Float): Offset {
+ return if (orientation == null) {
+ val touchSlopOffset =
+ totalPositionChange / totalPositionChange.getDistance() * touchSlop
+ // update postSlopOffset
+ totalPositionChange - touchSlopOffset
+ } else {
+ val finalMainAxisChange = totalPositionChange.mainAxis() -
+ (sign(totalPositionChange.mainAxis()) * touchSlop)
+ val finalCrossAxisChange = totalPositionChange.crossAxis()
+ if (orientation == Orientation.Horizontal) {
+ Offset(finalMainAxisChange, finalCrossAxisChange)
+ } else {
+ Offset(finalCrossAxisChange, finalMainAxisChange)
+ }
+ }
}
}
/**
- * Used for monitoring changes on Y axis.
- */
-internal val VerticalPointerDirectionConfig = object : PointerDirectionConfig {
- override fun calculateDeltaChange(offset: Offset): Float = abs(offset.y)
-
- override fun calculatePostSlopOffset(
- totalPositionChange: Offset,
- touchSlop: Float
- ): Offset {
- val finalMainPositionChange = totalPositionChange.y -
- (sign(totalPositionChange.y) * touchSlop)
- return Offset(totalPositionChange.x, finalMainPositionChange)
- }
-}
-
-/**
- * Used for monitoring changes on both X and Y axes.
- */
-internal val BidirectionalPointerDirectionConfig = object : PointerDirectionConfig {
- override fun calculateDeltaChange(offset: Offset): Float = offset.getDistance()
-
- override fun calculatePostSlopOffset(
- totalPositionChange: Offset,
- touchSlop: Float
- ): Offset {
- val touchSlopOffset =
- totalPositionChange / calculateDeltaChange(totalPositionChange) * touchSlop
- return totalPositionChange - touchSlopOffset
- }
-}
-
-internal fun Orientation.toPointerDirectionConfig(): PointerDirectionConfig =
- if (this == Orientation.Vertical) VerticalPointerDirectionConfig
- else HorizontalPointerDirectionConfig
-
-/**
* Waits for a long press by examining [pointerId].
*
* If that [pointerId] is raised (that is, the user lifts their finger), but another
@@ -839,7 +919,7 @@
// should technically never happen as we checked it above
finished = true
}
- // Pointer (id) stayed down.
+ // Pointer (id) stayed down.
} else {
longPress = event.changes.fastFirstOrNull { it.id == currentDown.id }
}
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable.kt
index 5db29b1..92f3e6c 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable.kt
@@ -31,16 +31,11 @@
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.input.pointer.AwaitPointerEventScope
import androidx.compose.ui.input.pointer.PointerEvent
import androidx.compose.ui.input.pointer.PointerEventPass
-import androidx.compose.ui.input.pointer.PointerId
import androidx.compose.ui.input.pointer.PointerInputChange
import androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNode
-import androidx.compose.ui.input.pointer.changedToUpIgnoreConsumed
import androidx.compose.ui.input.pointer.pointerInput
-import androidx.compose.ui.input.pointer.positionChange
-import androidx.compose.ui.input.pointer.positionChangeIgnoreConsumed
import androidx.compose.ui.input.pointer.util.VelocityTracker
import androidx.compose.ui.input.pointer.util.addPointerInputChange
import androidx.compose.ui.node.CompositionLocalConsumerModifierNode
@@ -56,7 +51,6 @@
import kotlin.math.sign
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.channels.SendChannel
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
@@ -301,9 +295,10 @@
private var onDragStopped: suspend CoroutineScope.(velocity: Float) -> Unit,
private var reverseDirection: Boolean
) : DragGestureNode(
- canDrag,
- enabled,
- interactionSource
+ canDrag = canDrag,
+ enabled = enabled,
+ interactionSource = interactionSource,
+ orientationLock = orientation
) {
override suspend fun drag(forEachDelta: suspend ((dragDelta: DragDelta) -> Unit) -> Unit) {
@@ -314,8 +309,6 @@
}
}
- override val pointerDirectionConfig = orientation.toPointerDirectionConfig()
-
override suspend fun CoroutineScope.onDragStarted(startedPosition: Offset) =
[email protected](this, startedPosition)
@@ -357,6 +350,7 @@
canDrag,
enabled,
interactionSource,
+ orientation,
resetPointerInputHandling
)
}
@@ -372,6 +366,7 @@
canDrag: (PointerInputChange) -> Boolean,
enabled: Boolean,
interactionSource: MutableInteractionSource?,
+ private var orientationLock: Orientation?
) : DelegatingNode(), PointerInputModifierNode, CompositionLocalConsumerModifierNode {
protected var canDrag = canDrag
@@ -397,13 +392,6 @@
abstract suspend fun drag(forEachDelta: suspend ((dragDelta: DragDelta) -> Unit) -> Unit)
/**
- * Returns the pointerDirectionConfig which specifies the main and cross axis deltas. This is
- * important when observing the delta change for Draggable, as we want to observe the change
- * in the main axis only.
- */
- abstract val pointerDirectionConfig: PointerDirectionConfig
-
- /**
* Passes the action needed when a drag starts. This gives the ability to pass the desired
* behavior from other nodes implementing AbstractDraggableNode
*/
@@ -478,62 +466,63 @@
// re-create tracker when pointer input block restarts. This lazily creates the tracker
// only when it is need.
val velocityTracker = VelocityTracker()
+ val onDragStart: (change: PointerInputChange, initialDelta: Offset) -> Unit =
+ { startEvent, initialDelta ->
+ if (canDrag.invoke(startEvent)) {
+ if (!isListeningForEvents) {
+ if (channel == null) {
+ channel = Channel(capacity = Channel.UNLIMITED)
+ }
+ startListeningForEvents()
+ }
+ val overSlopOffset = initialDelta
+ val xSign = sign(startEvent.position.x)
+ val ySign = sign(startEvent.position.y)
+ val adjustedStart = startEvent.position -
+ Offset(overSlopOffset.x * xSign, overSlopOffset.y * ySign)
+
+ channel?.trySend(DragStarted(adjustedStart))
+ }
+ }
+
+ val onDragEnd: (change: PointerInputChange) -> Unit = { upEvent ->
+ velocityTracker.addPointerInputChange(upEvent)
+ val maximumVelocity = currentValueOf(LocalViewConfiguration)
+ .maximumFlingVelocity
+ val velocity = velocityTracker.calculateVelocity(
+ Velocity(maximumVelocity, maximumVelocity)
+ )
+ velocityTracker.resetTracking()
+ channel?.trySend(DragStopped(velocity))
+ }
+
+ val onDragCancel: () -> Unit = {
+ channel?.trySend(DragCancelled)
+ }
+
+ val shouldAwaitTouchSlop: () -> Boolean = {
+ !startDragImmediately()
+ }
+
+ val onDrag: (change: PointerInputChange, dragAmount: Offset) -> Unit =
+ { change, delta ->
+ velocityTracker.addPointerInputChange(change)
+ channel?.trySend(DragDelta(delta))
+ }
+
coroutineScope {
try {
- awaitPointerEventScope {
- while (isActive) {
- awaitDownAndSlop(
- _canDrag,
- ::startDragImmediately,
- velocityTracker,
- pointerDirectionConfig
- )?.let {
- /**
- * The gesture crossed the touch slop, events are now relevant
- * and should be propagated
- */
- if (!isListeningForEvents) {
- if (channel == null) {
- channel = Channel(capacity = Channel.UNLIMITED)
- }
- startListeningForEvents()
- }
- var isDragSuccessful = false
- try {
- isDragSuccessful = awaitDrag(
- it.first,
- it.second,
- velocityTracker,
- channel
- ) { event ->
- pointerDirectionConfig.calculateDeltaChange(
- event.positionChangeIgnoreConsumed()
- ) != 0f
- }
- } catch (cancellation: CancellationException) {
- isDragSuccessful = false
- if (!isActive) throw cancellation
- } finally {
- val maximumVelocity = currentValueOf(LocalViewConfiguration)
- .maximumFlingVelocity
- val event = if (isDragSuccessful) {
- val velocity = velocityTracker.calculateVelocity(
- Velocity(maximumVelocity, maximumVelocity)
- )
- velocityTracker.resetTracking()
- DragStopped(velocity)
- } else {
- DragCancelled
- }
- channel?.trySend(event)
- }
- }
- }
- }
- } catch (exception: CancellationException) {
- if (!isActive) {
- throw exception
- }
+ detectDragGestures(
+ orientationLock = orientationLock,
+ onDragStart = onDragStart,
+ onDragEnd = onDragEnd,
+ onDragCancel = onDragCancel,
+ shouldAwaitTouchSlop = shouldAwaitTouchSlop,
+ onDrag = onDrag
+ )
+ } catch (cancellation: CancellationException) {
+ channel?.trySend(DragCancelled)
+ if (!isActive) throw cancellation
}
}
}
@@ -580,9 +569,10 @@
canDrag: (PointerInputChange) -> Boolean = this.canDrag,
enabled: Boolean = this.enabled,
interactionSource: MutableInteractionSource? = this.interactionSource,
- isResetPointerInputHandling: Boolean = false
+ orientationLock: Orientation? = this.orientationLock,
+ shouldResetPointerInputHandling: Boolean = false
) {
- var resetPointerInputHandling = isResetPointerInputHandling
+ var resetPointerInputHandling = shouldResetPointerInputHandling
this.canDrag = canDrag
if (this.enabled != enabled) {
@@ -599,91 +589,17 @@
this.interactionSource = interactionSource
}
+ if (this.orientationLock != orientationLock) {
+ this.orientationLock = orientationLock
+ resetPointerInputHandling = true
+ }
+
if (resetPointerInputHandling) {
pointerInputNode?.resetPointerInputHandler()
}
}
}
-private suspend fun AwaitPointerEventScope.awaitDownAndSlop(
- canDrag: (PointerInputChange) -> Boolean,
- startDragImmediately: () -> Boolean,
- velocityTracker: VelocityTracker,
- pointerDirectionConfig: PointerDirectionConfig
-): Pair<PointerInputChange, Offset>? {
- val initialDown =
- awaitFirstDown(requireUnconsumed = false, pass = PointerEventPass.Initial)
- return if (!canDrag(initialDown)) {
- null
- } else if (startDragImmediately()) {
- initialDown.consume()
- velocityTracker.addPointerInputChange(initialDown)
- // since we start immediately we don't wait for slop and the initial delta is 0
- initialDown to Offset.Zero
- } else {
- val down = awaitFirstDown(requireUnconsumed = false)
- velocityTracker.addPointerInputChange(down)
- var initialDelta = Offset.Zero
- val postPointerSlop = { event: PointerInputChange, offset: Offset ->
- velocityTracker.addPointerInputChange(event)
- event.consume()
- initialDelta = offset
- }
-
- val afterSlopResult = awaitPointerSlopOrCancellation(
- down.id,
- down.type,
- pointerDirectionConfig = pointerDirectionConfig,
- onPointerSlopReached = postPointerSlop
- )
-
- if (afterSlopResult != null) afterSlopResult to initialDelta else null
- }
-}
-
-private suspend fun AwaitPointerEventScope.awaitDrag(
- startEvent: PointerInputChange,
- initialDelta: Offset,
- velocityTracker: VelocityTracker,
- channel: SendChannel<DragEvent>?,
- hasDragged: (PointerInputChange) -> Boolean,
-): Boolean {
-
- val overSlopOffset = initialDelta
- val xSign = sign(startEvent.position.x)
- val ySign = sign(startEvent.position.y)
- val adjustedStart = startEvent.position -
- Offset(overSlopOffset.x * xSign, overSlopOffset.y * ySign)
- channel?.trySend(DragStarted(adjustedStart))
-
- channel?.trySend(DragDelta(initialDelta))
-
- return onDragOrUp(hasDragged, startEvent.id) { event ->
- // Velocity tracker takes all events, even UP
- velocityTracker.addPointerInputChange(event)
-
- // Dispatch only MOVE events
- if (!event.changedToUpIgnoreConsumed()) {
- val delta = event.positionChange()
- event.consume()
- channel?.trySend(DragDelta(delta))
- }
- }
-}
-
-private suspend fun AwaitPointerEventScope.onDragOrUp(
- hasDragged: (PointerInputChange) -> Boolean,
- pointerId: PointerId,
- onDrag: (PointerInputChange) -> Unit
-): Boolean {
- return drag(
- pointerId = pointerId,
- onDrag = onDrag,
- hasDragged = hasDragged,
- motionConsumed = { it.isConsumed }
- )?.let(onDrag) != null
-}
-
private class DefaultDraggableState(val onDelta: (Float) -> Unit) : DraggableState {
private val dragScope: DragScope = object : DragScope {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable2D.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable2D.kt
index f9c9571..4184042 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable2D.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable2D.kt
@@ -143,6 +143,53 @@
* press-based gestures). This is intended to allow end users to "catch" an animating widget by
* pressing on it. It's useful to set it when value you're dragging is settling / animating.
* @param onDragStarted callback that will be invoked when drag is about to start at the starting
+ * position, allowing user to perform preparation for drag.
+ * @param onDragStopped callback that will be invoked when drag is finished, allowing the
+ * user to react on velocity and process it.
+ * @param reverseDirection reverse the direction of the scroll, so top to bottom scroll will
+ * behave like bottom to top and left to right will behave like right to left.
+ */
+@ExperimentalFoundationApi
+@Stable
+fun Modifier.draggable2D(
+ state: Draggable2DState,
+ enabled: Boolean = true,
+ interactionSource: MutableInteractionSource? = null,
+ startDragImmediately: Boolean = false,
+ onDragStarted: (startedPosition: Offset) -> Unit = NoOpOnDragStart,
+ onDragStopped: (velocity: Velocity) -> Unit = NoOpOnDragStop,
+ reverseDirection: Boolean = false
+): Modifier = this then Draggable2DElement(
+ state = state,
+ enabled = enabled,
+ interactionSource = interactionSource,
+ startDragImmediately = startDragImmediately,
+ onDragStarted = onDragStarted,
+ onDragStopped = onDragStopped,
+ reverseDirection = reverseDirection
+)
+
+/**
+ * Configure touch dragging for the UI element in both orientations. The drag distance
+ * reported to [Draggable2DState], allowing users to react to the drag delta and update their state.
+ *
+ * The common common usecase for this component is when you need to be able to drag something
+ * inside the component on the screen and represent this state via one float value
+ *
+ * If you are implementing dragging in a single orientation, consider using [draggable].
+ *
+ * @sample androidx.compose.foundation.samples.Draggable2DSample
+ *
+ * @param state [Draggable2DState] state of the draggable2D. Defines how drag events will be
+ * interpreted by the user land logic.
+ * @param enabled whether or not drag is enabled
+ * @param interactionSource [MutableInteractionSource] that will be used to emit
+ * [DragInteraction.Start] when this draggable is being dragged.
+ * @param startDragImmediately when set to true, draggable2D will start dragging immediately and
+ * prevent other gesture detectors from reacting to "down" events (in order to block composed
+ * press-based gestures). This is intended to allow end users to "catch" an animating widget by
+ * pressing on it. It's useful to set it when value you're dragging is settling / animating.
+ * @param onDragStarted callback that will be invoked when drag is about to start at the starting
* position, allowing user to suspend and perform preparation for drag, if desired.This suspend
* function is invoked with the draggable2D scope, allowing for async processing, if desired. Note
* that the scope used here is the one provided by the draggable2D node, for long-running work that
@@ -156,6 +203,10 @@
* @param reverseDirection reverse the direction of the scroll, so top to bottom scroll will
* behave like bottom to top and left to right will behave like right to left.
*/
+@Deprecated(
+ "Please use overload without the suspend onDragStarted onDragStopped and callbacks",
+ level = DeprecationLevel.HIDDEN
+)
@ExperimentalFoundationApi
@Stable
fun Modifier.draggable2D(
@@ -166,7 +217,7 @@
onDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit = NoOpOnDragStarted,
onDragStopped: suspend CoroutineScope.(velocity: Velocity) -> Unit = NoOpOnDragStopped,
reverseDirection: Boolean = false
-): Modifier = this then Draggable2DElement(
+): Modifier = this then Draggable2DCompatElement(
state = state,
enabled = enabled,
interactionSource = interactionSource,
@@ -177,25 +228,24 @@
)
@OptIn(ExperimentalFoundationApi::class)
-internal class Draggable2DElement(
+internal class Draggable2DCompatElement(
private val state: Draggable2DState,
private val enabled: Boolean,
private val interactionSource: MutableInteractionSource?,
private val startDragImmediately: Boolean,
private val onDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit,
private val onDragStopped: suspend CoroutineScope.(velocity: Velocity) -> Unit,
- private val reverseDirection: Boolean,
-
- ) : ModifierNodeElement<Draggable2DNode>() {
+ private val reverseDirection: Boolean
+) : ModifierNodeElement<Draggable2DNode>() {
override fun create(): Draggable2DNode = Draggable2DNode(
state,
CanDrag,
enabled,
interactionSource,
startDragImmediately,
- onDragStarted,
- onDragStopped,
- reverseDirection
+ reverseDirection,
+ onDragStarted = onDragStarted,
+ onDragStopped = onDragStopped,
)
override fun update(node: Draggable2DNode) {
@@ -205,9 +255,88 @@
enabled,
interactionSource,
startDragImmediately,
- onDragStarted,
- onDragStopped,
- reverseDirection
+ reverseDirection,
+ onDragStarted = onDragStarted,
+ onDragStopped = onDragStopped,
+ )
+ }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (other === null) return false
+ if (this::class != other::class) return false
+
+ other as Draggable2DCompatElement
+
+ if (state != other.state) return false
+ if (enabled != other.enabled) return false
+ if (interactionSource != other.interactionSource) return false
+ if (startDragImmediately != other.startDragImmediately) return false
+ if (onDragStarted !== other.onDragStarted) return false
+ if (onDragStopped !== other.onDragStopped) return false
+ if (reverseDirection != other.reverseDirection) return false
+
+ return true
+ }
+
+ override fun hashCode(): Int {
+ var result = state.hashCode()
+ result = 31 * result + enabled.hashCode()
+ result = 31 * result + (interactionSource?.hashCode() ?: 0)
+ result = 31 * result + startDragImmediately.hashCode()
+ result = 31 * result + onDragStarted.hashCode()
+ result = 31 * result + onDragStopped.hashCode()
+ result = 31 * result + reverseDirection.hashCode()
+ return result
+ }
+
+ override fun InspectorInfo.inspectableProperties() {
+ name = "draggable2D"
+ properties["enabled"] = enabled
+ properties["interactionSource"] = interactionSource
+ properties["startDragImmediately"] = startDragImmediately
+ properties["onDragStarted"] = onDragStarted
+ properties["onDragStopped"] = onDragStopped
+ properties["reverseDirection"] = reverseDirection
+ properties["state"] = state
+ }
+
+ companion object {
+ val CanDrag: (PointerInputChange) -> Boolean = { true }
+ }
+}
+
+@OptIn(ExperimentalFoundationApi::class)
+internal class Draggable2DElement(
+ private val state: Draggable2DState,
+ private val enabled: Boolean,
+ private val interactionSource: MutableInteractionSource?,
+ private val startDragImmediately: Boolean,
+ private val onDragStarted: (startedPosition: Offset) -> Unit,
+ private val onDragStopped: (velocity: Velocity) -> Unit,
+ private val reverseDirection: Boolean
+) : ModifierNodeElement<Draggable2DNode>() {
+ override fun create(): Draggable2DNode = Draggable2DNode(
+ state,
+ CanDrag,
+ enabled,
+ interactionSource,
+ startDragImmediately,
+ reverseDirection,
+ onDragStart = onDragStarted,
+ onDragStop = onDragStopped,
+ )
+
+ override fun update(node: Draggable2DNode) {
+ node.update(
+ state,
+ CanDrag,
+ enabled,
+ interactionSource,
+ startDragImmediately,
+ reverseDirection,
+ onDragStart = onDragStarted,
+ onDragStop = onDragStopped,
)
}
@@ -222,8 +351,8 @@
if (enabled != other.enabled) return false
if (interactionSource != other.interactionSource) return false
if (startDragImmediately != other.startDragImmediately) return false
- if (onDragStarted != other.onDragStarted) return false
- if (onDragStopped != other.onDragStopped) return false
+ if (onDragStarted !== other.onDragStarted) return false
+ if (onDragStopped !== other.onDragStopped) return false
if (reverseDirection != other.reverseDirection) return false
return true
@@ -263,13 +392,20 @@
enabled: Boolean,
interactionSource: MutableInteractionSource?,
private var startDragImmediately: Boolean,
- private var onDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit,
- private var onDragStopped: suspend CoroutineScope.(velocity: Velocity) -> Unit,
- private var reverseDirection: Boolean
+ private var reverseDirection: Boolean,
+ // keeping both lambdas for compatibility
+ private var onDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit =
+ NoOpOnDragStarted,
+ private var onDragStart: (startedPosition: Offset) -> Unit =
+ NoOpOnDragStart,
+ private var onDragStopped: suspend CoroutineScope.(velocity: Velocity) -> Unit =
+ NoOpOnDragStopped,
+ private var onDragStop: (velocity: Velocity) -> Unit = NoOpOnDragStop,
) : DragGestureNode(
- canDrag,
- enabled,
- interactionSource
+ canDrag = canDrag,
+ enabled = enabled,
+ interactionSource = interactionSource,
+ orientationLock = null
) {
override suspend fun drag(
@@ -282,13 +418,15 @@
}
}
- override val pointerDirectionConfig = BidirectionalPointerDirectionConfig
+ override suspend fun CoroutineScope.onDragStarted(startedPosition: Offset) {
+ onDragStarted(this, startedPosition)
+ onDragStart.invoke(startedPosition)
+ }
- override suspend fun CoroutineScope.onDragStarted(startedPosition: Offset) =
- [email protected](this, startedPosition)
-
- override suspend fun CoroutineScope.onDragStopped(velocity: Velocity) =
- [email protected](this, velocity.reverseIfNeeded())
+ override suspend fun CoroutineScope.onDragStopped(velocity: Velocity) {
+ onDragStopped(this, velocity.reverseIfNeeded())
+ onDragStop.invoke(velocity)
+ }
override fun startDragImmediately(): Boolean = startDragImmediately
@@ -298,9 +436,13 @@
enabled: Boolean,
interactionSource: MutableInteractionSource?,
startDragImmediately: Boolean,
- onDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit,
- onDragStopped: suspend CoroutineScope.(velocity: Velocity) -> Unit,
- reverseDirection: Boolean
+ reverseDirection: Boolean,
+ onDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit =
+ this.onDragStarted,
+ onDragStopped: suspend CoroutineScope.(velocity: Velocity) -> Unit =
+ this.onDragStopped,
+ onDragStart: (startedPosition: Offset) -> Unit = this.onDragStart,
+ onDragStop: (velocity: Velocity) -> Unit = this.onDragStop,
) {
var resetPointerInputHandling = false
if (this.state != state) {
@@ -314,13 +456,16 @@
this.onDragStarted = onDragStarted
this.onDragStopped = onDragStopped
+ this.onDragStart = onDragStart
+ this.onDragStop = onDragStop
this.startDragImmediately = startDragImmediately
update(
- canDrag,
- enabled,
- interactionSource,
- resetPointerInputHandling
+ canDrag = canDrag,
+ enabled = enabled,
+ interactionSource = interactionSource,
+ orientationLock = null,
+ shouldResetPointerInputHandling = resetPointerInputHandling
)
}
@@ -349,4 +494,6 @@
}
private val NoOpOnDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit = {}
+private val NoOpOnDragStart: (startedPosition: Offset) -> Unit = {}
private val NoOpOnDragStopped: suspend CoroutineScope.(velocity: Velocity) -> Unit = {}
+private val NoOpOnDragStop: (velocity: Velocity) -> Unit = {}
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Scrollable.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Scrollable.kt
index cf62744a..bcfaf97 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Scrollable.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Scrollable.kt
@@ -273,7 +273,8 @@
) : DragGestureNode(
canDrag = CanDragCalculation,
enabled = enabled,
- interactionSource = interactionSource
+ interactionSource = interactionSource,
+ orientationLock = orientation
), ObserverModifierNode, CompositionLocalConsumerModifierNode,
FocusPropertiesModifierNode, KeyInputModifierNode {
@@ -333,9 +334,6 @@
scrollingLogic.dispatchDragEvents(forEachDelta)
}
- override val pointerDirectionConfig: PointerDirectionConfig
- get() = scrollingLogic.pointerDirectionConfig()
-
override suspend fun CoroutineScope.onDragStarted(startedPosition: Offset) {}
override suspend fun CoroutineScope.onDragStopped(velocity: Velocity) {
@@ -386,7 +384,13 @@
this.flingBehavior = flingBehavior
// update DragGestureNode
- update(CanDragCalculation, enabled, interactionSource, resetPointerInputHandling)
+ update(
+ canDrag = CanDragCalculation,
+ enabled = enabled,
+ interactionSource = interactionSource,
+ orientationLock = if (scrollingLogic.isVertical()) Vertical else Horizontal,
+ shouldResetPointerInputHandling = resetPointerInputHandling
+ )
}
override fun onAttach() {
@@ -777,8 +781,6 @@
return resetPointerInputHandling
}
- fun pointerDirectionConfig(): PointerDirectionConfig = orientation.toPointerDirectionConfig()
-
fun isVertical(): Boolean = orientation == Vertical
}
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutItemAnimator.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutItemAnimator.kt
index 0d1bb80..3a0d825 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutItemAnimator.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutItemAnimator.kt
@@ -205,6 +205,11 @@
val info = keyToItemInfoMap[key]!!
val newIndex = keyIndexMap.getIndex(key)
+ // it is possible that we are being remeasured with smaller laneCount. make sure
+ // `lane` and `span` we remembered are not larger than the new max values.
+ info.span = minOf(laneCount, info.span)
+ info.lane = minOf(laneCount - info.span, info.lane)
+
if (newIndex == -1) {
var isProgress = false
info.animations.forEachIndexed { index, animation ->
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerState.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerState.kt
index a4310c5..4f4b24e 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerState.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerState.kt
@@ -131,7 +131,7 @@
save = {
listOf(
it.currentPage,
- it.currentPageOffsetFraction,
+ (it.currentPageOffsetFraction).coerceIn(MinPageOffset, MaxPageOffset),
it.pageCount
)
},
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/TextLinkScope.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/TextLinkScope.kt
index 14af807..5d1623d 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/TextLinkScope.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/TextLinkScope.kt
@@ -182,11 +182,11 @@
// we calculate the latest style based on the link state and apply it to the
// initialText's style. This allows us to merge the style with the original instead
// of fully replacing it
- val mergedStyle = range.item.style?.merge(
+ val mergedStyle = range.item.style.mergeOrUse(
if (isFocused) range.item.focusedStyle else null
- )?.merge(
+ ).mergeOrUse(
if (isHovered) range.item.hoveredStyle else null
- )?.merge(
+ ).mergeOrUse(
if (isPressed) range.item.pressedStyle else null
)
mergedStyle?.let {
@@ -196,6 +196,8 @@
}
}
+ private fun SpanStyle?.mergeOrUse(other: SpanStyle?) = this?.merge(other) ?: other
+
private fun handleLink(
link: LinkAnnotation,
uriHandler: UriHandler
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/input/TextFieldState.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/input/TextFieldState.kt
index b3d6216..20cfe61 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/input/TextFieldState.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/input/TextFieldState.kt
@@ -112,6 +112,9 @@
internal var value: TextFieldCharSequence by mutableStateOf(
TextFieldCharSequence(initialText, initialSelection)
)
+ /**
+ * Do not set directly. Always go through [updateValueAndNotifyListeners].
+ */
private set
/**
@@ -206,9 +209,9 @@
}
/**
- * If the text or selection in [newValue] was actually modified, updates this state's internal
- * values. If [newValue] was not modified at all, the state is not updated, and this will not
- * invalidate anyone who is observing this state.
+ * If the text or selection in [newValue] was actually modified, updates this state's
+ * internal values. If [newValue] was not modified at all, the state is not updated, and
+ * this will not invalidate anyone who is observing this state.
*
* @param newValue [TextFieldBuffer] that contains the latest updates
*/
@@ -217,11 +220,16 @@
internal fun commitEdit(newValue: TextFieldBuffer) {
val textChanged = newValue.changes.changeCount > 0
val selectionChanged = newValue.selection != mainBuffer.selection
- if (textChanged || selectionChanged) {
- val finalValue = newValue.toTextFieldCharSequence()
- resetStateAndNotifyIme(finalValue)
+ if (textChanged) {
+ // clear the undo history after a programmatic edit if the text content has changed
+ textUndoManager.clearHistory()
}
- textUndoManager.clearHistory()
+ syncMainBufferToTemporaryBuffer(
+ textFieldBuffer = newValue,
+ newComposition = null, // new composition will be decided by the IME
+ textChanged = textChanged,
+ selectionChanged = selectionChanged
+ )
}
@Suppress("ShowingMemberInHiddenClass")
@@ -233,7 +241,7 @@
/**
* An edit block that updates [TextFieldState] on behalf of user actions such as gestures,
* IME commands, hardware keyboard events, clipboard actions, and more. These modifications
- * must also run through the given [filter] since they are user actions.
+ * must also run through the given [inputTransformation] since they are user actions.
*
* Be careful that this method is not snapshot aware. It is only safe to call this from main
* thread, or global snapshot. Also, this function is defined as inline for performance gains,
@@ -256,21 +264,10 @@
undoBehavior: TextFieldEditUndoBehavior = TextFieldEditUndoBehavior.MergeIfPossible,
block: EditingBuffer.() -> Unit
) {
- val previousValue = value
-
mainBuffer.changeTracker.clearChanges()
mainBuffer.block()
- if (mainBuffer.changeTracker.changeCount == 0 &&
- previousValue.selection == mainBuffer.selection &&
- previousValue.composition == mainBuffer.composition &&
- previousValue.highlight == mainBuffer.highlight) {
- // nothing has changed after applying block.
- return
- }
-
commitEditAsUser(
- previousValue = previousValue,
inputTransformation = inputTransformation,
restartImeIfContentChanges = restartImeIfContentChanges,
undoBehavior = undoBehavior
@@ -288,8 +285,6 @@
* a public API.
*/
internal inline fun editWithNoSideEffects(block: EditingBuffer.() -> Unit) {
- val previousValue = value
-
mainBuffer.changeTracker.clearChanges()
mainBuffer.block()
@@ -299,20 +294,49 @@
composition = mainBuffer.composition
)
- value = afterEditValue
- sendChangesToIme(
- oldValue = previousValue,
+ updateValueAndNotifyListeners(
+ oldValue = value,
newValue = afterEditValue,
restartImeIfContentChanges = true
)
}
+ // Do not inline this function into editAsUser. Inline functions should be kept short.
private fun commitEditAsUser(
- previousValue: TextFieldCharSequence,
inputTransformation: InputTransformation?,
- restartImeIfContentChanges: Boolean,
- undoBehavior: TextFieldEditUndoBehavior
+ restartImeIfContentChanges: Boolean = true,
+ undoBehavior: TextFieldEditUndoBehavior = TextFieldEditUndoBehavior.MergeIfPossible,
) {
+ val beforeEditValue = value
+
+ // first immediately check whether there's any actual change of content or selection.
+ // We only look at the operation count for content change because inputTransformation
+ // should still run even if text doesn't change as a result of an input.
+ // If there is no change at all, or only composition or highlight has changed, we can end
+ // early.
+ if (mainBuffer.changeTracker.changeCount == 0 &&
+ beforeEditValue.selection == mainBuffer.selection) {
+ if (beforeEditValue.composition != mainBuffer.composition ||
+ beforeEditValue.highlight != mainBuffer.highlight) {
+ // edit operation caused no change to text content or selection
+ // No need to run an existing InputTransformation, or record an undo. Only update
+ // the IME that composition has been accepted.
+ updateValueAndNotifyListeners(
+ oldValue = value,
+ newValue = TextFieldCharSequence(
+ text = mainBuffer.toString(),
+ selection = mainBuffer.selection,
+ composition = mainBuffer.composition,
+ highlight = mainBuffer.highlight
+ ),
+ restartImeIfContentChanges = restartImeIfContentChanges
+ )
+ }
+ return
+ }
+
+ // There's a meaningful change to the buffer, let's run the full logic.
+ // first take a _snapshot_ of current state of the mainBuffer after changes are applied.
val afterEditValue = TextFieldCharSequence(
text = mainBuffer.toString(),
selection = mainBuffer.selection,
@@ -320,56 +344,92 @@
highlight = mainBuffer.highlight
)
+ // if there's no filter; just record the undo, update the snapshot value, end.
if (inputTransformation == null) {
- val oldValue = value
- value = afterEditValue
- sendChangesToIme(
- oldValue = oldValue,
+ updateValueAndNotifyListeners(
+ oldValue = beforeEditValue,
newValue = afterEditValue,
restartImeIfContentChanges = restartImeIfContentChanges
)
- recordEditForUndo(previousValue, value, mainBuffer.changeTracker, undoBehavior)
- return
- }
-
- val oldValue = value
-
- // if only difference is composition, don't run filter, don't send it to undo manager
- if (afterEditValue.contentEquals(oldValue) &&
- afterEditValue.selection == oldValue.selection
- ) {
- value = afterEditValue
- sendChangesToIme(
- oldValue = oldValue,
- newValue = afterEditValue,
- restartImeIfContentChanges = restartImeIfContentChanges
+ recordEditForUndo(
+ previousValue = beforeEditValue,
+ postValue = afterEditValue,
+ changes = mainBuffer.changeTracker,
+ undoBehavior = undoBehavior
)
return
}
+ // Prepare a TextFieldBuffer to run InputTransformation. TextFieldBuffer should be
+ // initialized with the edits that are already applied on mainBuffer, hence the difference
+ // between originalValue and initialValue.
val textFieldBuffer = TextFieldBuffer(
+ originalValue = beforeEditValue,
initialValue = afterEditValue,
- originalValue = oldValue,
initialChanges = mainBuffer.changeTracker
)
+
+ // apply the inputTransformation.
with(inputTransformation) { textFieldBuffer.transformInput() }
- // If neither the text nor the selection changed, we want to preserve the composition.
- // Otherwise, the IME will reset it anyway.
- val afterFilterValue = textFieldBuffer.toTextFieldCharSequence(
- composition = afterEditValue.composition
- )
- if (afterFilterValue == afterEditValue) {
- value = afterFilterValue
- sendChangesToIme(
- oldValue = oldValue,
- newValue = afterEditValue,
- restartImeIfContentChanges = restartImeIfContentChanges
+
+ val textChangedByFilter = !textFieldBuffer.asCharSequence().contentEquals(afterEditValue)
+ val selectionChangedByFilter = textFieldBuffer.selection != afterEditValue.selection
+ if (textChangedByFilter || selectionChangedByFilter) {
+ syncMainBufferToTemporaryBuffer(
+ textFieldBuffer = textFieldBuffer,
+ newComposition = afterEditValue.composition,
+ textChanged = textChangedByFilter,
+ selectionChanged = selectionChangedByFilter
)
} else {
- resetStateAndNotifyIme(afterFilterValue)
+ updateValueAndNotifyListeners(
+ oldValue = beforeEditValue,
+ // If neither the text nor the selection changed by the filter, we want to preserve
+ // the composition. Otherwise, the IME will reset it anyway.
+ newValue = textFieldBuffer.toTextFieldCharSequence(
+ composition = afterEditValue.composition
+ ),
+ restartImeIfContentChanges = restartImeIfContentChanges
+ )
}
- // mutableValue contains all the changes from user and the filter.
- recordEditForUndo(previousValue, value, textFieldBuffer.changes, undoBehavior)
+ // textFieldBuffer contains all the changes from both the user and the filter.
+ recordEditForUndo(
+ previousValue = beforeEditValue,
+ postValue = value,
+ changes = textFieldBuffer.changes,
+ undoBehavior = undoBehavior
+ )
+ }
+
+ /**
+ * There are 3 types of edits that are defined on [TextFieldState];
+ * 1. Programmatic changes that are created by [edit] function,
+ * 2. User edits coming from the system that are initiated through IME, semantics, or gestures
+ * 3. Applying Undo/Redo actions that should not trigger side effects.
+ *
+ * Eventually all changes, no matter the source, should be committed to [value]. Also, they
+ * have to trigger the content change listeners. However, we have two different buffers called
+ * [EditingBuffer] and [TextFieldBuffer]. All developer facing APIs use [TextFieldBuffer] to
+ * change the state but internal ones use [EditingBuffer]. This function consolidates both
+ * forms of updates, then commits the result to [value].
+ *
+ * Finally notifies the listeners in [notifyImeListeners] that the contents of this
+ * [TextFieldState] has changed.
+ */
+ private fun updateValueAndNotifyListeners(
+ oldValue: TextFieldCharSequence,
+ newValue: TextFieldCharSequence,
+ restartImeIfContentChanges: Boolean
+ ) {
+ // value must be set before notifyImeListeners are called. Even though we are sending the
+ // previous and current values, a system callback may request the latest state e.g. IME
+ // restartInput call is handled before notifyImeListeners return.
+ value = newValue
+ finishEditing()
+
+ notifyImeListeners.forEach {
+ it.onChange(oldValue, newValue, restartImeIfContentChanges)
+ }
}
/**
@@ -440,41 +500,50 @@
}
/**
- * Must be called whenever [text] needs to change but the content of the changes are not yet
- * replicated on [mainBuffer].
+ * Carries changes made to a [TextFieldBuffer] into [mainBuffer], then updates the [value].
+ * This usually happens when the edit source is something programmatic like [edit] or
+ * [InputTransformation]. IME commands are applied directly on [mainBuffer].
*
- * This method updates the internal editing buffer with the given [TextFieldCharSequence], it
- * also notifies the IME about the selection or composition changes.
+ * @param textFieldBuffer Source buffer that will be used to sync the mainBuffer.
+ * @param newComposition TextFieldBuffer does not allow changing composition. This parameter
+ * is an opportunity to decide what the mainBuffer's new composition should be.
+ * @param textChanged Whether the text content inside [textFieldBuffer] is different than
+ * [mainBuffer]'s text content. Although this value can be calculated by this function, some
+ * callers already do the comparison before hand, so there's no need to recalculate it.
+ * @param selectionChanged Whether the selection inside [textFieldBuffer] is different than
+ * [mainBuffer]'s selection.
*/
@VisibleForTesting
- internal fun resetStateAndNotifyIme(newValue: TextFieldCharSequence) {
+ internal fun syncMainBufferToTemporaryBuffer(
+ textFieldBuffer: TextFieldBuffer,
+ newComposition: TextRange?,
+ textChanged: Boolean,
+ selectionChanged: Boolean
+ ) {
+ val bufferString = mainBuffer.toString()
+
val bufferState = TextFieldCharSequence(
- mainBuffer.toString(),
+ bufferString,
mainBuffer.selection,
mainBuffer.composition
)
- var textChanged = false
- var selectionChanged = false
- val compositionChanged = newValue.composition != mainBuffer.composition
+ val compositionChanged = newComposition != mainBuffer.composition
- if (!bufferState.contentEquals(newValue)) {
+ if (textChanged) {
// reset the buffer in its entirety
mainBuffer = EditingBuffer(
- text = newValue.toString(),
- selection = newValue.selection
+ text = textFieldBuffer.toString(),
+ selection = textFieldBuffer.selection
)
- textChanged = true
- } else if (bufferState.selection != newValue.selection) {
- mainBuffer.setSelection(newValue.selection.start, newValue.selection.end)
- selectionChanged = true
+ } else if (selectionChanged) {
+ mainBuffer.setSelection(textFieldBuffer.selection.start, textFieldBuffer.selection.end)
}
- val composition = newValue.composition
- if (composition == null || composition.collapsed) {
+ if (newComposition == null || newComposition.collapsed) {
mainBuffer.commitComposition()
} else {
- mainBuffer.setComposition(composition.min, composition.max)
+ mainBuffer.setComposition(newComposition.min, newComposition.max)
}
if (textChanged || (!selectionChanged && compositionChanged)) {
@@ -482,17 +551,16 @@
}
val finalValue = TextFieldCharSequence(
- text = if (textChanged) newValue else bufferState,
+ text = if (textChanged) textFieldBuffer.toString() else bufferString,
selection = mainBuffer.selection,
composition = mainBuffer.composition
)
- // value must be set before notifyImeListeners are called. Even though we are sending the
- // previous and current values, a system callback may request the latest state e.g. IME
- // restartInput call is handled before notifyImeListeners return.
- value = finalValue
-
- sendChangesToIme(
+ // We cannot use `value` as the old value here because intermediate IME changes are only
+ // applied on mainBuffer (this only happens if syncMainBufferToTemporaryBuffer is triggered
+ // after an InputTransformation). We must pass in the latest state just before finalValue is
+ // calculated. This is the state IME knows about and is synced with.
+ updateValueAndNotifyListeners(
oldValue = bufferState,
newValue = finalValue,
restartImeIfContentChanges = true
@@ -502,19 +570,6 @@
private val notifyImeListeners = mutableVectorOf<NotifyImeListener>()
/**
- * Sends an update to the IME depending on .
- */
- private fun sendChangesToIme(
- oldValue: TextFieldCharSequence,
- newValue: TextFieldCharSequence,
- restartImeIfContentChanges: Boolean
- ) {
- notifyImeListeners.forEach {
- it.onChange(oldValue, newValue, restartImeIfContentChanges)
- }
- }
-
- /**
* Saves and restores a [TextFieldState] for [rememberSaveable].
*
* @see rememberTextFieldState
diff --git a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/AccessibilityNodeInspector.kt b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/AccessibilityNodeInspector.kt
index 4c04bf5..5e7b574 100644
--- a/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/AccessibilityNodeInspector.kt
+++ b/compose/integration-tests/demos/src/main/java/androidx/compose/integration/demos/AccessibilityNodeInspector.kt
@@ -42,6 +42,7 @@
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentSize
@@ -64,6 +65,7 @@
import androidx.compose.material.icons.filled.ArrowDropDown
import androidx.compose.material.icons.filled.Info
import androidx.compose.material.lightColors
+import androidx.compose.material.primarySurface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
@@ -479,9 +481,7 @@
NodeProperties(
node = leafNode,
onNodeClick = onNodeClick,
- modifier = Modifier
- .verticalScroll(rememberScrollState())
- .padding(16.dp)
+ modifier = Modifier.verticalScroll(rememberScrollState())
)
}
}
@@ -513,7 +513,7 @@
modifier: Modifier
) {
SelectionContainer {
- Column(modifier = modifier, verticalArrangement = spacedBy(8.dp)) {
+ Column(modifier = modifier) {
NodeAncestorLinks(node, onNodeClick)
val properties = node.getProperties()
@@ -530,7 +530,10 @@
}
}
.toList()
- KeyValueView(elements = properties)
+ KeyValueView(
+ elements = properties,
+ modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
+ )
}
}
}
@@ -552,7 +555,13 @@
}
}
}
- Text(ancestorLinks)
+
+ Surface(
+ color = MaterialTheme.colors.primarySurface.copy(alpha = 0.5f),
+ modifier = Modifier.fillMaxWidth(),
+ ) {
+ Text(ancestorLinks, modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp))
+ }
}
}
@@ -571,8 +580,14 @@
* Shows a table of keys and their values. Values are rendered using [PropertyValueRepresentation].
*/
@Composable
-private fun KeyValueView(elements: List<Pair<String, PropertyValueRepresentation>>) {
- Column(verticalArrangement = spacedBy(8.dp)) {
+private fun KeyValueView(
+ elements: List<Pair<String, PropertyValueRepresentation>>,
+ modifier: Modifier = Modifier,
+) {
+ Column(
+ modifier = modifier,
+ verticalArrangement = spacedBy(8.dp)
+ ) {
elements.forEach { (name, valueRepresentation) ->
KeyValueRow(name, valueRepresentation)
}
diff --git a/compose/material/material/api/current.txt b/compose/material/material/api/current.txt
index 004b759..08e7c46 100644
--- a/compose/material/material/api/current.txt
+++ b/compose/material/material/api/current.txt
@@ -886,9 +886,8 @@
}
public final class TextDefaults {
- method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.ui.text.LinkAnnotation.Clickable Clickable(String tag, optional androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle, androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener);
- method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.ui.text.LinkAnnotation.Url Url(String url, optional androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle, optional androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener);
- method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.ui.text.AnnotatedString fromHtml(String htmlString, optional androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle, optional androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener);
+ method @androidx.compose.runtime.Composable public androidx.compose.material.TextLinkStyles linkStyles();
+ method @androidx.compose.runtime.Composable public androidx.compose.material.TextLinkStyles linkStyles(optional androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle);
field public static final androidx.compose.material.TextDefaults INSTANCE;
}
@@ -947,7 +946,8 @@
public final class TextKt {
method @androidx.compose.runtime.Composable public static void ProvideTextStyle(androidx.compose.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> content);
- method @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+ method @Deprecated @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+ method @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style, optional androidx.compose.material.TextLinkStyles linkStyles);
method @Deprecated @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
method @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit>? onTextLayout, optional androidx.compose.ui.text.TextStyle style);
method @Deprecated @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
@@ -955,6 +955,19 @@
property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> LocalTextStyle;
}
+ @androidx.compose.runtime.Immutable public final class TextLinkStyles {
+ ctor public TextLinkStyles(androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle);
+ method public androidx.compose.material.TextLinkStyles copy(optional androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle);
+ method public androidx.compose.ui.text.SpanStyle? getLinkFocusedStyle();
+ method public androidx.compose.ui.text.SpanStyle? getLinkHoveredStyle();
+ method public androidx.compose.ui.text.SpanStyle? getLinkPressedStyle();
+ method public androidx.compose.ui.text.SpanStyle? getLinkStyle();
+ property public final androidx.compose.ui.text.SpanStyle? linkFocusedStyle;
+ property public final androidx.compose.ui.text.SpanStyle? linkHoveredStyle;
+ property public final androidx.compose.ui.text.SpanStyle? linkPressedStyle;
+ property public final androidx.compose.ui.text.SpanStyle? linkStyle;
+ }
+
@Deprecated @SuppressCompatibility @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Stable public interface ThresholdConfig {
method @Deprecated public float computeThreshold(androidx.compose.ui.unit.Density, float fromValue, float toValue);
}
diff --git a/compose/material/material/api/restricted_current.txt b/compose/material/material/api/restricted_current.txt
index 004b759..08e7c46 100644
--- a/compose/material/material/api/restricted_current.txt
+++ b/compose/material/material/api/restricted_current.txt
@@ -886,9 +886,8 @@
}
public final class TextDefaults {
- method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.ui.text.LinkAnnotation.Clickable Clickable(String tag, optional androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle, androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener);
- method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.ui.text.LinkAnnotation.Url Url(String url, optional androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle, optional androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener);
- method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.ui.text.AnnotatedString fromHtml(String htmlString, optional androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle, optional androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener);
+ method @androidx.compose.runtime.Composable public androidx.compose.material.TextLinkStyles linkStyles();
+ method @androidx.compose.runtime.Composable public androidx.compose.material.TextLinkStyles linkStyles(optional androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle);
field public static final androidx.compose.material.TextDefaults INSTANCE;
}
@@ -947,7 +946,8 @@
public final class TextKt {
method @androidx.compose.runtime.Composable public static void ProvideTextStyle(androidx.compose.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> content);
- method @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+ method @Deprecated @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+ method @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style, optional androidx.compose.material.TextLinkStyles linkStyles);
method @Deprecated @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
method @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit>? onTextLayout, optional androidx.compose.ui.text.TextStyle style);
method @Deprecated @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
@@ -955,6 +955,19 @@
property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> LocalTextStyle;
}
+ @androidx.compose.runtime.Immutable public final class TextLinkStyles {
+ ctor public TextLinkStyles(androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle);
+ method public androidx.compose.material.TextLinkStyles copy(optional androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle);
+ method public androidx.compose.ui.text.SpanStyle? getLinkFocusedStyle();
+ method public androidx.compose.ui.text.SpanStyle? getLinkHoveredStyle();
+ method public androidx.compose.ui.text.SpanStyle? getLinkPressedStyle();
+ method public androidx.compose.ui.text.SpanStyle? getLinkStyle();
+ property public final androidx.compose.ui.text.SpanStyle? linkFocusedStyle;
+ property public final androidx.compose.ui.text.SpanStyle? linkHoveredStyle;
+ property public final androidx.compose.ui.text.SpanStyle? linkPressedStyle;
+ property public final androidx.compose.ui.text.SpanStyle? linkStyle;
+ }
+
@Deprecated @SuppressCompatibility @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Stable public interface ThresholdConfig {
method @Deprecated public float computeThreshold(androidx.compose.ui.unit.Density, float fromValue, float toValue);
}
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/TextSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/TextSamples.kt
index 7d5c9ee..1b126c7 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/TextSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/TextSamples.kt
@@ -18,8 +18,8 @@
import androidx.annotation.Sampled
import androidx.compose.material.Text
-import androidx.compose.material.TextDefaults
import androidx.compose.runtime.Composable
+import androidx.compose.ui.text.LinkAnnotation
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.withLink
@@ -28,7 +28,7 @@
fun AnnotatedStringWithLinks() {
Text(buildAnnotatedString {
append("Build better apps faster with ")
- withLink(TextDefaults.Url(url = "https://developer.android.com/jetpack/compose")) {
+ withLink(LinkAnnotation.Url(url = "https://developer.android.com/jetpack/compose")) {
append("Jetpack Compose")
}
})
diff --git a/compose/material/material/src/androidInstrumentedTest/kotlin/androidx/compose/material/TextTest.kt b/compose/material/material/src/androidInstrumentedTest/kotlin/androidx/compose/material/TextTest.kt
index 9b8e5a3..2299680 100644
--- a/compose/material/material/src/androidInstrumentedTest/kotlin/androidx/compose/material/TextTest.kt
+++ b/compose/material/material/src/androidInstrumentedTest/kotlin/androidx/compose/material/TextTest.kt
@@ -20,6 +20,7 @@
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.testutils.assertContainsColor
+import androidx.compose.testutils.assertDoesNotContainColor
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.testTag
@@ -34,10 +35,14 @@
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performSemanticsAction
+import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.LinkAnnotation
+import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontStyle
+import androidx.compose.ui.text.fromHtml
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.em
@@ -292,7 +297,7 @@
var primary: Color? = null
rule.setMaterialContent {
primary = MaterialTheme.colors.primary
- Text(TextDefaults.fromHtml("<a href=url>link</a>"))
+ Text(AnnotatedString.fromHtml("<a href=url>link</a>"))
}
rule.runOnIdle {
@@ -305,13 +310,59 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@Test
+ fun fromHtml_links_materialThemeRespectsStyleInLinkAnnotation() {
+ var primary: Color? = null
+ rule.setMaterialContent {
+ primary = MaterialTheme.colors.primary
+ Text(
+ AnnotatedString.fromHtml(
+ "<a href=url>link</a>",
+ linkStyle = SpanStyle(color = Color.Green)
+ )
+ )
+ }
+
+ rule.runOnIdle {
+ assertThat(primary).isNotNull()
+ }
+ rule.onNode(hasClickAction(), useUnmergedTree = true)
+ .captureToImage()
+ .assertContainsColor(Color.Green)
+ .assertDoesNotContainColor(primary!!)
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+ @Test
+ fun fromHtml_links_materialThemeMergedIntoStyleInLinkAnnotation() {
+ var primary: Color? = null
+ rule.setMaterialContent {
+ primary = MaterialTheme.colors.primary
+ Text(
+ AnnotatedString.fromHtml(
+ "<a href=url>link</a>",
+ linkStyle = SpanStyle(background = Color.Green)
+ )
+ )
+ }
+
+ rule.runOnIdle {
+ assertThat(primary).isNotNull()
+ }
+ rule.onNode(hasClickAction(), useUnmergedTree = true)
+ .captureToImage()
+ .assertContainsColor(Color.Green)
+ .assertContainsColor(primary!!)
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+ @Test
fun links_getColorFromMaterialTheme() {
var primary: Color? = null
rule.setMaterialContent {
primary = MaterialTheme.colors.primary
Text(buildAnnotatedString {
append("link")
- addLink(TextDefaults.Url(url = "url"), 0, 4)
+ addLink(LinkAnnotation.Url(url = "url"), 0, 4)
})
}
@@ -322,4 +373,46 @@
.captureToImage()
.assertContainsColor(primary!!)
}
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+ @Test
+ fun links_materialThemeRespectsStyleInLinkAnnotation() {
+ var primary: Color? = null
+ rule.setMaterialContent {
+ primary = MaterialTheme.colors.primary
+ Text(buildAnnotatedString {
+ append("link")
+ addLink(LinkAnnotation.Url(url = "url", SpanStyle(color = Color.Green)), 0, 4)
+ })
+ }
+
+ rule.runOnIdle {
+ assertThat(primary).isNotNull()
+ }
+ rule.onNode(hasClickAction(), useUnmergedTree = true)
+ .captureToImage()
+ .assertContainsColor(Color.Green)
+ .assertDoesNotContainColor(primary!!)
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+ @Test
+ fun links_materialThemeMergedIntoStyleInLinkAnnotation() {
+ var primary: Color? = null
+ rule.setMaterialContent {
+ primary = MaterialTheme.colors.primary
+ Text(buildAnnotatedString {
+ append("link")
+ addLink(LinkAnnotation.Url(url = "url", SpanStyle(background = Color.Green)), 0, 4)
+ })
+ }
+
+ rule.runOnIdle {
+ assertThat(primary).isNotNull()
+ }
+ rule.onNode(hasClickAction(), useUnmergedTree = true)
+ .captureToImage()
+ .assertContainsColor(primary!!)
+ .assertContainsColor(Color.Green)
+ }
}
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Colors.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Colors.kt
index cd270e8..cb90062 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Colors.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Colors.kt
@@ -156,6 +156,8 @@
"isLight=$isLight" +
")"
}
+
+ internal var defaultTextLinkStylesCached: TextLinkStyles? = null
}
/**
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Text.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Text.kt
index 98563bf..5d2209b 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Text.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Text.kt
@@ -20,7 +20,7 @@
import androidx.compose.foundation.text.InlineTextContent
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.ReadOnlyComposable
+import androidx.compose.runtime.Immutable
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.structuralEqualityPolicy
import androidx.compose.ui.Modifier
@@ -28,7 +28,6 @@
import androidx.compose.ui.graphics.isSpecified
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.LinkAnnotation
-import androidx.compose.ui.text.LinkInteractionListener
import androidx.compose.ui.text.Paragraph
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.TextLayoutResult
@@ -36,11 +35,11 @@
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.text.fromHtml
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.TextUnit
+import androidx.compose.ui.util.fastForEach
/**
* High level element that displays text and provides semantics / accessibility information.
@@ -260,6 +259,13 @@
* text, baselines and other details. The callback can be used to add additional decoration or
* functionality to the text. For example, to draw selection around the text.
* @param style Style configuration for the text such as color, font, line height etc.
+ * @param linkStyles Configures styles for the links in different states which are present in text
+ * as [androidx.compose.ui.text.LinkAnnotation] annotations. This object passes the styles directly
+ * to the link annotations. If you style the [text] either using the [SpanStyle] annotations or
+ * via the parameters from this composable like [color], [style] and others, the [linkStyles] will
+ * override them for links
+ *
+ * @sample androidx.compose.material.samples.AnnotatedStringWithLinks
*/
@Composable
fun Text(
@@ -280,7 +286,8 @@
minLines: Int = 1,
inlineContent: Map<String, InlineTextContent> = mapOf(),
onTextLayout: (TextLayoutResult) -> Unit = {},
- style: TextStyle = LocalTextStyle.current
+ style: TextStyle = LocalTextStyle.current,
+ linkStyles: TextLinkStyles = TextDefaults.linkStyles()
) {
// TL:DR: profile before you change any line of code in this method
//
@@ -310,7 +317,7 @@
}
BasicText(
- text = text,
+ text = textWithLinkStyles(text, linkStyles),
modifier = modifier,
style = style.merge(
fontSize = fontSize,
@@ -333,6 +340,53 @@
}
@Deprecated(
+ "Maintained for binary compatibility. Use version with a textLinkStyles instead",
+ level = DeprecationLevel.HIDDEN
+)
+@Composable
+fun Text(
+ text: AnnotatedString,
+ modifier: Modifier = Modifier,
+ color: Color = Color.Unspecified,
+ fontSize: TextUnit = TextUnit.Unspecified,
+ fontStyle: FontStyle? = null,
+ fontWeight: FontWeight? = null,
+ fontFamily: FontFamily? = null,
+ letterSpacing: TextUnit = TextUnit.Unspecified,
+ textDecoration: TextDecoration? = null,
+ textAlign: TextAlign? = null,
+ lineHeight: TextUnit = TextUnit.Unspecified,
+ overflow: TextOverflow = TextOverflow.Clip,
+ softWrap: Boolean = true,
+ maxLines: Int = Int.MAX_VALUE,
+ minLines: Int = 1,
+ inlineContent: Map<String, InlineTextContent> = mapOf(),
+ onTextLayout: (TextLayoutResult) -> Unit = {},
+ style: TextStyle = LocalTextStyle.current
+) {
+ Text(
+ text,
+ modifier,
+ color,
+ fontSize,
+ fontStyle,
+ fontWeight,
+ fontFamily,
+ letterSpacing,
+ textDecoration,
+ textAlign,
+ lineHeight,
+ overflow,
+ softWrap,
+ maxLines,
+ minLines,
+ inlineContent,
+ onTextLayout,
+ style
+ )
+}
+
+@Deprecated(
"Maintained for binary compatibility. Use version with minLines instead",
level = DeprecationLevel.HIDDEN
)
@@ -403,93 +457,114 @@
/** Contains the methods to be used by [Text] */
object TextDefaults {
- /**
- * Converts a string with HTML tags into [AnnotatedString]. Applies default styling from the
- * [MaterialTheme] to links present in the [htmlString].
- *
- * Check [androidx.compose.ui.text.AnnotatedString.Companion.fromHtml] for more details on
- * supported tags and usage.
- *
- * @param htmlString HTML-tagged string to be parsed to construct AnnotatedString
- * @param linkStyle style to be applied to links present in the string
- * @param linkFocusedStyle style to be applied to links present in the string when they are
- * focused
- * @param linkHoveredStyle style to be applied to links present in the string when they are
- * hovered
- * @param linkPressedStyle style to be applied to links present in the string when they are
- * pressed
- * @param linkInteractionListener a listener that will be attached to links that are present in
- * the string and triggered when user clicks on those links. When set to null, which is
- * a default, the system will try to open the corresponding links with the
- * [androidx.compose.ui.platform.UriHandler] composition local
- *
- * @see androidx.compose.ui.text.AnnotatedString.Companion.fromHtml
- */
- @Composable
- @ReadOnlyComposable
- fun fromHtml(
- htmlString: String,
- linkStyle: SpanStyle? = SpanStyle(color = MaterialTheme.colors.primary),
- linkFocusedStyle: SpanStyle? = null,
- linkHoveredStyle: SpanStyle? = null,
- linkPressedStyle: SpanStyle? = null,
- linkInteractionListener: LinkInteractionListener? = null
- ): AnnotatedString {
- return AnnotatedString.fromHtml(
- htmlString,
- linkStyle,
- linkFocusedStyle,
- linkHoveredStyle,
- linkPressedStyle,
- linkInteractionListener
- )
- }
/**
- * Constructs a [LinkAnnotation.Url] and applies default styling from the [MaterialTheme]
- *
- * @sample androidx.compose.material.samples.AnnotatedStringWithLinks
+ * Creates a [TextLinkStyles] that are used to style the links present in the text
*/
@Composable
- @ReadOnlyComposable
- fun Url(
- url: String,
- linkStyle: SpanStyle? = SpanStyle(color = MaterialTheme.colors.primary),
- linkFocusedStyle: SpanStyle? = null,
- linkHoveredStyle: SpanStyle? = null,
- linkPressedStyle: SpanStyle? = null,
- linkInteractionListener: LinkInteractionListener? = null
- ): LinkAnnotation.Url {
- return LinkAnnotation.Url(
- url,
- linkStyle,
- linkFocusedStyle,
- linkHoveredStyle,
- linkPressedStyle,
- linkInteractionListener
- )
- }
+ fun linkStyles(): TextLinkStyles = MaterialTheme.colors.defaultTextLinkStyles
/**
- * Constructs a [LinkAnnotation.Clickable] and applies default styling from the [MaterialTheme]
+ * Creates a [TextLinkStyles] that are used to style the links present in the text based on
+ * their state
+ *
+ * @see LinkAnnotation
*/
@Composable
- @ReadOnlyComposable
- fun Clickable(
- tag: String,
- linkStyle: SpanStyle? = SpanStyle(color = MaterialTheme.colors.primary),
+ fun linkStyles(
+ linkStyle: SpanStyle? = null,
linkFocusedStyle: SpanStyle? = null,
linkHoveredStyle: SpanStyle? = null,
- linkPressedStyle: SpanStyle? = null,
- linkInteractionListener: LinkInteractionListener?
- ): LinkAnnotation.Clickable {
- return LinkAnnotation.Clickable(
- tag,
- linkStyle,
- linkFocusedStyle,
- linkHoveredStyle,
- linkPressedStyle,
- linkInteractionListener
- )
+ linkPressedStyle: SpanStyle? = null
+ ): TextLinkStyles = MaterialTheme.colors.defaultTextLinkStyles.copy(
+ linkStyle, linkFocusedStyle, linkHoveredStyle, linkPressedStyle
+ )
+
+ private val Colors.defaultTextLinkStyles: TextLinkStyles
+ get() {
+ return defaultTextLinkStylesCached ?: TextLinkStyles(
+ linkStyle = SpanStyle(color = primary)
+ ).also {
+ defaultTextLinkStylesCached = it
+ }
+ }
+}
+
+/**
+ * Represents the styles of the links in the Text in different states
+ *
+ * @param linkStyle style to be applied to links present in the string
+ * @param linkFocusedStyle style to be applied to links present in the string when they are
+ * focused
+ * @param linkHoveredStyle style to be applied to links present in the string when they are
+ * hovered
+ * @param linkPressedStyle style to be applied to links present in the string when they are
+ * pressed
+ */
+@Immutable
+class TextLinkStyles(
+ val linkStyle: SpanStyle?,
+ val linkFocusedStyle: SpanStyle? = null,
+ val linkHoveredStyle: SpanStyle? = null,
+ val linkPressedStyle: SpanStyle? = null
+) {
+ /**
+ * Returns a copy of this TextLinkStyles, optionally overriding some of the values.
+ * This uses the null to mean “use the value from the source”
+ */
+ fun copy(
+ linkStyle: SpanStyle? = this.linkStyle,
+ linkFocusedStyle: SpanStyle? = this.linkFocusedStyle,
+ linkHoveredStyle: SpanStyle? = this.linkHoveredStyle,
+ linkPressedStyle: SpanStyle? = this.linkPressedStyle
+ ) = TextLinkStyles(
+ linkStyle ?: this.linkStyle,
+ linkFocusedStyle ?: this.linkFocusedStyle,
+ linkHoveredStyle ?: this.linkHoveredStyle,
+ linkPressedStyle ?: this.linkPressedStyle
+ )
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (other == null || other !is TextLinkStyles) return false
+
+ if (linkStyle != other.linkStyle) return false
+ if (linkFocusedStyle != other.linkFocusedStyle) return false
+ if (linkHoveredStyle != other.linkHoveredStyle) return false
+ if (linkPressedStyle != other.linkPressedStyle) return false
+
+ return true
}
+
+ override fun hashCode(): Int {
+ var result = linkStyle?.hashCode() ?: 0
+ result = 31 * result + (linkFocusedStyle?.hashCode() ?: 0)
+ result = 31 * result + (linkHoveredStyle?.hashCode() ?: 0)
+ result = 31 * result + (linkPressedStyle?.hashCode() ?: 0)
+ return result
+ }
+}
+
+/**
+ * Replaces all link annotations in the AnnotatedString with the new link annotations the styles of
+ * which are merged with the Material styling.
+ *
+ * If the [text]'s link annotation has a style defined in the annotation, Material theming will
+ * not fully override it but apply on top the _missing_ fields.
+*/
+private fun textWithLinkStyles(text: AnnotatedString, linkStyles: TextLinkStyles): AnnotatedString {
+ val links = text.getLinkAnnotations(0, text.length)
+ if (links.isEmpty()) return text
+
+ val builder = AnnotatedString.Builder(text)
+ links.fastForEach {
+ val styledLink = it.item.withDefaultsFrom(
+ linkStyles.linkStyle,
+ linkStyles.linkFocusedStyle,
+ linkStyles.linkHoveredStyle,
+ linkStyles.linkPressedStyle
+ )
+ builder.replace(it, styledLink)
+ }
+ return builder.toAnnotatedString()
}
diff --git a/compose/material3/material3/api/current.txt b/compose/material3/material3/api/current.txt
index 83a3415..1083ae8 100644
--- a/compose/material3/material3/api/current.txt
+++ b/compose/material3/material3/api/current.txt
@@ -1774,9 +1774,8 @@
}
public final class TextDefaults {
- method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.ui.text.LinkAnnotation.Clickable Clickable(String tag, optional androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle, androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener);
- method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.ui.text.LinkAnnotation.Url Url(String url, optional androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle, optional androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener);
- method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.ui.text.AnnotatedString fromHtml(String htmlString, optional androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle, optional androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener);
+ method @androidx.compose.runtime.Composable public androidx.compose.material3.TextLinkStyles linkStyles();
+ method @androidx.compose.runtime.Composable public androidx.compose.material3.TextLinkStyles linkStyles(optional androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle);
field public static final androidx.compose.material3.TextDefaults INSTANCE;
}
@@ -1911,7 +1910,8 @@
public final class TextKt {
method @androidx.compose.runtime.Composable public static void ProvideTextStyle(androidx.compose.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> content);
- method @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+ method @Deprecated @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+ method @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style, optional androidx.compose.material3.TextLinkStyles linkStyles);
method @Deprecated @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
method @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit>? onTextLayout, optional androidx.compose.ui.text.TextStyle style);
method @Deprecated @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
@@ -1919,6 +1919,19 @@
property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> LocalTextStyle;
}
+ @androidx.compose.runtime.Immutable public final class TextLinkStyles {
+ ctor public TextLinkStyles(androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle);
+ method public androidx.compose.material3.TextLinkStyles copy(optional androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle);
+ method public androidx.compose.ui.text.SpanStyle? getLinkFocusedStyle();
+ method public androidx.compose.ui.text.SpanStyle? getLinkHoveredStyle();
+ method public androidx.compose.ui.text.SpanStyle? getLinkPressedStyle();
+ method public androidx.compose.ui.text.SpanStyle? getLinkStyle();
+ property public final androidx.compose.ui.text.SpanStyle? linkFocusedStyle;
+ property public final androidx.compose.ui.text.SpanStyle? linkHoveredStyle;
+ property public final androidx.compose.ui.text.SpanStyle? linkPressedStyle;
+ property public final androidx.compose.ui.text.SpanStyle? linkStyle;
+ }
+
@SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Immutable public final class TimePickerColors {
ctor public TimePickerColors(long clockDialColor, long selectorColor, long containerColor, long periodSelectorBorderColor, long clockDialSelectedContentColor, long clockDialUnselectedContentColor, long periodSelectorSelectedContainerColor, long periodSelectorUnselectedContainerColor, long periodSelectorSelectedContentColor, long periodSelectorUnselectedContentColor, long timeSelectorSelectedContainerColor, long timeSelectorUnselectedContainerColor, long timeSelectorSelectedContentColor, long timeSelectorUnselectedContentColor);
method public androidx.compose.material3.TimePickerColors copy(optional long clockDialColor, optional long selectorColor, optional long containerColor, optional long periodSelectorBorderColor, optional long clockDialSelectedContentColor, optional long clockDialUnselectedContentColor, optional long periodSelectorSelectedContainerColor, optional long periodSelectorUnselectedContainerColor, optional long periodSelectorSelectedContentColor, optional long periodSelectorUnselectedContentColor, optional long timeSelectorSelectedContainerColor, optional long timeSelectorUnselectedContainerColor, optional long timeSelectorSelectedContentColor, optional long timeSelectorUnselectedContentColor);
diff --git a/compose/material3/material3/api/restricted_current.txt b/compose/material3/material3/api/restricted_current.txt
index 83a3415..1083ae8 100644
--- a/compose/material3/material3/api/restricted_current.txt
+++ b/compose/material3/material3/api/restricted_current.txt
@@ -1774,9 +1774,8 @@
}
public final class TextDefaults {
- method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.ui.text.LinkAnnotation.Clickable Clickable(String tag, optional androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle, androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener);
- method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.ui.text.LinkAnnotation.Url Url(String url, optional androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle, optional androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener);
- method @androidx.compose.runtime.Composable @androidx.compose.runtime.ReadOnlyComposable public androidx.compose.ui.text.AnnotatedString fromHtml(String htmlString, optional androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle, optional androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener);
+ method @androidx.compose.runtime.Composable public androidx.compose.material3.TextLinkStyles linkStyles();
+ method @androidx.compose.runtime.Composable public androidx.compose.material3.TextLinkStyles linkStyles(optional androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle);
field public static final androidx.compose.material3.TextDefaults INSTANCE;
}
@@ -1911,7 +1910,8 @@
public final class TextKt {
method @androidx.compose.runtime.Composable public static void ProvideTextStyle(androidx.compose.ui.text.TextStyle value, kotlin.jvm.functions.Function0<kotlin.Unit> content);
- method @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+ method @Deprecated @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
+ method @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style, optional androidx.compose.material3.TextLinkStyles linkStyles);
method @Deprecated @androidx.compose.runtime.Composable public static void Text(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
method @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional int minLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit>? onTextLayout, optional androidx.compose.ui.text.TextStyle style);
method @Deprecated @androidx.compose.runtime.Composable public static void Text(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional long fontSize, optional androidx.compose.ui.text.font.FontStyle? fontStyle, optional androidx.compose.ui.text.font.FontWeight? fontWeight, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional long letterSpacing, optional androidx.compose.ui.text.style.TextDecoration? textDecoration, optional androidx.compose.ui.text.style.TextAlign? textAlign, optional long lineHeight, optional int overflow, optional boolean softWrap, optional int maxLines, optional kotlin.jvm.functions.Function1<? super androidx.compose.ui.text.TextLayoutResult,kotlin.Unit> onTextLayout, optional androidx.compose.ui.text.TextStyle style);
@@ -1919,6 +1919,19 @@
property public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.text.TextStyle> LocalTextStyle;
}
+ @androidx.compose.runtime.Immutable public final class TextLinkStyles {
+ ctor public TextLinkStyles(androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle);
+ method public androidx.compose.material3.TextLinkStyles copy(optional androidx.compose.ui.text.SpanStyle? linkStyle, optional androidx.compose.ui.text.SpanStyle? linkFocusedStyle, optional androidx.compose.ui.text.SpanStyle? linkHoveredStyle, optional androidx.compose.ui.text.SpanStyle? linkPressedStyle);
+ method public androidx.compose.ui.text.SpanStyle? getLinkFocusedStyle();
+ method public androidx.compose.ui.text.SpanStyle? getLinkHoveredStyle();
+ method public androidx.compose.ui.text.SpanStyle? getLinkPressedStyle();
+ method public androidx.compose.ui.text.SpanStyle? getLinkStyle();
+ property public final androidx.compose.ui.text.SpanStyle? linkFocusedStyle;
+ property public final androidx.compose.ui.text.SpanStyle? linkHoveredStyle;
+ property public final androidx.compose.ui.text.SpanStyle? linkPressedStyle;
+ property public final androidx.compose.ui.text.SpanStyle? linkStyle;
+ }
+
@SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Immutable public final class TimePickerColors {
ctor public TimePickerColors(long clockDialColor, long selectorColor, long containerColor, long periodSelectorBorderColor, long clockDialSelectedContentColor, long clockDialUnselectedContentColor, long periodSelectorSelectedContainerColor, long periodSelectorUnselectedContainerColor, long periodSelectorSelectedContentColor, long periodSelectorUnselectedContentColor, long timeSelectorSelectedContainerColor, long timeSelectorUnselectedContainerColor, long timeSelectorSelectedContentColor, long timeSelectorUnselectedContentColor);
method public androidx.compose.material3.TimePickerColors copy(optional long clockDialColor, optional long selectorColor, optional long containerColor, optional long periodSelectorBorderColor, optional long clockDialSelectedContentColor, optional long clockDialUnselectedContentColor, optional long periodSelectorSelectedContainerColor, optional long periodSelectorUnselectedContainerColor, optional long periodSelectorSelectedContentColor, optional long periodSelectorUnselectedContentColor, optional long timeSelectorSelectedContainerColor, optional long timeSelectorUnselectedContainerColor, optional long timeSelectorSelectedContentColor, optional long timeSelectorUnselectedContentColor);
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/IconButtonSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/IconButtonSamples.kt
index 38ce76c..be0ef90 100644
--- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/IconButtonSamples.kt
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/IconButtonSamples.kt
@@ -57,7 +57,7 @@
Icon(
rememberVectorPainter(image = Icons.Outlined.Lock),
contentDescription = "Localized description",
- tint = { Color.Blue })
+ tint = { Color.Red })
}
}
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/TextSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/TextSamples.kt
index 11f84f0..ae5ef28 100644
--- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/TextSamples.kt
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/TextSamples.kt
@@ -18,8 +18,8 @@
import androidx.annotation.Sampled
import androidx.compose.material3.Text
-import androidx.compose.material3.TextDefaults
import androidx.compose.runtime.Composable
+import androidx.compose.ui.text.LinkAnnotation
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.withLink
@@ -28,7 +28,7 @@
fun AnnotatedStringWithLinks() {
Text(buildAnnotatedString {
append("Build better apps faster with ")
- withLink(TextDefaults.Url(url = "https://developer.android.com/jetpack/compose")) {
+ withLink(LinkAnnotation.Url(url = "https://developer.android.com/jetpack/compose")) {
append("Jetpack Compose")
}
})
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/TextTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/TextTest.kt
index 1e877c4..adc8085 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/TextTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/TextTest.kt
@@ -22,6 +22,7 @@
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.testutils.assertContainsColor
+import androidx.compose.testutils.assertDoesNotContainColor
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.testTag
@@ -36,10 +37,13 @@
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performSemanticsAction
import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.LinkAnnotation
+import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontStyle
+import androidx.compose.ui.text.fromHtml
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.em
@@ -361,7 +365,7 @@
@Test
fun fromHtml_links_getColorFromMaterialTheme() {
rule.setMaterialContent(lightColorScheme(primary = Color.Red)) {
- Text(TextDefaults.fromHtml("<a href=url>link</a>"))
+ Text(AnnotatedString.fromHtml("<a href=url>link</a>"))
}
rule.onNode(hasClickAction(), useUnmergedTree = true)
@@ -371,11 +375,47 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@Test
+ fun fromHtml_links_materialThemeRespectsStyleInLinkAnnotation() {
+ rule.setMaterialContent(lightColorScheme(primary = Color.Red)) {
+ Text(
+ AnnotatedString.fromHtml(
+ "<a href=url>link</a>",
+ linkStyle = SpanStyle(color = Color.Green)
+ )
+ )
+ }
+
+ rule.onNode(hasClickAction(), useUnmergedTree = true)
+ .captureToImage()
+ .assertContainsColor(Color.Green)
+ .assertDoesNotContainColor(Color.Red)
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+ @Test
+ fun fromHtml_links_materialThemeMergedIntoStyleInLinkAnnotation() {
+ rule.setMaterialContent(lightColorScheme(primary = Color.Red)) {
+ Text(
+ AnnotatedString.fromHtml(
+ "<a href=url>link</a>",
+ linkStyle = SpanStyle(background = Color.Green)
+ )
+ )
+ }
+
+ rule.onNode(hasClickAction(), useUnmergedTree = true)
+ .captureToImage()
+ .assertContainsColor(Color.Green)
+ .assertContainsColor(Color.Red)
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+ @Test
fun links_getColorFromMaterialTheme() {
rule.setMaterialContent(lightColorScheme(primary = Color.Red)) {
Text(buildAnnotatedString {
append("link")
- addLink(TextDefaults.Url(url = "url"), 0, 4)
+ addLink(LinkAnnotation.Url(url = "url"), 0, 4)
})
}
@@ -383,4 +423,36 @@
.captureToImage()
.assertContainsColor(Color.Red)
}
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+ @Test
+ fun links_materialThemeRespectsStyleInLinkAnnotation() {
+ rule.setMaterialContent(lightColorScheme(primary = Color.Red)) {
+ Text(buildAnnotatedString {
+ append("link")
+ addLink(LinkAnnotation.Url(url = "url", SpanStyle(color = Color.Green)), 0, 4)
+ })
+ }
+
+ rule.onNode(hasClickAction(), useUnmergedTree = true)
+ .captureToImage()
+ .assertContainsColor(Color.Green)
+ .assertDoesNotContainColor(Color.Red)
+ }
+
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+ @Test
+ fun links_materialThemeMergedIntoStyleInLinkAnnotation() {
+ rule.setMaterialContent(lightColorScheme(primary = Color.Red)) {
+ Text(buildAnnotatedString {
+ append("link")
+ addLink(LinkAnnotation.Url(url = "url", SpanStyle(background = Color.Green)), 0, 4)
+ })
+ }
+
+ rule.onNode(hasClickAction(), useUnmergedTree = true)
+ .captureToImage()
+ .assertContainsColor(Color.Red)
+ .assertContainsColor(Color.Green)
+ }
}
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ColorScheme.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ColorScheme.kt
index c93dafa..0bfb76e 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ColorScheme.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ColorScheme.kt
@@ -509,6 +509,8 @@
internal var defaultOutlinedTextFieldColorsCached: TextFieldColors? = null
internal var defaultTextFieldColorsCached: TextFieldColors? = null
+ internal var defaultTextLinkStylesCached: TextLinkStyles? = null
+
@OptIn(ExperimentalMaterial3Api::class)
internal var defaultTimePickerColorsCached: TimePickerColors? = null
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Text.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Text.kt
index d007957..652375c 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Text.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Text.kt
@@ -21,7 +21,7 @@
import androidx.compose.material3.tokens.DefaultTextStyle
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.ReadOnlyComposable
+import androidx.compose.runtime.Immutable
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.structuralEqualityPolicy
import androidx.compose.ui.Modifier
@@ -29,7 +29,6 @@
import androidx.compose.ui.graphics.takeOrElse
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.LinkAnnotation
-import androidx.compose.ui.text.LinkInteractionListener
import androidx.compose.ui.text.Paragraph
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.TextLayoutResult
@@ -37,11 +36,11 @@
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.text.fromHtml
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.TextUnit
+import androidx.compose.ui.util.fastForEach
/**
* High level element that displays text and provides semantics / accessibility information.
@@ -237,6 +236,13 @@
* text, baselines and other details. The callback can be used to add additional decoration or
* functionality to the text. For example, to draw selection around the text.
* @param style style configuration for the text such as color, font, line height etc.
+ * @param linkStyles Configures styles for the links in different states which are present in text
+ * as [androidx.compose.ui.text.LinkAnnotation] annotations. This object passes the styles directly
+ * to the link annotations. If you style the [text] either using the [SpanStyle] annotations or
+ * via the parameters from this composable like [color], [style] and others, the [linkStyles] will
+ * override them for links
+ *
+ * @sample androidx.compose.material3.samples.AnnotatedStringWithLinks
*/
@Composable
fun Text(
@@ -257,34 +263,82 @@
minLines: Int = 1,
inlineContent: Map<String, InlineTextContent> = mapOf(),
onTextLayout: (TextLayoutResult) -> Unit = {},
+ style: TextStyle = LocalTextStyle.current,
+ linkStyles: TextLinkStyles = TextDefaults.linkStyles()
+) {
+ val textColor = color.takeOrElse {
+ style.color.takeOrElse {
+ LocalContentColor.current
+ }
+ }
+
+ BasicText(
+ text = textWithLinkStyles(text, linkStyles),
+ modifier = modifier,
+ style = style.merge(
+ color = textColor,
+ fontSize = fontSize,
+ fontWeight = fontWeight,
+ textAlign = textAlign ?: TextAlign.Unspecified,
+ lineHeight = lineHeight,
+ fontFamily = fontFamily,
+ textDecoration = textDecoration,
+ fontStyle = fontStyle,
+ letterSpacing = letterSpacing
+ ),
+ onTextLayout = onTextLayout,
+ overflow = overflow,
+ softWrap = softWrap,
+ maxLines = maxLines,
+ minLines = minLines,
+ inlineContent = inlineContent
+ )
+}
+
+@Deprecated(
+ "Maintained for binary compatibility. Use version with a textLinkStyles instead",
+ level = DeprecationLevel.HIDDEN
+)
+@Composable
+fun Text(
+ text: AnnotatedString,
+ modifier: Modifier = Modifier,
+ color: Color = Color.Unspecified,
+ fontSize: TextUnit = TextUnit.Unspecified,
+ fontStyle: FontStyle? = null,
+ fontWeight: FontWeight? = null,
+ fontFamily: FontFamily? = null,
+ letterSpacing: TextUnit = TextUnit.Unspecified,
+ textDecoration: TextDecoration? = null,
+ textAlign: TextAlign? = null,
+ lineHeight: TextUnit = TextUnit.Unspecified,
+ overflow: TextOverflow = TextOverflow.Clip,
+ softWrap: Boolean = true,
+ maxLines: Int = Int.MAX_VALUE,
+ minLines: Int = 1,
+ inlineContent: Map<String, InlineTextContent> = mapOf(),
+ onTextLayout: (TextLayoutResult) -> Unit = {},
style: TextStyle = LocalTextStyle.current
) {
- val textColor = color.takeOrElse {
- style.color.takeOrElse {
- LocalContentColor.current
- }
- }
-
- BasicText(
- text = text,
- modifier = modifier,
- style = style.merge(
- color = textColor,
- fontSize = fontSize,
- fontWeight = fontWeight,
- textAlign = textAlign ?: TextAlign.Unspecified,
- lineHeight = lineHeight,
- fontFamily = fontFamily,
- textDecoration = textDecoration,
- fontStyle = fontStyle,
- letterSpacing = letterSpacing
- ),
- onTextLayout = onTextLayout,
- overflow = overflow,
- softWrap = softWrap,
- maxLines = maxLines,
- minLines = minLines,
- inlineContent = inlineContent
+ Text(
+ text,
+ modifier,
+ color,
+ fontSize,
+ fontStyle,
+ fontWeight,
+ fontFamily,
+ letterSpacing,
+ textDecoration,
+ textAlign,
+ lineHeight,
+ overflow,
+ softWrap,
+ maxLines,
+ minLines,
+ inlineContent,
+ onTextLayout,
+ style
)
}
@@ -359,96 +413,114 @@
/** Contains the methods to be used by [Text] */
object TextDefaults {
- /**
- * Converts a string with HTML tags into [AnnotatedString]. Applies default styling from the
- * [MaterialTheme] to links present in the [htmlString].
- *
- * Check [androidx.compose.ui.text.AnnotatedString.Companion.fromHtml] for more details on
- * supported tags and usage.
- *
- * @param htmlString HTML-tagged string to be parsed to construct AnnotatedString
- * @param linkStyle style to be applied to links present in the string
- * @param linkFocusedStyle style to be applied to links present in the string when they are
- * focused
- * @param linkHoveredStyle style to be applied to links present in the string when they are
- * hovered
- * @param linkPressedStyle style to be applied to links present in the string when they are
- * pressed
- * @param linkInteractionListener a listener that will be attached to links that are present in
- * the string and triggered when user clicks on those links. When set to null, which is
- * a default, the system will try to open the corresponding links with the
- * [androidx.compose.ui.platform.UriHandler] composition local
- *
- * @see androidx.compose.ui.text.AnnotatedString.Companion.fromHtml
- */
- @Composable
- @ReadOnlyComposable
- @Suppress("ExecutorRegistration") // LinkInteractionListener is a UI event handler
- fun fromHtml(
- htmlString: String,
- linkStyle: SpanStyle? = SpanStyle(color = MaterialTheme.colorScheme.primary),
- linkFocusedStyle: SpanStyle? = null,
- linkHoveredStyle: SpanStyle? = null,
- linkPressedStyle: SpanStyle? = null,
- linkInteractionListener: LinkInteractionListener? = null
- ): AnnotatedString {
- return AnnotatedString.fromHtml(
- htmlString,
- linkStyle,
- linkFocusedStyle,
- linkHoveredStyle,
- linkPressedStyle,
- linkInteractionListener
- )
- }
/**
- * Constructs a [LinkAnnotation.Url] and applies default styling from the [MaterialTheme]
- *
- * @sample androidx.compose.material3.samples.AnnotatedStringWithLinks
+ * Creates a [TextLinkStyles] that are used to style the links present in the text
*/
@Composable
- @ReadOnlyComposable
- @Suppress("ExecutorRegistration") // LinkInteractionListener is a UI event handler
- fun Url(
- url: String,
- linkStyle: SpanStyle? = SpanStyle(color = MaterialTheme.colorScheme.primary),
- linkFocusedStyle: SpanStyle? = null,
- linkHoveredStyle: SpanStyle? = null,
- linkPressedStyle: SpanStyle? = null,
- linkInteractionListener: LinkInteractionListener? = null
- ): LinkAnnotation.Url {
- return LinkAnnotation.Url(
- url,
- linkStyle,
- linkFocusedStyle,
- linkHoveredStyle,
- linkPressedStyle,
- linkInteractionListener
- )
- }
+ fun linkStyles(): TextLinkStyles = MaterialTheme.colorScheme.defaultTextLinkStyles
/**
- * Constructs a [LinkAnnotation.Clickable] and applies default styling from the [MaterialTheme]
+ * Creates a [TextLinkStyles] that are used to style the links present in the text based on
+ * their state
+ *
+ * @see LinkAnnotation
*/
@Composable
- @ReadOnlyComposable
- @Suppress("ExecutorRegistration") // LinkInteractionListener is a UI event handler
- fun Clickable(
- tag: String,
- linkStyle: SpanStyle? = SpanStyle(color = MaterialTheme.colorScheme.primary),
+ fun linkStyles(
+ linkStyle: SpanStyle? = null,
linkFocusedStyle: SpanStyle? = null,
linkHoveredStyle: SpanStyle? = null,
- linkPressedStyle: SpanStyle? = null,
- linkInteractionListener: LinkInteractionListener?
- ): LinkAnnotation.Clickable {
- return LinkAnnotation.Clickable(
- tag,
- linkStyle,
- linkFocusedStyle,
- linkHoveredStyle,
- linkPressedStyle,
- linkInteractionListener
- )
+ linkPressedStyle: SpanStyle? = null
+ ): TextLinkStyles = MaterialTheme.colorScheme.defaultTextLinkStyles.copy(
+ linkStyle, linkFocusedStyle, linkHoveredStyle, linkPressedStyle
+ )
+
+ private val ColorScheme.defaultTextLinkStyles: TextLinkStyles
+ get() {
+ return defaultTextLinkStylesCached ?: TextLinkStyles(
+ linkStyle = SpanStyle(color = primary)
+ ).also {
+ defaultTextLinkStylesCached = it
+ }
+ }
+}
+
+/**
+ * Represents the styles of the links in the Text in different states
+ *
+ * @param linkStyle style to be applied to links present in the string
+ * @param linkFocusedStyle style to be applied to links present in the string when they are
+ * focused
+ * @param linkHoveredStyle style to be applied to links present in the string when they are
+ * hovered
+ * @param linkPressedStyle style to be applied to links present in the string when they are
+ * pressed
+ */
+@Immutable
+class TextLinkStyles(
+ val linkStyle: SpanStyle?,
+ val linkFocusedStyle: SpanStyle? = null,
+ val linkHoveredStyle: SpanStyle? = null,
+ val linkPressedStyle: SpanStyle? = null
+) {
+ /**
+ * Returns a copy of this TextLinkStyles, optionally overriding some of the values.
+ * This uses the null to mean “use the value from the source”
+ */
+ fun copy(
+ linkStyle: SpanStyle? = this.linkStyle,
+ linkFocusedStyle: SpanStyle? = this.linkFocusedStyle,
+ linkHoveredStyle: SpanStyle? = this.linkHoveredStyle,
+ linkPressedStyle: SpanStyle? = this.linkPressedStyle
+ ) = TextLinkStyles(
+ linkStyle ?: this.linkStyle,
+ linkFocusedStyle ?: this.linkFocusedStyle,
+ linkHoveredStyle ?: this.linkHoveredStyle,
+ linkPressedStyle ?: this.linkPressedStyle
+ )
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (other == null || other !is TextLinkStyles) return false
+
+ if (linkStyle != other.linkStyle) return false
+ if (linkFocusedStyle != other.linkFocusedStyle) return false
+ if (linkHoveredStyle != other.linkHoveredStyle) return false
+ if (linkPressedStyle != other.linkPressedStyle) return false
+
+ return true
}
+
+ override fun hashCode(): Int {
+ var result = linkStyle?.hashCode() ?: 0
+ result = 31 * result + (linkFocusedStyle?.hashCode() ?: 0)
+ result = 31 * result + (linkHoveredStyle?.hashCode() ?: 0)
+ result = 31 * result + (linkPressedStyle?.hashCode() ?: 0)
+ return result
+ }
+}
+
+/**
+ * Replaces all link annotations in the AnnotatedString with the new link annotations the styles of
+ * which are merged with the Material styling.
+ *
+ * If the [text]'s link annotation has a style defined in the annotation, Material theming will
+ * not fully override it but apply on top the _missing_ fields.
+*/
+private fun textWithLinkStyles(text: AnnotatedString, linkStyles: TextLinkStyles): AnnotatedString {
+ val links = text.getLinkAnnotations(0, text.length)
+ if (links.isEmpty()) return text
+
+ val builder = AnnotatedString.Builder(text)
+ links.fastForEach {
+ val styledLink = it.item.withDefaultsFrom(
+ linkStyles.linkStyle,
+ linkStyles.linkFocusedStyle,
+ linkStyles.linkHoveredStyle,
+ linkStyles.linkPressedStyle
+ )
+ builder.replace(it, styledLink)
+ }
+ return builder.toAnnotatedString()
}
diff --git a/compose/ui/ui-text/api/current.txt b/compose/ui/ui-text/api/current.txt
index 76206b2..c5f790c 100644
--- a/compose/ui/ui-text/api/current.txt
+++ b/compose/ui/ui-text/api/current.txt
@@ -58,6 +58,7 @@
method public int pushStyle(androidx.compose.ui.text.SpanStyle style);
method public int pushTtsAnnotation(androidx.compose.ui.text.TtsAnnotation ttsAnnotation);
method @Deprecated @SuppressCompatibility @androidx.compose.ui.text.ExperimentalTextApi public int pushUrlAnnotation(androidx.compose.ui.text.UrlAnnotation urlAnnotation);
+ method public void replace(androidx.compose.ui.text.AnnotatedString.Range<androidx.compose.ui.text.LinkAnnotation> old, androidx.compose.ui.text.LinkAnnotation new);
method public androidx.compose.ui.text.AnnotatedString toAnnotatedString();
property public final int length;
}
@@ -130,6 +131,7 @@
method public abstract androidx.compose.ui.text.LinkInteractionListener? getLinkInteractionListener();
method public abstract androidx.compose.ui.text.SpanStyle? getPressedStyle();
method public abstract androidx.compose.ui.text.SpanStyle? getStyle();
+ method public abstract androidx.compose.ui.text.LinkAnnotation withDefaultsFrom(androidx.compose.ui.text.SpanStyle? defaultStyle, androidx.compose.ui.text.SpanStyle? defaultFocusedStyle, androidx.compose.ui.text.SpanStyle? defaultHoveredStyle, androidx.compose.ui.text.SpanStyle? defaultPressedStyle);
property public abstract androidx.compose.ui.text.SpanStyle? focusedStyle;
property public abstract androidx.compose.ui.text.SpanStyle? hoveredStyle;
property public abstract androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener;
@@ -145,6 +147,7 @@
method public androidx.compose.ui.text.SpanStyle? getPressedStyle();
method public androidx.compose.ui.text.SpanStyle? getStyle();
method public String getTag();
+ method public androidx.compose.ui.text.LinkAnnotation.Clickable withDefaultsFrom(androidx.compose.ui.text.SpanStyle? defaultStyle, androidx.compose.ui.text.SpanStyle? defaultFocusedStyle, androidx.compose.ui.text.SpanStyle? defaultHoveredStyle, androidx.compose.ui.text.SpanStyle? defaultPressedStyle);
property public androidx.compose.ui.text.SpanStyle? focusedStyle;
property public androidx.compose.ui.text.SpanStyle? hoveredStyle;
property public androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener;
@@ -161,6 +164,7 @@
method public androidx.compose.ui.text.SpanStyle? getPressedStyle();
method public androidx.compose.ui.text.SpanStyle? getStyle();
method public String getUrl();
+ method public androidx.compose.ui.text.LinkAnnotation.Url withDefaultsFrom(androidx.compose.ui.text.SpanStyle? defaultStyle, androidx.compose.ui.text.SpanStyle? defaultFocusedStyle, androidx.compose.ui.text.SpanStyle? defaultHoveredStyle, androidx.compose.ui.text.SpanStyle? defaultPressedStyle);
property public androidx.compose.ui.text.SpanStyle? focusedStyle;
property public androidx.compose.ui.text.SpanStyle? hoveredStyle;
property public androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener;
diff --git a/compose/ui/ui-text/api/restricted_current.txt b/compose/ui/ui-text/api/restricted_current.txt
index 2156b8f..68ce109 100644
--- a/compose/ui/ui-text/api/restricted_current.txt
+++ b/compose/ui/ui-text/api/restricted_current.txt
@@ -58,6 +58,7 @@
method public int pushStyle(androidx.compose.ui.text.SpanStyle style);
method public int pushTtsAnnotation(androidx.compose.ui.text.TtsAnnotation ttsAnnotation);
method @Deprecated @SuppressCompatibility @androidx.compose.ui.text.ExperimentalTextApi public int pushUrlAnnotation(androidx.compose.ui.text.UrlAnnotation urlAnnotation);
+ method public void replace(androidx.compose.ui.text.AnnotatedString.Range<androidx.compose.ui.text.LinkAnnotation> old, androidx.compose.ui.text.LinkAnnotation new);
method public androidx.compose.ui.text.AnnotatedString toAnnotatedString();
property public final int length;
}
@@ -130,6 +131,7 @@
method public abstract androidx.compose.ui.text.LinkInteractionListener? getLinkInteractionListener();
method public abstract androidx.compose.ui.text.SpanStyle? getPressedStyle();
method public abstract androidx.compose.ui.text.SpanStyle? getStyle();
+ method public abstract androidx.compose.ui.text.LinkAnnotation withDefaultsFrom(androidx.compose.ui.text.SpanStyle? defaultStyle, androidx.compose.ui.text.SpanStyle? defaultFocusedStyle, androidx.compose.ui.text.SpanStyle? defaultHoveredStyle, androidx.compose.ui.text.SpanStyle? defaultPressedStyle);
property public abstract androidx.compose.ui.text.SpanStyle? focusedStyle;
property public abstract androidx.compose.ui.text.SpanStyle? hoveredStyle;
property public abstract androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener;
@@ -145,6 +147,7 @@
method public androidx.compose.ui.text.SpanStyle? getPressedStyle();
method public androidx.compose.ui.text.SpanStyle? getStyle();
method public String getTag();
+ method public androidx.compose.ui.text.LinkAnnotation.Clickable withDefaultsFrom(androidx.compose.ui.text.SpanStyle? defaultStyle, androidx.compose.ui.text.SpanStyle? defaultFocusedStyle, androidx.compose.ui.text.SpanStyle? defaultHoveredStyle, androidx.compose.ui.text.SpanStyle? defaultPressedStyle);
property public androidx.compose.ui.text.SpanStyle? focusedStyle;
property public androidx.compose.ui.text.SpanStyle? hoveredStyle;
property public androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener;
@@ -161,6 +164,7 @@
method public androidx.compose.ui.text.SpanStyle? getPressedStyle();
method public androidx.compose.ui.text.SpanStyle? getStyle();
method public String getUrl();
+ method public androidx.compose.ui.text.LinkAnnotation.Url withDefaultsFrom(androidx.compose.ui.text.SpanStyle? defaultStyle, androidx.compose.ui.text.SpanStyle? defaultFocusedStyle, androidx.compose.ui.text.SpanStyle? defaultHoveredStyle, androidx.compose.ui.text.SpanStyle? defaultPressedStyle);
property public androidx.compose.ui.text.SpanStyle? focusedStyle;
property public androidx.compose.ui.text.SpanStyle? hoveredStyle;
property public androidx.compose.ui.text.LinkInteractionListener? linkInteractionListener;
diff --git a/compose/ui/ui-text/samples/src/main/java/androidx/compose/ui/text/samples/AnnotatedStringBuilderSamples.kt b/compose/ui/ui-text/samples/src/main/java/androidx/compose/ui/text/samples/AnnotatedStringBuilderSamples.kt
index b527fce3..4f178fc 100644
--- a/compose/ui/ui-text/samples/src/main/java/androidx/compose/ui/text/samples/AnnotatedStringBuilderSamples.kt
+++ b/compose/ui/ui-text/samples/src/main/java/androidx/compose/ui/text/samples/AnnotatedStringBuilderSamples.kt
@@ -192,7 +192,6 @@
append("Build better apps faster with ")
val link = LinkAnnotation.Url(
"https://developer.android.com/jetpack/compose",
- style = SpanStyle(color = Color.Magenta),
hoveredStyle = SpanStyle(textDecoration = TextDecoration.Underline)
)
withLink(link) { append("Jetpack Compose") }
@@ -210,8 +209,7 @@
buildAnnotatedString {
append("Build better apps faster with ")
val link = LinkAnnotation.Url(
- "https://developer.android.com/jetpack/compose",
- style = SpanStyle(color = Color.Magenta),
+ "https://developer.android.com/jetpack/compose"
) {
val url = (it as LinkAnnotation.Url).url
// log some metrics
diff --git a/compose/ui/ui-text/src/androidInstrumentedTest/kotlin/androidx/compose/ui/text/AnnotatedStringFromHtmlTest.kt b/compose/ui/ui-text/src/androidInstrumentedTest/kotlin/androidx/compose/ui/text/AnnotatedStringFromHtmlTest.kt
index 586f0d3..4543351 100644
--- a/compose/ui/ui-text/src/androidInstrumentedTest/kotlin/androidx/compose/ui/text/AnnotatedStringFromHtmlTest.kt
+++ b/compose/ui/ui-text/src/androidInstrumentedTest/kotlin/androidx/compose/ui/text/AnnotatedStringFromHtmlTest.kt
@@ -356,6 +356,21 @@
@Test
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+ fun link_appliesColorFromHtmlTag() {
+ val stringWithColoredLink = "<span style=\"color:blue\"><a href=\"url\">link</a></span>"
+ val annotatedString = AnnotatedString.fromHtml(stringWithColoredLink)
+
+ rule.setContent {
+ BasicText(text = annotatedString)
+ }
+
+ rule.onNode(hasClickAction(), useUnmergedTree = true)
+ .captureToImage()
+ .assertContainsColor(Color.Blue)
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
fun link_appliesColorFromMethod() {
val stringWithColoredLink = "<span style=\"color:blue\"><a href=\"url\">link</a></span>"
val annotatedString = AnnotatedString.fromHtml(
diff --git a/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/AnnotatedStringTest.kt b/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/AnnotatedStringTest.kt
index e2d34a5..2ad35c9 100644
--- a/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/AnnotatedStringTest.kt
+++ b/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/AnnotatedStringTest.kt
@@ -565,4 +565,77 @@
// already covered by existing tests if this is true
assertThat(AnnotatedString.Saver).isSameInstanceAs(AnnotatedStringSaver)
}
+
+ @Test
+ fun replace_linkAnnotation_sameRange_differentAnnotation_noOp() {
+ val original = buildAnnotatedString {
+ pushLink(LinkAnnotation.Url("url"))
+ append("text")
+ pop()
+ }
+ val result = AnnotatedString.Builder(original).also {
+ it.replace(
+ Range(LinkAnnotation.Url("anotherUrl"), 0, 4),
+ LinkAnnotation.Url("another")
+ )
+ }.toAnnotatedString()
+
+ assertThat(result.getLinkAnnotations(0, 4).first().item).isEqualTo(
+ LinkAnnotation.Url("url")
+ )
+ }
+
+ @Test
+ fun replace_linkAnnotation_sameLink_differentRange_noOp() {
+ val original = buildAnnotatedString {
+ pushLink(LinkAnnotation.Url("url"))
+ append("text")
+ pop()
+ }
+ val result = AnnotatedString.Builder(original).also {
+ it.replace(
+ Range(LinkAnnotation.Url("url"), 2, 4),
+ LinkAnnotation.Url("another")
+ )
+ }.toAnnotatedString()
+
+ assertThat(result.getLinkAnnotations(0, 4).first().item).isEqualTo(
+ LinkAnnotation.Url("url")
+ )
+ }
+
+ @Test
+ fun replace_linkAnnotation() {
+ val original = buildAnnotatedString {
+ pushLink(LinkAnnotation.Url("url"))
+ append("text")
+ pop()
+ }
+ val result = AnnotatedString.Builder(original).also {
+ it.replace(
+ Range(LinkAnnotation.Url("url"), 0, 4),
+ LinkAnnotation.Url("another")
+ )
+ }.toAnnotatedString()
+
+ assertThat(result.getLinkAnnotations(0, 4).first().item).isEqualTo(
+ LinkAnnotation.Url("another")
+ )
+ }
+
+ @Test
+ fun replace_linkAnnotation_withHandler() {
+ val original = buildAnnotatedString {
+ pushLink(LinkAnnotation.Url("url") { /* do something */ })
+ append("text")
+ pop()
+ }
+ val result = AnnotatedString.Builder(original).also {
+ it.replace(original.getLinkAnnotations(0, 4).first(), LinkAnnotation.Url("another"))
+ }.toAnnotatedString()
+
+ assertThat(result.getLinkAnnotations(0, 4).first().item).isEqualTo(
+ LinkAnnotation.Url("another")
+ )
+ }
}
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/AnnotatedString.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/AnnotatedString.kt
index 57fb08f..53c4854 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/AnnotatedString.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/AnnotatedString.kt
@@ -590,6 +590,18 @@
}
/**
+ * Replaces the LinkAnnotation with a [new] LinkAnnotation at the same range.
+ * If the original annotation range is not found (including if the range matches but the
+ * attached annotation is different and visa versa), this method will be a no-op.
+ */
+ fun replace(old: Range<LinkAnnotation>, new: LinkAnnotation) {
+ val removed = annotations.remove(MutableRange(old.item, old.start, old.end))
+ if (removed) {
+ annotations.add(MutableRange(new, old.start, old.end))
+ }
+ }
+
+ /**
* Applies the given [SpanStyle] to any appended text until a corresponding [pop] is
* called.
*
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Html.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Html.kt
index 09a4e98..da80888 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Html.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Html.kt
@@ -16,8 +16,6 @@
package androidx.compose.ui.text
-import androidx.compose.ui.text.style.TextDecoration
-
/**
* Converts a string with HTML tags into [AnnotatedString].
*
@@ -52,7 +50,7 @@
*/
expect fun AnnotatedString.Companion.fromHtml(
htmlString: String,
- linkStyle: SpanStyle? = SpanStyle(textDecoration = TextDecoration.Underline),
+ linkStyle: SpanStyle? = null,
linkFocusedStyle: SpanStyle? = null,
linkHoveredStyle: SpanStyle? = null,
linkPressedStyle: SpanStyle? = null,
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/LinkAnnotation.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/LinkAnnotation.kt
index 3a1c75a..b8595b3 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/LinkAnnotation.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/LinkAnnotation.kt
@@ -16,8 +16,6 @@
package androidx.compose.ui.text
-import androidx.compose.ui.text.style.TextDecoration
-
/**
* An annotation that represents a clickable part of the text.
*/
@@ -50,6 +48,21 @@
*/
abstract val pressedStyle: SpanStyle?
/**
+ * Returns a new [LinkAnnotation] which styles are a combination of its original styles and
+ * the given default styles.
+ *
+ * This link's style's null or inherit properties are replaced with the non-null properties of
+ * the corresponding default style. Another way to think of it is that the "missing" properties
+ * of the style are _filled_ by the properties of the corresponding default style.
+ */
+ abstract fun withDefaultsFrom(
+ defaultStyle: SpanStyle?,
+ defaultFocusedStyle: SpanStyle?,
+ defaultHoveredStyle: SpanStyle?,
+ defaultPressedStyle: SpanStyle?
+ ): LinkAnnotation
+
+ /**
* An annotation that contains a [url] string. When clicking on the text to which this annotation
* is attached, the app will try to open the url using [androidx.compose.ui.platform.UriHandler].
* However, if [linkInteractionListener] is provided, its [LinkInteractionListener.onClick]
@@ -58,12 +71,27 @@
*/
class Url(
val url: String,
- override val style: SpanStyle? = SpanStyle(textDecoration = TextDecoration.Underline),
+ override val style: SpanStyle? = null,
override val focusedStyle: SpanStyle? = null,
override val hoveredStyle: SpanStyle? = null,
override val pressedStyle: SpanStyle? = null,
override val linkInteractionListener: LinkInteractionListener? = null
) : LinkAnnotation() {
+
+ override fun withDefaultsFrom(
+ defaultStyle: SpanStyle?,
+ defaultFocusedStyle: SpanStyle?,
+ defaultHoveredStyle: SpanStyle?,
+ defaultPressedStyle: SpanStyle?
+ ) = Url(
+ url = this.url,
+ style = defaultStyle?.merge(style) ?: this.style,
+ focusedStyle = defaultFocusedStyle?.merge(this.focusedStyle) ?: this.focusedStyle,
+ hoveredStyle = defaultHoveredStyle?.merge(this.hoveredStyle) ?: this.hoveredStyle,
+ pressedStyle = defaultPressedStyle?.merge(this.pressedStyle) ?: this.pressedStyle,
+ linkInteractionListener = this.linkInteractionListener
+ )
+
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is Url) return false
@@ -100,12 +128,26 @@
class Clickable(
val tag: String,
// nullable for the save/restore purposes
- override val style: SpanStyle? = SpanStyle(textDecoration = TextDecoration.Underline),
+ override val style: SpanStyle? = null,
override val focusedStyle: SpanStyle? = null,
override val hoveredStyle: SpanStyle? = null,
override val pressedStyle: SpanStyle? = null,
override val linkInteractionListener: LinkInteractionListener?
- ) : LinkAnnotation() {
+ ) : LinkAnnotation() {
+
+ override fun withDefaultsFrom(
+ defaultStyle: SpanStyle?,
+ defaultFocusedStyle: SpanStyle?,
+ defaultHoveredStyle: SpanStyle?,
+ defaultPressedStyle: SpanStyle?
+ ) = Clickable(
+ tag = this.tag,
+ style = defaultStyle?.merge(style) ?: this.style,
+ focusedStyle = defaultFocusedStyle?.merge(this.focusedStyle) ?: this.focusedStyle,
+ hoveredStyle = defaultHoveredStyle?.merge(this.hoveredStyle) ?: this.hoveredStyle,
+ pressedStyle = defaultPressedStyle?.merge(this.pressedStyle) ?: this.pressedStyle,
+ linkInteractionListener = this.linkInteractionListener
+ )
override fun equals(other: Any?): Boolean {
if (this === other) return true
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/UrlAnnotation.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/UrlAnnotation.kt
index e407743..2dcd993 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/UrlAnnotation.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/UrlAnnotation.kt
@@ -26,10 +26,8 @@
*/
@ExperimentalTextApi
@Deprecated(
- "Use LinkAnnotatation.Url instead. If you're using material/material3 then use " +
- "TextDefaults.Url(url) constructor to create a link annotation. " +
- "Otherwise LinkAnnotation.Url(url)",
- ReplaceWith("TextDefaults.Url(url)", "androidx.compose.material3.TextDefaults")
+ "Use LinkAnnotatation.Url(url) instead",
+ ReplaceWith("LinkAnnotation.Url(url)")
)
@Suppress("Deprecation")
class UrlAnnotation(val url: String) {
diff --git a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/TraverseModifierDemo.kt b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/TraverseModifierDemo.kt
index 26ca5c1..ad2cdbe 100644
--- a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/TraverseModifierDemo.kt
+++ b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/TraverseModifierDemo.kt
@@ -41,10 +41,8 @@
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.drawOutline
@@ -59,7 +57,6 @@
import androidx.compose.ui.node.traverseDescendants
import androidx.compose.ui.platform.InspectorInfo
import androidx.compose.ui.text.style.TextAlign
-import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
// Default colors for all the TraversableNode(s):
@@ -690,12 +687,6 @@
// All the rest of the code in this node is to enable the background color changing, you
// can ignore it if you are only wanting to learn the traversable APIs.
- // naive cache outline calculation if size is the same
- private var lastSize: Size? = null
- private var lastLayoutDirection: LayoutDirection? = null
- private var lastOutline: Outline? = null
- private var lastShape: Shape? = null
-
override fun ContentDrawScope.draw() {
if (shape === RectangleShape) {
// shortcut to avoid Outline calculation and allocation
@@ -712,18 +703,9 @@
}
private fun ContentDrawScope.drawOutline() {
- val outline =
- if (size == lastSize && layoutDirection == lastLayoutDirection && lastShape == shape) {
- lastOutline!!
- } else {
- shape.createOutline(size, layoutDirection, this)
- }
+ val outline = shape.createOutline(size, layoutDirection, this)
if (color != Color.Unspecified) drawOutline(outline, color = color)
brush?.let { drawOutline(outline, brush = it, alpha = alpha) }
- lastOutline = outline
- lastSize = size
- lastLayoutDirection = layoutDirection
- lastShape = shape
}
override fun toString() =
"CustomTraversableModifierNode of key: $TRAVERSAL_NODE_KEY"
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/AndroidPointerInputTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/AndroidPointerInputTest.kt
index e9bd13b..24392c8 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/AndroidPointerInputTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/AndroidPointerInputTest.kt
@@ -3425,22 +3425,8 @@
// don't wait several frames before triggering the ACTION_DOWN. Thus, no hover exit is
// triggered.
dispatchMouseEvent(ACTION_HOVER_EXIT, box1LayoutCoordinates!!)
-
- rule.runOnUiThread {
- // Verify Box 1 events and pointer id
- assertThat(originalPointerId).isEqualTo(box1PointerId)
- assertThat(hoverEventCount).isEqualTo(1)
- assertThat(hoverExitCount).isEqualTo(0)
- assertThat(downCount).isEqualTo(0)
- assertThat(unknownCount).isEqualTo(0)
- assertThat(upCount).isEqualTo(0)
-
- assertThat(pointerEvent).isNull()
- assertThat(eventsThatShouldNotTrigger).isFalse()
- }
-
- pointerEvent = null // Reset before each event
dispatchMouseEvent(ACTION_DOWN, box1LayoutCoordinates!!)
+
rule.runOnUiThread {
assertThat(originalPointerId).isEqualTo(box1PointerId)
assertThat(hoverEventCount).isEqualTo(1)
@@ -3488,21 +3474,8 @@
pointerEvent = null // Reset before each event
dispatchMouseEvent(ACTION_UP, box1LayoutCoordinates!!)
- rule.runOnUiThread {
- assertThat(originalPointerId).isEqualTo(box1PointerId)
- assertThat(hoverEventCount).isEqualTo(1)
- assertThat(hoverExitCount).isEqualTo(0)
- assertThat(downCount).isEqualTo(1)
- assertThat(unknownCount).isEqualTo(2)
- assertThat(upCount).isEqualTo(1)
-
- assertThat(pointerEvent).isNotNull()
- assertThat(eventsThatShouldNotTrigger).isFalse()
- }
-
- pointerEvent = null // Reset before each event
// Compose already considered us as ENTERING the UI Element, so we don't need to trigger
- // it again.
+ // it again. (This is a synthetic hover enter anyway sent from platform with UP.)
dispatchMouseEvent(ACTION_HOVER_ENTER, box1LayoutCoordinates!!)
rule.runOnUiThread {
@@ -3513,7 +3486,7 @@
assertThat(unknownCount).isEqualTo(2)
assertThat(upCount).isEqualTo(1)
- assertThat(pointerEvent).isNull()
+ assertThat(pointerEvent).isNotNull()
assertThat(eventsThatShouldNotTrigger).isFalse()
}
diff --git a/datastore/datastore-core-okio/src/commonMain/kotlin/androidx/datastore/core/okio/OkioSerializer.kt b/datastore/datastore-core-okio/src/commonMain/kotlin/androidx/datastore/core/okio/OkioSerializer.kt
index 963b699..9ec0c11 100644
--- a/datastore/datastore-core-okio/src/commonMain/kotlin/androidx/datastore/core/okio/OkioSerializer.kt
+++ b/datastore/datastore-core-okio/src/commonMain/kotlin/androidx/datastore/core/okio/OkioSerializer.kt
@@ -36,6 +36,11 @@
* Unmarshal object from source.
*
* @param source the BufferedSource with the data to deserialize
+ *
+ * @throws androidx.datastore.core.CorruptionException if the data from [input] is corrupted
+ * and/or unparseable, e.g. [InvalidProtocolBufferException] when the type [T] is a
+ * protobuf message and it is corrupted. Other unrecoverable [IOException] from the file
+ * system should not be thrown as [CorruptionException].
*/
public suspend fun readFrom(source: BufferedSource): T
diff --git a/datastore/datastore-core/src/commonJvmMain/kotlin/androidx/datastore/core/Serializer.kt b/datastore/datastore-core/src/commonJvmMain/kotlin/androidx/datastore/core/Serializer.kt
index 5fc0640..5f53ec8 100644
--- a/datastore/datastore-core/src/commonJvmMain/kotlin/androidx/datastore/core/Serializer.kt
+++ b/datastore/datastore-core/src/commonJvmMain/kotlin/androidx/datastore/core/Serializer.kt
@@ -22,7 +22,7 @@
/**
* The serializer determines the on-disk format and API for accessing it.
*
- * The type T MUST be immutable. Mutable types will result in broken DataStore functionality.
+ * The type [T] MUST be immutable. Mutable types will result in broken DataStore functionality.
*
* TODO(b/151635324): consider changing InputStream to File.
*/
@@ -37,6 +37,11 @@
* Unmarshal object from stream.
*
* @param input the InputStream with the data to deserialize
+ *
+ * @throws androidx.datastore.core.CorruptionException if the data from [input] is corrupted
+ * and/or unparseable, e.g. [InvalidProtocolBufferException] when the type [T] is a
+ * protobuf message and it is corrupted. Other unrecoverable [IOException] from the file
+ * system should not be thrown as [CorruptionException].
*/
public suspend fun readFrom(input: InputStream): T
diff --git a/development/diagnose-build-failure/diagnose-build-failure.sh b/development/diagnose-build-failure/diagnose-build-failure.sh
index 36504c2..57ac654 100755
--- a/development/diagnose-build-failure/diagnose-build-failure.sh
+++ b/development/diagnose-build-failure/diagnose-build-failure.sh
@@ -113,6 +113,9 @@
COLOR_WHITE="\e[97m"
COLOR_GREEN="\e[32m"
+# link to ab-damage-estimator including potentially some relevant query parameters
+AB_DAMAGE_ESTIMATOR_LINK="https://dashboards.corp.google.com/_d7c29bbb_d22c_4d60_833b_98f096f089e7?f=branch:in:aosp-androidx-main&f=day:pd:90"
+
function checkStatusRepo() {
repo status >&2
}
@@ -213,14 +216,31 @@
if runBuild ./gradlew -Pandroidx.summarizeStderr $gradleArgs; then
echo >&2
echo "This script failed to reproduce the build failure." >&2
- echo "If the build failure you were observing was in Android Studio, then:"
- echo ' Were you launching Android Studio by running `./studiow`?'
- echo " Try asking a team member why Android Studio is failing but gradlew is succeeding"
- echo "If you previously observed a build failure, then this means one of:"
- echo " The state of your build is different than when you started your previous build"
- echo " You could ask a team member if they've seen this error."
- echo " The build is nondeterministic"
- echo " If this seems likely to you, then please open a bug."
+ echo >&2
+ echo "Some possibilities:" >&2
+ echo >&2
+ # This message is probably important for users that run this command directly, so we put it first
+ # This message is probably not important when running on the build server so we send it to stdout rather than to stderr (so we don't put ">&2")
+ echo " Was the previous failure that you observed in Android Studio? This script cannot necessarily reproduce errors from the editor"
+ echo
+ echo " A) You could ask a teammate for help"
+ echo
+ echo " The build may be nondeterministic" >&2
+ echo >&2
+ echo " A) ab-damage-estimator can search for examples of this error on build servers $AB_DAMAGE_ESTIMATOR_LINK" >&2
+ echo >&2
+ echo " B) Develocity can search for examples of this error on developer computers https://ge.androidx.dev/scans/failures" >&2
+ echo >&2
+ echo " To upload your own build scan data, see https://g3doc.corp.google.com/company/teams/androidx/onboarding.md?cl=head#gradle-build-scans" >&2
+ echo >&2
+ echo " C) You could run the build in a loop, in hopes of reproducing the error again" >&2
+ echo >&2
+ echo " The state of your build could be different from when you started your previous build" >&2
+ echo >&2
+ echo " Running the failing build may have deleted the problematic state (cleared caches etc)" >&2
+ echo >&2
+ echo " A) Next time, you could make a backup of the build state ( development/diagnose-build-failure/impl/backup-state.sh ) before the failure occurs and compare to the build state after the failure occurs" >&2
+ echo >&2
exit 1
else
echo >&2
@@ -255,9 +275,14 @@
if runBuild ./gradlew --no-daemon $gradleArgs; then
echo >&2
echo "The build passed when disabling the Gradle Daemon" >&2
+ echo >&2
echo "This suggests that there is some state saved in the Gradle Daemon that is causing a failure." >&2
- echo "Unfortunately, this script does not know how to diagnose this further." >&2
- echo "You could ask a team member if they've seen this error." >&2
+ echo >&2
+ echo "Some ideas:" >&2
+ echo >&2
+ echo " A) Next time you could get a heap dump" >&2 # should diagnose-build-failure preemptively do this automatically?
+ echo >&2
+ echo " B) You could look for more examples of this error on build servers using ab-damage-estimator $AB_DAMAGE_ESTIMATOR_LINK" >&2
exit 1
else
echo >&2
diff --git a/docs-public/build.gradle b/docs-public/build.gradle
index 8ef736c..2d63f9c 100644
--- a/docs-public/build.gradle
+++ b/docs-public/build.gradle
@@ -70,30 +70,20 @@
kmpDocs("androidx.compose.animation:animation:1.7.0-alpha07")
kmpDocs("androidx.compose.animation:animation-core:1.7.0-alpha07")
kmpDocs("androidx.compose.animation:animation-graphics:1.7.0-alpha07")
- samples("androidx.compose.animation:animation-samples:1.7.0-alpha07")
- samples("androidx.compose.animation:animation-core-samples:1.7.0-alpha07")
- samples("androidx.compose.animation:animation-graphics-samples:1.7.0-alpha07")
kmpDocs("androidx.compose.foundation:foundation:1.7.0-alpha07")
kmpDocs("androidx.compose.foundation:foundation-layout:1.7.0-alpha07")
- samples("androidx.compose.foundation:foundation-layout-samples:1.7.0-alpha07")
- samples("androidx.compose.foundation:foundation-samples:1.7.0-alpha07")
kmpDocs("androidx.compose.material3.adaptive:adaptive:1.0.0-alpha11")
kmpDocs("androidx.compose.material3.adaptive:adaptive-layout:1.0.0-alpha11")
kmpDocs("androidx.compose.material3.adaptive:adaptive-navigation:1.0.0-alpha11")
- samples("androidx.compose.material3.adaptive:adaptive-samples:1.0.0-alpha11")
kmpDocs("androidx.compose.material3:material3:1.3.0-alpha05")
kmpDocs("androidx.compose.material3:material3-adaptive-navigation-suite:1.0.0-alpha06")
- samples("androidx.compose.material3:material3-adaptive-navigation-suite-samples:1.3.0-alpha04")
docs("androidx.compose.material3:material3-common:1.0.0-alpha01")
samples("androidx.compose.material3:material3-common-samples:1.3.0-alpha05")
- samples("androidx.compose.material3:material3-samples:1.3.0-alpha05")
kmpDocs("androidx.compose.material3:material3-window-size-class:1.3.0-alpha05")
samples("androidx.compose.material3:material3-window-size-class-samples:1.3.0-alpha04")
kmpDocs("androidx.compose.material:material:1.7.0-alpha07")
kmpDocs("androidx.compose.material:material-icons-core:1.7.0-alpha07")
- samples("androidx.compose.material:material-icons-core-samples:1.7.0-alpha07")
docs("androidx.compose.material:material-navigation:1.7.0-alpha07")
- samples("androidx.compose.material:material-navigation-samples:1.7.0-alpha07")
kmpDocs("androidx.compose.material:material-ripple:1.7.0-alpha07")
kmpDocs("androidx.compose.runtime:runtime:1.7.0-alpha07")
docs("androidx.compose.runtime:runtime-livedata:1.7.0-alpha07")
@@ -105,20 +95,16 @@
docs("androidx.compose.ui:ui-android-stubs:1.7.0-alpha07")
kmpDocs("androidx.compose.ui:ui-geometry:1.7.0-alpha07")
kmpDocs("androidx.compose.ui:ui-graphics:1.7.0-alpha07")
- samples("androidx.compose.ui:ui-graphics-samples:1.7.0-alpha07")
kmpDocs("androidx.compose.ui:ui-test:1.7.0-alpha07")
kmpDocs("androidx.compose.ui:ui-test-junit4:1.7.0-alpha07")
- samples("androidx.compose.ui:ui-test-samples:1.7.0-alpha07")
kmpDocs("androidx.compose.ui:ui-text:1.7.0-alpha07")
docs("androidx.compose.ui:ui-text-google-fonts:1.7.0-alpha07")
- samples("androidx.compose.ui:ui-text-samples:1.7.0-alpha07")
kmpDocs("androidx.compose.ui:ui-tooling:1.7.0-alpha07")
kmpDocs("androidx.compose.ui:ui-tooling-data:1.7.0-alpha07")
kmpDocs("androidx.compose.ui:ui-tooling-preview:1.7.0-alpha07")
kmpDocs("androidx.compose.ui:ui-unit:1.7.0-alpha07")
kmpDocs("androidx.compose.ui:ui-util:1.7.0-alpha07")
docs("androidx.compose.ui:ui-viewbinding:1.7.0-alpha07")
- samples("androidx.compose.ui:ui-samples:1.7.0-alpha07")
docs("androidx.concurrent:concurrent-futures:1.2.0-alpha03")
docs("androidx.concurrent:concurrent-futures-ktx:1.2.0-alpha03")
docs("androidx.constraintlayout:constraintlayout:2.2.0-alpha13")
@@ -149,7 +135,6 @@
docs("androidx.credentials:credentials-e2ee:1.0.0-alpha02")
docs("androidx.credentials:credentials-fido:1.0.0-alpha02")
docs("androidx.credentials:credentials-play-services-auth:1.3.0-alpha03")
- samples("androidx.credentials:credentials-samples:1.3.0-alpha03")
docs("androidx.cursoradapter:cursoradapter:1.0.0")
docs("androidx.customview:customview:1.2.0-alpha02")
// TODO(b/294531403): Turn on apiSince for customview-poolingcontainer when it releases as alpha
@@ -194,7 +179,6 @@
docs("androidx.glance:glance-testing:1.1.0-beta02")
docs("androidx.glance:glance-wear-tiles:1.0.0-alpha06")
docs("androidx.graphics:graphics-core:1.0.0-rc01")
- samples("androidx.graphics:graphics-core-samples:1.0.0-rc01")
docs("androidx.graphics:graphics-path:1.0.0")
kmpDocs("androidx.graphics:graphics-shapes:1.0.0-alpha05")
docs("androidx.gridlayout:gridlayout:1.1.0-beta01")
@@ -232,7 +216,6 @@
docs("androidx.lifecycle:lifecycle-service:2.8.0-beta01")
kmpDocs("androidx.lifecycle:lifecycle-viewmodel:2.8.0-beta01")
kmpDocs("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.0-beta01")
- samples("androidx.lifecycle:lifecycle-viewmodel-compose-samples:2.8.0-beta01")
docs("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.0-beta01")
docs("androidx.lifecycle:lifecycle-viewmodel-savedstate:2.8.0-beta01")
docs("androidx.loader:loader:1.1.0")
diff --git a/docs-tip-of-tree/build.gradle b/docs-tip-of-tree/build.gradle
index 4bc6eed..9314304 100644
--- a/docs-tip-of-tree/build.gradle
+++ b/docs-tip-of-tree/build.gradle
@@ -27,16 +27,6 @@
// ads-identifier is deprecated
kmpDocs(project(":annotation:annotation"))
docs(project(":annotation:annotation-experimental"))
- docs(project(":appactions:builtintypes:builtintypes"))
- docs(project(":appactions:interaction:interaction-capabilities-communication"))
- docs(project(":appactions:interaction:interaction-capabilities-core"))
- docs(project(":appactions:interaction:interaction-capabilities-productivity"))
- docs(project(":appactions:interaction:interaction-capabilities-safety"))
- docs(project(":appactions:interaction:interaction-capabilities-fitness"))
- docs(project(":appactions:interaction:interaction-capabilities-testing"))
- docs(project(":appactions:interaction:interaction-service"))
- docs(project(":appactions:interaction:interaction-service-testing"))
- docs(project(":appactions:interaction:interaction-service-wear"))
docs(project(":appcompat:appcompat"))
docs(project(":appcompat:appcompat-resources"))
docs(project(":appsearch:appsearch"))
@@ -66,6 +56,8 @@
docs(project(":camera:camera-effects-still-portrait"))
docs(project(":camera:camera-extensions"))
stubs(fileTree(dir: "../camera/camera-extensions-stub", include: ["camera-extensions-stub.jar"]))
+ docs(project(":camera:camera-feature-combination-query"))
+ docs(project(":camera:camera-feature-combination-query-play-services"))
docs(project(":camera:camera-lifecycle"))
samples(project(":camera:camera-lifecycle:camera-lifecycle-samples"))
docs(project(":camera:camera-mlkit-vision"))
diff --git a/libraryversions.toml b/libraryversions.toml
index 9df5691..7f96b78 100644
--- a/libraryversions.toml
+++ b/libraryversions.toml
@@ -2,8 +2,6 @@
ACTIVITY = "1.10.0-alpha01"
ANNOTATION = "1.8.0-rc01"
ANNOTATION_EXPERIMENTAL = "1.4.0-rc01"
-APPACTIONS_BUILTINTYPES = "1.0.0-alpha01"
-APPACTIONS_INTERACTION = "1.0.0-alpha01"
APPCOMPAT = "1.7.0-beta01"
APPSEARCH = "1.1.0-alpha04"
ARCH_CORE = "2.3.0-alpha01"
@@ -69,7 +67,7 @@
GLANCE = "1.1.0-beta02"
GLANCE_TEMPLATE = "1.0.0-alpha06"
GLANCE_WEAR_TILES = "1.0.0-alpha06"
-GRAPHICS_CORE = "1.0.0-rc01"
+GRAPHICS_CORE = "1.0.0"
GRAPHICS_FILTERS = "1.0.0-alpha01"
GRAPHICS_PATH = "1.0.0-rc01"
GRAPHICS_SHAPES = "1.0.0-beta01"
@@ -180,8 +178,6 @@
[groups]
ACTIVITY = { group = "androidx.activity", atomicGroupVersion = "versions.ACTIVITY" }
ANNOTATION = { group = "androidx.annotation" }
-APPACTIONS_BUILTINTYPES = { group = "androidx.appactions.builtintypes", atomicGroupVersion = "versions.APPACTIONS_BUILTINTYPES" }
-APPACTIONS_INTERACTION = { group = "androidx.appactions.interaction", atomicGroupVersion = "versions.APPACTIONS_INTERACTION" }
APPCOMPAT = { group = "androidx.appcompat", atomicGroupVersion = "versions.APPCOMPAT" }
APPSEARCH = { group = "androidx.appsearch", atomicGroupVersion = "versions.APPSEARCH" }
ARCH_CORE = { group = "androidx.arch.core", atomicGroupVersion = "versions.ARCH_CORE" }
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/app/MediaRouteControllerDialog.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/app/MediaRouteControllerDialog.java
index e1d423a..cc391a4 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/app/MediaRouteControllerDialog.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/app/MediaRouteControllerDialog.java
@@ -47,7 +47,6 @@
import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
-import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
@@ -189,7 +188,6 @@
private Interpolator mInterpolator;
private Interpolator mLinearOutSlowInInterpolator;
private Interpolator mFastOutSlowInInterpolator;
- private Interpolator mAccelerateDecelerateInterpolator;
final AccessibilityManager mAccessibilityManager;
@@ -219,13 +217,10 @@
R.dimen.mr_controller_volume_group_list_padding_top);
mAccessibilityManager =
(AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
- if (android.os.Build.VERSION.SDK_INT >= 21) {
- mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
- R.interpolator.mr_linear_out_slow_in);
- mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
- R.interpolator.mr_fast_out_slow_in);
- }
- mAccelerateDecelerateInterpolator = new AccelerateDecelerateInterpolator();
+ mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
+ R.interpolator.mr_linear_out_slow_in);
+ mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
+ R.interpolator.mr_fast_out_slow_in);
}
/**
@@ -719,19 +714,13 @@
}
};
anim.setDuration(mGroupListAnimationDurationMs);
- if (android.os.Build.VERSION.SDK_INT >= 21) {
- anim.setInterpolator(mInterpolator);
- }
+ anim.setInterpolator(mInterpolator);
view.startAnimation(anim);
}
void loadInterpolator() {
- if (android.os.Build.VERSION.SDK_INT >= 21) {
- mInterpolator = mIsGroupExpanded ? mLinearOutSlowInInterpolator
- : mFastOutSlowInInterpolator;
- } else {
- mInterpolator = mAccelerateDecelerateInterpolator;
- }
+ mInterpolator = mIsGroupExpanded ? mLinearOutSlowInInterpolator
+ : mFastOutSlowInInterpolator;
}
private void updateVolumeControlLayout() {
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/GlobalMediaRouter.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/GlobalMediaRouter.java
index bf75d84..9487a2e 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/GlobalMediaRouter.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/GlobalMediaRouter.java
@@ -97,22 +97,6 @@
new RemoteControlClientCompat.PlaybackInfo();
private final ProviderCallback mProviderCallback = new ProviderCallback();
private final boolean mLowRam;
- private final MediaSessionCompat.OnActiveChangeListener mSessionActiveListener =
- new MediaSessionCompat.OnActiveChangeListener() {
- @Override
- public void onActiveChanged() {
- if (mRccMediaSession != null) {
- android.media.RemoteControlClient remoteControlClient =
- (android.media.RemoteControlClient)
- mRccMediaSession.getRemoteControlClient();
- if (mRccMediaSession.isActive()) {
- addRemoteControlClient(remoteControlClient);
- } else {
- removeRemoteControlClient(remoteControlClient);
- }
- }
- }
- };
private boolean mTransferReceiverDeclared;
private boolean mUseMediaRouter2ForSystemRouting;
@@ -130,7 +114,6 @@
private MediaRouteDiscoveryRequest mDiscoveryRequestForMr2Provider;
private int mCallbackCount;
private MediaSessionRecord mMediaSession;
- private MediaSessionCompat mRccMediaSession;
private MediaSessionCompat mCompatSession;
/* package */ GlobalMediaRouter(Context applicationContext) {
@@ -1190,24 +1173,7 @@
/* package */ void setMediaSessionCompat(final MediaSessionCompat session) {
mCompatSession = session;
- if (Build.VERSION.SDK_INT >= 21) {
- setMediaSessionRecord(session != null ? new MediaSessionRecord(session) : null);
- } else {
- if (mRccMediaSession != null) {
- removeRemoteControlClient(
- (android.media.RemoteControlClient)
- mRccMediaSession.getRemoteControlClient());
- mRccMediaSession.removeOnActiveChangeListener(mSessionActiveListener);
- }
- mRccMediaSession = session;
- if (session != null) {
- session.addOnActiveChangeListener(mSessionActiveListener);
- if (session.isActive()) {
- addRemoteControlClient(
- (android.media.RemoteControlClient) session.getRemoteControlClient());
- }
- }
- }
+ setMediaSessionRecord(session != null ? new MediaSessionRecord(session) : null);
}
private void setMediaSessionRecord(MediaSessionRecord mediaSessionRecord) {
diff --git a/navigation/navigation-common/src/main/java/androidx/navigation/NavDestinationBuilder.kt b/navigation/navigation-common/src/main/java/androidx/navigation/NavDestinationBuilder.kt
index d9a4c79..c3fc3fc 100644
--- a/navigation/navigation-common/src/main/java/androidx/navigation/NavDestinationBuilder.kt
+++ b/navigation/navigation-common/src/main/java/androidx/navigation/NavDestinationBuilder.kt
@@ -363,7 +363,7 @@
*
* All values added here should be able to be added to a [android.os.Bundle].
*
- * @see NavAction.getDefaultArguments
+ * @see NavAction.defaultArguments
*/
public val defaultArguments: MutableMap<String, Any?> = mutableMapOf()
diff --git a/navigation/navigation-common/src/main/java/androidx/navigation/NavType.kt b/navigation/navigation-common/src/main/java/androidx/navigation/NavType.kt
index 3f09a49..1304f9c 100644
--- a/navigation/navigation-common/src/main/java/androidx/navigation/NavType.kt
+++ b/navigation/navigation-common/src/main/java/androidx/navigation/NavType.kt
@@ -31,6 +31,7 @@
* You should only use one of the static NavType instances and subclasses defined in this class.
*
* @param T the type of the data that is supported by this NavType
+ * @param isNullableAllowed whether an argument with this type can hold a null value.
*/
public abstract class NavType<T>(
/**
diff --git a/appactions/interaction/interaction-service-proto/src/main/java/androidx/appactions/interaction/package-info.java b/navigation/navigation-compose/integration-tests/navigation-demos/src/main/java/androidx/navigation/compose/demos/AnimatedDemo.kt
similarity index 69%
rename from appactions/interaction/interaction-service-proto/src/main/java/androidx/appactions/interaction/package-info.java
rename to navigation/navigation-compose/integration-tests/navigation-demos/src/main/java/androidx/navigation/compose/demos/AnimatedDemo.kt
index 8fae19e..ae230732 100644
--- a/appactions/interaction/interaction-service-proto/src/main/java/androidx/appactions/interaction/package-info.java
+++ b/navigation/navigation-compose/integration-tests/navigation-demos/src/main/java/androidx/navigation/compose/demos/AnimatedDemo.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright 2024 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.
@@ -14,10 +14,12 @@
* limitations under the License.
*/
-/**
- * Internal protos for interaction-service.
- */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-package androidx.appactions.interaction.service.proto;
+package androidx.navigation.compose.demos
-import androidx.annotation.RestrictTo;
\ No newline at end of file
+import androidx.compose.runtime.Composable
+import androidx.navigation.compose.samples.AnimatedNav
+
+@Composable
+fun AnimatedDemo() {
+ AnimatedNav()
+}
diff --git a/navigation/navigation-compose/integration-tests/navigation-demos/src/main/java/androidx/navigation/compose/demos/NavigationDemos.kt b/navigation/navigation-compose/integration-tests/navigation-demos/src/main/java/androidx/navigation/compose/demos/NavigationDemos.kt
index 6e11a87..378f5b2 100644
--- a/navigation/navigation-compose/integration-tests/navigation-demos/src/main/java/androidx/navigation/compose/demos/NavigationDemos.kt
+++ b/navigation/navigation-compose/integration-tests/navigation-demos/src/main/java/androidx/navigation/compose/demos/NavigationDemos.kt
@@ -23,6 +23,7 @@
"Navigation",
listOf(
ComposableDemo("Basic Nav Demo") { BasicNavDemo() },
+ ComposableDemo("Animated Nav Demo") { AnimatedDemo() },
ComposableDemo("Nested Nav Start Destination Demo") { NestNavStartDestinationDemo() },
ComposableDemo("Nested Nav In Graph Demo") { NestNavInGraphDemo() },
ComposableDemo("Bottom Bar Nav Demo") { BottomBarNavDemo() },
diff --git a/navigation/navigation-compose/samples/build.gradle b/navigation/navigation-compose/samples/build.gradle
index 8b287c0..122c540 100644
--- a/navigation/navigation-compose/samples/build.gradle
+++ b/navigation/navigation-compose/samples/build.gradle
@@ -22,6 +22,7 @@
* modifying its settings.
*/
import androidx.build.LibraryType
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("AndroidXPlugin")
@@ -36,6 +37,7 @@
implementation(libs.kotlinStdlib)
compileOnly(project(":annotation:annotation-sampled"))
+ implementation(project(":compose:animation:animation"))
implementation("androidx.compose.foundation:foundation:1.0.1")
implementation("androidx.compose.ui:ui-tooling:1.4.0")
implementation(projectOrArtifact(":navigation:navigation-compose"))
@@ -52,6 +54,10 @@
description = "Samples for Compose integration with Navigation"
}
+tasks.withType(KotlinCompile).configureEach {
+ kotlinOptions.freeCompilerArgs += "-Xcontext-receivers"
+}
+
android {
namespace "androidx.navigation.compose.samples"
}
diff --git a/navigation/navigation-compose/samples/src/main/java/androidx/navigation/compose/samples/SharedElementSample.kt b/navigation/navigation-compose/samples/src/main/java/androidx/navigation/compose/samples/SharedElementSample.kt
new file mode 100644
index 0000000..9358d65
--- /dev/null
+++ b/navigation/navigation-compose/samples/src/main/java/androidx/navigation/compose/samples/SharedElementSample.kt
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2024 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.navigation.compose.samples
+
+import androidx.compose.animation.AnimatedContentScope
+import androidx.compose.animation.AnimatedContentTransitionScope.SlideDirection
+import androidx.compose.animation.ExperimentalSharedTransitionApi
+import androidx.compose.animation.SharedTransitionLayout
+import androidx.compose.animation.SharedTransitionScope
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.heightIn
+import androidx.compose.foundation.layout.offset
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.material.Button
+import androidx.compose.material.Text
+import androidx.compose.material.TopAppBar
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.alpha
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.unit.dp
+import androidx.navigation.compose.NavHost
+import androidx.navigation.compose.composable
+import androidx.navigation.compose.rememberNavController
+import kotlinx.serialization.Serializable
+
+@Serializable
+object Select
+
+@Serializable
+object SharedElement
+
+@Serializable
+object TopAppBarShared
+
+@Serializable
+object RedBox
+
+@Serializable
+object BlueBox
+
+@Serializable
+object First
+
+@Serializable
+object Second
+
+@Serializable
+object Third
+
+@Composable
+fun AnimatedNav() {
+ val navController = rememberNavController()
+ NavHost(navController, startDestination = Select) {
+ composable<Select> {
+ Column {
+ Box(
+ Modifier
+ .heightIn(min = 48.dp)
+ .fillMaxWidth()
+ .clickable(onClick = { navController.navigate(SharedElement) })
+ .padding(horizontal = 16.dp)
+ .wrapContentHeight(Alignment.CenterVertically),
+ contentAlignment = Alignment.CenterStart
+ ) { Text("AnimationNav") }
+ Box(
+ Modifier
+ .heightIn(min = 48.dp)
+ .fillMaxWidth()
+ .clickable(onClick = { navController.navigate(TopAppBarShared) })
+ .padding(horizontal = 16.dp)
+ .wrapContentHeight(Alignment.CenterVertically),
+ contentAlignment = Alignment.CenterStart
+ ) { Text("Top Bar Shared Element") }
+ }
+ }
+ composable<SharedElement> {
+ SharedElementAnimationNav()
+ }
+ composable<TopAppBarShared> {
+ TopAppBarElement()
+ }
+ }
+}
+
+@OptIn(ExperimentalSharedTransitionApi::class)
+@Composable
+fun SharedElementAnimationNav() {
+ val navController = rememberNavController()
+ SharedTransitionLayout {
+ val selectFirst = mutableStateOf(true)
+ NavHost(navController, startDestination = RedBox) {
+ composable<RedBox> {
+ RedBox(this, selectFirst) { navController.navigate(BlueBox) }
+ }
+ composable<BlueBox> {
+ BlueBox(this, selectFirst) { navController.popBackStack() }
+ }
+ }
+ }
+}
+
+context(SharedTransitionScope)
+@OptIn(ExperimentalSharedTransitionApi::class)
+@Composable
+fun RedBox(
+ scope: AnimatedContentScope,
+ selectFirst: MutableState<Boolean>,
+ onNavigate: () -> Unit
+) {
+ Box(
+ Modifier
+ .sharedBounds(
+ rememberSharedContentState("name"),
+ scope,
+ renderInOverlayDuringTransition = selectFirst.value
+ )
+ .clickable(onClick = {
+ selectFirst.value = !selectFirst.value
+ onNavigate()
+ })
+ .background(Color.Red)
+ .size(100.dp)
+ ) {
+ Text("start", color = Color.White)
+ }
+}
+
+context(SharedTransitionScope)
+@OptIn(ExperimentalSharedTransitionApi::class)
+@Composable
+fun BlueBox(
+ scope: AnimatedContentScope,
+ selectFirst: MutableState<Boolean>,
+ onPopBack: () -> Unit
+) {
+ Box(
+ Modifier
+ .offset(180.dp, 180.dp)
+ .sharedBounds(
+ rememberSharedContentState("name"),
+ scope,
+ renderInOverlayDuringTransition = !selectFirst.value
+ )
+ .clickable(onClick = {
+ selectFirst.value = !selectFirst.value
+ onPopBack()
+ })
+ .alpha(0.5f)
+ .background(Color.Blue)
+ .size(180.dp)
+ ) {
+ Text("finish", color = Color.White)
+ }
+}
+
+@OptIn(ExperimentalSharedTransitionApi::class)
+@Composable
+fun TopAppBarElement() {
+ val navController = rememberNavController()
+ SharedTransitionLayout {
+ NavHost(navController, startDestination = First) {
+ composable<First>(
+ enterTransition = { slideIntoContainer(SlideDirection.Right) },
+ exitTransition = { slideOutOfContainer(SlideDirection.Left) },
+ popExitTransition = { slideOutOfContainer(SlideDirection.Right) }
+ ) {
+ Column {
+ TopAppBar(
+ title = { Text("first") },
+ modifier = Modifier.sharedElement(
+ rememberSharedContentState("appBar"),
+ this@composable
+ )
+ )
+ Text("first", color = Color.White)
+ Button(onClick = { navController.navigate(Second) }) {
+ Text("Navigate to Second")
+ }
+ }
+ }
+ composable<Second>(
+ enterTransition = { slideIntoContainer(SlideDirection.Right) },
+ exitTransition = { slideOutOfContainer(SlideDirection.Left) },
+ popExitTransition = { slideOutOfContainer(SlideDirection.Right) }
+ ) {
+ Column {
+ TopAppBar(
+ title = { Text("second") },
+ modifier = Modifier.sharedElement(
+ rememberSharedContentState("appBar"),
+ this@composable
+ )
+ )
+ Text("second", color = Color.White)
+ Button(onClick = { navController.navigate(Third) }) {
+ Text("Navigate to Third")
+ }
+ }
+ }
+ composable<Third>(
+ enterTransition = { slideIntoContainer(SlideDirection.Right) },
+ exitTransition = { slideOutOfContainer(SlideDirection.Left) },
+ popExitTransition = { slideOutOfContainer(SlideDirection.Right) }
+ ) {
+ Column {
+ Text("third", color = Color.White)
+ Button(onClick = { navController.popBackStack<First>(false) }) {
+ Text("Pop back to First")
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigatorDestinationBuilder.kt b/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigatorDestinationBuilder.kt
index 80d1781..a1610b2 100644
--- a/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigatorDestinationBuilder.kt
+++ b/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigatorDestinationBuilder.kt
@@ -88,6 +88,7 @@
/**
* Construct a new [DynamicFragmentNavigator.Destination]
* @param route Destination route.
+ * @param builder the builder used to construct the fragment destination
*/
public inline fun <reified F : Fragment> DynamicNavGraphBuilder.fragment(
route: String,
@@ -98,6 +99,7 @@
* Construct a new [DynamicFragmentNavigator.Destination]
* @param route Destination route.
* @param fragmentClassName Fully qualified class name of destination Fragment.
+ * @param builder the builder used to construct the fragment destination
*/
public inline fun DynamicNavGraphBuilder.fragment(
route: String,
@@ -128,6 +130,7 @@
* @param T the destination's unique route from a [KClass]
* @param typeMap map of destination arguments' kotlin type [KType] to its respective custom
* [NavType]. May be empty if [T] does not use custom NavTypes.
+ * @param builder the builder used to construct the fragment destination
*/
public inline fun <reified F : Fragment, reified T : Any> DynamicNavGraphBuilder.fragment(
typeMap: Map<KType, @JvmSuppressWildcards NavType<*>> = emptyMap(),
@@ -141,6 +144,7 @@
* @param typeMap map of destination arguments' kotlin type [KType] to its respective custom
* [NavType]. May be empty if [T] does not use custom NavTypes.
* @param fragmentClassName Fully qualified class name of destination Fragment.
+ * @param builder the builder used to construct the fragment destination
*/
public inline fun <reified T : Any> DynamicNavGraphBuilder.fragment(
fragmentClassName: String,
diff --git a/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicActivityNavigatorDestinationBuilder.kt b/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicActivityNavigatorDestinationBuilder.kt
index 934f684..ba5e7a5 100644
--- a/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicActivityNavigatorDestinationBuilder.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicActivityNavigatorDestinationBuilder.kt
@@ -51,6 +51,7 @@
/**
* Construct a new [DynamicActivityNavigator.Destination]
* @param route Destination route.
+ * @param builder the builder used to construct the graph
*/
public inline fun DynamicNavGraphBuilder.activity(
route: String,
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
index d0b7a2e..5982b02 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
+++ b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
@@ -1287,6 +1287,8 @@
* The graph can be retrieved later via [graph].
*
* @param graph graph to set
+ * @param startDestinationArgs arguments to send to the start destination of the graph
+ *
* @see NavController.setGraph
* @see NavController.graph
*/
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/XPropertySpec.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/XPropertySpec.kt
index 520f3cd..241acff 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/XPropertySpec.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/XPropertySpec.kt
@@ -22,7 +22,10 @@
import androidx.room.compiler.codegen.java.toJavaVisibilityModifier
import androidx.room.compiler.codegen.kotlin.KotlinPropertySpec
import androidx.room.compiler.codegen.kotlin.toKotlinVisibilityModifier
+import androidx.room.compiler.processing.PropertySpecHelper
+import androidx.room.compiler.processing.XMethodElement
import androidx.room.compiler.processing.XNullability
+import androidx.room.compiler.processing.XType
import com.squareup.javapoet.FieldSpec
import com.squareup.kotlinpoet.PropertySpec
import javax.lang.model.element.Modifier
@@ -34,7 +37,26 @@
interface Builder : TargetLanguage {
fun addAnnotation(annotation: XAnnotationSpec): Builder
fun initializer(initExpr: XCodeBlock): Builder
+ fun getter(code: XCodeBlock): Builder
fun build(): XPropertySpec
+
+ companion object {
+ fun Builder.apply(
+ javaFieldBuilder: com.squareup.javapoet.FieldSpec.Builder.() -> Unit,
+ kotlinPropertyBuilder: com.squareup.kotlinpoet.PropertySpec.Builder.() -> Unit,
+ ): Builder = apply {
+ when (language) {
+ CodeLanguage.JAVA -> {
+ check(this is JavaPropertySpec.Builder)
+ this.actual.javaFieldBuilder()
+ }
+ CodeLanguage.KOTLIN -> {
+ check(this is KotlinPropertySpec.Builder)
+ this.actual.kotlinPropertyBuilder()
+ }
+ }
+ }
+ }
}
companion object {
@@ -74,19 +96,20 @@
}
}
- fun XPropertySpec.Builder.apply(
- javaFieldBuilder: com.squareup.javapoet.FieldSpec.Builder.() -> Unit,
- kotlinPropertyBuilder: com.squareup.kotlinpoet.PropertySpec.Builder.() -> Unit,
- ): XPropertySpec.Builder = apply {
- when (language) {
- CodeLanguage.JAVA -> {
- check(this is JavaPropertySpec.Builder)
- this.actual.javaFieldBuilder()
- }
- CodeLanguage.KOTLIN -> {
- check(this is KotlinPropertySpec.Builder)
- this.actual.kotlinPropertyBuilder()
- }
+ fun overridingBuilder(
+ language: CodeLanguage,
+ element: XMethodElement,
+ owner: XType
+ ): Builder {
+ require(element.isKotlinPropertyMethod())
+ return when (language) {
+ CodeLanguage.JAVA -> error(
+ "Overriding a property is not supported when code language is Java."
+ )
+ CodeLanguage.KOTLIN -> KotlinPropertySpec.Builder(
+ name = element.name,
+ actual = PropertySpecHelper.overriding(element, owner)
+ )
}
}
}
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/java/JavaPropertySpec.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/java/JavaPropertySpec.kt
index e0490e0..d065ef2 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/java/JavaPropertySpec.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/java/JavaPropertySpec.kt
@@ -41,6 +41,11 @@
actual.initializer(initExpr.actual)
}
+ override fun getter(code: XCodeBlock) = apply {
+ require(code is JavaCodeBlock)
+ error("Adding a property getter when code language is Java is not supported.")
+ }
+
override fun build(): XPropertySpec {
return JavaPropertySpec(name, actual.build())
}
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/kotlin/KotlinPropertySpec.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/kotlin/KotlinPropertySpec.kt
index 59d4c51..61f941e 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/kotlin/KotlinPropertySpec.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/codegen/kotlin/KotlinPropertySpec.kt
@@ -19,6 +19,7 @@
import androidx.room.compiler.codegen.XAnnotationSpec
import androidx.room.compiler.codegen.XCodeBlock
import androidx.room.compiler.codegen.XPropertySpec
+import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.PropertySpec
internal class KotlinPropertySpec(
@@ -41,6 +42,11 @@
actual.initializer(initExpr.actual)
}
+ override fun getter(code: XCodeBlock) = apply {
+ require(code is KotlinCodeBlock)
+ actual.getter(FunSpec.getterBuilder().addCode(code.actual).build())
+ }
+
override fun build(): XPropertySpec {
return KotlinPropertySpec(name, actual.build())
}
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/KotlinPoetExt.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/KotlinPoetExt.kt
index c2ae895..cee5df8 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/KotlinPoetExt.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/KotlinPoetExt.kt
@@ -21,6 +21,7 @@
import com.squareup.kotlinpoet.KModifier
import com.squareup.kotlinpoet.OriginatingElementsHolder
import com.squareup.kotlinpoet.ParameterizedTypeName
+import com.squareup.kotlinpoet.PropertySpec
import com.squareup.kotlinpoet.TypeName
import com.squareup.kotlinpoet.javapoet.KClassName
@@ -108,3 +109,36 @@
}
}
}
+
+object PropertySpecHelper {
+ fun overriding(
+ elm: XMethodElement,
+ owner: XType
+ ): PropertySpec.Builder {
+ require(elm.isKotlinPropertyMethod())
+ val asMember = elm.asMemberOf(owner)
+ return overriding(
+ executableElement = elm,
+ resolvedType = asMember
+ )
+ }
+
+ private fun overriding(
+ executableElement: XMethodElement,
+ resolvedType: XMethodType
+ ): PropertySpec.Builder {
+ return PropertySpec.builder(
+ name = checkNotNull(executableElement.propertyName),
+ type = resolvedType.returnType.asTypeName().kotlin
+ ).apply {
+ addModifiers(KModifier.OVERRIDE)
+ if (executableElement.isInternal()) {
+ addModifiers(KModifier.INTERNAL)
+ } else if (executableElement.isProtected()) {
+ addModifiers(KModifier.PROTECTED)
+ } else if (executableElement.isPublic()) {
+ addModifiers(KModifier.PUBLIC)
+ }
+ }
+ }
+}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/DatabaseProcessingStep.kt b/room/room-compiler/src/main/kotlin/androidx/room/DatabaseProcessingStep.kt
index 5a051fd..2d6d941 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/DatabaseProcessingStep.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/DatabaseProcessingStep.kt
@@ -33,6 +33,7 @@
import androidx.room.writer.DaoWriter
import androidx.room.writer.DatabaseWriter
import androidx.room.writer.InstantiateImplWriter
+import androidx.room.writer.TypeWriter
import java.nio.file.Path
class DatabaseProcessingStep : XProcessingStep {
@@ -96,8 +97,7 @@
DaoWriter(
dao = daoMethod.dao,
dbElement = db.element,
- codeLanguage = context.codeLanguage,
- javaLambdaSyntaxAvailable = context.javaLambdaSyntaxAvailable
+ writerContext = TypeWriter.WriterContext.fromProcessingContext(context)
).write(context.processingEnv)
}
}
@@ -105,8 +105,7 @@
databases?.forEach { db ->
DatabaseWriter(
database = db,
- codeLanguage = context.codeLanguage,
- javaLambdaSyntaxAvailable = context.javaLambdaSyntaxAvailable
+ writerContext = TypeWriter.WriterContext.fromProcessingContext(context)
).write(context.processingEnv)
if (db.exportSchema) {
val qName = db.element.qualifiedName
@@ -139,8 +138,7 @@
AutoMigrationWriter(
autoMigration = autoMigration,
dbElement = db.element,
- codeLanguage = context.codeLanguage,
- javaLambdaSyntaxAvailable = context.javaLambdaSyntaxAvailable
+ writerContext = TypeWriter.WriterContext.fromProcessingContext(context)
).write(context.processingEnv)
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/processor/DaoProcessor.kt b/room/room-compiler/src/main/kotlin/androidx/room/processor/DaoProcessor.kt
index 962c54a..c8bf673 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/processor/DaoProcessor.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/processor/DaoProcessor.kt
@@ -24,7 +24,6 @@
import androidx.room.Transaction
import androidx.room.Update
import androidx.room.Upsert
-import androidx.room.compiler.codegen.CodeLanguage
import androidx.room.compiler.processing.XConstructorElement
import androidx.room.compiler.processing.XMethodElement
import androidx.room.compiler.processing.XType
@@ -83,10 +82,19 @@
.filter {
it.isAbstract() && !it.hasKotlinDefaultImpl()
}.groupBy { method ->
- context.checker.check(
- PROCESSED_ANNOTATIONS.count { method.hasAnnotation(it) } <= 1, method,
- ProcessorErrors.INVALID_ANNOTATION_COUNT_IN_DAO_METHOD
- )
+ if (method.isKotlinPropertyMethod()) {
+ context.checker.check(
+ predicate = method.hasAnnotation(Query::class),
+ element = method,
+ errorMsg = ProcessorErrors.INVALID_ANNOTATION_IN_DAO_PROPERTY
+ )
+ } else {
+ context.checker.check(
+ predicate = PROCESSED_ANNOTATIONS.count { method.hasAnnotation(it) } <= 1,
+ element = method,
+ errorMsg = ProcessorErrors.INVALID_ANNOTATION_COUNT_IN_DAO_METHOD
+ )
+ }
if (method.hasAnnotation(JvmName::class)) {
context.logger.w(
Warning.JVM_NAME_ON_OVERRIDDEN_METHOD,
@@ -94,12 +102,6 @@
ProcessorErrors.JVM_NAME_ON_OVERRIDDEN_METHOD
)
}
- if (
- context.codeLanguage == CodeLanguage.KOTLIN &&
- method.isKotlinPropertyMethod()
- ) {
- context.logger.e(method, ProcessorErrors.KOTLIN_PROPERTY_OVERRIDE)
- }
if (method.hasAnnotation(Query::class)) {
Query::class
} else if (method.hasAnnotation(Insert::class)) {
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt b/room/room-compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
index 135ebb4..31b8ab0 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/processor/DatabaseProcessor.kt
@@ -18,7 +18,6 @@
import androidx.room.AutoMigration
import androidx.room.SkipQueryVerification
-import androidx.room.compiler.codegen.CodeLanguage
import androidx.room.compiler.codegen.XTypeName
import androidx.room.compiler.processing.XAnnotationBox
import androidx.room.compiler.processing.XElement
@@ -110,12 +109,6 @@
ProcessorErrors.JVM_NAME_ON_OVERRIDDEN_METHOD
)
}
- if (
- context.codeLanguage == CodeLanguage.KOTLIN &&
- executable.isKotlinPropertyMethod()
- ) {
- context.logger.e(executable, ProcessorErrors.KOTLIN_PROPERTY_OVERRIDE)
- }
val dao = DaoProcessor(context, daoElement, declaredType, dbVerifier)
.process()
DaoMethod(executable, dao)
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/processor/ProcessorErrors.kt b/room/room-compiler/src/main/kotlin/androidx/room/processor/ProcessorErrors.kt
index 5c711a60..1e4c3e7 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/processor/ProcessorErrors.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/processor/ProcessorErrors.kt
@@ -50,9 +50,11 @@
"room/Transaction.html"
val INVALID_ANNOTATION_COUNT_IN_DAO_METHOD = "An abstract DAO method must be" +
" annotated with one and only one of the following annotations: " +
- DaoProcessor.PROCESSED_ANNOTATIONS.joinToString(",") {
- it.java.simpleName
+ DaoProcessor.PROCESSED_ANNOTATIONS.joinToString(", ") {
+ "@" + it.java.simpleName
}
+ val INVALID_ANNOTATION_IN_DAO_PROPERTY = "An abstract DAO property must be" +
+ " annotated with @get:${Query::class.java}."
val CANNOT_RESOLVE_RETURN_TYPE = "Cannot resolve return type for %s"
val CANNOT_USE_UNBOUND_GENERICS_IN_QUERY_METHODS = "Cannot use unbound generics in query" +
" methods. It must be bound to a type through base Dao class."
@@ -1120,9 +1122,6 @@
ENTITY,
}
- val KOTLIN_PROPERTY_OVERRIDE = "Property getter overrides are not support when generating " +
- "Kotlin code, please rewrite as an abstract function."
-
val NONNULL_VOID = "Invalid non-null declaration of 'Void', should be nullable. The 'Void' " +
"class represents a placeholder type that is uninstantiable and 'null' is always returned."
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/solver/CodeGenScope.kt b/room/room-compiler/src/main/kotlin/androidx/room/solver/CodeGenScope.kt
index a11d2dc..1811d11 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/solver/CodeGenScope.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/solver/CodeGenScope.kt
@@ -27,8 +27,8 @@
// TODO(b/319660042): Remove once migration to driver API is done.
val useDriverApi: Boolean = false
) {
- val language = writer.codeLanguage
- val javaLambdaSyntaxAvailable = writer.javaLambdaSyntaxAvailable
+ val language = writer.context.codeLanguage
+ val javaLambdaSyntaxAvailable = writer.context.javaLambdaSyntaxAvailable
val builder by lazy { XCodeBlock.builder(language) }
private val tmpVarIndices = mutableMapOf<String, Int>()
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/vo/DaoMethod.kt b/room/room-compiler/src/main/kotlin/androidx/room/vo/DaoMethod.kt
index d89e0fd..b5a528b4 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/vo/DaoMethod.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/vo/DaoMethod.kt
@@ -21,4 +21,6 @@
/**
* References a method that returns a dao in a Database
*/
-data class DaoMethod(val element: XMethodElement, val dao: Dao)
+data class DaoMethod(val element: XMethodElement, val dao: Dao) {
+ val isProperty = element.isKotlinPropertyMethod()
+}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/vo/QueryMethod.kt b/room/room-compiler/src/main/kotlin/androidx/room/vo/QueryMethod.kt
index cfc5138..2d3e8cd 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/vo/QueryMethod.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/vo/QueryMethod.kt
@@ -61,7 +61,9 @@
parameters: List<QueryParameter>,
val inTransaction: Boolean,
val queryResultBinder: QueryResultBinder
-) : QueryMethod(element, query, returnType, parameters)
+) : QueryMethod(element, query, returnType, parameters) {
+ val isProperty = element.isKotlinPropertyMethod()
+}
/**
* A query method who's query is a INSERT, UPDATE or DELETE statement.
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/writer/AutoMigrationWriter.kt b/room/room-compiler/src/main/kotlin/androidx/room/writer/AutoMigrationWriter.kt
index 1ddb717..eb98374 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/writer/AutoMigrationWriter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/writer/AutoMigrationWriter.kt
@@ -40,9 +40,8 @@
class AutoMigrationWriter(
private val autoMigration: AutoMigration,
private val dbElement: XTypeElement,
- codeLanguage: CodeLanguage,
- javaLambdaSyntaxAvailable: Boolean
-) : TypeWriter(codeLanguage, javaLambdaSyntaxAvailable) {
+ writerContext: WriterContext,
+) : TypeWriter(writerContext) {
private val addedColumns = autoMigration.schemaDiff.addedColumns
private val addedTables = autoMigration.schemaDiff.addedTables
private val renamedTables = autoMigration.schemaDiff.renamedTables
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/writer/DaoWriter.kt b/room/room-compiler/src/main/kotlin/androidx/room/writer/DaoWriter.kt
index 352ab40..dd79bef 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/writer/DaoWriter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/writer/DaoWriter.kt
@@ -29,6 +29,7 @@
import androidx.room.compiler.codegen.XTypeSpec.Builder.Companion.addOriginatingElement
import androidx.room.compiler.processing.XElement
import androidx.room.compiler.processing.XMethodElement
+import androidx.room.compiler.processing.XProcessingEnv
import androidx.room.compiler.processing.XType
import androidx.room.ext.CommonTypeNames
import androidx.room.ext.RoomMemberNames
@@ -41,6 +42,7 @@
import androidx.room.ext.RoomTypeNames.UPSERT_ADAPTER
import androidx.room.ext.RoomTypeNames.UPSERT_ADAPTER_COMPAT
import androidx.room.ext.SupportDbTypeNames
+import androidx.room.ext.capitalize
import androidx.room.processor.OnConflictProcessor
import androidx.room.solver.CodeGenScope
import androidx.room.solver.KotlinBoxedPrimitiveMethodDelegateBinder
@@ -58,6 +60,9 @@
import androidx.room.vo.UpdateMethod
import androidx.room.vo.UpsertMethod
import androidx.room.vo.WriteQueryMethod
+import com.squareup.kotlinpoet.KModifier
+import com.squareup.kotlinpoet.jvm.jvmName
+import java.util.Locale
/**
* Creates the implementation for a class annotated with Dao.
@@ -65,9 +70,8 @@
class DaoWriter(
val dao: Dao,
private val dbElement: XElement,
- codeLanguage: CodeLanguage,
- javaLambdaSyntaxAvailable: Boolean
-) : TypeWriter(codeLanguage, javaLambdaSyntaxAvailable) {
+ writerContext: WriterContext,
+) : TypeWriter(writerContext) {
private val declaredDao = dao.element.type
// TODO nothing prevents this from conflicting, we should fix.
@@ -138,6 +142,10 @@
}
dao.queryMethods.filterIsInstance<ReadQueryMethod>().forEach { method ->
addFunction(createSelectMethod(method))
+ if (codeLanguage == CodeLanguage.KOTLIN && method.isProperty) {
+ // DAO function is a getter from a Kotlin property, generate property override.
+ addProperty(createSelectProperty(method))
+ }
}
preparedQueries.forEach {
addFunction(createPreparedQueryMethod(it))
@@ -282,10 +290,45 @@
private fun createSelectMethod(method: ReadQueryMethod): XFunSpec {
return overrideWithoutAnnotations(method.element, declaredDao)
+ .apply(
+ javaMethodBuilder = { },
+ kotlinFunctionBuilder = {
+ // TODO: Update XPoet to better handle this case.
+ if (method.isProperty) {
+ // When the DAO function is from a Kotlin property, we'll still generate
+ // a DAO function, but it won't be an override and it'll be private, to be
+ // called from the overridden property's getter.
+ modifiers.remove(KModifier.OVERRIDE)
+ modifiers.removeAll(
+ listOf(KModifier.PUBLIC, KModifier.INTERNAL, KModifier.PROTECTED)
+ )
+ addModifiers(KModifier.PRIVATE)
+
+ // For JVM emit a @JvmName to avoid same-signature conflict with
+ // actual property.
+ if (
+ context.targetPlatforms.size == 1 &&
+ context.targetPlatforms.contains(XProcessingEnv.Platform.JVM)
+ ) {
+ jvmName("_private${method.element.name.capitalize(Locale.US)}")
+ }
+ }
+ }
+ )
.addCode(createQueryMethodBody(method))
.build()
}
+ private fun createSelectProperty(method: ReadQueryMethod): XPropertySpec {
+ return XPropertySpec.overridingBuilder(
+ language = codeLanguage,
+ element = method.element,
+ owner = declaredDao
+ ).getter(
+ XCodeBlock.of(codeLanguage, "return %L()", method.element.name)
+ ).build()
+ }
+
private fun createRawQueryMethod(method: RawQueryMethod): XFunSpec {
val body = XCodeBlock.builder(codeLanguage).apply {
val scope = CodeGenScope(this@DaoWriter)
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/writer/DatabaseWriter.kt b/room/room-compiler/src/main/kotlin/androidx/room/writer/DatabaseWriter.kt
index 44206f5..0a8a740 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/writer/DatabaseWriter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/writer/DatabaseWriter.kt
@@ -23,7 +23,7 @@
import androidx.room.compiler.codegen.XFunSpec
import androidx.room.compiler.codegen.XFunSpec.Builder.Companion.addStatement
import androidx.room.compiler.codegen.XPropertySpec
-import androidx.room.compiler.codegen.XPropertySpec.Companion.apply
+import androidx.room.compiler.codegen.XPropertySpec.Builder.Companion.apply
import androidx.room.compiler.codegen.XTypeName
import androidx.room.compiler.codegen.XTypeSpec
import androidx.room.compiler.codegen.XTypeSpec.Builder.Companion.addOriginatingElement
@@ -44,9 +44,8 @@
*/
class DatabaseWriter(
val database: Database,
- codeLanguage: CodeLanguage,
- javaLambdaSyntaxAvailable: Boolean
-) : TypeWriter(codeLanguage, javaLambdaSyntaxAvailable) {
+ writerContext: WriterContext,
+) : TypeWriter(writerContext) {
override fun createTypeSpecBuilder(): XTypeSpec.Builder {
return XTypeSpec.classBuilder(codeLanguage, database.implTypeName).apply {
addOriginatingElement(database.element)
@@ -77,7 +76,7 @@
CodeLanguage.JAVA -> CommonTypeNames.JAVA_CLASS
CodeLanguage.KOTLIN -> CommonTypeNames.KOTLIN_CLASS
}.parametrizedBy(
- XTypeName.getProducerExtendsName(KotlinTypeNames.ANY)
+ XTypeName.ANY_WILDCARD
)
val typeConvertersTypeName = CommonTypeNames.MUTABLE_MAP.parametrizedBy(
classOfAnyTypeName,
@@ -89,7 +88,8 @@
CodeLanguage.JAVA -> addLocalVariable(
name = typeConvertersVar,
typeName = typeConvertersTypeName,
- assignExpr = XCodeBlock.ofNewInstance(codeLanguage,
+ assignExpr = XCodeBlock.ofNewInstance(
+ codeLanguage,
CommonTypeNames.HASH_MAP
.parametrizedBy(
classOfAnyTypeName,
@@ -362,7 +362,11 @@
kotlinPropertyBuilder = { }
).build()
builder.addProperty(privateDaoProperty)
- builder.addFunction(createDaoGetter(method, privateDaoProperty))
+ if (codeLanguage == CodeLanguage.KOTLIN && method.isProperty) {
+ builder.addProperty(createDaoProperty(method, privateDaoProperty))
+ } else {
+ builder.addFunction(createDaoGetter(method, privateDaoProperty))
+ }
}
}
@@ -410,6 +414,16 @@
}.build()
}
+ private fun createDaoProperty(method: DaoMethod, daoProperty: XPropertySpec): XPropertySpec {
+ return XPropertySpec.overridingBuilder(
+ language = codeLanguage,
+ element = method.element,
+ owner = database.type
+ ).getter(
+ XCodeBlock.of(codeLanguage, "return %L.value", daoProperty.name)
+ ).build()
+ }
+
private fun createOpenDelegate(): XFunSpec {
val scope = CodeGenScope(this)
val body = XCodeBlock.builder(codeLanguage).apply {
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/writer/TypeWriter.kt b/room/room-compiler/src/main/kotlin/androidx/room/writer/TypeWriter.kt
index 1700a64..74a01dc 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/writer/TypeWriter.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/writer/TypeWriter.kt
@@ -26,6 +26,7 @@
import androidx.room.compiler.codegen.XTypeSpec.Builder.Companion.apply
import androidx.room.compiler.processing.XProcessingEnv
import androidx.room.compiler.processing.writeTo
+import androidx.room.processor.Context
import androidx.room.solver.CodeGenScope
import com.squareup.kotlinpoet.javapoet.JAnnotationSpec
import com.squareup.kotlinpoet.javapoet.JClassName
@@ -36,10 +37,7 @@
/**
* Base class for all writers that can produce a class.
*/
-abstract class TypeWriter(
- val codeLanguage: CodeLanguage,
- val javaLambdaSyntaxAvailable: Boolean,
-) {
+abstract class TypeWriter(val context: WriterContext) {
private val sharedFieldSpecs = mutableMapOf<String, XPropertySpec>()
private val sharedMethodSpecs = mutableMapOf<String, XFunSpec>()
private val sharedFieldNames = mutableSetOf<String>()
@@ -47,6 +45,8 @@
private val metadata = mutableMapOf<KClass<*>, Any>()
+ val codeLanguage: CodeLanguage = context.codeLanguage
+
abstract fun createTypeSpecBuilder(): XTypeSpec.Builder
/**
@@ -200,4 +200,19 @@
return builder.build()
}
}
+
+ class WriterContext(
+ val codeLanguage: CodeLanguage,
+ val targetPlatforms: Set<XProcessingEnv.Platform>,
+ val javaLambdaSyntaxAvailable: Boolean
+ ) {
+ companion object {
+ fun fromProcessingContext(context: Context) =
+ WriterContext(
+ codeLanguage = context.codeLanguage,
+ targetPlatforms = context.processingEnv.targetPlatforms,
+ javaLambdaSyntaxAvailable = context.javaLambdaSyntaxAvailable
+ )
+ }
+ }
}
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/processor/BaseDaoTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/processor/BaseDaoTest.kt
index a680f2d..e525fbe 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/processor/BaseDaoTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/processor/BaseDaoTest.kt
@@ -2,11 +2,13 @@
import COMMON
import androidx.room.compiler.codegen.CodeLanguage
+import androidx.room.compiler.processing.XProcessingEnv
import androidx.room.compiler.processing.util.Source
import androidx.room.compiler.processing.util.runProcessorTest
import androidx.room.testing.context
import androidx.room.vo.Dao
import androidx.room.writer.DaoWriter
+import androidx.room.writer.TypeWriter
import org.hamcrest.CoreMatchers.`is`
import org.hamcrest.MatcherAssert.assertThat
import org.junit.Test
@@ -219,8 +221,15 @@
val processed = DaoProcessor(
invocation.context, dao, dbType, null
).process()
- DaoWriter(processed, dbElm, CodeLanguage.JAVA, false)
- .write(invocation.processingEnv)
+ DaoWriter(
+ dao = processed,
+ dbElement = dbElm,
+ writerContext = TypeWriter.WriterContext(
+ codeLanguage = CodeLanguage.JAVA,
+ javaLambdaSyntaxAvailable = false,
+ targetPlatforms = setOf(XProcessingEnv.Platform.JVM)
+ )
+ ).write(invocation.processingEnv)
}
}
}
@@ -270,8 +279,15 @@
invocation.context, daoElm, dbType, null
).process()
handler(processedDao)
- DaoWriter(processedDao, dbElm, CodeLanguage.JAVA, false)
- .write(invocation.processingEnv)
+ DaoWriter(
+ dao = processedDao,
+ dbElement = dbElm,
+ writerContext = TypeWriter.WriterContext(
+ codeLanguage = CodeLanguage.JAVA,
+ javaLambdaSyntaxAvailable = false,
+ targetPlatforms = setOf(XProcessingEnv.Platform.JVM)
+ )
+ ).write(invocation.processingEnv)
}
}
}
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/processor/DaoProcessorTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/processor/DaoProcessorTest.kt
index 24b55f7..87ff783 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/processor/DaoProcessorTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/processor/DaoProcessorTest.kt
@@ -475,7 +475,82 @@
}
@Test
- fun disallowPropertyDao() {
+ fun allowDaoQueryProperty() {
+ val src = Source.kotlin(
+ "MyDatabase.kt",
+ """
+ import androidx.room.*
+
+ @Dao
+ interface MyDao {
+ @get:Query("SELECT * FROM MyEntity")
+ val allEntities: List<MyEntity>
+ }
+
+ @Entity
+ data class MyEntity(
+ @PrimaryKey
+ var pk: Int
+ )
+ """.trimIndent()
+ )
+ runKspTest(
+ sources = listOf(src),
+ options = mapOf(Context.BooleanProcessorOptions.GENERATE_KOTLIN.argName to "true"),
+ ) { invocation ->
+ val dao = invocation.processingEnv.requireTypeElement("MyDao")
+ val dbType = invocation.context.processingEnv.requireType(ROOM_DB)
+ DaoProcessor(
+ baseContext = invocation.context,
+ element = dao,
+ dbType = dbType,
+ dbVerifier = null
+ ).process()
+ invocation.assertCompilationResult {
+ hasNoWarnings()
+ }
+ }
+ }
+
+ @Test
+ fun missingAnnotationInDaoProperty() {
+ val src = Source.kotlin(
+ "MyDatabase.kt",
+ """
+ import androidx.room.*
+
+ @Dao
+ interface MyDao {
+ val allEntities: List<MyEntity>
+ }
+
+ @Entity
+ data class MyEntity(
+ @PrimaryKey
+ var pk: Int
+ )
+ """.trimIndent()
+ )
+ runKspTest(
+ sources = listOf(src),
+ options = mapOf(Context.BooleanProcessorOptions.GENERATE_KOTLIN.argName to "true"),
+ ) { invocation ->
+ val dao = invocation.processingEnv.requireTypeElement("MyDao")
+ val dbType = invocation.context.processingEnv.requireType(ROOM_DB)
+ DaoProcessor(
+ baseContext = invocation.context,
+ element = dao,
+ dbType = dbType,
+ dbVerifier = null
+ ).process()
+ invocation.assertCompilationResult {
+ hasErrorContaining(ProcessorErrors.INVALID_ANNOTATION_IN_DAO_PROPERTY)
+ }
+ }
+ }
+
+ @Test
+ fun missplacedAnnotationInDaoProperty() {
val src = Source.kotlin(
"MyDatabase.kt",
"""
@@ -507,7 +582,7 @@
dbVerifier = null
).process()
invocation.assertCompilationResult {
- hasErrorContaining(ProcessorErrors.KOTLIN_PROPERTY_OVERRIDE)
+ hasErrorContaining(ProcessorErrors.INVALID_ANNOTATION_IN_DAO_PROPERTY)
}
}
}
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/processor/DatabaseProcessorTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/processor/DatabaseProcessorTest.kt
index 63fd4dc..7d9e374 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/processor/DatabaseProcessorTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/processor/DatabaseProcessorTest.kt
@@ -1559,7 +1559,7 @@
}
@Test
- fun disallowPropertyDao() {
+ fun allowPropertyDao() {
val src = Source.kotlin(
"MyDatabase.kt",
"""
@@ -1593,7 +1593,7 @@
element = element
).process()
invocation.assertCompilationResult {
- hasErrorContaining(ProcessorErrors.KOTLIN_PROPERTY_OVERRIDE)
+ hasNoWarnings()
}
}
}
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/solver/CustomTypeConverterResolutionTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/solver/CustomTypeConverterResolutionTest.kt
index c188e08..f4ade0b 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/solver/CustomTypeConverterResolutionTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/solver/CustomTypeConverterResolutionTest.kt
@@ -35,7 +35,6 @@
import androidx.room.ext.CommonTypeNames
import androidx.room.ext.RoomAnnotationTypeNames
import androidx.room.ext.RoomTypeNames.ROOM_DB
-import androidx.room.processor.Context
import androidx.room.processor.ProcessorErrors.CANNOT_BIND_QUERY_PARAMETER_INTO_STMT
import org.junit.Test
import org.junit.runner.RunWith
@@ -260,7 +259,6 @@
runProcessorTest(
sources = sources + CUSTOM_TYPE_JFO + CUSTOM_TYPE_CONVERTER_JFO +
CUSTOM_TYPE_SET_CONVERTER_JFO,
- options = mapOf(Context.BooleanProcessorOptions.GENERATE_KOTLIN.argName to "false"),
createProcessingSteps = {
listOf(DatabaseProcessingStep())
},
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/solver/NullabilityAwareTypeConverterStoreTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/solver/NullabilityAwareTypeConverterStoreTest.kt
index d8a127c..01bb8af1 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/solver/NullabilityAwareTypeConverterStoreTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/solver/NullabilityAwareTypeConverterStoreTest.kt
@@ -19,6 +19,7 @@
import androidx.kruth.assertThat
import androidx.room.RoomKspProcessor
import androidx.room.compiler.codegen.CodeLanguage
+import androidx.room.compiler.processing.XProcessingEnv
import androidx.room.compiler.processing.XType
import androidx.room.compiler.processing.util.Source
import androidx.room.compiler.processing.util.XTestInvocation
@@ -34,6 +35,7 @@
import androidx.room.testing.context
import androidx.room.vo.BuiltInConverterFlags
import androidx.room.writer.DaoWriter
+import androidx.room.writer.TypeWriter
import javax.tools.Diagnostic
import org.junit.Rule
import org.junit.Test
@@ -402,8 +404,11 @@
dao = daoProcessor.process(),
dbElement = invocation.processingEnv
.requireTypeElement("androidx.room.RoomDatabase"),
- codeLanguage = CodeLanguage.JAVA,
- javaLambdaSyntaxAvailable = false
+ writerContext = TypeWriter.WriterContext(
+ codeLanguage = CodeLanguage.JAVA,
+ javaLambdaSyntaxAvailable = false,
+ targetPlatforms = setOf(XProcessingEnv.Platform.JVM)
+ )
).write(invocation.processingEnv)
invocation.assertCompilationResult {
generatedSourceFileWithPath("MyDao_Impl.java").let {
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/testing/test_util.kt b/room/room-compiler/src/test/kotlin/androidx/room/testing/test_util.kt
index 2a63f03..fbc3252 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/testing/test_util.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/testing/test_util.kt
@@ -21,6 +21,7 @@
import androidx.room.compiler.codegen.XTypeSpec
import androidx.room.compiler.processing.XElement
import androidx.room.compiler.processing.XFieldElement
+import androidx.room.compiler.processing.XProcessingEnv.Platform
import androidx.room.compiler.processing.XType
import androidx.room.compiler.processing.XTypeElement
import androidx.room.compiler.processing.util.Source
@@ -332,7 +333,9 @@
fun testCodeGenScope(): CodeGenScope {
return CodeGenScope(
- object : TypeWriter(CodeLanguage.JAVA, true) {
+ object : TypeWriter(
+ WriterContext(CodeLanguage.JAVA, setOf(Platform.JVM), true)
+ ) {
override fun createTypeSpecBuilder(): XTypeSpec.Builder {
return XTypeSpec.classBuilder(codeLanguage, XClassName.get("test", "Foo"))
}
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/writer/AutoMigrationWriterTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/writer/AutoMigrationWriterTest.kt
index 298b09e..c553782 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/writer/AutoMigrationWriterTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/writer/AutoMigrationWriterTest.kt
@@ -17,6 +17,7 @@
package androidx.room.writer
import androidx.room.compiler.codegen.CodeLanguage
+import androidx.room.compiler.processing.XProcessingEnv
import androidx.room.compiler.processing.util.Source
import androidx.room.compiler.processing.util.XTestInvocation
import androidx.room.compiler.processing.util.runJavaProcessorTest
@@ -114,8 +115,11 @@
autoMigration = autoMigrationResultWithNewAddedColumn,
dbElement =
invocation.processingEnv.requireTypeElement("foo.bar.MyDatabase"),
- codeLanguage = codeLanguage,
- javaLambdaSyntaxAvailable = false
+ writerContext = TypeWriter.WriterContext(
+ codeLanguage = codeLanguage,
+ javaLambdaSyntaxAvailable = false,
+ targetPlatforms = setOf(XProcessingEnv.Platform.JVM)
+ )
).write(invocation.processingEnv)
val expectedFile = when (codeLanguage) {
@@ -190,8 +194,11 @@
autoMigration = autoMigrationResultWithNewAddedColumn,
dbElement =
invocation.processingEnv.requireTypeElement("foo.bar.MyDatabase"),
- codeLanguage = codeLanguage,
- javaLambdaSyntaxAvailable = false
+ writerContext = TypeWriter.WriterContext(
+ codeLanguage = codeLanguage,
+ javaLambdaSyntaxAvailable = false,
+ targetPlatforms = setOf(XProcessingEnv.Platform.JVM)
+ )
).write(invocation.processingEnv)
val expectedFile = when (codeLanguage) {
@@ -274,8 +281,11 @@
autoMigration = autoMigrationResultWithNewAddedColumn,
dbElement =
invocation.processingEnv.requireTypeElement("foo.bar.MyDatabase"),
- codeLanguage = codeLanguage,
- javaLambdaSyntaxAvailable = false
+ writerContext = TypeWriter.WriterContext(
+ codeLanguage = codeLanguage,
+ javaLambdaSyntaxAvailable = false,
+ targetPlatforms = setOf(XProcessingEnv.Platform.JVM)
+ )
).write(invocation.processingEnv)
val expectedFile = when (codeLanguage) {
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/writer/DaoKotlinCodeGenTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/writer/DaoKotlinCodeGenTest.kt
index 786c995..dbae386 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/writer/DaoKotlinCodeGenTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/writer/DaoKotlinCodeGenTest.kt
@@ -2412,4 +2412,30 @@
expectedFilePath = getTestGoldenPath(testName.methodName)
)
}
+
+ @Test
+ fun overridePropertyQuery() {
+ val src = Source.kotlin(
+ "MyDao.kt",
+ """
+ import androidx.room.*
+
+ @Dao
+ interface MyDao {
+ @get:Query("SELECT * FROM MyEntity")
+ val entities: List<MyEntity>
+ }
+
+ @Entity
+ data class MyEntity(
+ @PrimaryKey
+ val pk: Int
+ )
+ """.trimIndent()
+ )
+ runTest(
+ sources = listOf(src, databaseSrc),
+ expectedFilePath = getTestGoldenPath(testName.methodName)
+ )
+ }
}
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/writer/DaoWriterTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/writer/DaoWriterTest.kt
index 7643c91..8872607 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/writer/DaoWriterTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/writer/DaoWriterTest.kt
@@ -18,6 +18,7 @@
import COMMON
import androidx.room.compiler.codegen.CodeLanguage
+import androidx.room.compiler.processing.XProcessingEnv
import androidx.room.compiler.processing.XTypeElement
import androidx.room.compiler.processing.util.Source
import androidx.room.compiler.processing.util.XTestInvocation
@@ -154,8 +155,15 @@
dbVerifier = dbVerifier
)
val parsedDao = parser.process()
- DaoWriter(parsedDao, db, CodeLanguage.JAVA, javaLambdaSyntaxAvailable)
- .write(invocation.processingEnv)
+ DaoWriter(
+ dao = parsedDao,
+ dbElement = db,
+ writerContext = TypeWriter.WriterContext(
+ codeLanguage = CodeLanguage.JAVA,
+ javaLambdaSyntaxAvailable = javaLambdaSyntaxAvailable,
+ targetPlatforms = setOf(XProcessingEnv.Platform.JVM)
+ )
+ ).write(invocation.processingEnv)
val outputSubFolder = outputFolder(invocation, javaLambdaSyntaxAvailable)
invocation.assertCompilationResult {
val expectedFilePath = "daoWriter/output/$outputSubFolder/$outputFileName"
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/writer/DatabaseKotlinCodeGenTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/writer/DatabaseKotlinCodeGenTest.kt
index 9bb0578..fa0ce7f 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/writer/DatabaseKotlinCodeGenTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/writer/DatabaseKotlinCodeGenTest.kt
@@ -160,6 +160,81 @@
)
}
+ @Test
+ fun database_javaSource() {
+ val dbSrc = Source.java(
+ "MyDatabase",
+ """
+ import androidx.room.*;
+
+ @Database(entities = { MyEntity.class }, version = 1, exportSchema = false)
+ public abstract class MyDatabase extends RoomDatabase {
+ abstract MyDao getDao();
+ }
+ """.trimIndent()
+ )
+ val daoSrc = Source.java(
+ "MyDao",
+ """
+ import androidx.annotation.NonNull;
+ import androidx.room.*;
+
+ @Dao
+ public interface MyDao {
+ @Query("SELECT * FROM MyEntity")
+ @NonNull MyEntity getEntity();
+ }
+ """.trimIndent()
+ )
+ val entitySrc = Source.java(
+ "MyEntity",
+ """
+ import androidx.room.*;
+
+ @Entity
+ public class MyEntity {
+ @PrimaryKey
+ public int pk;
+ }
+ """.trimIndent()
+ )
+ runTest(
+ sources = listOf(dbSrc, daoSrc, entitySrc),
+ expectedFilePath = getTestGoldenPath(testName.methodName)
+ )
+ }
+
+ @Test
+ fun database_daoProperty() {
+ val src = Source.kotlin(
+ "MyDatabase.kt",
+ """
+ import androidx.room.*
+
+ @Database(entities = [MyEntity::class], version = 1, exportSchema = false)
+ abstract class MyDatabase : RoomDatabase() {
+ abstract val dao: MyDao
+ }
+
+ @Dao
+ abstract class MyDao {
+ @Query("SELECT * FROM MyEntity")
+ abstract fun getEntity(): MyEntity
+ }
+
+ @Entity
+ data class MyEntity(
+ @PrimaryKey
+ val pk: Int
+ )
+ """.trimIndent()
+ )
+ runTest(
+ sources = listOf(src),
+ expectedFilePath = getTestGoldenPath(testName.methodName)
+ )
+ }
+
private fun getTestGoldenPath(testName: String): String {
return "kotlinCodeGen/$testName.kt"
}
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/writer/DefaultsInDaoTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/writer/DefaultsInDaoTest.kt
index 5600862..4692faa 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/writer/DefaultsInDaoTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/writer/DefaultsInDaoTest.kt
@@ -18,6 +18,7 @@
import COMMON
import androidx.room.compiler.codegen.CodeLanguage
+import androidx.room.compiler.processing.XProcessingEnv
import androidx.room.compiler.processing.XTypeElement
import androidx.room.compiler.processing.util.Source
import androidx.room.compiler.processing.util.runProcessorTest
@@ -195,8 +196,15 @@
dbVerifier = createVerifierFromEntitiesAndViews(invocation)
)
val parsedDao = parser.process()
- DaoWriter(parsedDao, db, CodeLanguage.JAVA, true)
- .write(invocation.processingEnv)
+ DaoWriter(
+ dao = parsedDao,
+ dbElement = db,
+ writerContext = TypeWriter.WriterContext(
+ codeLanguage = CodeLanguage.JAVA,
+ javaLambdaSyntaxAvailable = true,
+ targetPlatforms = setOf(XProcessingEnv.Platform.JVM)
+ )
+ ).write(invocation.processingEnv)
invocation.assertCompilationResult {
val relativePath =
parsedDao.implTypeName.canonicalName + ".java"
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/writer/EntityCursorConverterWriterTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/writer/EntityCursorConverterWriterTest.kt
index 76d5b76..dcbfab3 100644
--- a/room/room-compiler/src/test/kotlin/androidx/room/writer/EntityCursorConverterWriterTest.kt
+++ b/room/room-compiler/src/test/kotlin/androidx/room/writer/EntityCursorConverterWriterTest.kt
@@ -20,6 +20,7 @@
import androidx.room.compiler.codegen.XClassName
import androidx.room.compiler.codegen.XTypeSpec
import androidx.room.compiler.codegen.XTypeSpec.Builder.Companion.apply
+import androidx.room.compiler.processing.XProcessingEnv.Platform
import androidx.room.compiler.processing.util.Source
import androidx.room.compiler.processing.util.XTestInvocation
import androidx.room.processor.BaseEntityParserTest
@@ -122,7 +123,9 @@
) {
singleEntity(input) { entity, invocation ->
val className = XClassName.get("foo.bar", "MyContainerClass")
- val writer = object : TypeWriter(CodeLanguage.JAVA, true) {
+ val writer = object : TypeWriter(
+ WriterContext(CodeLanguage.JAVA, setOf(Platform.JVM), true)
+ ) {
override fun createTypeSpecBuilder(): XTypeSpec.Builder {
getOrCreateFunction(EntityCursorConverterWriter(entity))
return XTypeSpec.classBuilder(codeLanguage, className)
diff --git a/room/room-compiler/src/test/test-data/kotlinCodeGen/database_daoProperty.kt b/room/room-compiler/src/test/test-data/kotlinCodeGen/database_daoProperty.kt
new file mode 100644
index 0000000..b2b2e71
--- /dev/null
+++ b/room/room-compiler/src/test/test-data/kotlinCodeGen/database_daoProperty.kt
@@ -0,0 +1,115 @@
+import androidx.room.InvalidationTracker
+import androidx.room.RoomOpenDelegate
+import androidx.room.migration.AutoMigrationSpec
+import androidx.room.migration.Migration
+import androidx.room.util.TableInfo
+import androidx.room.util.TableInfo.Companion.read
+import androidx.room.util.dropFtsSyncTriggers
+import androidx.sqlite.SQLiteConnection
+import androidx.sqlite.execSQL
+import javax.`annotation`.processing.Generated
+import kotlin.Lazy
+import kotlin.String
+import kotlin.Suppress
+import kotlin.collections.List
+import kotlin.collections.Map
+import kotlin.collections.MutableList
+import kotlin.collections.MutableMap
+import kotlin.collections.MutableSet
+import kotlin.collections.Set
+import kotlin.collections.mutableListOf
+import kotlin.collections.mutableMapOf
+import kotlin.collections.mutableSetOf
+import kotlin.reflect.KClass
+
+@Generated(value = ["androidx.room.RoomProcessor"])
+@Suppress(names = ["UNCHECKED_CAST", "DEPRECATION", "REDUNDANT_PROJECTION", "REMOVAL"])
+public class MyDatabase_Impl : MyDatabase() {
+ private val _myDao: Lazy<MyDao> = lazy {
+ MyDao_Impl(this)
+ }
+
+
+ public override val dao: MyDao
+ get() = _myDao.value
+
+ protected override fun createOpenDelegate(): RoomOpenDelegate {
+ val _openDelegate: RoomOpenDelegate = object : RoomOpenDelegate(1,
+ "195d7974660177325bd1a32d2c7b8b8c", "7458a901120796c5bbc554e2fefd262f") {
+ public override fun createAllTables(connection: SQLiteConnection) {
+ connection.execSQL("CREATE TABLE IF NOT EXISTS `MyEntity` (`pk` INTEGER NOT NULL, PRIMARY KEY(`pk`))")
+ connection.execSQL("CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)")
+ connection.execSQL("INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '195d7974660177325bd1a32d2c7b8b8c')")
+ }
+
+ public override fun dropAllTables(connection: SQLiteConnection) {
+ connection.execSQL("DROP TABLE IF EXISTS `MyEntity`")
+ }
+
+ public override fun onCreate(connection: SQLiteConnection) {
+ }
+
+ public override fun onOpen(connection: SQLiteConnection) {
+ internalInitInvalidationTracker(connection)
+ }
+
+ public override fun onPreMigrate(connection: SQLiteConnection) {
+ dropFtsSyncTriggers(connection)
+ }
+
+ public override fun onPostMigrate(connection: SQLiteConnection) {
+ }
+
+ public override fun onValidateSchema(connection: SQLiteConnection):
+ RoomOpenDelegate.ValidationResult {
+ val _columnsMyEntity: MutableMap<String, TableInfo.Column> = mutableMapOf()
+ _columnsMyEntity.put("pk", TableInfo.Column("pk", "INTEGER", true, 1, null,
+ TableInfo.CREATED_FROM_ENTITY))
+ val _foreignKeysMyEntity: MutableSet<TableInfo.ForeignKey> = mutableSetOf()
+ val _indicesMyEntity: MutableSet<TableInfo.Index> = mutableSetOf()
+ val _infoMyEntity: TableInfo = TableInfo("MyEntity", _columnsMyEntity, _foreignKeysMyEntity,
+ _indicesMyEntity)
+ val _existingMyEntity: TableInfo = read(connection, "MyEntity")
+ if (!_infoMyEntity.equals(_existingMyEntity)) {
+ return RoomOpenDelegate.ValidationResult(false, """
+ |MyEntity(MyEntity).
+ | Expected:
+ |""".trimMargin() + _infoMyEntity + """
+ |
+ | Found:
+ |""".trimMargin() + _existingMyEntity)
+ }
+ return RoomOpenDelegate.ValidationResult(true, null)
+ }
+ }
+ return _openDelegate
+ }
+
+ protected override fun createInvalidationTracker(): InvalidationTracker {
+ val _shadowTablesMap: MutableMap<String, String> = mutableMapOf()
+ val _viewTables: MutableMap<String, Set<String>> = mutableMapOf()
+ return InvalidationTracker(this, _shadowTablesMap, _viewTables, "MyEntity")
+ }
+
+ public override fun clearAllTables() {
+ super.performClear(false, "MyEntity")
+ }
+
+ protected override fun getRequiredTypeConverterClasses(): Map<KClass<*>, List<KClass<*>>> {
+ val _typeConvertersMap: MutableMap<KClass<*>, List<KClass<*>>> = mutableMapOf()
+ _typeConvertersMap.put(MyDao::class, MyDao_Impl.getRequiredConverters())
+ return _typeConvertersMap
+ }
+
+ public override fun getRequiredAutoMigrationSpecClasses(): Set<KClass<out AutoMigrationSpec>> {
+ val _autoMigrationSpecsSet: MutableSet<KClass<out AutoMigrationSpec>> = mutableSetOf()
+ return _autoMigrationSpecsSet
+ }
+
+ public override
+ fun createAutoMigrations(autoMigrationSpecs: Map<KClass<out AutoMigrationSpec>, AutoMigrationSpec>):
+ List<Migration> {
+ val _autoMigrations: MutableList<Migration> = mutableListOf()
+ return _autoMigrations
+ }
+}
diff --git a/room/room-compiler/src/test/test-data/kotlinCodeGen/database_internalVisibility.kt b/room/room-compiler/src/test/test-data/kotlinCodeGen/database_internalVisibility.kt
index 3febf79..1af517e 100644
--- a/room/room-compiler/src/test/test-data/kotlinCodeGen/database_internalVisibility.kt
+++ b/room/room-compiler/src/test/test-data/kotlinCodeGen/database_internalVisibility.kt
@@ -8,7 +8,6 @@
import androidx.sqlite.SQLiteConnection
import androidx.sqlite.execSQL
import javax.`annotation`.processing.Generated
-import kotlin.Any
import kotlin.Lazy
import kotlin.String
import kotlin.Suppress
@@ -93,9 +92,8 @@
super.performClear(false, "MyEntity")
}
- protected override fun getRequiredTypeConverterClasses():
- Map<KClass<out Any>, List<KClass<out Any>>> {
- val _typeConvertersMap: MutableMap<KClass<out Any>, List<KClass<out Any>>> = mutableMapOf()
+ protected override fun getRequiredTypeConverterClasses(): Map<KClass<*>, List<KClass<*>>> {
+ val _typeConvertersMap: MutableMap<KClass<*>, List<KClass<*>>> = mutableMapOf()
_typeConvertersMap.put(MyDao::class, MyDao_Impl.getRequiredConverters())
return _typeConvertersMap
}
diff --git a/room/room-compiler/src/test/test-data/kotlinCodeGen/database_javaSource.kt b/room/room-compiler/src/test/test-data/kotlinCodeGen/database_javaSource.kt
new file mode 100644
index 0000000..3781f68
--- /dev/null
+++ b/room/room-compiler/src/test/test-data/kotlinCodeGen/database_javaSource.kt
@@ -0,0 +1,114 @@
+import androidx.room.InvalidationTracker
+import androidx.room.RoomOpenDelegate
+import androidx.room.migration.AutoMigrationSpec
+import androidx.room.migration.Migration
+import androidx.room.util.TableInfo
+import androidx.room.util.TableInfo.Companion.read
+import androidx.room.util.dropFtsSyncTriggers
+import androidx.sqlite.SQLiteConnection
+import androidx.sqlite.execSQL
+import javax.`annotation`.processing.Generated
+import kotlin.Lazy
+import kotlin.String
+import kotlin.Suppress
+import kotlin.collections.List
+import kotlin.collections.Map
+import kotlin.collections.MutableList
+import kotlin.collections.MutableMap
+import kotlin.collections.MutableSet
+import kotlin.collections.Set
+import kotlin.collections.mutableListOf
+import kotlin.collections.mutableMapOf
+import kotlin.collections.mutableSetOf
+import kotlin.reflect.KClass
+
+@Generated(value = ["androidx.room.RoomProcessor"])
+@Suppress(names = ["UNCHECKED_CAST", "DEPRECATION", "REDUNDANT_PROJECTION", "REMOVAL"])
+public class MyDatabase_Impl : MyDatabase() {
+ private val _myDao: Lazy<MyDao> = lazy {
+ MyDao_Impl(this)
+ }
+
+
+ protected override fun createOpenDelegate(): RoomOpenDelegate {
+ val _openDelegate: RoomOpenDelegate = object : RoomOpenDelegate(1,
+ "195d7974660177325bd1a32d2c7b8b8c", "7458a901120796c5bbc554e2fefd262f") {
+ public override fun createAllTables(connection: SQLiteConnection) {
+ connection.execSQL("CREATE TABLE IF NOT EXISTS `MyEntity` (`pk` INTEGER NOT NULL, PRIMARY KEY(`pk`))")
+ connection.execSQL("CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)")
+ connection.execSQL("INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '195d7974660177325bd1a32d2c7b8b8c')")
+ }
+
+ public override fun dropAllTables(connection: SQLiteConnection) {
+ connection.execSQL("DROP TABLE IF EXISTS `MyEntity`")
+ }
+
+ public override fun onCreate(connection: SQLiteConnection) {
+ }
+
+ public override fun onOpen(connection: SQLiteConnection) {
+ internalInitInvalidationTracker(connection)
+ }
+
+ public override fun onPreMigrate(connection: SQLiteConnection) {
+ dropFtsSyncTriggers(connection)
+ }
+
+ public override fun onPostMigrate(connection: SQLiteConnection) {
+ }
+
+ public override fun onValidateSchema(connection: SQLiteConnection):
+ RoomOpenDelegate.ValidationResult {
+ val _columnsMyEntity: MutableMap<String, TableInfo.Column> = mutableMapOf()
+ _columnsMyEntity.put("pk", TableInfo.Column("pk", "INTEGER", true, 1, null,
+ TableInfo.CREATED_FROM_ENTITY))
+ val _foreignKeysMyEntity: MutableSet<TableInfo.ForeignKey> = mutableSetOf()
+ val _indicesMyEntity: MutableSet<TableInfo.Index> = mutableSetOf()
+ val _infoMyEntity: TableInfo = TableInfo("MyEntity", _columnsMyEntity, _foreignKeysMyEntity,
+ _indicesMyEntity)
+ val _existingMyEntity: TableInfo = read(connection, "MyEntity")
+ if (!_infoMyEntity.equals(_existingMyEntity)) {
+ return RoomOpenDelegate.ValidationResult(false, """
+ |MyEntity(MyEntity).
+ | Expected:
+ |""".trimMargin() + _infoMyEntity + """
+ |
+ | Found:
+ |""".trimMargin() + _existingMyEntity)
+ }
+ return RoomOpenDelegate.ValidationResult(true, null)
+ }
+ }
+ return _openDelegate
+ }
+
+ protected override fun createInvalidationTracker(): InvalidationTracker {
+ val _shadowTablesMap: MutableMap<String, String> = mutableMapOf()
+ val _viewTables: MutableMap<String, Set<String>> = mutableMapOf()
+ return InvalidationTracker(this, _shadowTablesMap, _viewTables, "MyEntity")
+ }
+
+ public override fun clearAllTables() {
+ super.performClear(false, "MyEntity")
+ }
+
+ protected override fun getRequiredTypeConverterClasses(): Map<KClass<*>, List<KClass<*>>> {
+ val _typeConvertersMap: MutableMap<KClass<*>, List<KClass<*>>> = mutableMapOf()
+ _typeConvertersMap.put(MyDao::class, MyDao_Impl.getRequiredConverters())
+ return _typeConvertersMap
+ }
+
+ public override fun getRequiredAutoMigrationSpecClasses(): Set<KClass<out AutoMigrationSpec>> {
+ val _autoMigrationSpecsSet: MutableSet<KClass<out AutoMigrationSpec>> = mutableSetOf()
+ return _autoMigrationSpecsSet
+ }
+
+ public override
+ fun createAutoMigrations(autoMigrationSpecs: Map<KClass<out AutoMigrationSpec>, AutoMigrationSpec>):
+ List<Migration> {
+ val _autoMigrations: MutableList<Migration> = mutableListOf()
+ return _autoMigrations
+ }
+
+ override fun getDao(): MyDao = _myDao.value
+}
diff --git a/room/room-compiler/src/test/test-data/kotlinCodeGen/database_simple.kt b/room/room-compiler/src/test/test-data/kotlinCodeGen/database_simple.kt
index ead51a6..cc897ff 100644
--- a/room/room-compiler/src/test/test-data/kotlinCodeGen/database_simple.kt
+++ b/room/room-compiler/src/test/test-data/kotlinCodeGen/database_simple.kt
@@ -8,7 +8,6 @@
import androidx.sqlite.SQLiteConnection
import androidx.sqlite.execSQL
import javax.`annotation`.processing.Generated
-import kotlin.Any
import kotlin.Lazy
import kotlin.String
import kotlin.Suppress
@@ -93,9 +92,8 @@
super.performClear(false, "MyEntity")
}
- protected override fun getRequiredTypeConverterClasses():
- Map<KClass<out Any>, List<KClass<out Any>>> {
- val _typeConvertersMap: MutableMap<KClass<out Any>, List<KClass<out Any>>> = mutableMapOf()
+ protected override fun getRequiredTypeConverterClasses(): Map<KClass<*>, List<KClass<*>>> {
+ val _typeConvertersMap: MutableMap<KClass<*>, List<KClass<*>>> = mutableMapOf()
_typeConvertersMap.put(MyDao::class, MyDao_Impl.getRequiredConverters())
return _typeConvertersMap
}
diff --git a/room/room-compiler/src/test/test-data/kotlinCodeGen/database_withFtsAndView.kt b/room/room-compiler/src/test/test-data/kotlinCodeGen/database_withFtsAndView.kt
index 092892d..e2f4e84 100644
--- a/room/room-compiler/src/test/test-data/kotlinCodeGen/database_withFtsAndView.kt
+++ b/room/room-compiler/src/test/test-data/kotlinCodeGen/database_withFtsAndView.kt
@@ -9,7 +9,6 @@
import androidx.sqlite.SQLiteConnection
import androidx.sqlite.execSQL
import javax.`annotation`.processing.Generated
-import kotlin.Any
import kotlin.Lazy
import kotlin.String
import kotlin.Suppress
@@ -159,9 +158,8 @@
super.performClear(true, "MyParentEntity", "MyEntity", "MyFtsEntity")
}
- protected override fun getRequiredTypeConverterClasses():
- Map<KClass<out Any>, List<KClass<out Any>>> {
- val _typeConvertersMap: MutableMap<KClass<out Any>, List<KClass<out Any>>> = mutableMapOf()
+ protected override fun getRequiredTypeConverterClasses(): Map<KClass<*>, List<KClass<*>>> {
+ val _typeConvertersMap: MutableMap<KClass<*>, List<KClass<*>>> = mutableMapOf()
_typeConvertersMap.put(MyDao::class, MyDao_Impl.getRequiredConverters())
return _typeConvertersMap
}
diff --git a/room/room-compiler/src/test/test-data/kotlinCodeGen/overridePropertyQuery.kt b/room/room-compiler/src/test/test-data/kotlinCodeGen/overridePropertyQuery.kt
new file mode 100644
index 0000000..89718c2
--- /dev/null
+++ b/room/room-compiler/src/test/test-data/kotlinCodeGen/overridePropertyQuery.kt
@@ -0,0 +1,54 @@
+import androidx.room.RoomDatabase
+import androidx.room.util.getColumnIndexOrThrow
+import androidx.room.util.performBlocking
+import androidx.sqlite.SQLiteStatement
+import javax.`annotation`.processing.Generated
+import kotlin.Int
+import kotlin.String
+import kotlin.Suppress
+import kotlin.collections.List
+import kotlin.collections.MutableList
+import kotlin.collections.mutableListOf
+import kotlin.jvm.JvmName
+import kotlin.reflect.KClass
+
+@Generated(value = ["androidx.room.RoomProcessor"])
+@Suppress(names = ["UNCHECKED_CAST", "DEPRECATION", "REDUNDANT_PROJECTION", "REMOVAL"])
+public class MyDao_Impl(
+ __db: RoomDatabase,
+) : MyDao {
+ private val __db: RoomDatabase
+
+ public override val entities: List<MyEntity>
+ get() = getEntities()
+
+ init {
+ this.__db = __db
+ }
+
+ @JvmName("_privateGetEntities")
+ private fun getEntities(): List<MyEntity> {
+ val _sql: String = "SELECT * FROM MyEntity"
+ return performBlocking(__db, true, false) { _connection ->
+ val _stmt: SQLiteStatement = _connection.prepare(_sql)
+ try {
+ val _cursorIndexOfPk: Int = getColumnIndexOrThrow(_stmt, "pk")
+ val _result: MutableList<MyEntity> = mutableListOf()
+ while (_stmt.step()) {
+ val _item: MyEntity
+ val _tmpPk: Int
+ _tmpPk = _stmt.getLong(_cursorIndexOfPk).toInt()
+ _item = MyEntity(_tmpPk)
+ _result.add(_item)
+ }
+ _result
+ } finally {
+ _stmt.close()
+ }
+ }
+ }
+
+ public companion object {
+ public fun getRequiredConverters(): List<KClass<*>> = emptyList()
+ }
+}
diff --git a/room/room-runtime/src/androidMain/kotlin/androidx/room/RoomDatabase.android.kt b/room/room-runtime/src/androidMain/kotlin/androidx/room/RoomDatabase.android.kt
index 7421bac..f8b5911 100644
--- a/room/room-runtime/src/androidMain/kotlin/androidx/room/RoomDatabase.android.kt
+++ b/room/room-runtime/src/androidMain/kotlin/androidx/room/RoomDatabase.android.kt
@@ -462,7 +462,7 @@
/**
* Property delegate of [getRequiredTypeConverterClasses] for common ext functionality.
*/
- internal actual val requiredTypeConverterClasses: Map<KClass<*>, List<KClass<*>>>
+ internal actual val requiredTypeConverterClassesMap: Map<KClass<*>, List<KClass<*>>>
get() = getRequiredTypeConverterClasses()
/**
diff --git a/room/room-runtime/src/commonMain/kotlin/androidx/room/RoomDatabase.kt b/room/room-runtime/src/commonMain/kotlin/androidx/room/RoomDatabase.kt
index 8e59497..e7c763b 100644
--- a/room/room-runtime/src/commonMain/kotlin/androidx/room/RoomDatabase.kt
+++ b/room/room-runtime/src/commonMain/kotlin/androidx/room/RoomDatabase.kt
@@ -167,7 +167,7 @@
/**
* Property delegate of [getRequiredTypeConverterClasses] for common ext functionality.
*/
- internal val requiredTypeConverterClasses: Map<KClass<*>, List<KClass<*>>>
+ internal val requiredTypeConverterClassesMap: Map<KClass<*>, List<KClass<*>>>
/**
* Initialize invalidation tracker. Note that this method is called when the [RoomDatabase] is
@@ -576,7 +576,7 @@
}
internal fun RoomDatabase.validateTypeConverters(configuration: DatabaseConfiguration) {
- val requiredFactories = this.requiredTypeConverterClasses
+ val requiredFactories = this.requiredTypeConverterClassesMap
// Indices for each converter on whether it is used or not so that we can throw an exception
// if developer provides an unused converter. It is not necessarily an error but likely
// to be because why would developer add a converter if it won't be used?
diff --git a/room/room-runtime/src/jvmNativeMain/kotlin/androidx/room/RoomDatabase.jvmNative.kt b/room/room-runtime/src/jvmNativeMain/kotlin/androidx/room/RoomDatabase.jvmNative.kt
index 89b1adf..4ab3e55 100644
--- a/room/room-runtime/src/jvmNativeMain/kotlin/androidx/room/RoomDatabase.jvmNative.kt
+++ b/room/room-runtime/src/jvmNativeMain/kotlin/androidx/room/RoomDatabase.jvmNative.kt
@@ -211,7 +211,7 @@
/**
* Property delegate of [getRequiredTypeConverterClasses] for common ext functionality.
*/
- internal actual val requiredTypeConverterClasses: Map<KClass<*>, List<KClass<*>>>
+ internal actual val requiredTypeConverterClassesMap: Map<KClass<*>, List<KClass<*>>>
get() = getRequiredTypeConverterClasses()
/**
diff --git a/settings.gradle b/settings.gradle
index 0578a99..d9f439e 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -344,20 +344,6 @@
includeProject(":annotation:annotation-experimental-lint")
includeProject(":annotation:annotation-experimental-lint-integration-tests", "annotation/annotation-experimental-lint/integration-tests")
includeProject(":annotation:annotation-sampled")
-includeProject(":appactions:builtintypes:builtintypes", [BuildType.MAIN])
-includeProject(":appactions:builtintypes:builtintypes:builtintypes-samples", "appactions/builtintypes/builtintypes/samples", [BuildType.MAIN])
-includeProject(":appactions:interaction:interaction-capabilities-communication", [BuildType.MAIN])
-includeProject(":appactions:interaction:interaction-capabilities-core", [BuildType.MAIN])
-includeProject(":appactions:interaction:interaction-capabilities-fitness", [BuildType.MAIN])
-includeProject(":appactions:interaction:interaction-capabilities-productivity", [BuildType.MAIN])
-includeProject(":appactions:interaction:interaction-capabilities-safety", [BuildType.MAIN])
-includeProject(":appactions:interaction:interaction-capabilities-testing", [BuildType.MAIN])
-includeProject(":appactions:interaction:interaction-proto", [BuildType.MAIN])
-includeProject(":appactions:interaction:interaction-service", [BuildType.MAIN])
-includeProject(":appactions:interaction:interaction-service-proto", [BuildType.MAIN])
-includeProject(":appactions:interaction:interaction-service-testing", [BuildType.MAIN])
-includeProject(":appactions:interaction:interaction-service-wear", [BuildType.MAIN])
-includeProject(":appactions:interaction:integration-tests:testapp", [BuildType.MAIN])
includeProject(":appcompat:appcompat", [BuildType.MAIN])
includeProject(":appcompat:appcompat-benchmark", [BuildType.MAIN])
includeProject(":appcompat:appcompat-lint", [BuildType.MAIN])
@@ -427,6 +413,8 @@
includeProject(":camera:camera-effects-still-portrait", [BuildType.CAMERA])
includeProject(":camera:camera-extensions", [BuildType.CAMERA])
includeProject(":camera:camera-extensions-stub", [BuildType.CAMERA])
+includeProject(":camera:camera-feature-combination-query", [BuildType.CAMERA])
+includeProject(":camera:camera-feature-combination-query-play-services", [BuildType.CAMERA])
includeProject(":camera:camera-lifecycle", [BuildType.CAMERA])
includeProject(":camera:camera-lifecycle:camera-lifecycle-samples", "camera/camera-lifecycle/samples", [BuildType.CAMERA])
includeProject(":camera:camera-mlkit-vision", [BuildType.CAMERA])
diff --git a/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiDeviceTest.java b/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiDeviceTest.java
index 4192492..110d81f 100644
--- a/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiDeviceTest.java
+++ b/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiDeviceTest.java
@@ -356,23 +356,28 @@
@Test
public void testSetOrientations() throws Exception {
- launchTestActivity(KeycodeTestActivity.class);
+ launchTestActivity(MainActivity.class);
try {
mDevice.setOrientationNatural();
- assertEquals(Surface.ROTATION_0, mDevice.getDisplayRotation());
+ assertTrue("Failed to set natural orientation",
+ mDevice.wait(d -> d.getDisplayRotation() == Surface.ROTATION_0, TIMEOUT_MS));
mDevice.setOrientationLeft();
- assertEquals(Surface.ROTATION_90, mDevice.getDisplayRotation());
+ assertTrue("Failed to set left orientation",
+ mDevice.wait(d -> d.getDisplayRotation() == Surface.ROTATION_90, TIMEOUT_MS));
mDevice.setOrientationRight();
- assertEquals(Surface.ROTATION_270, mDevice.getDisplayRotation());
+ assertTrue("Failed to set right orientation",
+ mDevice.wait(d -> d.getDisplayRotation() == Surface.ROTATION_270, TIMEOUT_MS));
mDevice.setOrientationPortrait();
- assertTrue(mDevice.getDisplayHeight() >= mDevice.getDisplayWidth());
+ assertTrue("Failed to set portrait orientation",
+ mDevice.wait(d -> d.getDisplayHeight() >= d.getDisplayWidth(), TIMEOUT_MS));
mDevice.setOrientationLandscape();
- assertTrue(mDevice.getDisplayHeight() <= mDevice.getDisplayWidth());
+ assertTrue("Failed to set landscape orientation",
+ mDevice.wait(d -> d.getDisplayHeight() <= d.getDisplayWidth(), TIMEOUT_MS));
} finally {
mDevice.setOrientationNatural();
}
@@ -392,7 +397,7 @@
mDevice.wakeUp();
mDevice.pressMenu();
assertTrue("Failed to wake up device and remove lockscreen",
- mDevice.hasObject(By.pkg(TEST_APP)));
+ mDevice.wait(Until.hasObject(By.pkg(TEST_APP)), TIMEOUT_MS));
}
}
diff --git a/test/uiautomator/integration-tests/testapp/src/main/AndroidManifest.xml b/test/uiautomator/integration-tests/testapp/src/main/AndroidManifest.xml
index 7fe8b3c..b1e9077 100644
--- a/test/uiautomator/integration-tests/testapp/src/main/AndroidManifest.xml
+++ b/test/uiautomator/integration-tests/testapp/src/main/AndroidManifest.xml
@@ -27,7 +27,8 @@
<application android:label="UiAutomator Test App"
android:theme="@android:style/Theme.Holo.NoActionBar">
<activity android:name=".MainActivity"
- android:exported="true">
+ android:exported="true"
+ android:configChanges="orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedColumn.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedColumn.kt
index 825a3ee..3ab85ce 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedColumn.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedColumn.kt
@@ -44,6 +44,7 @@
* than the curved column, either at the [CurvedAlignment.Angular.Start] of the layout,
* at the [CurvedAlignment.Angular.End], or [CurvedAlignment.Angular.Center].
* If unspecified or null, they can choose for themselves.
+ * @param contentBuilder Scope used to provide the content for this column.
*/
public fun CurvedScope.curvedColumn(
modifier: CurvedModifier = CurvedModifier,
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedRow.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedRow.kt
index f4fa3ca..4f5daea 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedRow.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/CurvedRow.kt
@@ -42,6 +42,7 @@
* and if those needs to be reversed in a Rtl layout.
* If not specified, it will be inherited from the enclosing [curvedRow] or [CurvedLayout]
* See [CurvedDirection.Angular].
+ * @param contentBuilder Scope used to provide the content for this row.
*/
public fun CurvedScope.curvedRow(
modifier: CurvedModifier = CurvedModifier,
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/SwipeToReveal.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/SwipeToReveal.kt
index 75aaf7e..00474ee 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/SwipeToReveal.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/SwipeToReveal.kt
@@ -165,7 +165,7 @@
@ExperimentalWearFoundationApi
public fun createAnchors(
coveredAnchor: Float = 0f,
- revealingAnchor: Float = 0.7f,
+ revealingAnchor: Float = SwipeToRevealDefaults.revealingRatio,
revealedAnchor: Float = 1f
): Map<RevealValue, Float> {
return mapOf(
@@ -349,7 +349,7 @@
animationSpec: AnimationSpec<Float> = SwipeToRevealDefaults.animationSpec,
confirmValueChange: (RevealValue) -> Boolean = { true },
positionalThreshold: Density.(totalDistance: Float) -> Float =
- SwipeToRevealDefaults.defaultThreshold(),
+ SwipeToRevealDefaults.positionalThreshold,
anchors: Map<RevealValue, Float> = createAnchors(),
): RevealState {
val coroutineScope = rememberCoroutineScope()
@@ -618,14 +618,32 @@
*/
@OptIn(ExperimentalWearFoundationApi::class)
internal object SwipeToRevealDefaults {
-
+ /**
+ * Default animation spec used when moving between states.
+ */
internal val animationSpec = SwipeableV2Defaults.AnimationSpec
+ /**
+ * Default padding space between action slots.
+ */
internal val padding = 2.dp
- internal const val threshold = 0.5f
+ /**
+ * Default ratio of the content displayed when in [RevealValue.Revealing] state, i.e. all the
+ * actions are revealed and the top content is not being swiped. For example, a value of 0.7
+ * means that 70% of the width is used to place the actions.
+ */
+ internal const val revealingRatio = 0.7f
- internal fun defaultThreshold() = fractionalPositionalThreshold(threshold)
+ /**
+ * Default position threshold that needs to be swiped in order to transition to the next state.
+ * Used in conjunction with [revealingRatio]; for example, a threshold of 0.5 with a revealing
+ * ratio of 0.7 means that the user needs to swipe at least 35% (0.5 * 0.7) of the component
+ * width to go from [RevealValue.Covered] to [RevealValue.Revealing] and at least 85%
+ * (0.7 + 0.5 * (1 - 0.7)) of the component width to go from [RevealValue.Revealing] to
+ * [RevealValue.Revealed].
+ */
+ internal val positionalThreshold = fractionalPositionalThreshold(0.5f)
}
@OptIn(ExperimentalWearFoundationApi::class)
diff --git a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/SelectionControls.kt b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/SelectionControls.kt
index 1fdbc11..114fd30 100644
--- a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/SelectionControls.kt
+++ b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/SelectionControls.kt
@@ -310,10 +310,9 @@
// Canvas internally uses Spacer.drawBehind.
// Using Spacer.drawWithCache to optimize the stroke allocations.
Spacer(
+ // NB We must set the semantic role to Role.RadioButton in the parent Button,
+ // not here in the selection control - see b/330869742
modifier = modifier
- .semantics {
- this.role = Role.RadioButton
- }
.maybeSelectable(
onClick, enabled, selected, interactionSource, ripple, width, height
)
diff --git a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/ToggleButton.kt b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/ToggleButton.kt
index 792bd00..3b0332a 100644
--- a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/ToggleButton.kt
+++ b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/ToggleButton.kt
@@ -211,6 +211,9 @@
indication = ripple,
interactionSource = interactionSource
)
+ // For a toggleable button, the role could be Checkbox or Switch,
+ // so we cannot set the semantics here. Instead,
+ // we set them in the toggle control
} else {
Modifier.selectable(
enabled = enabled,
@@ -218,7 +221,12 @@
onClick = { onCheckedChange(true) },
indication = ripple,
interactionSource = interactionSource
- )
+ ).semantics {
+ // For a selectable button, the role is always RadioButton.
+ // See also b/330869742 for issue with setting the RadioButton role
+ // within the selection control.
+ role = Role.RadioButton
+ }
}
)
.padding(contentPadding),
@@ -375,6 +383,12 @@
indication = ripple,
interactionSource = checkedInteractionSource
)
+ .semantics {
+ // For a selectable button, the role is always RadioButton.
+ // See also b/330869742 for issue with setting the RadioButton role
+ // within the selection control.
+ role = Role.RadioButton
+ }
}
Box(
diff --git a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SelectableChipTest.kt b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SelectableChipTest.kt
index 2fde27b..c3d34d8 100644
--- a/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SelectableChipTest.kt
+++ b/wear/compose/compose-material/src/androidTest/kotlin/androidx/wear/compose/material/SelectableChipTest.kt
@@ -136,6 +136,28 @@
}
@Test
+ fun selectable_chip_has_role_radiobutton() {
+ rule.setContentWithTheme {
+ SelectableChip(
+ selected = true,
+ onClick = {},
+ enabled = false,
+ label = { Text("Label") },
+ selectionControl = { TestImage() },
+ modifier = Modifier.testTag(TEST_TAG)
+ )
+ }
+
+ rule.onNodeWithTag(TEST_TAG)
+ .assert(
+ SemanticsMatcher.expectValue(
+ SemanticsProperties.Role,
+ Role.RadioButton
+ )
+ )
+ }
+
+ @Test
fun split_chip_has_clickaction_when_disabled() {
rule.setContentWithTheme {
SplitSelectableChip(
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/RadioButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/RadioButtonTest.kt
index f5c3ef0..3997c14 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/RadioButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/RadioButtonTest.kt
@@ -82,6 +82,23 @@
}
@Test
+ fun radio_button_has_role_radiobutton() {
+ rule.setContentWithTheme {
+ RadioButtonWithDefaults(
+ modifier = Modifier.testTag(TEST_TAG)
+ )
+ }
+
+ rule.onNodeWithTag(TEST_TAG)
+ .assert(
+ SemanticsMatcher.expectValue(
+ SemanticsProperties.Role,
+ Role.RadioButton
+ )
+ )
+ }
+
+ @Test
fun radio_button_samples_build() {
rule.setContentWithTheme {
RadioButton()
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SelectionControlsTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SelectionControlsTest.kt
index 600e737..a8ac0da 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SelectionControlsTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SelectionControlsTest.kt
@@ -22,10 +22,6 @@
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.testTag
-import androidx.compose.ui.semantics.Role
-import androidx.compose.ui.semantics.SemanticsProperties
-import androidx.compose.ui.test.SemanticsMatcher
-import androidx.compose.ui.test.assert
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertWidthIsEqualTo
import androidx.compose.ui.test.captureToImage
@@ -67,25 +63,6 @@
}
@Test
- fun radio_control_has_role_radiobutton() {
- rule.setContentWithTheme {
- with(SelectionControlScope(isEnabled = true, isSelected = true)) {
- Radio(
- modifier = Modifier.testTag(TEST_TAG)
- )
- }
- }
-
- rule.onNodeWithTag(TEST_TAG)
- .assert(
- SemanticsMatcher.expectValue(
- SemanticsProperties.Role,
- Role.RadioButton
- )
- )
- }
-
- @Test
fun radio_control_is_correctly_enabled() {
rule.setContentWithTheme {
with(SelectionControlScope(isEnabled = true, isSelected = true)) {
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/RadioButton.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/RadioButton.kt
index 70dbab71..b4a6f53 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/RadioButton.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/RadioButton.kt
@@ -144,7 +144,13 @@
indication = rippleOrFallbackImplementation(),
interactionSource = interactionSource
)
- .padding(contentPadding),
+ .padding(contentPadding)
+ .semantics {
+ // For a selectable button, the role is always RadioButton.
+ // See also b/330869742 for issue with setting the RadioButton role
+ // within the selection control.
+ role = Role.RadioButton
+ },
verticalAlignment = Alignment.CenterVertically
) {
if (icon != null) {
@@ -329,7 +335,13 @@
.width(SPLIT_WIDTH)
.wrapContentHeight(align = Alignment.CenterVertically)
.wrapContentWidth(align = Alignment.End)
- .then(endPadding),
+ .then(endPadding)
+ .semantics {
+ // For a selectable button, the role is always RadioButton.
+ // See also b/330869742 for issue with setting the RadioButton role
+ // within the selection control.
+ role = Role.RadioButton
+ },
) {
val scope = remember(enabled, selected) { SelectionControlScope(enabled, selected) }
selectionControl(scope)
diff --git a/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewFontScales.kt b/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewFontScales.kt
index 7981cf2..5b295fc 100644
--- a/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewFontScales.kt
+++ b/wear/compose/compose-ui-tooling/src/main/java/androidx/wear/compose/ui/tooling/preview/WearPreviewFontScales.kt
@@ -34,7 +34,7 @@
* note, the above list is not exhaustive. It previews the composables on a small round Wear device.
*
* @sample androidx.wear.compose.material.samples.TitleCardWithImagePreview
- * @see [Preview.fontScale]
+ * @see Preview.fontScale
*/
@Preview(
device = WearDevices.SMALL_ROUND,
diff --git a/wear/compose/integration-tests/demos/build.gradle b/wear/compose/integration-tests/demos/build.gradle
index 28d0392..d68e962 100644
--- a/wear/compose/integration-tests/demos/build.gradle
+++ b/wear/compose/integration-tests/demos/build.gradle
@@ -25,8 +25,8 @@
defaultConfig {
applicationId "androidx.wear.compose.integration.demos"
minSdk 25
- versionCode 23
- versionName "1.23"
+ versionCode 24
+ versionName "1.24"
}
buildTypes {
diff --git a/wear/protolayout/protolayout-expression/api/current.txt b/wear/protolayout/protolayout-expression/api/current.txt
index bd9565b..756cbe0 100644
--- a/wear/protolayout/protolayout-expression/api/current.txt
+++ b/wear/protolayout/protolayout-expression/api/current.txt
@@ -14,7 +14,7 @@
}
public static final class AnimationParameterBuilders.AnimationParameters.Builder {
- ctor public AnimationParameterBuilders.AnimationParameters.Builder();
+ ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public AnimationParameterBuilders.AnimationParameters.Builder();
method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters build();
method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters.Builder setDelayMillis(@IntRange(from=0) long);
method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters.Builder setDurationMillis(@IntRange(from=0) long);
@@ -27,10 +27,10 @@
}
public static final class AnimationParameterBuilders.AnimationSpec.Builder {
- ctor public AnimationParameterBuilders.AnimationSpec.Builder();
+ ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public AnimationParameterBuilders.AnimationSpec.Builder();
method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec build();
method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec.Builder setAnimationParameters(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters);
- method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec.Builder setRepeatable(androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable);
+ method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec.Builder setRepeatable(androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable);
}
@androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface AnimationParameterBuilders.Easing {
@@ -53,7 +53,7 @@
}
public static final class AnimationParameterBuilders.Repeatable.Builder {
- ctor public AnimationParameterBuilders.Repeatable.Builder();
+ ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public AnimationParameterBuilders.Repeatable.Builder();
method public androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable build();
method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable.Builder setForwardRepeatOverride(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters);
method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable.Builder setIterations(@IntRange(from=1) int);
diff --git a/wear/protolayout/protolayout-expression/api/restricted_current.txt b/wear/protolayout/protolayout-expression/api/restricted_current.txt
index bd9565b..756cbe0 100644
--- a/wear/protolayout/protolayout-expression/api/restricted_current.txt
+++ b/wear/protolayout/protolayout-expression/api/restricted_current.txt
@@ -14,7 +14,7 @@
}
public static final class AnimationParameterBuilders.AnimationParameters.Builder {
- ctor public AnimationParameterBuilders.AnimationParameters.Builder();
+ ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public AnimationParameterBuilders.AnimationParameters.Builder();
method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters build();
method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters.Builder setDelayMillis(@IntRange(from=0) long);
method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters.Builder setDurationMillis(@IntRange(from=0) long);
@@ -27,10 +27,10 @@
}
public static final class AnimationParameterBuilders.AnimationSpec.Builder {
- ctor public AnimationParameterBuilders.AnimationSpec.Builder();
+ ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public AnimationParameterBuilders.AnimationSpec.Builder();
method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec build();
method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec.Builder setAnimationParameters(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters);
- method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec.Builder setRepeatable(androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable);
+ method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec.Builder setRepeatable(androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable);
}
@androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static interface AnimationParameterBuilders.Easing {
@@ -53,7 +53,7 @@
}
public static final class AnimationParameterBuilders.Repeatable.Builder {
- ctor public AnimationParameterBuilders.Repeatable.Builder();
+ ctor @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public AnimationParameterBuilders.Repeatable.Builder();
method public androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable build();
method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable.Builder setForwardRepeatOverride(androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters);
method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public androidx.wear.protolayout.expression.AnimationParameterBuilders.Repeatable.Builder setIterations(@IntRange(from=1) int);
diff --git a/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/AnimationParameterBuilders.java b/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/AnimationParameterBuilders.java
index 44eb9a7..a800b2a 100644
--- a/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/AnimationParameterBuilders.java
+++ b/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/AnimationParameterBuilders.java
@@ -140,6 +140,7 @@
AnimationParameterProto.AnimationSpec.newBuilder();
private final Fingerprint mFingerprint = new Fingerprint(-2136602843);
+ @RequiresSchemaVersion(major = 1, minor = 200)
public Builder() {}
/** Sets animation parameters including duration, easing and repeat delay. */
@@ -158,6 +159,7 @@
* Sets the repeatable mode to be used for specifying repetition parameters for the
* animation. If not set, animation won't be repeated.
*/
+ @RequiresSchemaVersion(major = 1, minor = 200)
@NonNull
public Builder setRepeatable(@NonNull Repeatable repeatable) {
mImpl.setRepeatable(repeatable.toProto());
@@ -261,6 +263,7 @@
AnimationParameterProto.AnimationParameters.newBuilder();
private final Fingerprint mFingerprint = new Fingerprint(-1301308590);
+ @RequiresSchemaVersion(major = 1, minor = 200)
public Builder() {}
/**
@@ -491,7 +494,6 @@
}
/** Returns the internal proto instance. */
- @RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
AnimationParameterProto.CubicBezierEasing toProto() {
return mImpl;
@@ -525,6 +527,7 @@
AnimationParameterProto.CubicBezierEasing.newBuilder();
private final Fingerprint mFingerprint = new Fingerprint(856403705);
+ @RequiresSchemaVersion(major = 1, minor = 200)
public Builder() {}
/**
@@ -704,6 +707,7 @@
AnimationParameterProto.Repeatable.newBuilder();
private final Fingerprint mFingerprint = new Fingerprint(2110475048);
+ @RequiresSchemaVersion(major = 1, minor = 200)
public Builder() {}
/**
diff --git a/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/ConditionScopes.java b/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/ConditionScopes.java
index 36e1b0b..5a088b9 100644
--- a/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/ConditionScopes.java
+++ b/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/ConditionScopes.java
@@ -48,12 +48,14 @@
}
/** Sets the value to use as the value when true in a conditional expression. */
- public @NonNull IfTrueScope<T, RawT> use(T valueWhenTrue) {
+ @NonNull
+ public IfTrueScope<T, RawT> use(T valueWhenTrue) {
return new IfTrueScope<>(valueWhenTrue, conditionBuilder, rawTypeMapper);
}
/** Sets the value to use as the value when true in a conditional expression. */
- public @NonNull IfTrueScope<T, RawT> use(RawT valueWhenTrue) {
+ @NonNull
+ public IfTrueScope<T, RawT> use(RawT valueWhenTrue) {
return use(rawTypeMapper.apply(valueWhenTrue));
}
}
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 17d89ce..500985d 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
@@ -708,7 +708,7 @@
return this;
}
- /** Sets the name space for the state key. */
+ /** Sets the namespace for the state key. */
@RequiresSchemaVersion(major = 1, minor = 200)
@NonNull
public Builder setSourceNamespace(@NonNull String sourceNamespace) {
@@ -1255,7 +1255,7 @@
/** Sets the value to start animating from. */
@RequiresSchemaVersion(major = 1, minor = 200)
@NonNull
- public AnimatableFixedInt32.Builder setFromValue(int fromValue) {
+ public Builder setFromValue(int fromValue) {
mImpl.setFromValue(fromValue);
mFingerprint.recordPropertyUpdate(1, fromValue);
return this;
@@ -1264,7 +1264,7 @@
/** Sets the value to animate to. */
@RequiresSchemaVersion(major = 1, minor = 200)
@NonNull
- public AnimatableFixedInt32.Builder setToValue(int toValue) {
+ public Builder setToValue(int toValue) {
mImpl.setToValue(toValue);
mFingerprint.recordPropertyUpdate(2, toValue);
return this;
@@ -1398,7 +1398,7 @@
/** Sets the value to watch, and animate when it changes. */
@RequiresSchemaVersion(major = 1, minor = 200)
@NonNull
- public AnimatableDynamicInt32.Builder setInput(@NonNull DynamicInt32 input) {
+ public Builder setInput(@NonNull DynamicInt32 input) {
mImpl.setInput(input.toDynamicInt32Proto());
mFingerprint.recordPropertyUpdate(
1, checkNotNull(input.getFingerprint()).aggregateValueAsInt());
@@ -2413,7 +2413,7 @@
/** Returns whether digit grouping is used or not. */
public boolean isGroupingUsed() {
- return mInt32FormatOp.getGroupingUsed();
+ return mInt32FormatOp.isGroupingUsed();
}
/** Builder to create {@link IntFormatter} objects. */
@@ -2579,7 +2579,7 @@
* locale. If not defined, defaults to false. For example, for locale en_US, using grouping
* with 1234 would yield "1,234".
*/
- public boolean getGroupingUsed() {
+ public boolean isGroupingUsed() {
return mImpl.getGroupingUsed();
}
@@ -2638,13 +2638,13 @@
+ ", minIntegerDigits="
+ getMinIntegerDigits()
+ ", groupingUsed="
- + getGroupingUsed()
+ + isGroupingUsed()
+ "}";
}
/** Builder for {@link Int32FormatOp}. */
public static final class Builder implements DynamicString.Builder {
- final DynamicProto.Int32FormatOp.Builder mImpl =
+ private final DynamicProto.Int32FormatOp.Builder mImpl =
DynamicProto.Int32FormatOp.newBuilder();
private final Fingerprint mFingerprint = new Fingerprint(196209833);
@@ -2792,7 +2792,7 @@
return this;
}
- /** Sets the name space for the state key. */
+ /** Sets the namespace for the state key. */
@RequiresSchemaVersion(major = 1, minor = 200)
@NonNull
public Builder setSourceNamespace(@NonNull String sourceNamespace) {
@@ -3143,7 +3143,7 @@
* locale. If not defined, defaults to false. For example, for locale en_US, using grouping
* with 1234.56 would yield "1,234.56".
*/
- public boolean getGroupingUsed() {
+ public boolean isGroupingUsed() {
return mImpl.getGroupingUsed();
}
@@ -3206,7 +3206,7 @@
+ ", minIntegerDigits="
+ getMinIntegerDigits()
+ ", groupingUsed="
- + getGroupingUsed()
+ + isGroupingUsed()
+ "}";
}
@@ -3736,7 +3736,7 @@
return this;
}
- /** Sets the name space for the state key. */
+ /** Sets the namespace for the state key. */
@RequiresSchemaVersion(major = 1, minor = 200)
@NonNull
public Builder setSourceNamespace(@NonNull String sourceNamespace) {
@@ -5012,7 +5012,7 @@
/** Returns whether digit grouping is used or not. */
public boolean isGroupingUsed() {
- return mFloatFormatOp.getGroupingUsed();
+ return mFloatFormatOp.isGroupingUsed();
}
/** Builder to create {@link FloatFormatter} objects. */
@@ -5228,8 +5228,8 @@
@NonNull
public DynamicProto.DynamicBool toDynamicBoolProto(boolean withFingerprint) {
if (withFingerprint) {
- return DynamicProto.DynamicBool.newBuilder().
- setStateSource(mImpl)
+ return DynamicProto.DynamicBool.newBuilder()
+ .setStateSource(mImpl)
.setFingerprint(checkNotNull(mFingerprint).toProto())
.build();
}
@@ -5265,7 +5265,7 @@
return this;
}
- /** Sets the name space for the state key. */
+ /** Sets the namespace for the state key. */
@RequiresSchemaVersion(major = 1, minor = 200)
@NonNull
public Builder setSourceNamespace(@NonNull String sourceNamespace) {
@@ -6144,7 +6144,7 @@
return this;
}
- /** Sets the name space for the state key. */
+ /** Sets the namespace for the state key. */
@RequiresSchemaVersion(major = 1, minor = 200)
@NonNull
public Builder setSourceNamespace(@NonNull String sourceNamespace) {
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 69c88e3..c3b5c45 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
@@ -28,7 +28,6 @@
import androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant;
import androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32;
import androidx.wear.protolayout.expression.DynamicBuilders.DynamicString;
-import androidx.wear.protolayout.expression.DynamicBuilders.DynamicType;
import androidx.wear.protolayout.expression.FixedValueBuilders.FixedBool;
import androidx.wear.protolayout.expression.FixedValueBuilders.FixedColor;
import androidx.wear.protolayout.expression.FixedValueBuilders.FixedDuration;
@@ -51,7 +50,7 @@
/** Interface defining a dynamic data value. */
@RequiresSchemaVersion(major = 1, minor = 200)
- public interface DynamicDataValue<T extends DynamicType> {
+ public interface DynamicDataValue<T extends DynamicBuilders.DynamicType> {
/** Get the protocol buffer representation of this object. */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
@@ -310,7 +309,7 @@
/** Builder to create {@link DynamicDataValue} objects. */
@RestrictTo(Scope.LIBRARY_GROUP)
- interface Builder<T extends DynamicType> {
+ interface Builder<T extends DynamicBuilders.DynamicType> {
/** Builds an instance with values accumulated in this Builder. */
@NonNull
diff --git a/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/FixedValueBuilders.java b/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/FixedValueBuilders.java
index ced6685..e16e059 100644
--- a/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/FixedValueBuilders.java
+++ b/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/FixedValueBuilders.java
@@ -78,7 +78,6 @@
}
/** Returns the internal proto instance. */
- @RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
FixedProto.FixedInt32 toProto() {
return mImpl;
@@ -144,6 +143,7 @@
private final FixedProto.FixedInt32.Builder mImpl = FixedProto.FixedInt32.newBuilder();
private final Fingerprint mFingerprint = new Fingerprint(974881783);
+ @RequiresSchemaVersion(major = 1, minor = 200)
public Builder() {}
/** Sets the value. */
@@ -203,7 +203,6 @@
}
/** Returns the internal proto instance. */
- @RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
FixedProto.FixedString toProto() {
return mImpl;
@@ -271,6 +270,7 @@
FixedProto.FixedString.newBuilder();
private final Fingerprint mFingerprint = new Fingerprint(1963352072);
+ @RequiresSchemaVersion(major = 1, minor = 200)
public Builder() {}
/** Sets the value. */
@@ -333,7 +333,6 @@
}
/** Returns the internal proto instance. */
- @RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
FixedProto.FixedFloat toProto() {
return mImpl;
@@ -399,6 +398,7 @@
private final FixedProto.FixedFloat.Builder mImpl = FixedProto.FixedFloat.newBuilder();
private final Fingerprint mFingerprint = new Fingerprint(-144724541);
+ @RequiresSchemaVersion(major = 1, minor = 200)
public Builder() {}
/**
@@ -461,7 +461,6 @@
}
/** Returns the internal proto instance. */
- @RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
FixedProto.FixedBool toProto() {
return mImpl;
@@ -527,6 +526,7 @@
private final FixedProto.FixedBool.Builder mImpl = FixedProto.FixedBool.newBuilder();
private final Fingerprint mFingerprint = new Fingerprint(-665116398);
+ @RequiresSchemaVersion(major = 1, minor = 200)
public Builder() {}
/** Sets the value. */
@@ -587,7 +587,6 @@
}
/** Returns the internal proto instance. */
- @RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
FixedProto.FixedColor toProto() {
return mImpl;
@@ -653,6 +652,7 @@
private final FixedProto.FixedColor.Builder mImpl = FixedProto.FixedColor.newBuilder();
private final Fingerprint mFingerprint = new Fingerprint(-1895809356);
+ @RequiresSchemaVersion(major = 1, minor = 200)
public Builder() {}
/** Sets the color value, in ARGB format. */
@@ -733,7 +733,6 @@
}
/** Returns the internal proto instance. */
- @RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
FixedProto.FixedInstant toProto() {
return mImpl;
@@ -778,6 +777,7 @@
FixedProto.FixedInstant.newBuilder();
private final Fingerprint mFingerprint = new Fingerprint(-1986552556);
+ @RequiresSchemaVersion(major = 1, minor = 200)
public Builder() {}
/**
@@ -860,7 +860,6 @@
}
/** Returns the internal proto instance. */
- @RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
FixedProto.FixedDuration toProto() {
return mImpl;
@@ -905,6 +904,7 @@
FixedProto.FixedDuration.newBuilder();
private final Fingerprint mFingerprint = new Fingerprint(9029504);
+ @RequiresSchemaVersion(major = 1, minor = 200)
public Builder() {}
/** Sets duration in seconds. */
diff --git a/wear/protolayout/protolayout-proto/src/main/proto/layout.proto b/wear/protolayout/protolayout-proto/src/main/proto/layout.proto
index 8b4eebc..0f6d876 100644
--- a/wear/protolayout/protolayout-proto/src/main/proto/layout.proto
+++ b/wear/protolayout/protolayout-proto/src/main/proto/layout.proto
@@ -140,31 +140,29 @@
// defaults to "body".
FontVariantProp variant = 7;
- // The collection of font variation settings to be applied.
+ // The collection of font settings to be applied.
//
- // Supported settings depend on the font used and renderer version. Renderers supporting 1.4 will
- // have custom weight always available. If this is used with the variable fonts on those
- // renderers, width setting will be always available too.
- FontVariation variation_settings = 8;
+ // Supported settings depend on the font used and renderer version.
+ // If this is used with the variable fonts on renderers supporting 1.4, weight and width setting
+ // will be always available.
+ repeated FontSetting settings = 8;
}
-// The collection of font variation settings.
-//
-// Supported settings depend on the font used and renderer version. Renderers supporting 1.4 will
-// have custom weight always available. If this is used with the variable fonts on those renderers,
-// width setting will be always available too.
-message FontVariation {
- // A single point of customization in a variation, with axis name and a value for it.
- repeated Setting settings = 1;
+// A single point of customization in a font.
+message FontSetting {
+ oneof inner {
+ // A single point of customization in a font variation, with axis name and a value for it.
+ FontVariationSetting variation = 1;
+ }
}
-// A single point of customization in a variation, with axis name and a value for it.
-message Setting {
+// A single point of customization in a font variation, with axis name and a value for it.
+message FontVariationSetting {
// The axis name for this setting. This represents a 4 ASCII characters tag.
fixed32 axis_name = 1;
// The value for this setting.
- float variation_value = 2;
+ float value = 2;
}
// How text that will not fit inside the bounds of a Text element will be
diff --git a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/common/Constants.java b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/common/Constants.java
new file mode 100644
index 0000000..d6a206c
--- /dev/null
+++ b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/common/Constants.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License = 0 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 = 0 software
+ * distributed under the License is distributed on an "AS IS" BASIS = 0
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND = 0 either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.protolayout.renderer.common;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.RestrictTo;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/** Shared constants. */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+public class Constants {
+
+ private Constants() {}
+
+ /** The reason why an update was requested. */
+ @IntDef({
+ UPDATE_REQUEST_REASON_UNKNOWN,
+ UPDATE_REQUEST_REASON_SYSUI_CAROUSEL,
+ UPDATE_REQUEST_REASON_FRESHNESS,
+ UPDATE_REQUEST_REASON_USER_INTERACTION,
+ UPDATE_REQUEST_REASON_UPDATE_REQUESTER,
+ UPDATE_REQUEST_REASON_CACHE_INVALIDATION,
+ UPDATE_REQUEST_REASON_RETRY
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface UpdateRequestReason {}
+
+ /** Unknown reason. */
+ public static final int UPDATE_REQUEST_REASON_UNKNOWN = 0;
+
+ /** Update triggered by SysUI Carousel. */
+ public static final int UPDATE_REQUEST_REASON_SYSUI_CAROUSEL = 1;
+
+ /** Update triggered by freshness. */
+ public static final int UPDATE_REQUEST_REASON_FRESHNESS = 2;
+
+ /** Update triggered by user interaction (e.g. clicking on the tile). */
+ public static final int UPDATE_REQUEST_REASON_USER_INTERACTION = 3;
+
+ /** Update triggered using update requester. */
+ public static final int UPDATE_REQUEST_REASON_UPDATE_REQUESTER = 4;
+
+ /** Update triggered due to clearing the cache. */
+ public static final int UPDATE_REQUEST_REASON_CACHE_INVALIDATION = 5;
+
+ /** Update triggered by retry policy. */
+ public static final int UPDATE_REQUEST_REASON_RETRY = 6;
+}
diff --git a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/common/NoOpProviderStatsLogger.java b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/common/NoOpProviderStatsLogger.java
new file mode 100644
index 0000000..f292c98
--- /dev/null
+++ b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/common/NoOpProviderStatsLogger.java
@@ -0,0 +1,91 @@
+/*
+ * 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.renderer.common;
+
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.wear.protolayout.proto.StateProto.State;
+import androidx.wear.protolayout.renderer.common.Constants.UpdateRequestReason;
+
+/** A No-Op implementation of {@link ProviderStatsLogger}. */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+public class NoOpProviderStatsLogger implements ProviderStatsLogger {
+ private static final String TAG = "NoOpProviderStatsLogger";
+
+ /** Creates an instance of {@link NoOpProviderStatsLogger}. */
+ public NoOpProviderStatsLogger(@NonNull String reason) {
+ Log.i(TAG, "Instance used because " + reason);
+ }
+
+ /** No-op method. */
+ @Override
+ public void logLayoutSchemaVersion(int major, int minor) {}
+
+ /** No-op method. */
+ @Override
+ public void logStateStructure(@NonNull State state, boolean isInitialState) {}
+
+ /** No-op method. */
+ @Override
+ public void logIgnoredFailure(int failure) {}
+
+ /** No-op method. */
+ @Override
+ public void logInflationFailed(@InflationFailureReason int failureReason) {}
+
+ /** No-op method. */
+ @Override
+ @NonNull
+ public InflaterStatsLogger createInflaterStatsLogger() {
+ return new NoOpInflaterStatsLogger();
+ }
+
+ /** No-op method. */
+ @Override
+ public void logInflationFinished(@NonNull InflaterStatsLogger inflaterStatsLogger) {}
+
+ /** No-op method. */
+ @Override
+ public void logTileRequestReason(@UpdateRequestReason int updateRequestReason) {}
+
+ /** A No-Op implementation of {@link InflaterStatsLogger}. */
+ public static class NoOpInflaterStatsLogger implements InflaterStatsLogger {
+
+ private NoOpInflaterStatsLogger() {}
+
+ @Override
+ public void logMutationChangedNodes(int changedNodesCount) {}
+
+ @Override
+ public void logTotalNodeCount(int totalNodesCount) {}
+
+ /** No-op method. */
+ @Override
+ public void logDrawableUsage(@NonNull Drawable drawable) {}
+
+ /** No-op method. */
+ @Override
+ public void logIgnoredFailure(@IgnoredFailure int failure) {}
+
+ /** No-op method. */
+ @Override
+ public void logInflationFailed(@InflationFailureReason int failureReason) {}
+ }
+}
diff --git a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/common/ProviderStatsLogger.java b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/common/ProviderStatsLogger.java
new file mode 100644
index 0000000..96a6fb0
--- /dev/null
+++ b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/common/ProviderStatsLogger.java
@@ -0,0 +1,135 @@
+/*
+ * 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.renderer.common;
+
+import android.graphics.drawable.Drawable;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.UiThread;
+import androidx.wear.protolayout.proto.StateProto.State;
+import androidx.wear.protolayout.renderer.common.Constants.UpdateRequestReason;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/** Logger used for collecting metrics. */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+public interface ProviderStatsLogger {
+
+ /** Failures that doesn't cause the inflation to fail. */
+ @IntDef({
+ IGNORED_FAILURE_UNKNOWN,
+ IGNORED_FAILURE_APPLY_MUTATION_EXCEPTION,
+ IGNORED_FAILURE_ANIMATION_QUOTA_EXCEEDED,
+ IGNORED_FAILURE_DIFFING_FAILURE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface IgnoredFailure {}
+
+ /** Unknown failure. */
+ int IGNORED_FAILURE_UNKNOWN = 0;
+
+ /** Failure applying the diff mutation. */
+ int IGNORED_FAILURE_APPLY_MUTATION_EXCEPTION = 1;
+
+ /** Failure caused by exceeding animation quota. */
+ int IGNORED_FAILURE_ANIMATION_QUOTA_EXCEEDED = 2;
+
+ /** Failure diffing the layout. */
+ int IGNORED_FAILURE_DIFFING_FAILURE = 3;
+
+ /** Failures that causes the inflation to fail. */
+ @IntDef({
+ INFLATION_FAILURE_REASON_UNKNOWN,
+ INFLATION_FAILURE_REASON_LAYOUT_DEPTH_EXCEEDED,
+ INFLATION_FAILURE_REASON_EXPRESSION_NODE_COUNT_EXCEEDED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface InflationFailureReason {}
+
+ /** Unknown failure. */
+ int INFLATION_FAILURE_REASON_UNKNOWN = 0;
+
+ /** Failure caused by exceeding maximum layout depth. */
+ int INFLATION_FAILURE_REASON_LAYOUT_DEPTH_EXCEEDED = 1;
+
+ /** Failure caused by exceeding maximum expression node count. */
+ int INFLATION_FAILURE_REASON_EXPRESSION_NODE_COUNT_EXCEEDED = 2;
+
+ /** Log the schema version of the received layout. */
+ void logLayoutSchemaVersion(int major, int minor);
+
+ /** Log Protolayout state structure. */
+ void logStateStructure(@NonNull State state, boolean isInitialState);
+
+ /** Log the occurrence of an ignored failure. */
+ @UiThread
+ void logIgnoredFailure(@IgnoredFailure int failure);
+
+ /** Log the reason for inflation failure. */
+ @UiThread
+ void logInflationFailed(@InflationFailureReason int failureReason);
+
+ /**
+ * Creates an {@link InflaterStatsLogger} and marks the start of inflation. The atoms will be
+ * logged to statsd only when {@link #logInflationFinished} is called.
+ */
+ @UiThread
+ @NonNull
+ InflaterStatsLogger createInflaterStatsLogger();
+
+ /** Makes the end of inflation and log the inflation results. */
+ @UiThread
+ void logInflationFinished(@NonNull InflaterStatsLogger inflaterStatsLogger);
+
+ /** Log tile request reason. */
+ void logTileRequestReason(@UpdateRequestReason int updateRequestReason);
+
+ /** Logger used for logging inflation stats. */
+ interface InflaterStatsLogger {
+ /** log the mutation changed nodes count for the ongoing inflation. */
+ @UiThread
+ void logMutationChangedNodes(int changedNodesCount);
+
+ /** Log the total nodes count for the ongoing inflation. */
+ @UiThread
+ void logTotalNodeCount(int totalNodesCount);
+
+ /**
+ * Log the usage of a drawable. This method should be called between {@link
+ * #createInflaterStatsLogger()} and {@link #logInflationFinished(InflaterStatsLogger)}.
+ */
+ @UiThread
+ void logDrawableUsage(@NonNull Drawable drawable);
+
+ /**
+ * Log the occurrence of an ignored failure. The usage of this method is not restricted to
+ * inflation start or end.
+ */
+ @UiThread
+ void logIgnoredFailure(@IgnoredFailure int failure);
+
+ /**
+ * Log the reason for inflation failure. This will make any future call {@link
+ * #logInflationFinished(InflaterStatsLogger)} a Noop.
+ */
+ @UiThread
+ void logInflationFailed(@InflationFailureReason int failureReason);
+ }
+}
diff --git a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/common/RenderingArtifact.java b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/common/RenderingArtifact.java
new file mode 100644
index 0000000..8424728
--- /dev/null
+++ b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/common/RenderingArtifact.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2024 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.renderer.common;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.annotation.RestrictTo.Scope;
+import androidx.wear.protolayout.renderer.common.ProviderStatsLogger.InflaterStatsLogger;
+
+/** Artifacts resulted from the layout rendering. */
+@RestrictTo(Scope.LIBRARY_GROUP)
+public interface RenderingArtifact {
+
+ /** Creates a {@link RenderingArtifact} instance. */
+ @NonNull
+ static RenderingArtifact create(@NonNull InflaterStatsLogger inflaterStatsLogger) {
+ return new SuccessfulRenderingArtifact(inflaterStatsLogger);
+ }
+
+ /** Creates a {@link RenderingArtifact} instance for a skipped inflation. */
+ @NonNull
+ static RenderingArtifact skipped() {
+ return new SkippedRenderingArtifact();
+ }
+
+ /** Creates a {@link RenderingArtifact} instance for a failed inflation. */
+ @NonNull
+ static RenderingArtifact failed() {
+ return new FailedRenderingArtifact();
+ }
+
+ /** Artifacts resulted from a successful layout rendering. */
+ class SuccessfulRenderingArtifact implements RenderingArtifact {
+ @NonNull private final InflaterStatsLogger mInflaterStatsLogger;
+
+ private SuccessfulRenderingArtifact(@NonNull InflaterStatsLogger inflaterStatsLogger) {
+ mInflaterStatsLogger = inflaterStatsLogger;
+ }
+
+ /**
+ * Returns the {@link ProviderStatsLogger.InflaterStatsLogger} used log inflation stats.
+ * This will return {@code null} if the inflation was skipped or failed.
+ */
+ @NonNull
+ public InflaterStatsLogger getInflaterStatsLogger() {
+ return mInflaterStatsLogger;
+ }
+ }
+
+ /** Artifacts resulted from a skipped layout rendering. */
+ class SkippedRenderingArtifact implements RenderingArtifact {}
+
+ /** Artifacts resulted from a failed layout rendering. */
+ class FailedRenderingArtifact implements RenderingArtifact {}
+}
diff --git a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/dynamicdata/ProtoLayoutDynamicDataPipeline.java b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/dynamicdata/ProtoLayoutDynamicDataPipeline.java
index 8a933ec..b67c8dc 100644
--- a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/dynamicdata/ProtoLayoutDynamicDataPipeline.java
+++ b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/dynamicdata/ProtoLayoutDynamicDataPipeline.java
@@ -534,22 +534,6 @@
@NonNull
public PipelineMaker addPipelineFor(
@NonNull DynamicInt32 int32Source,
- int invalidData,
- @NonNull String posId,
- @NonNull Consumer<Integer> consumer) {
- return addPipelineFor(
- int32Source, posId, buildStateUpdateCallback(invalidData, consumer));
- }
-
- /**
- * Add the given source to the pipeline for future evaluation. Evaluation will start when
- * {@link PipelineMaker} is committed with {@link PipelineMaker#commit}.
- */
- @RestrictTo(Scope.LIBRARY_GROUP)
- @SuppressWarnings("RestrictTo")
- @NonNull
- public PipelineMaker addPipelineFor(
- @NonNull DynamicInt32 int32Source,
@NonNull String posId,
@NonNull DynamicTypeValueReceiver<Integer> consumer) {
DynamicTypeBindingRequest bindingRequest =
@@ -630,22 +614,6 @@
* {@link PipelineMaker} is committed with {@link PipelineMaker#commit}.
*/
@RestrictTo(Scope.LIBRARY_GROUP)
- @SuppressWarnings("RestrictTo")
- @NonNull
- public PipelineMaker addPipelineFor(
- @NonNull DynamicColor colorSource,
- int invalidData,
- @NonNull String posId,
- @NonNull Consumer<Integer> consumer) {
- return addPipelineFor(
- colorSource, posId, buildStateUpdateCallback(invalidData, consumer));
- }
-
- /**
- * Add the given source to the pipeline for future evaluation. Evaluation will start when
- * {@link PipelineMaker} is committed with {@link PipelineMaker#commit}.
- */
- @RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
public PipelineMaker addPipelineFor(
@NonNull DynamicBool boolSource,
diff --git a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/impl/ProtoLayoutViewInstance.java b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/impl/ProtoLayoutViewInstance.java
index 08f0228..8f18ca8 100644
--- a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/impl/ProtoLayoutViewInstance.java
+++ b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/impl/ProtoLayoutViewInstance.java
@@ -20,6 +20,13 @@
import static android.widget.FrameLayout.LayoutParams.UNSPECIFIED_GRAVITY;
import static androidx.core.util.Preconditions.checkNotNull;
+import static androidx.wear.protolayout.renderer.common.ProviderStatsLogger.IGNORED_FAILURE_ANIMATION_QUOTA_EXCEEDED;
+import static androidx.wear.protolayout.renderer.common.ProviderStatsLogger.IGNORED_FAILURE_APPLY_MUTATION_EXCEPTION;
+import static androidx.wear.protolayout.renderer.common.ProviderStatsLogger.INFLATION_FAILURE_REASON_EXPRESSION_NODE_COUNT_EXCEEDED;
+import static androidx.wear.protolayout.renderer.common.ProviderStatsLogger.INFLATION_FAILURE_REASON_LAYOUT_DEPTH_EXCEEDED;
+
+import static com.google.common.util.concurrent.Futures.immediateCancelledFuture;
+import static com.google.common.util.concurrent.Futures.immediateFuture;
import android.content.Context;
import android.content.res.Resources;
@@ -41,6 +48,7 @@
import androidx.wear.protolayout.expression.PlatformDataKey;
import androidx.wear.protolayout.expression.pipeline.FixedQuotaManagerImpl;
import androidx.wear.protolayout.expression.pipeline.PlatformDataProvider;
+import androidx.wear.protolayout.expression.pipeline.QuotaManager;
import androidx.wear.protolayout.expression.pipeline.StateStore;
import androidx.wear.protolayout.proto.LayoutElementProto.ArcLayoutElement;
import androidx.wear.protolayout.proto.LayoutElementProto.ArcLayoutElement.InnerCase;
@@ -52,7 +60,11 @@
import androidx.wear.protolayout.renderer.ProtoLayoutTheme;
import androidx.wear.protolayout.renderer.ProtoLayoutVisibilityState;
import androidx.wear.protolayout.renderer.common.LoggingUtils;
+import androidx.wear.protolayout.renderer.common.NoOpProviderStatsLogger;
import androidx.wear.protolayout.renderer.common.ProtoLayoutDiffer;
+import androidx.wear.protolayout.renderer.common.ProviderStatsLogger;
+import androidx.wear.protolayout.renderer.common.ProviderStatsLogger.InflaterStatsLogger;
+import androidx.wear.protolayout.renderer.common.RenderingArtifact;
import androidx.wear.protolayout.renderer.dynamicdata.ProtoLayoutDynamicDataPipeline;
import androidx.wear.protolayout.renderer.inflater.ProtoLayoutInflater;
import androidx.wear.protolayout.renderer.inflater.ProtoLayoutInflater.InflateResult;
@@ -114,6 +126,7 @@
@NonNull private final ListeningExecutorService mUiExecutorService;
@NonNull private final ListeningExecutorService mBgExecutorService;
@NonNull private final String mClickableIdExtra;
+ @NonNull private final ProviderStatsLogger mProviderStatsLogger;
@Nullable private final LoggingUtils mLoggingUtils;
@Nullable private final ProtoLayoutExtensionViewProvider mExtensionViewProvider;
@@ -219,10 +232,11 @@
*/
@UiThread
@NonNull
- ListenableFuture<Void> postInflate(
+ ListenableFuture<RenderingArtifact> postInflate(
@NonNull ViewGroup attachParent,
@Nullable ViewGroup prevInflateParent,
- boolean isReattaching);
+ boolean isReattaching,
+ InflaterStatsLogger inflaterStatsLogger);
}
/** Result of a {@link #renderOrComputeMutations} call when no changes are required. */
@@ -234,11 +248,12 @@
@NonNull
@Override
- public ListenableFuture<Void> postInflate(
+ public ListenableFuture<RenderingArtifact> postInflate(
@NonNull ViewGroup attachParent,
@Nullable ViewGroup prevInflateParent,
- boolean isReattaching) {
- return Futures.immediateVoidFuture();
+ boolean isReattaching,
+ InflaterStatsLogger inflaterStatsLogger) {
+ return immediateFuture(RenderingArtifact.create(inflaterStatsLogger));
}
}
@@ -251,11 +266,12 @@
@NonNull
@Override
- public ListenableFuture<Void> postInflate(
+ public ListenableFuture<RenderingArtifact> postInflate(
@NonNull ViewGroup attachParent,
@Nullable ViewGroup prevInflateParent,
- boolean isReattaching) {
- return Futures.immediateVoidFuture();
+ boolean isReattaching,
+ InflaterStatsLogger inflaterStatsLogger) {
+ return immediateFuture(RenderingArtifact.failed());
}
}
@@ -278,10 +294,11 @@
@NonNull
@Override
@UiThread
- public ListenableFuture<Void> postInflate(
+ public ListenableFuture<RenderingArtifact> postInflate(
@NonNull ViewGroup attachParent,
@Nullable ViewGroup prevInflateParent,
- boolean isReattaching) {
+ boolean isReattaching,
+ InflaterStatsLogger inflaterStatsLogger) {
InflateResult inflateResult =
checkNotNull(
mNewInflateParentData.mInflateResult,
@@ -292,7 +309,7 @@
attachParent.addView(
inflateResult.inflateParent, new LayoutParams(MATCH_PARENT, MATCH_PARENT));
inflateResult.updateDynamicDataPipeline(isReattaching);
- return Futures.immediateVoidFuture();
+ return immediateFuture(RenderingArtifact.create(inflaterStatsLogger));
}
}
@@ -318,10 +335,11 @@
@NonNull
@Override
@UiThread
- public ListenableFuture<Void> postInflate(
+ public ListenableFuture<RenderingArtifact> postInflate(
@NonNull ViewGroup attachParent,
@Nullable ViewGroup prevInflateParent,
- boolean isReattaching) {
+ boolean isReattaching,
+ InflaterStatsLogger inflaterStatsLogger) {
return mInflater.applyMutation(checkNotNull(prevInflateParent), mMutation);
}
}
@@ -345,6 +363,7 @@
@NonNull private final String mClickableIdExtra;
@Nullable private final LoggingUtils mLoggingUtils;
+ @NonNull private final ProviderStatsLogger mProviderStatsLogger;
private final boolean mAnimationEnabled;
private final int mRunningAnimationsLimit;
@@ -366,6 +385,7 @@
@Nullable ProtoLayoutExtensionViewProvider extensionViewProvider,
@NonNull String clickableIdExtra,
@Nullable LoggingUtils loggingUtils,
+ @NonNull ProviderStatsLogger providerStatsLogger,
boolean animationEnabled,
int runningAnimationsLimit,
boolean updatesEnabled,
@@ -384,6 +404,7 @@
this.mExtensionViewProvider = extensionViewProvider;
this.mClickableIdExtra = clickableIdExtra;
this.mLoggingUtils = loggingUtils;
+ this.mProviderStatsLogger = providerStatsLogger;
this.mAnimationEnabled = animationEnabled;
this.mRunningAnimationsLimit = runningAnimationsLimit;
this.mUpdatesEnabled = updatesEnabled;
@@ -468,6 +489,13 @@
return mLoggingUtils;
}
+ /** Returns the provider stats logger used for telemetry. */
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @NonNull
+ public ProviderStatsLogger getProviderStatsLogger() {
+ return mProviderStatsLogger;
+ }
+
/** Returns whether animations are enabled. */
@RestrictTo(Scope.LIBRARY)
public boolean getAnimationEnabled() {
@@ -529,6 +557,7 @@
@Nullable private ProtoLayoutExtensionViewProvider mExtensionViewProvider;
@NonNull private final String mClickableIdExtra;
@Nullable private LoggingUtils mLoggingUtils;
+ @Nullable private ProviderStatsLogger mProviderStatsLogger;
private boolean mAnimationEnabled = true;
private int mRunningAnimationsLimit = DEFAULT_MAX_CONCURRENT_RUNNING_ANIMATIONS;
@@ -632,6 +661,15 @@
return this;
}
+ /** Sets the provider stats logger used for telemetry. */
+ @RestrictTo(Scope.LIBRARY_GROUP)
+ @NonNull
+ public Builder setProviderStatsLogger(
+ @NonNull ProviderStatsLogger providerStatsLogger) {
+ this.mProviderStatsLogger = providerStatsLogger;
+ return this;
+ }
+
/**
* Sets whether animation are enabled. If disabled, none of the animation will be
* played.
@@ -715,6 +753,12 @@
if (mRendererResources == null) {
this.mRendererResources = mUiContext.getResources();
}
+
+ if (mProviderStatsLogger == null) {
+ mProviderStatsLogger =
+ new NoOpProviderStatsLogger(
+ "ProviderStatsLogger not provided to " + TAG);
+ }
return new Config(
mUiContext,
mRendererResources,
@@ -728,6 +772,7 @@
mExtensionViewProvider,
mClickableIdExtra,
mLoggingUtils,
+ mProviderStatsLogger,
mAnimationEnabled,
mRunningAnimationsLimit,
mUpdatesEnabled,
@@ -754,24 +799,51 @@
this.mWasFullyVisibleBefore = false;
this.mAllowLayoutChangingBindsWithoutDefault =
config.getAllowLayoutChangingBindsWithoutDefault();
+ this.mProviderStatsLogger = config.getProviderStatsLogger();
StateStore stateStore = config.getStateStore();
- if (stateStore != null) {
- mDataPipeline =
- config.getAnimationEnabled()
- ? new ProtoLayoutDynamicDataPipeline(
- config.getPlatformDataProviders(),
- stateStore,
- new FixedQuotaManagerImpl(
- config.getRunningAnimationsLimit(), "animations"),
- new FixedQuotaManagerImpl(
- DYNAMIC_NODES_MAX_COUNT, "dynamic nodes"))
- : new ProtoLayoutDynamicDataPipeline(
- config.getPlatformDataProviders(), stateStore);
- mDataPipeline.setFullyVisible(config.getIsViewFullyVisible());
- } else {
+ if (stateStore == null) {
mDataPipeline = null;
+ return;
}
+
+ if (config.getAnimationEnabled()) {
+ QuotaManager nodeQuotaManager =
+ new FixedQuotaManagerImpl(DYNAMIC_NODES_MAX_COUNT, "dynamic nodes") {
+ @Override
+ public boolean tryAcquireQuota(int quota) {
+ boolean success = super.tryAcquireQuota(quota);
+ if (!success) {
+ mProviderStatsLogger.logInflationFailed(
+ INFLATION_FAILURE_REASON_EXPRESSION_NODE_COUNT_EXCEEDED);
+ }
+ return success;
+ }
+ };
+ mDataPipeline =
+ new ProtoLayoutDynamicDataPipeline(
+ config.getPlatformDataProviders(),
+ stateStore,
+ new FixedQuotaManagerImpl(
+ config.getRunningAnimationsLimit(), "animations") {
+ @Override
+ public boolean tryAcquireQuota(int quota) {
+ boolean success = super.tryAcquireQuota(quota);
+ if (!success) {
+ mProviderStatsLogger.logIgnoredFailure(
+ IGNORED_FAILURE_ANIMATION_QUOTA_EXCEEDED);
+ }
+ return success;
+ }
+ },
+ nodeQuotaManager);
+ } else {
+ mDataPipeline =
+ new ProtoLayoutDynamicDataPipeline(
+ config.getPlatformDataProviders(), stateStore);
+ }
+
+ mDataPipeline.setFullyVisible(config.getIsViewFullyVisible());
}
@WorkerThread
@@ -780,7 +852,8 @@
@NonNull Layout layout,
@NonNull ResourceProto.Resources resources,
@Nullable RenderedMetadata prevRenderedMetadata,
- @NonNull ViewProperties parentViewProp) {
+ @NonNull ViewProperties parentViewProp,
+ @NonNull InflaterStatsLogger inflaterStatsLogger) {
ResourceResolvers resolvers =
mResourceResolversProvider.getResourceResolvers(
mUiContext, resources, mUiExecutorService, mAnimationEnabled);
@@ -797,10 +870,10 @@
if (sameFingerprint) {
if (mPrevLayoutAlreadyFailingDepthCheck) {
- throwExceptionForLayoutDepthCheckFailure();
+ handleLayoutDepthCheckFailure(inflaterStatsLogger);
}
} else {
- checkLayoutDepth(layout.getRoot(), MAX_LAYOUT_ELEMENT_DEPTH);
+ checkLayoutDepth(layout.getRoot(), MAX_LAYOUT_ELEMENT_DEPTH, inflaterStatsLogger);
}
mPrevLayoutAlreadyFailingDepthCheck = false;
@@ -815,6 +888,7 @@
.setClickableIdExtra(mClickableIdExtra)
.setAllowLayoutChangingBindsWithoutDefault(
mAllowLayoutChangingBindsWithoutDefault)
+ .setInflaterStatsLogger(inflaterStatsLogger)
.setApplyFontVariantBodyAsDefault(true);
if (mDataPipeline != null) {
inflaterConfigBuilder.setDynamicDataPipeline(mDataPipeline);
@@ -886,6 +960,18 @@
return new InflateParentData(result);
}
+ @UiThread
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ @NonNull
+ public ListenableFuture<RenderingArtifact> renderLayoutAndAttach(
+ @NonNull Layout layout,
+ @NonNull ResourceProto.Resources resources,
+ @NonNull ViewGroup attachParent) {
+
+ return renderAndAttach(
+ layout, resources, attachParent, mProviderStatsLogger.createInflaterStatsLogger());
+ }
+
/**
* Render the layout for this layout and attach this layout instance to a {@code attachParent}
* container. Note that this method may clear all of {@code attachParent}'s children before
@@ -911,6 +997,47 @@
@NonNull Layout layout,
@NonNull ResourceProto.Resources resources,
@NonNull ViewGroup attachParent) {
+ SettableFuture<Void> result = SettableFuture.create();
+ ListenableFuture<RenderingArtifact> future =
+ renderLayoutAndAttach(layout, resources, attachParent);
+ if (future.isDone()) {
+ if (future.isCancelled()) {
+ return immediateCancelledFuture();
+ }
+ return immediateFuture(null);
+ } else {
+ future.addListener(
+ () -> {
+ if (future.isCancelled()) {
+ result.cancel(/* mayInterruptIfRunning= */ false);
+ } else {
+ try {
+ RenderingArtifact ignored = future.get();
+ result.set(null);
+ } catch (ExecutionException
+ | InterruptedException
+ | CancellationException e) {
+ Log.e(TAG, "Failed to render layout", e);
+ result.setException(e);
+ }
+ }
+ },
+ mUiExecutorService);
+ }
+ return result;
+ }
+
+ @UiThread
+ @SuppressWarnings({
+ "ReferenceEquality",
+ "ExecutorTaskName",
+ }) // layout == prevLayout is intentional (and enough in this case)
+ @NonNull
+ private ListenableFuture<RenderingArtifact> renderAndAttach(
+ @NonNull Layout layout,
+ @NonNull ResourceProto.Resources resources,
+ @NonNull ViewGroup attachParent,
+ @NonNull InflaterStatsLogger inflaterStatsLogger) {
if (mLoggingUtils != null && mLoggingUtils.canLogD(TAG)) {
mLoggingUtils.logD(TAG, "Layout received in #renderAndAttach:\n %s", layout.toString());
mLoggingUtils.logD(
@@ -930,7 +1057,7 @@
if (layout == mPrevLayout && mInflateParent != null) {
// Nothing to do.
- return Futures.immediateVoidFuture();
+ return Futures.immediateFuture(RenderingArtifact.skipped());
}
boolean isReattaching = false;
@@ -1000,10 +1127,11 @@
layout,
resources,
prevRenderedMetadata,
- parentViewProp));
+ parentViewProp,
+ inflaterStatsLogger));
mCanReattachWithoutRendering = false;
}
- SettableFuture<Void> result = SettableFuture.create();
+ SettableFuture<RenderingArtifact> result = SettableFuture.create();
if (!checkNotNull(mRenderFuture).isDone()) {
ListenableFuture<RenderResult> rendererFuture = mRenderFuture;
mRenderFuture.addListener(
@@ -1023,7 +1151,8 @@
checkNotNull(rendererFuture).get(),
/* isReattaching= */ false,
layout,
- resources));
+ resources,
+ inflaterStatsLogger));
} catch (ExecutionException
| InterruptedException
| CancellationException e) {
@@ -1048,7 +1177,8 @@
mRenderFuture.get(),
isReattaching,
layout,
- resources));
+ resources,
+ inflaterStatsLogger));
} catch (ExecutionException | InterruptedException | CancellationException e) {
Log.e(TAG, "Failed to render layout", e);
result.setException(e);
@@ -1064,6 +1194,12 @@
*/
public void invalidateCache() {
mPrevResourcesVersion = null;
+ // Cancel any ongoing rendering which might have a reference to older app resources.
+ if (mRenderFuture != null && !mRenderFuture.isDone()) {
+ mRenderFuture.cancel(/* mayInterruptIfRunning= */ false);
+ mRenderFuture = null;
+ Log.w(TAG, "Cancelled ongoing rendering due to cache invalidation.");
+ }
}
@Nullable
@@ -1080,13 +1216,14 @@
@UiThread
@SuppressWarnings("ExecutorTaskName")
@NonNull
- private ListenableFuture<Void> postInflate(
+ private ListenableFuture<RenderingArtifact> postInflate(
@NonNull ViewGroup attachParent,
@Nullable ViewGroup prevInflateParent,
@NonNull RenderResult renderResult,
boolean isReattaching,
@NonNull Layout layout,
- @NonNull ResourceProto.Resources resources) {
+ @NonNull ResourceProto.Resources resources,
+ InflaterStatsLogger inflaterStatsLogger) {
mCanReattachWithoutRendering = renderResult.canReattachWithoutRendering();
if (renderResult instanceof InflatedIntoNewParentRenderResult) {
@@ -1101,9 +1238,10 @@
.inflateParent;
}
- ListenableFuture<Void> postInflateFuture =
- renderResult.postInflate(attachParent, prevInflateParent, isReattaching);
- SettableFuture<Void> result = SettableFuture.create();
+ ListenableFuture<RenderingArtifact> postInflateFuture =
+ renderResult.postInflate(
+ attachParent, prevInflateParent, isReattaching, inflaterStatsLogger);
+ SettableFuture<RenderingArtifact> result = SettableFuture.create();
if (!postInflateFuture.isDone()) {
postInflateFuture.addListener(
() -> {
@@ -1114,20 +1252,24 @@
| CancellationException e) {
result.setFuture(
handlePostInflateFailure(
- e, layout, resources, prevInflateParent, attachParent));
+ e,
+ layout,
+ resources,
+ prevInflateParent,
+ attachParent,
+ inflaterStatsLogger));
}
},
mUiExecutorService);
} else {
try {
- postInflateFuture.get();
- return Futures.immediateVoidFuture();
+ return immediateFuture(postInflateFuture.get());
} catch (ExecutionException
| InterruptedException
| CancellationException
| ViewMutationException e) {
return handlePostInflateFailure(
- e, layout, resources, prevInflateParent, attachParent);
+ e, layout, resources, prevInflateParent, attachParent, inflaterStatsLogger);
}
}
return result;
@@ -1136,22 +1278,24 @@
@UiThread
@SuppressWarnings("ReferenceEquality") // layout == prevLayout is intentional
@NonNull
- private ListenableFuture<Void> handlePostInflateFailure(
+ private ListenableFuture<RenderingArtifact> handlePostInflateFailure(
@NonNull Throwable error,
@NonNull Layout layout,
@NonNull ResourceProto.Resources resources,
@Nullable ViewGroup prevInflateParent,
- @NonNull ViewGroup parent) {
+ @NonNull ViewGroup parent,
+ InflaterStatsLogger inflaterStatsLogger) {
// If a RuntimeError is thrown, it'll be wrapped in an UncheckedExecutionException
Throwable e = error.getCause();
if (e instanceof ViewMutationException) {
+ inflaterStatsLogger.logIgnoredFailure(IGNORED_FAILURE_APPLY_MUTATION_EXCEPTION);
Log.w(TAG, "applyMutation failed." + e.getMessage());
if (mPrevLayout == layout && parent == mAttachParent) {
Log.w(TAG, "Retrying full inflation.");
// Clear rendering metadata and prevLayout to force a full reinflation.
ProtoLayoutInflater.clearRenderedMetadata(checkNotNull(prevInflateParent));
mPrevLayout = null;
- return renderAndAttach(layout, resources, parent);
+ return renderAndAttach(layout, resources, parent, inflaterStatsLogger);
}
} else {
Log.e(TAG, "postInflate failed.", error);
@@ -1176,6 +1320,7 @@
private void detachInternal() {
if (mRenderFuture != null && !mRenderFuture.isDone()) {
mRenderFuture.cancel(/* mayInterruptIfRunning= */ false);
+ mRenderFuture = null;
}
setLayoutVisibility(ProtoLayoutVisibilityState.VISIBILITY_STATE_INVISIBLE);
@@ -1227,9 +1372,12 @@
}
/** Returns true if the layout element depth doesn't exceed the given {@code allowedDepth}. */
- private void checkLayoutDepth(LayoutElement layoutElement, int allowedDepth) {
+ private void checkLayoutDepth(
+ LayoutElement layoutElement,
+ int allowedDepth,
+ InflaterStatsLogger inflaterStatsLogger) {
if (allowedDepth <= 0) {
- throwExceptionForLayoutDepthCheckFailure();
+ handleLayoutDepthCheckFailure(inflaterStatsLogger);
}
List<LayoutElement> children = ImmutableList.of();
switch (layoutElement.getInnerCase()) {
@@ -1245,28 +1393,32 @@
case ARC:
List<ArcLayoutElement> arcElements = layoutElement.getArc().getContentsList();
if (!arcElements.isEmpty() && allowedDepth == 1) {
- throwExceptionForLayoutDepthCheckFailure();
+ handleLayoutDepthCheckFailure(inflaterStatsLogger);
}
for (ArcLayoutElement element : arcElements) {
if (element.getInnerCase() == InnerCase.ADAPTER) {
- checkLayoutDepth(element.getAdapter().getContent(), allowedDepth - 1);
+ checkLayoutDepth(
+ element.getAdapter().getContent(),
+ allowedDepth - 1,
+ inflaterStatsLogger);
}
}
break;
case SPANNABLE:
if (layoutElement.getSpannable().getSpansCount() > 0 && allowedDepth == 1) {
- throwExceptionForLayoutDepthCheckFailure();
+ handleLayoutDepthCheckFailure(inflaterStatsLogger);
}
break;
default:
// Other LayoutElements have depth of one.
}
for (LayoutElement child : children) {
- checkLayoutDepth(child, allowedDepth - 1);
+ checkLayoutDepth(child, allowedDepth - 1, inflaterStatsLogger);
}
}
- private void throwExceptionForLayoutDepthCheckFailure() {
+ private void handleLayoutDepthCheckFailure(InflaterStatsLogger inflaterStatsLogger) {
+ inflaterStatsLogger.logInflationFailed(INFLATION_FAILURE_REASON_LAYOUT_DEPTH_EXCEEDED);
mPrevLayoutAlreadyFailingDepthCheck = true;
throw new IllegalStateException(
"Layout depth exceeds maximum allowed depth: " + MAX_LAYOUT_ELEMENT_DEPTH);
diff --git a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflater.java b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflater.java
index 1ca9a23..4997dde 100644
--- a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflater.java
+++ b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflater.java
@@ -28,7 +28,7 @@
import static androidx.wear.protolayout.renderer.common.ProtoLayoutDiffer.getParentNodePosId;
import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
-import static com.google.common.util.concurrent.Futures.immediateVoidFuture;
+import static com.google.common.util.concurrent.Futures.immediateFuture;
import static java.lang.Math.max;
import static java.lang.Math.min;
@@ -180,9 +180,12 @@
import androidx.wear.protolayout.renderer.ProtoLayoutTheme.FontSet;
import androidx.wear.protolayout.renderer.R;
import androidx.wear.protolayout.renderer.common.LoggingUtils;
+import androidx.wear.protolayout.renderer.common.NoOpProviderStatsLogger;
import androidx.wear.protolayout.renderer.common.ProtoLayoutDiffer;
import androidx.wear.protolayout.renderer.common.ProtoLayoutDiffer.LayoutDiff;
import androidx.wear.protolayout.renderer.common.ProtoLayoutDiffer.TreeNodeWithChange;
+import androidx.wear.protolayout.renderer.common.ProviderStatsLogger.InflaterStatsLogger;
+import androidx.wear.protolayout.renderer.common.RenderingArtifact;
import androidx.wear.protolayout.renderer.common.SeekableAnimatedVectorDrawable;
import androidx.wear.protolayout.renderer.dynamicdata.ProtoLayoutDynamicDataPipeline;
import androidx.wear.protolayout.renderer.inflater.RenderedMetadata.LayoutInfo;
@@ -301,6 +304,7 @@
final String mClickableIdExtra;
@Nullable private final LoggingUtils mLoggingUtils;
+ @NonNull private final InflaterStatsLogger mInflaterStatsLogger;
@Nullable final Executor mLoadActionExecutor;
final LoadActionListener mLoadActionListener;
@@ -528,6 +532,7 @@
@NonNull private final String mClickableIdExtra;
@Nullable private final LoggingUtils mLoggingUtils;
+ @NonNull private final InflaterStatsLogger mInflaterStatsLogger;
@Nullable private final ProtoLayoutExtensionViewProvider mExtensionViewProvider;
private final boolean mAnimationEnabled;
@@ -547,6 +552,7 @@
@Nullable ProtoLayoutExtensionViewProvider extensionViewProvider,
@NonNull String clickableIdExtra,
@Nullable LoggingUtils loggingUtils,
+ @NonNull InflaterStatsLogger inflaterStatsLogger,
boolean animationEnabled,
boolean allowLayoutChangingBindsWithoutDefault,
boolean applyFontVariantBodyAsDefault) {
@@ -562,6 +568,7 @@
this.mAllowLayoutChangingBindsWithoutDefault = allowLayoutChangingBindsWithoutDefault;
this.mClickableIdExtra = clickableIdExtra;
this.mLoggingUtils = loggingUtils;
+ this.mInflaterStatsLogger = inflaterStatsLogger;
this.mExtensionViewProvider = extensionViewProvider;
this.mApplyFontVariantBodyAsDefault = applyFontVariantBodyAsDefault;
}
@@ -638,6 +645,12 @@
return mLoggingUtils;
}
+ /** Stats logger used for telemetry. */
+ @NonNull
+ public InflaterStatsLogger getInflaterStatsLogger() {
+ return mInflaterStatsLogger;
+ }
+
/** View provider for the renderer extension. */
@Nullable
public ProtoLayoutExtensionViewProvider getExtensionViewProvider() {
@@ -678,6 +691,7 @@
@Nullable private String mClickableIdExtra;
@Nullable private LoggingUtils mLoggingUtils;
+ @Nullable private InflaterStatsLogger mInflaterStatsLogger;
@Nullable private ProtoLayoutExtensionViewProvider mExtensionViewProvider = null;
@@ -788,6 +802,14 @@
return this;
}
+ /** Sets the stats logger used for telemetry. */
+ @NonNull
+ public Builder setInflaterStatsLogger(
+ @NonNull InflaterStatsLogger inflaterStatsLogger) {
+ this.mInflaterStatsLogger = inflaterStatsLogger;
+ return this;
+ }
+
/**
* Sets whether a "layout changing" data bind can be applied without the
* "value_for_layout" field being filled in, or being set to zero / empty. Defaults to
@@ -834,7 +856,11 @@
if (mClickableIdExtra == null) {
mClickableIdExtra = DEFAULT_CLICKABLE_ID_EXTRA;
}
-
+ if (mInflaterStatsLogger == null) {
+ mInflaterStatsLogger =
+ new NoOpProviderStatsLogger("No implementation was provided")
+ .createInflaterStatsLogger();
+ }
return new Config(
mUiContext,
mLayout,
@@ -847,6 +873,7 @@
mExtensionViewProvider,
checkNotNull(mClickableIdExtra),
mLoggingUtils,
+ mInflaterStatsLogger,
mAnimationEnabled,
mAllowLayoutChangingBindsWithoutDefault,
mApplyFontVariantBodyAsDefault);
@@ -873,6 +900,7 @@
config.getAllowLayoutChangingBindsWithoutDefault();
this.mClickableIdExtra = config.getClickableIdExtra();
this.mLoggingUtils = config.getLoggingUtils();
+ this.mInflaterStatsLogger = config.getInflaterStatsLogger();
this.mExtensionViewProvider = config.getExtensionViewProvider();
this.mApplyFontVariantBodyAsDefault = config.getApplyFontVariantBodyAsDefault();
}
@@ -1731,7 +1759,9 @@
if (modifiers.hasTransformation()) {
applyTransformation(
- wrapper == null ? view : wrapper, modifiers.getTransformation(), posId,
+ wrapper == null ? view : wrapper,
+ modifiers.getTransformation(),
+ posId,
pipelineMaker);
}
@@ -2565,8 +2595,7 @@
}
@Override
- public void onViewDetachedFromWindow(@NonNull View v) {
- }
+ public void onViewDetachedFromWindow(@NonNull View v) {}
});
}
@@ -3152,7 +3181,7 @@
* to the image view; otherwise returns null to indicate the failure of setting drawable.
*/
@Nullable
- private static Drawable setImageDrawable(
+ private Drawable setImageDrawable(
ImageView imageView, Future<Drawable> drawableFuture, String protoResId) {
try {
return setImageDrawable(imageView, drawableFuture.get(), protoResId);
@@ -3169,8 +3198,10 @@
* null to indicate the failure of setting drawable.
*/
@Nullable
- private static Drawable setImageDrawable(
- ImageView imageView, Drawable drawable, String protoResId) {
+ private Drawable setImageDrawable(ImageView imageView, Drawable drawable, String protoResId) {
+ if (drawable != null) {
+ mInflaterStatsLogger.logDrawableUsage(drawable);
+ }
if (drawable instanceof BitmapDrawable
&& ((BitmapDrawable) drawable).getBitmap().getByteCount()
> DEFAULT_MAX_BITMAP_RAW_SIZE) {
@@ -3300,7 +3331,7 @@
Log.w(
TAG,
"ArcLine length's value_for_layout is not a positive value. Element"
- + " won't be visible.");
+ + " won't be visible.");
}
sizeWrapper.setSweepAngleDegrees(sizeForLayout);
sizedLp.setAngularAlignment(
@@ -4079,8 +4110,9 @@
Optional<ProtoLayoutDynamicDataPipeline.PipelineMaker> pipelineMaker) {
if (dpProp.hasDynamicValue() && pipelineMaker.isPresent()) {
try {
- pipelineMaker.get().addPipelineFor(dpProp, dpProp.getValue(), posId,
- dynamicValueConsumer);
+ pipelineMaker
+ .get()
+ .addPipelineFor(dpProp, dpProp.getValue(), posId, dynamicValueConsumer);
} catch (RuntimeException ex) {
Log.e(TAG, "Error building pipeline", ex);
staticValueConsumer.accept(dpProp.getValue());
@@ -4143,7 +4175,9 @@
pipelineMaker
.get()
.addPipelineFor(
- floatProp.getDynamicValue(), floatProp.getValue(), posId,
+ floatProp.getDynamicValue(),
+ floatProp.getValue(),
+ posId,
dynamicValueconsumer);
} catch (RuntimeException ex) {
Log.e(TAG, "Error building pipeline", ex);
@@ -4548,7 +4582,7 @@
/** Apply the mutation that was previously computed with {@link #computeMutation}. */
@UiThread
@NonNull
- public ListenableFuture<Void> applyMutation(
+ public ListenableFuture<RenderingArtifact> applyMutation(
@NonNull ViewGroup prevInflatedParent, @NonNull ViewGroupMutation groupMutation) {
RenderedMetadata prevRenderedMetadata = getRenderedMetadata(prevInflatedParent);
if (prevRenderedMetadata != null
@@ -4561,11 +4595,11 @@
}
if (groupMutation.isNoOp()) {
// Nothing to do.
- return immediateVoidFuture();
+ return immediateFuture(RenderingArtifact.create(mInflaterStatsLogger));
}
if (groupMutation.mPipelineMaker.isPresent()) {
- SettableFuture<Void> result = SettableFuture.create();
+ SettableFuture<RenderingArtifact> result = SettableFuture.create();
groupMutation
.mPipelineMaker
.get()
@@ -4575,7 +4609,7 @@
() -> {
try {
applyMutationInternal(prevInflatedParent, groupMutation);
- result.set(null);
+ result.set(RenderingArtifact.create(mInflaterStatsLogger));
} catch (ViewMutationException ex) {
result.setException(ex);
}
@@ -4584,7 +4618,7 @@
} else {
try {
applyMutationInternal(prevInflatedParent, groupMutation);
- return immediateVoidFuture();
+ return immediateFuture(RenderingArtifact.create(mInflaterStatsLogger));
} catch (ViewMutationException ex) {
return immediateFailedFuture(ex);
}
@@ -4593,6 +4627,7 @@
private void applyMutationInternal(
@NonNull ViewGroup prevInflatedParent, @NonNull ViewGroupMutation groupMutation) {
+ mInflaterStatsLogger.logMutationChangedNodes(groupMutation.mInflatedViews.size());
for (InflatedView inflatedView : groupMutation.mInflatedViews) {
String posId = inflatedView.getTag();
if (posId == null) {
@@ -4620,15 +4655,21 @@
}
// Remove the touch delegate to the view to be updated
if (immediateParent.getTouchDelegate() != null) {
- ((TouchDelegateComposite) immediateParent.getTouchDelegate())
- .removeDelegate(viewToUpdate);
+ TouchDelegateComposite delegateComposite =
+ (TouchDelegateComposite) immediateParent.getTouchDelegate();
+ delegateComposite.removeDelegate(viewToUpdate);
// Make sure to remove the touch delegate when the actual clickable view is wrapped,
// for example ImageView inside the RatioViewWrapper
if (viewToUpdate instanceof ViewGroup
&& ((ViewGroup) viewToUpdate).getChildCount() > 0) {
- ((TouchDelegateComposite) immediateParent.getTouchDelegate())
- .removeDelegate(((ViewGroup) viewToUpdate).getChildAt(0));
+ delegateComposite.removeDelegate(((ViewGroup) viewToUpdate).getChildAt(0));
+ }
+
+ // If no more touch delegate left in the composite, remove it completely from the
+ // parent
+ if (delegateComposite.isEmpty()) {
+ immediateParent.setTouchDelegate(null);
}
}
immediateParent.removeViewAt(childIndex);
diff --git a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/RatioViewWrapper.java b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/RatioViewWrapper.java
index 9cca584..1a4b550 100644
--- a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/RatioViewWrapper.java
+++ b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/RatioViewWrapper.java
@@ -86,10 +86,6 @@
requestLayout();
}
- public float getAspectRatio() {
- return mAspectRatio;
- }
-
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (getChildCount() != 1) {
@@ -118,11 +114,16 @@
return;
}
- // If we've already hit our aspect ratio, exit.
- if (Math.abs(
- (float) childView.getMeasuredWidth() / childView.getMeasuredHeight()
- - mAspectRatio)
- <= EPSILON) {
+ // 1. If measure gives zero size, exit. This happens when the child view is an
+ // ImageViewWithoutIntrinsicSize and gets a MeasureSpec which allows it to pick its own
+ // size.
+ // 2. If we've already hit our aspect ratio, exit.
+ if (childView.getMeasuredWidth() == 0
+ || childView.getMeasuredHeight() == 0
+ || Math.abs(
+ (float) childView.getMeasuredWidth() / childView.getMeasuredHeight()
+ - mAspectRatio)
+ <= EPSILON) {
setMeasuredDimension(childView.getMeasuredWidth(), childView.getMeasuredHeight());
return;
}
diff --git a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/StandardLineHeightSpan.java b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/StandardLineHeightSpan.java
index 2eee1b6..4b0f602 100644
--- a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/StandardLineHeightSpan.java
+++ b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/StandardLineHeightSpan.java
@@ -48,8 +48,4 @@
fm.descent = Math.round(fm.descent * ratio);
fm.ascent = fm.descent - mLineHeightPx;
}
-
- public int getLineHeight() {
- return mLineHeightPx;
- }
}
diff --git a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/TouchDelegateComposite.java b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/TouchDelegateComposite.java
index e6bf97c..6184ac8 100644
--- a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/TouchDelegateComposite.java
+++ b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/TouchDelegateComposite.java
@@ -83,6 +83,10 @@
mDelegates.remove(delegateView);
}
+ boolean isEmpty() {
+ return mDelegates.isEmpty();
+ }
+
@Override
public boolean onTouchEvent(@NonNull MotionEvent event) {
boolean eventForwarded = false;
@@ -125,7 +129,7 @@
@Override
@NonNull
public AccessibilityNodeInfo.TouchDelegateInfo getTouchDelegateInfo() {
- if (VERSION.SDK_INT >= VERSION_CODES.Q) {
+ if (VERSION.SDK_INT >= VERSION_CODES.Q && !mDelegates.isEmpty()) {
Map<Region, View> targetMap = new ArrayMap<>(mDelegates.size());
for (Map.Entry<View, DelegateInfo> entry : mDelegates.entrySet()) {
AccessibilityNodeInfo.TouchDelegateInfo info =
diff --git a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/WearCurvedLineView.java b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/WearCurvedLineView.java
index 8ca9e7a..5729186 100644
--- a/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/WearCurvedLineView.java
+++ b/wear/protolayout/protolayout-renderer/src/main/java/androidx/wear/protolayout/renderer/inflater/WearCurvedLineView.java
@@ -323,11 +323,6 @@
this.setColor(mBasePaint.getColor());
}
- /** Clears the stroke cap shadow. */
- public void clearStrokeCapShadow() {
- this.mCapShadow = null;
- }
-
@Override
protected void onDraw(@NonNull Canvas canvas) {
if (mArcDrawable == null) {
diff --git a/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/dynamicdata/ProtoLayoutDynamicDataPipelineTest.java b/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/dynamicdata/ProtoLayoutDynamicDataPipelineTest.java
index 096c2aa..d720d83 100644
--- a/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/dynamicdata/ProtoLayoutDynamicDataPipelineTest.java
+++ b/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/dynamicdata/ProtoLayoutDynamicDataPipelineTest.java
@@ -112,9 +112,9 @@
import java.util.function.Consumer;
import java.util.stream.Collectors;
-// Note: Most of the functionality of DynamicDataPipeline should be tested using //
-// DynamicDataPipelineProtoTest instead. This test class only exists for the cases that cannot be //
-// trivially tested there (e.g. throwing exceptions in response to feature flags or handling //
+// Note: Most of the functionality of DynamicDataPipeline should be tested using
+// DynamicDataPipelineProtoTest instead. This test class only exists for the cases that cannot be
+// trivially tested there (e.g. throwing exceptions in response to feature flags or handling
// animations).
@RunWith(AndroidJUnit4.class)
public class ProtoLayoutDynamicDataPipelineTest {
@@ -569,7 +569,8 @@
shadowOf(getMainLooper()).idle();
assertThat(results).containsExactly(3, 4, 5, 6).inOrder();
- // Remove node NODE_1_1_1. NODE_1_1, NODE_1_11 and NODE_1_2 should remain in the pipeline.
+ // Remove node NODE_1_1_1.
+ // NODE_1_1, NODE_1_11 and NODE_1_2 should remain in the pipeline.
pipeline.removeChildNodesFor(NODE_1_1);
assertThat(pipeline.size()).isEqualTo(5);
}
@@ -1388,7 +1389,7 @@
// one running, delayed animation is not started yet.
expect.that(pipeline.getRunningAnimationsCount()).isEqualTo(1);
- assertThat(results2).hasSize(0);
+ assertThat(results2).isEmpty();
shadowOf(getMainLooper()).idleFor(100, TimeUnit.MILLISECONDS);
assertAnimation(results1, start1, end1);
@@ -1441,7 +1442,7 @@
// one running, delayed animation is not started yet.
expect.that(pipeline.getRunningAnimationsCount()).isEqualTo(1);
- assertThat(results2).hasSize(0);
+ assertThat(results2).isEmpty();
shadowOf(getMainLooper()).idle();
assertAnimation(results1, start1, end1);
@@ -1461,7 +1462,9 @@
float end1 = 10.0f;
float end2 = 50.0f;
- // 0~100: forward animation 100~300: reverse delay 300~400: reverse animation
+ // 0~100: forward animation
+ // 100~300: reverse delay
+ // 300~400: reverse animation
DynamicFloat dynamicFloat1 =
animatableFixedFloat(start1, end1, /* duration= */ 100, /* delay= */ 0, 200, 2);
List<Float> results1 = new ArrayList<>();
diff --git a/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/impl/ProtoLayoutViewInstanceTest.java b/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/impl/ProtoLayoutViewInstanceTest.java
index 6db2dfb..d095d58 100644
--- a/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/impl/ProtoLayoutViewInstanceTest.java
+++ b/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/impl/ProtoLayoutViewInstanceTest.java
@@ -53,6 +53,7 @@
import androidx.wear.protolayout.expression.pipeline.StateStore;
import androidx.wear.protolayout.proto.LayoutElementProto.Layout;
import androidx.wear.protolayout.proto.ResourceProto.Resources;
+import androidx.wear.protolayout.renderer.common.RenderingArtifact;
import androidx.wear.protolayout.renderer.helper.TestDsl.LayoutNode;
import androidx.wear.protolayout.renderer.impl.ProtoLayoutViewInstance.Config;
@@ -97,8 +98,8 @@
@Test
public void adaptiveUpdateRatesDisabled_attach_reinflatesCompletely() throws Exception {
setupInstance(/* adaptiveUpdateRatesEnabled= */ false);
- ListenableFuture<Void> result =
- mInstanceUnderTest.renderAndAttach(
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(
layout(column(text(TEXT1), text(TEXT2))), RESOURCES, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
@@ -108,7 +109,7 @@
assertThat(layout1).hasSize(1);
result =
- mInstanceUnderTest.renderAndAttach(
+ mInstanceUnderTest.renderLayoutAndAttach(
layout(column(text(TEXT1), text(TEXT3))), RESOURCES, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
@@ -120,8 +121,8 @@
@Test
public void adaptiveUpdateRatesEnabled_attach_appliesDiffOnly() throws Exception {
setupInstance(/* adaptiveUpdateRatesEnabled= */ true);
- ListenableFuture<Void> result =
- mInstanceUnderTest.renderAndAttach(
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(
layout(column(text(TEXT1), text(TEXT2))), RESOURCES, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
@@ -131,7 +132,7 @@
assertThat(layout1).hasSize(1);
result =
- mInstanceUnderTest.renderAndAttach(
+ mInstanceUnderTest.renderLayoutAndAttach(
layout(column(text(TEXT1), text(TEXT3))), RESOURCES, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
@@ -144,8 +145,8 @@
@Test
public void reattach_usesCachedLayoutForDiffUpdate() throws Exception {
setupInstance(/* adaptiveUpdateRatesEnabled= */ true);
- ListenableFuture<Void> result =
- mInstanceUnderTest.renderAndAttach(
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(
layout(column(text(TEXT1), text(TEXT2))), RESOURCES, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
@@ -156,7 +157,7 @@
mInstanceUnderTest.detach(mRootContainer);
result =
- mInstanceUnderTest.renderAndAttach(
+ mInstanceUnderTest.renderLayoutAndAttach(
layout(column(text(TEXT1), text(TEXT3))), RESOURCES, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
@@ -172,8 +173,8 @@
setupInstance(/* adaptiveUpdateRatesEnabled= */ true);
// First one that does the full layout update.
- ListenableFuture<Void> result =
- mInstanceUnderTest.renderAndAttach(
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(
layout(column(text(TEXT1), text(TEXT2))), RESOURCES, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
@@ -184,7 +185,7 @@
// Second one that applies mutation only.
result =
- mInstanceUnderTest.renderAndAttach(
+ mInstanceUnderTest.renderLayoutAndAttach(
layout(column(text(TEXT1), text(TEXT3))), RESOURCES, mRootContainer);
// Detach so it can't apply update.
mInstanceUnderTest.detach(mRootContainer);
@@ -200,9 +201,8 @@
// Render the first layout.
Layout layout1 = layout(column(dynamicFixedText(TEXT1), dynamicFixedText(TEXT2)));
- ListenableFuture<Void> result =
- mInstanceUnderTest.renderAndAttach(
- layout1, RESOURCES, mRootContainer);
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(layout1, RESOURCES, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
assertNoException(result);
@@ -227,9 +227,7 @@
// not changed part of the layout was also changed in inflated View.
Layout layout2 = layout(column(dynamicFixedText(TEXT1), dynamicFixedText(TEXT3)));
- result =
- mInstanceUnderTest.renderAndAttach(
- layout2, RESOURCES, mRootContainer);
+ result = mInstanceUnderTest.renderLayoutAndAttach(layout2, RESOURCES, mRootContainer);
// Make sure future is computing result.
assertThat(result.isDone()).isFalse();
@@ -252,8 +250,8 @@
// Render the first layout.
Layout layout1 = layout(column(dynamicFixedText(TEXT1), dynamicFixedText(TEXT2)));
- ListenableFuture<Void> result =
- mInstanceUnderTest.renderAndAttach(layout1, RESOURCES, mRootContainer);
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(layout1, RESOURCES, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
assertNoException(result);
@@ -263,7 +261,7 @@
assertThat(findViewsWithText(mRootContainer, TEXT2)).hasSize(1);
Layout layout2 = layout(column(dynamicFixedText(TEXT1), dynamicFixedText(TEXT3)));
- result = mInstanceUnderTest.renderAndAttach(layout2, RESOURCES, mRootContainer);
+ result = mInstanceUnderTest.renderLayoutAndAttach(layout2, RESOURCES, mRootContainer);
// Make sure future is computing result.
assertThat(result.isDone()).isFalse();
shadowOf(Looper.getMainLooper()).idle();
@@ -279,13 +277,13 @@
public void adaptiveUpdateRatesEnabled_ongoingRendering_skipsPreviousLayout() {
FrameLayout container = new FrameLayout(mApplicationContext);
setupInstance(/* adaptiveUpdateRatesEnabled= */ true);
- ListenableFuture<Void> result1 =
- mInstanceUnderTest.renderAndAttach(
+ ListenableFuture<RenderingArtifact> result1 =
+ mInstanceUnderTest.renderLayoutAndAttach(
layout(column(text(TEXT1), text(TEXT2))), RESOURCES, container);
assertThat(result1.isDone()).isFalse();
- ListenableFuture<Void> result2 =
- mInstanceUnderTest.renderAndAttach(
+ ListenableFuture<RenderingArtifact> result2 =
+ mInstanceUnderTest.renderLayoutAndAttach(
layout(column(text(TEXT1), text(TEXT3))), RESOURCES, container);
shadowOf(Looper.getMainLooper()).idle();
@@ -301,14 +299,14 @@
FrameLayout container1 = new FrameLayout(mApplicationContext);
FrameLayout container2 = new FrameLayout(mApplicationContext);
setupInstance(/* adaptiveUpdateRatesEnabled= */ true);
- ListenableFuture<Void> result =
- mInstanceUnderTest.renderAndAttach(
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(
layout(column(text(TEXT1), text(TEXT2))), RESOURCES, container1);
assertThrows(
IllegalStateException.class,
() ->
- mInstanceUnderTest.renderAndAttach(
+ mInstanceUnderTest.renderLayoutAndAttach(
layout(column(text(TEXT1), text(TEXT2))), RESOURCES, container2));
shadowOf(Looper.getMainLooper()).idle();
@@ -321,12 +319,14 @@
FrameLayout container1 = new FrameLayout(mApplicationContext);
FrameLayout container2 = new FrameLayout(mApplicationContext);
setupInstance(/* adaptiveUpdateRatesEnabled= */ true);
- ListenableFuture<Void> result1 =
- mInstanceUnderTest.renderAndAttach(layout(text(TEXT1)), RESOURCES, container1);
+ ListenableFuture<RenderingArtifact> result1 =
+ mInstanceUnderTest.renderLayoutAndAttach(
+ layout(text(TEXT1)), RESOURCES, container1);
mInstanceUnderTest.detach(container1);
- ListenableFuture<Void> result2 =
- mInstanceUnderTest.renderAndAttach(layout(text(TEXT1)), RESOURCES, container2);
+ ListenableFuture<RenderingArtifact> result2 =
+ mInstanceUnderTest.renderLayoutAndAttach(
+ layout(text(TEXT1)), RESOURCES, container2);
shadowOf(Looper.getMainLooper()).idle();
assertThat(result1.isCancelled()).isTrue();
@@ -341,13 +341,13 @@
throws Exception {
Layout layout = layout(text(TEXT1));
setupInstance(/* adaptiveUpdateRatesEnabled= */ false);
- ListenableFuture<Void> result =
- mInstanceUnderTest.renderAndAttach(layout, RESOURCES, mRootContainer);
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(layout, RESOURCES, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
assertNoException(result);
- result = mInstanceUnderTest.renderAndAttach(layout, RESOURCES, mRootContainer);
+ result = mInstanceUnderTest.renderLayoutAndAttach(layout, RESOURCES, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
assertNoException(result);
@@ -360,14 +360,14 @@
Layout layout1 = layout(text(TEXT1));
Layout layout2 = layout(text(TEXT1));
setupInstance(/* adaptiveUpdateRatesEnabled= */ true);
- ListenableFuture<Void> result =
- mInstanceUnderTest.renderAndAttach(layout1, RESOURCES, mRootContainer);
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(layout1, RESOURCES, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
assertNoException(result);
// Make sure we have an UnchangedRenderResult
- result = mInstanceUnderTest.renderAndAttach(layout2, RESOURCES, mRootContainer);
+ result = mInstanceUnderTest.renderLayoutAndAttach(layout2, RESOURCES, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
assertNoException(result);
@@ -377,7 +377,7 @@
assertThat(findViewsWithText(mRootContainer, TEXT1)).isEmpty();
shadowOf(Looper.getMainLooper()).idle();
- result = mInstanceUnderTest.renderAndAttach(layout2, RESOURCES, mRootContainer);
+ result = mInstanceUnderTest.renderLayoutAndAttach(layout2, RESOURCES, mRootContainer);
assertThat(result.isDone()).isTrue();
assertNoException(result);
@@ -388,8 +388,8 @@
public void fullInflationResultCanBeReused() throws Exception {
setupInstance(/* adaptiveUpdateRatesEnabled= */ false);
Layout layout = layout(text(TEXT1));
- ListenableFuture<Void> result =
- mInstanceUnderTest.renderAndAttach(layout, RESOURCES, mRootContainer);
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(layout, RESOURCES, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
assertNoException(result);
@@ -397,7 +397,7 @@
ListenableFuture<?> renderFuture = mInstanceUnderTest.mRenderFuture;
mInstanceUnderTest.detach(mRootContainer);
- result = mInstanceUnderTest.renderAndAttach(layout, RESOURCES, mRootContainer);
+ result = mInstanceUnderTest.renderLayoutAndAttach(layout, RESOURCES, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
assertNoException(result);
@@ -409,15 +409,15 @@
throws Exception {
Layout layout = layout(text(TEXT1));
setupInstance(/* adaptiveUpdateRatesEnabled= */ false);
- ListenableFuture<Void> result =
- mInstanceUnderTest.renderAndAttach(layout, RESOURCES, mRootContainer);
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(layout, RESOURCES, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
assertNoException(result);
List<View> textViews1 = findViewsWithText(mRootContainer, TEXT1);
assertThat(textViews1).hasSize(1);
mInstanceUnderTest.close();
- result = mInstanceUnderTest.renderAndAttach(layout, RESOURCES, mRootContainer);
+ result = mInstanceUnderTest.renderLayoutAndAttach(layout, RESOURCES, mRootContainer);
assertThat(shadowOf(Looper.getMainLooper()).isIdle()).isFalse();
shadowOf(Looper.getMainLooper()).idle();
@@ -431,8 +431,8 @@
public void detach_clearsHostView() throws Exception {
Layout layout = layout(text(TEXT1));
setupInstance(/* adaptiveUpdateRatesEnabled= */ true);
- ListenableFuture<Void> result =
- mInstanceUnderTest.renderAndAttach(layout, RESOURCES, mRootContainer);
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(layout, RESOURCES, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
assertNoException(result);
assertThat(findViewsWithText(mRootContainer, TEXT1)).hasSize(1);
@@ -449,14 +449,14 @@
Layout layout2 = layout(text(TEXT1));
Resources resources2 = Resources.newBuilder().setVersion("2").build();
setupInstance(/* adaptiveUpdateRatesEnabled= */ true);
- ListenableFuture<Void> result =
- mInstanceUnderTest.renderAndAttach(layout1, resources1, mRootContainer);
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(layout1, resources1, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
assertNoException(result);
assertThat(findViewsWithText(mRootContainer, TEXT1)).hasSize(1);
View view1 = findViewsWithText(mRootContainer, TEXT1).get(0);
- result = mInstanceUnderTest.renderAndAttach(layout2, resources2, mRootContainer);
+ result = mInstanceUnderTest.renderLayoutAndAttach(layout2, resources2, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
assertNoException(result);
@@ -472,15 +472,15 @@
Layout layout2 = layout(text(TEXT1));
Resources resources2 = Resources.newBuilder().setVersion("1").build();
setupInstance(/* adaptiveUpdateRatesEnabled= */ true);
- ListenableFuture<Void> result =
- mInstanceUnderTest.renderAndAttach(layout1, resources1, mRootContainer);
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(layout1, resources1, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
assertNoException(result);
assertThat(findViewsWithText(mRootContainer, TEXT1)).hasSize(1);
View view1 = findViewsWithText(mRootContainer, TEXT1).get(0);
mInstanceUnderTest.invalidateCache();
- result = mInstanceUnderTest.renderAndAttach(layout2, resources2, mRootContainer);
+ result = mInstanceUnderTest.renderLayoutAndAttach(layout2, resources2, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
assertNoException(result);
@@ -490,13 +490,28 @@
}
@Test
+ public void invalidateCache_ongoingInflation_oldInflationGetsCancelled() throws Exception {
+ Layout layout1 = layout(text(TEXT1));
+ Resources resources1 = Resources.newBuilder().setVersion("1").build();
+ setupInstance(/* adaptiveUpdateRatesEnabled= */ true);
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(layout1, resources1, mRootContainer);
+
+ mInstanceUnderTest.invalidateCache();
+ shadowOf(Looper.getMainLooper()).idle();
+
+ assertThat(result.isCancelled()).isTrue();
+ assertThat(findViewsWithText(mRootContainer, TEXT1)).isEmpty();
+ }
+
+ @Test
public void adaptiveUpdateRatesEnabled_rootElementdiff_keepsElementCentered() throws Exception {
int dimension = 50;
setupInstance(/* adaptiveUpdateRatesEnabled= */ true);
// Full inflation.
- ListenableFuture<Void> result =
- mInstanceUnderTest.renderAndAttach(
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(
layout(
column(
props -> {
@@ -518,7 +533,7 @@
// Diff update only for the root element.
result =
- mInstanceUnderTest.renderAndAttach(
+ mInstanceUnderTest.renderLayoutAndAttach(
layout(
column(
props -> {
@@ -546,8 +561,8 @@
public void close_clearsHostView() throws Exception {
Layout layout = layout(text(TEXT1));
setupInstance(/* adaptiveUpdateRatesEnabled= */ true);
- ListenableFuture<Void> result =
- mInstanceUnderTest.renderAndAttach(layout, RESOURCES, mRootContainer);
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(layout, RESOURCES, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
assertNoException(result);
assertThat(findViewsWithText(mRootContainer, TEXT1)).hasSize(1);
@@ -562,7 +577,9 @@
setupInstance(/* adaptiveUpdateRatesEnabled= */ false);
assertThrows(
ExecutionException.class,
- () -> renderAndAttachLayout(layout(recursiveBox(MAX_LAYOUT_ELEMENT_DEPTH + 1))));
+ () ->
+ renderLayoutAndAttachLayout(
+ layout(recursiveBox(MAX_LAYOUT_ELEMENT_DEPTH + 1))));
}
@Test
@@ -573,8 +590,8 @@
for (int i = 0; i < children.length; i++) {
children[i] = recursiveBox(MAX_LAYOUT_ELEMENT_DEPTH - 1);
}
- ListenableFuture<Void> result =
- mInstanceUnderTest.renderAndAttach(
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(
// MAX_LAYOUT_ELEMENT_DEPTH branches of depth MAX_LAYOUT_ELEMENT_DEPTH - 1.
// Total depth is MAX_LAYOUT_ELEMENT_DEPTH (if we count the head).
layout(box(children)), RESOURCES, mRootContainer);
@@ -591,7 +608,7 @@
assertThrows(
ExecutionException.class,
() ->
- renderAndAttachLayout(
+ renderLayoutAndAttachLayout(
// Total number of views is = MAX_LAYOUT_ELEMENT_DEPTH + 1 (span
// text)
layout(
@@ -599,8 +616,8 @@
MAX_LAYOUT_ELEMENT_DEPTH,
spannable(spanText("Hello"))))));
- ListenableFuture<Void> result =
- mInstanceUnderTest.renderAndAttach(
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(
// Total number of views is = (MAX_LAYOUT_ELEMENT_DEPTH -1) + 1 (span text)
layout(
recursiveBox(
@@ -620,12 +637,12 @@
assertThrows(
ExecutionException.class,
() ->
- renderAndAttachLayout(
+ renderLayoutAndAttachLayout(
// Total number of views is = 1 (Arc) + (MAX_LAYOUT_ELEMENT_DEPTH)
layout(arc(arcAdapter(recursiveBox(MAX_LAYOUT_ELEMENT_DEPTH))))));
- ListenableFuture<Void> result =
- mInstanceUnderTest.renderAndAttach(
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(
// Total number of views is = 1 (Arc) + (MAX_LAYOUT_ELEMENT_DEPTH - 1)
// = MAX_LAYOUT_ELEMENT_DEPTH
layout(arc(arcAdapter(recursiveBox(MAX_LAYOUT_ELEMENT_DEPTH - 1)))),
@@ -637,9 +654,9 @@
assertThat(mRootContainer.getChildCount()).isEqualTo(1);
}
- private void renderAndAttachLayout(Layout layout) throws Exception {
- ListenableFuture<Void> result =
- mInstanceUnderTest.renderAndAttach(layout, RESOURCES, mRootContainer);
+ private void renderLayoutAndAttachLayout(Layout layout) throws Exception {
+ ListenableFuture<RenderingArtifact> result =
+ mInstanceUnderTest.renderLayoutAndAttach(layout, RESOURCES, mRootContainer);
shadowOf(Looper.getMainLooper()).idle();
assertNoException(result);
}
@@ -690,7 +707,8 @@
return views;
}
- private static void assertNoException(ListenableFuture<Void> result) throws Exception {
+ private static void assertNoException(ListenableFuture<RenderingArtifact> result)
+ throws Exception {
// Assert that result hasn't thrown exception.
result.get();
}
diff --git a/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflaterTest.java b/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflaterTest.java
index da07985..1a46140 100644
--- a/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflaterTest.java
+++ b/wear/protolayout/protolayout-renderer/src/test/java/androidx/wear/protolayout/renderer/inflater/ProtoLayoutInflaterTest.java
@@ -83,7 +83,6 @@
import androidx.core.content.ContextCompat;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.wear.protolayout.renderer.common.SeekableAnimatedVectorDrawable;
import androidx.wear.protolayout.expression.AppDataKey;
import androidx.wear.protolayout.expression.DynamicBuilders;
import androidx.wear.protolayout.expression.pipeline.FixedQuotaManagerImpl;
@@ -203,6 +202,8 @@
import androidx.wear.protolayout.proto.TypesProto.StringProp;
import androidx.wear.protolayout.protobuf.ByteString;
import androidx.wear.protolayout.renderer.ProtoLayoutTheme;
+import androidx.wear.protolayout.renderer.common.RenderingArtifact;
+import androidx.wear.protolayout.renderer.common.SeekableAnimatedVectorDrawable;
import androidx.wear.protolayout.renderer.dynamicdata.ProtoLayoutDynamicDataPipeline;
import androidx.wear.protolayout.renderer.helper.TestFingerprinter;
import androidx.wear.protolayout.renderer.inflater.ProtoLayoutInflater.InflateResult;
@@ -222,6 +223,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
+import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowChoreographer;
import org.robolectric.shadows.ShadowLooper;
import org.robolectric.shadows.ShadowPackageManager;
@@ -543,37 +545,41 @@
int width = 10;
int height = 12;
byte[] payload = "Hello World".getBytes(UTF_8);
+ LayoutElement extension =
+ LayoutElement.newBuilder()
+ .setExtension(
+ ExtensionLayoutElement.newBuilder()
+ .setExtensionId("foo")
+ .setPayload(ByteString.copyFrom(payload))
+ .setWidth(
+ ExtensionDimension.newBuilder()
+ .setLinearDimension(dp(width))
+ .build())
+ .setHeight(
+ ExtensionDimension.newBuilder()
+ .setLinearDimension(dp(height))
+ .build()))
+ .build();
LayoutElement root =
LayoutElement.newBuilder()
- .setBox(
- Box.newBuilder()
- // Outer box's width and height left at default value of "wrap"
- .addContents(
- LayoutElement.newBuilder()
- .setExtension(
- ExtensionLayoutElement.newBuilder()
- .setExtensionId("foo")
- .setPayload(ByteString.copyFrom(payload))
- .setWidth(
- ExtensionDimension.newBuilder()
- .setLinearDimension(dp(width))
- .build())
- .setHeight(
- ExtensionDimension.newBuilder()
- .setLinearDimension(dp(height))
- .build()))))
+ .setBox(
+ Box.newBuilder()
+ // Outer box's width and height left at default value of
+ // "wrap"
+ .addContents(extension))
.build();
FrameLayout rootLayout =
renderer(
- newRendererConfigBuilder(fingerprintedLayout(root))
- .setExtensionViewProvider(
- (extensionPayload, id) -> {
- TextView returnedView = new TextView(getApplicationContext());
- returnedView.setText("testing");
+ newRendererConfigBuilder(fingerprintedLayout(root))
+ .setExtensionViewProvider(
+ (extensionPayload, id) -> {
+ TextView returnedView =
+ new TextView(getApplicationContext());
+ returnedView.setText("testing");
- return returnedView;
- }))
+ return returnedView;
+ }))
.inflate();
// Check that the outer box is displayed and it has a child.
@@ -976,6 +982,23 @@
// A column with a row (Spacer + Spacer) and Spacer, everything has weighted expand
// dimension.
+
+ Row rowWithSpacers =
+ Row.newBuilder()
+ .setWidth(expand())
+ .setHeight(
+ ContainerDimension.newBuilder()
+ .setExpandedDimension(expandWithWeight(heightWeight1))
+ .build())
+ .addContents(
+ LayoutElement.newBuilder()
+ .setSpacer(
+ buildExpandedSpacer(widthWeight1, DEFAULT_WEIGHT)))
+ .addContents(
+ LayoutElement.newBuilder()
+ .setSpacer(
+ buildExpandedSpacer(widthWeight2, DEFAULT_WEIGHT)))
+ .build();
LayoutElement root =
LayoutElement.newBuilder()
.setColumn(
@@ -983,26 +1006,13 @@
.setWidth(expand())
.setHeight(expand())
.addContents(
- LayoutElement.newBuilder()
- .setRow(
- Row.newBuilder()
- .setWidth(expand())
- .setHeight(
- ContainerDimension.newBuilder()
- .setExpandedDimension(expandWithWeight(heightWeight1))
- .build())
- .addContents(
- LayoutElement.newBuilder()
- .setSpacer(
- buildExpandedSpacer(widthWeight1, DEFAULT_WEIGHT)))
- .addContents(
- LayoutElement.newBuilder()
- .setSpacer(
- buildExpandedSpacer(
- widthWeight2, DEFAULT_WEIGHT)))))
+ LayoutElement.newBuilder().setRow(rowWithSpacers))
.addContents(
LayoutElement.newBuilder()
- .setSpacer(buildExpandedSpacer(DEFAULT_WEIGHT, heightWeight2)))
+ .setSpacer(
+ buildExpandedSpacer(
+ DEFAULT_WEIGHT,
+ heightWeight2)))
.build())
.build();
@@ -1034,9 +1044,9 @@
.setExpandedDimension(
ExpandedDimensionProp
.getDefaultInstance()))
- .setWidth(SpacerDimension
- .newBuilder()
- .setLinearDimension(dp(width))))
+ .setWidth(
+ SpacerDimension.newBuilder()
+ .setLinearDimension(dp(width))))
.build();
FrameLayout rootLayout = renderer(fingerprintedLayout(root)).inflate();
@@ -1543,17 +1553,17 @@
ContainerDimension.newBuilder().setLinearDimension(dp(childSize)).build();
LayoutElement childBox =
- LayoutElement.newBuilder().setBox(
- Box.newBuilder()
- .setWidth(childBoxSize)
- .setHeight(childBoxSize)
- .setModifiers(
- Modifiers.newBuilder()
- .setClickable(
- Clickable.newBuilder()
- .setId("foo")
- .setOnClick(
- action))))
+ LayoutElement.newBuilder()
+ .setBox(
+ Box.newBuilder()
+ .setWidth(childBoxSize)
+ .setHeight(childBoxSize)
+ .setModifiers(
+ Modifiers.newBuilder()
+ .setClickable(
+ Clickable.newBuilder()
+ .setId("foo")
+ .setOnClick(action))))
.build();
LayoutElement root =
@@ -1563,13 +1573,14 @@
.setWidth(parentBoxSize)
.setHeight(parentBoxSize)
.addContents(childBox))
- .build();
+ .build();
State.Builder receivedState = State.newBuilder();
FrameLayout rootLayout =
renderer(
- newRendererConfigBuilder(fingerprintedLayout(root), resourceResolvers())
- .setLoadActionListener(receivedState::mergeFrom))
+ newRendererConfigBuilder(
+ fingerprintedLayout(root), resourceResolvers())
+ .setLoadActionListener(receivedState::mergeFrom))
.inflate();
shadowOf(Looper.getMainLooper()).idle();
@@ -1627,8 +1638,7 @@
.setWidth(
SpacerDimension.newBuilder()
.setLinearDimension(dp(spacerSize))
- .build()
- ));
+ .build()));
// |--clickable area child box 1 (5 - 35)--|
// |---clickable area child box 2 (30-60)--|
@@ -1647,8 +1657,7 @@
dp(clickTargetSize))
.setMinimumClickableHeight(
dp(clickTargetSize))
- .setOnClick(
- action)
+ .setOnClick(action)
.setId("foo1"))))
.build();
@@ -1666,8 +1675,7 @@
dp(clickTargetSize))
.setMinimumClickableHeight(
dp(clickTargetSize))
- .setOnClick(
- action)
+ .setOnClick(action)
.setId("foo2"))))
.build();
@@ -1692,8 +1700,9 @@
State.Builder receivedState = State.newBuilder();
FrameLayout rootLayout =
renderer(
- newRendererConfigBuilder(fingerprintedLayout(root), resourceResolvers())
- .setLoadActionListener(receivedState::mergeFrom))
+ newRendererConfigBuilder(
+ fingerprintedLayout(root), resourceResolvers())
+ .setLoadActionListener(receivedState::mergeFrom))
.inflate();
ShadowLooper.runUiThreadTasks();
@@ -1812,8 +1821,8 @@
// Compute the mutation
ViewGroupMutation mutation =
- renderer.computeMutation(getRenderedMetadata(rootLayout),
- fingerprintedLayout(root2));
+ renderer.computeMutation(
+ getRenderedMetadata(rootLayout), fingerprintedLayout(root2));
assertThat(mutation).isNotNull();
assertThat(mutation.isNoOp()).isFalse();
@@ -1848,8 +1857,9 @@
.setSpacer(
Spacer.newBuilder()
.setWidth(
- SpacerDimension.newBuilder().setLinearDimension(
- dp(spacerSize)).build()));
+ SpacerDimension.newBuilder()
+ .setLinearDimension(dp(spacerSize))
+ .build()));
int parentHeight = 45;
int parentWidth = 125;
@@ -1916,13 +1926,13 @@
// Compute the mutation
ViewGroupMutation mutation =
- renderer.computeMutation(getRenderedMetadata(rootLayout),
- fingerprintedLayout(root2));
+ renderer.computeMutation(
+ getRenderedMetadata(rootLayout), fingerprintedLayout(root2));
assertThat(mutation).isNotNull();
assertThat(mutation.isNoOp()).isFalse();
// Apply the mutation
- ListenableFuture<Void> applyMutationFuture =
+ ListenableFuture<RenderingArtifact> applyMutationFuture =
renderer.mRenderer.applyMutation(rootLayout, mutation);
shadowOf(getMainLooper()).idle();
try {
@@ -1958,6 +1968,108 @@
}
@Test
+ @Config(minSdk = VERSION_CODES.Q)
+ public void inflateThenMutate_withClickableSizeChange_clickableModifier_extendClickTargetSize()
+ {
+ Action action = Action.newBuilder().setLoadAction(LoadAction.getDefaultInstance()).build();
+ int parentSize = 50;
+ ContainerDimension parentBoxSize =
+ ContainerDimension.newBuilder().setLinearDimension(dp(parentSize)).build();
+ ContainerDimension childBoxSize =
+ ContainerDimension.newBuilder().setLinearDimension(dp(parentSize / 2f)).build();
+
+ Modifiers testModifiers1 =
+ Modifiers.newBuilder()
+ .setClickable(Clickable.newBuilder().setOnClick(action).setId("foo1"))
+ .build();
+
+ // Child box has a size smaller than the minimum clickable size, touch delegation is
+ // required.
+ LayoutElement root =
+ LayoutElement.newBuilder()
+ .setBox(
+ Box.newBuilder()
+ .setWidth(parentBoxSize)
+ .setHeight(parentBoxSize)
+ .addContents(
+ LayoutElement.newBuilder()
+ .setBox(
+ Box.newBuilder()
+ .setWidth(childBoxSize)
+ .setHeight(childBoxSize)
+ .setModifiers(
+ testModifiers1))))
+ .build();
+
+ State.Builder receivedState = State.newBuilder();
+ Renderer renderer =
+ renderer(
+ newRendererConfigBuilder(fingerprintedLayout(root), resourceResolvers())
+ .setLoadActionListener(receivedState::mergeFrom));
+ FrameLayout rootLayout = renderer.inflate();
+ ViewGroup parent = (ViewGroup) rootLayout.getChildAt(0);
+ // Confirm the touch delegation has happened.
+ assertThat(parent.getTouchDelegate()).isNotNull();
+ // Dispatch a click event to the parent View within the expanded clickable area;
+ // it should trigger the LoadAction...
+ receivedState.clearLastClickableId();
+ dispatchTouchEvent(parent, 5, 5);
+ expect.that(receivedState.getLastClickableId()).isEqualTo("foo1");
+
+ // Produce a new layout with child box specifies its minimum clickable size, NO touch
+ // delegation is required.
+ Modifiers testModifiers2 =
+ Modifiers.newBuilder()
+ .setClickable(
+ Clickable.newBuilder()
+ .setOnClick(action)
+ .setId("foo2")
+ .setMinimumClickableWidth(dp(parentSize / 2f))
+ .setMinimumClickableHeight(dp(parentSize / 2f)))
+ .build();
+ LayoutElement root2 =
+ LayoutElement.newBuilder()
+ .setBox(
+ Box.newBuilder()
+ .setWidth(parentBoxSize)
+ .setHeight(parentBoxSize)
+ .addContents(
+ LayoutElement.newBuilder()
+ .setBox(
+ Box.newBuilder()
+ .setWidth(childBoxSize)
+ .setHeight(childBoxSize)
+ .setModifiers(
+ testModifiers2))))
+ .build();
+
+ // Compute the mutation
+ ViewGroupMutation mutation =
+ renderer.computeMutation(getRenderedMetadata(rootLayout),
+ fingerprintedLayout(root2));
+ assertThat(mutation).isNotNull();
+ assertThat(mutation.isNoOp()).isFalse();
+
+ // Apply the mutation
+ boolean mutationResult = renderer.applyMutation(rootLayout, mutation);
+ assertThat(mutationResult).isTrue();
+
+ // Verify that the parent removed the touch delegation.
+ // Keep an empty touch delegate composite will lead to failure when calling
+ // {@link TouchDelegateComposite#getTouchDelegateInfo}
+ assertThat(parent.getTouchDelegate()).isNull();
+
+ // Dispatch a click event to the parent View within the expanded clickable area;
+ // it should no longer trigger the LoadAction.
+ receivedState.clearLastClickableId();
+ dispatchTouchEvent(parent, 5, 5);
+ expect.that(receivedState.getLastClickableId()).isEmpty();
+ View box = parent.getChildAt(0);
+ dispatchTouchEvent(box, 1, 1);
+ expect.that(receivedState.getLastClickableId()).isEqualTo("foo2");
+ }
+
+ @Test
public void inflate_clickable_withoutRippleEffect_rippleDrawableNotAdded() throws IOException {
final String textContentsWithRipple = "clickable with ripple";
final String textContentsWithoutRipple = "clickable without ripple";
@@ -1993,15 +2105,15 @@
FrameLayout rootLayout =
renderer(
- fingerprintedLayout(
- LayoutElement.newBuilder()
- .setColumn(
- Column.newBuilder()
- .addContents(textElementWithRipple)
- .addContents(
- textElementWithoutRipple)
- .build())
- .build()))
+ fingerprintedLayout(
+ LayoutElement.newBuilder()
+ .setColumn(
+ Column.newBuilder()
+ .addContents(textElementWithRipple)
+ .addContents(
+ textElementWithoutRipple)
+ .build())
+ .build()))
.inflate();
// Column
@@ -2025,6 +2137,49 @@
}
@Test
+ public void inflate_hiddenModifier_inhibitsClicks() {
+ final String textContents = "I am a clickable";
+
+ Action action = Action.newBuilder().setLoadAction(LoadAction.getDefaultInstance()).build();
+
+ LayoutElement root =
+ LayoutElement.newBuilder()
+ .setBox(
+ Box.newBuilder()
+ .addContents(
+ LayoutElement.newBuilder()
+ .setText(
+ createTextWithVisibility(
+ textContents,
+ "back",
+ action,
+ true)))
+ .addContents(
+ LayoutElement.newBuilder()
+ .setText(
+ createTextWithVisibility(
+ textContents,
+ "front",
+ action,
+ false))))
+ .build();
+
+ State.Builder receivedState = State.newBuilder();
+ FrameLayout rootLayout =
+ renderer(
+ newRendererConfigBuilder(
+ fingerprintedLayout(root), resourceResolvers())
+ .setLoadActionListener(receivedState::mergeFrom))
+ .inflate();
+
+ // Try to tap the stacked clickables.
+ dispatchTouchEvent(rootLayout, 5f, 5f);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ expect.that(receivedState.getLastClickableId()).isEqualTo("back");
+ }
+
+ @Test
public void inflate_arc_withLineDrawnWithArcTo() {
LayoutElement root =
LayoutElement.newBuilder()
@@ -2151,8 +2306,8 @@
@Test
public void inflate_arc_withText_autoSize_notSet() {
int lastSize = 12;
- FontStyle.Builder style = FontStyle.newBuilder()
- .addAllSize(buildSizesList(new int[]{10, 20, lastSize}));
+ FontStyle.Builder style =
+ FontStyle.newBuilder().addAllSize(buildSizesList(new int[] {10, 20, lastSize}));
LayoutElement root =
LayoutElement.newBuilder()
.setArc(
@@ -2889,12 +3044,13 @@
.setFontStyle(FontStyle.newBuilder().addSize(sp(16)))
.setMaxLines(Int32Prop.newBuilder().setValue(6))
.setOverflow(
- TextOverflowProp.newBuilder().setValue(
- TextOverflow.TEXT_OVERFLOW_ELLIPSIZE));
+ TextOverflowProp.newBuilder()
+ .setValue(TextOverflow.TEXT_OVERFLOW_ELLIPSIZE));
Layout layout1 =
fingerprintedLayout(
LayoutElement.newBuilder()
- .setBox(buildFixedSizeBoxWIthText(text1)).build());
+ .setBox(buildFixedSizeBoxWIthText(text1))
+ .build());
Text.Builder text2 =
Text.newBuilder()
@@ -2904,18 +3060,19 @@
.setFontStyle(FontStyle.newBuilder().addSize(sp(4)))
.setMaxLines(Int32Prop.newBuilder().setValue(6))
.setOverflow(
- TextOverflowProp.newBuilder().setValue(
- TextOverflow.TEXT_OVERFLOW_ELLIPSIZE));
+ TextOverflowProp.newBuilder()
+ .setValue(TextOverflow.TEXT_OVERFLOW_ELLIPSIZE));
Layout layout2 =
fingerprintedLayout(
LayoutElement.newBuilder()
- .setBox(buildFixedSizeBoxWIthText(text2)).build());
+ .setBox(buildFixedSizeBoxWIthText(text2))
+ .build());
// Initial layout.
Renderer renderer = renderer(layout1);
ViewGroup inflatedViewParent = renderer.inflate();
- TextView textView1 = (TextView) ((ViewGroup) inflatedViewParent
- .getChildAt(0)).getChildAt(0);
+ TextView textView1 =
+ (TextView) ((ViewGroup) inflatedViewParent.getChildAt(0)).getChildAt(0);
// Apply the mutation.
ViewGroupMutation mutation =
@@ -2926,8 +3083,8 @@
assertThat(mutationResult).isTrue();
// This contains layout after the mutation.
- TextView textView2 = (TextView) ((ViewGroup) inflatedViewParent
- .getChildAt(0)).getChildAt(0);
+ TextView textView2 =
+ (TextView) ((ViewGroup) inflatedViewParent.getChildAt(0)).getChildAt(0);
expect.that(textView1.getEllipsize()).isEqualTo(TruncateAt.END);
expect.that(textView1.getMaxLines()).isEqualTo(2);
@@ -3028,7 +3185,7 @@
@Test
public void inflate_textView_autosize_set() {
String text = "Test text";
- int[] presetSizes = new int[]{12, 20, 10};
+ int[] presetSizes = new int[] {12, 20, 10};
List<DimensionProto.SpProp> sizes = buildSizesList(presetSizes);
LayoutElement textElement =
@@ -3036,16 +3193,16 @@
.setText(
Text.newBuilder()
.setText(string(text))
- .setFontStyle(
- FontStyle.newBuilder()
- .addAllSize(sizes)))
+ .setFontStyle(FontStyle.newBuilder().addAllSize(sizes)))
.build();
LayoutElement root =
- LayoutElement.newBuilder().setBox(
- Box.newBuilder()
- .setWidth(expand())
- .setHeight(expand())
- .addContents(textElement)).build();
+ LayoutElement.newBuilder()
+ .setBox(
+ Box.newBuilder()
+ .setWidth(expand())
+ .setHeight(expand())
+ .addContents(textElement))
+ .build();
FrameLayout rootLayout = renderer(fingerprintedLayout(root)).inflate();
ViewGroup firstChild = (ViewGroup) rootLayout.getChildAt(0);
@@ -3076,16 +3233,16 @@
Text.newBuilder()
.setText(string(text))
.setMaxLines(Int32Prop.newBuilder().setValue(4))
- .setFontStyle(
- FontStyle.newBuilder()
- .addAllSize(sizes)))
+ .setFontStyle(FontStyle.newBuilder().addAllSize(sizes)))
.build();
LayoutElement root =
- LayoutElement.newBuilder().setBox(
- Box.newBuilder()
- .setWidth(expand())
- .setHeight(expand())
- .addContents(textElement)).build();
+ LayoutElement.newBuilder()
+ .setBox(
+ Box.newBuilder()
+ .setWidth(expand())
+ .setHeight(expand())
+ .addContents(textElement))
+ .build();
FrameLayout rootLayout = renderer(fingerprintedLayout(root)).inflate();
ViewGroup firstChild = (ViewGroup) rootLayout.getChildAt(0);
@@ -3099,23 +3256,23 @@
public void inflate_textView_autosize_notSet() {
String text = "Test text";
int size = 24;
- List<DimensionProto.SpProp> sizes = buildSizesList(new int[]{size});
+ List<DimensionProto.SpProp> sizes = buildSizesList(new int[] {size});
LayoutElement textElement =
LayoutElement.newBuilder()
.setText(
Text.newBuilder()
.setText(string(text))
- .setFontStyle(
- FontStyle.newBuilder()
- .addAllSize(sizes)))
+ .setFontStyle(FontStyle.newBuilder().addAllSize(sizes)))
.build();
LayoutElement root =
- LayoutElement.newBuilder().setBox(
- Box.newBuilder()
- .setWidth(expand())
- .setHeight(expand())
- .addContents(textElement)).build();
+ LayoutElement.newBuilder()
+ .setBox(
+ Box.newBuilder()
+ .setWidth(expand())
+ .setHeight(expand())
+ .addContents(textElement))
+ .build();
FrameLayout rootLayout = renderer(fingerprintedLayout(root)).inflate();
ViewGroup firstChild = (ViewGroup) rootLayout.getChildAt(0);
@@ -3129,23 +3286,23 @@
public void inflate_textView_autosize_setDynamic_noop() {
String text = "Test text";
int lastSize = 24;
- List<DimensionProto.SpProp> sizes = buildSizesList(new int[]{10, 30, lastSize});
+ List<DimensionProto.SpProp> sizes = buildSizesList(new int[] {10, 30, lastSize});
LayoutElement textElement =
LayoutElement.newBuilder()
.setText(
Text.newBuilder()
.setText(dynamicString(text))
- .setFontStyle(
- FontStyle.newBuilder()
- .addAllSize(sizes)))
+ .setFontStyle(FontStyle.newBuilder().addAllSize(sizes)))
.build();
LayoutElement root =
- LayoutElement.newBuilder().setBox(
- Box.newBuilder()
- .setWidth(expand())
- .setHeight(expand())
- .addContents(textElement)).build();
+ LayoutElement.newBuilder()
+ .setBox(
+ Box.newBuilder()
+ .setWidth(expand())
+ .setHeight(expand())
+ .addContents(textElement))
+ .build();
FrameLayout rootLayout = renderer(fingerprintedLayout(root)).inflate();
ArrayList<View> textChildren = new ArrayList<>();
@@ -3159,23 +3316,23 @@
@Test
public void inflate_textView_autosize_wrongSizes_noop() {
String text = "Test text";
- List<DimensionProto.SpProp> sizes = buildSizesList(new int[]{0, -2, 0});
+ List<DimensionProto.SpProp> sizes = buildSizesList(new int[] {0, -2, 0});
LayoutElement textElement =
LayoutElement.newBuilder()
.setText(
Text.newBuilder()
.setText(string(text))
- .setFontStyle(
- FontStyle.newBuilder()
- .addAllSize(sizes)))
+ .setFontStyle(FontStyle.newBuilder().addAllSize(sizes)))
.build();
LayoutElement root =
- LayoutElement.newBuilder().setBox(
- Box.newBuilder()
- .setWidth(expand())
- .setHeight(expand())
- .addContents(textElement)).build();
+ LayoutElement.newBuilder()
+ .setBox(
+ Box.newBuilder()
+ .setWidth(expand())
+ .setHeight(expand())
+ .addContents(textElement))
+ .build();
FrameLayout rootLayout = renderer(fingerprintedLayout(root)).inflate();
ArrayList<View> textChildren = new ArrayList<>();
@@ -3219,8 +3376,8 @@
public void inflate_spantext_ignoresMultipleSizes() {
String text = "Test text";
int firstSize = 12;
- FontStyle.Builder style = FontStyle.newBuilder()
- .addAllSize(buildSizesList(new int[]{firstSize, 10, 20}));
+ FontStyle.Builder style =
+ FontStyle.newBuilder().addAllSize(buildSizesList(new int[] {firstSize, 10, 20}));
LayoutElement root =
LayoutElement.newBuilder()
.setSpannable(
@@ -4780,7 +4937,7 @@
boolean applyMutation(ViewGroup parent, ViewGroupMutation mutation) {
try {
- ListenableFuture<Void> applyMutationFuture =
+ ListenableFuture<RenderingArtifact> applyMutationFuture =
mRenderer.applyMutation(parent, mutation);
shadowOf(Looper.getMainLooper()).idle();
applyMutationFuture.get();
@@ -5000,33 +5157,25 @@
LayoutElement image = buildImage(protoResId, 30, 30);
-
- BoolProp.Builder stateBoolPropBuilder = BoolProp
- .newBuilder()
- .setValue(
- true)
- .setDynamicValue(
- DynamicBool
- .newBuilder()
- .setStateSource(
- StateBoolSource
- .newBuilder()
- .setSourceKey(
- boolKey)));
- LayoutElement.Builder boxBuilder = LayoutElement.newBuilder()
- .setBox(
- Box.newBuilder()
- .addContents(image)
- .setModifiers(
- Modifiers
- .newBuilder()
- .setHidden(stateBoolPropBuilder)));
+ BoolProp.Builder stateBoolPropBuilder =
+ BoolProp.newBuilder()
+ .setValue(true)
+ .setDynamicValue(
+ DynamicBool.newBuilder()
+ .setStateSource(
+ StateBoolSource.newBuilder()
+ .setSourceKey(boolKey)));
+ LayoutElement.Builder boxBuilder =
+ LayoutElement.newBuilder()
+ .setBox(
+ Box.newBuilder()
+ .addContents(image)
+ .setModifiers(
+ Modifiers.newBuilder()
+ .setHidden(stateBoolPropBuilder)));
LayoutElement root =
LayoutElement.newBuilder()
- .setRow(
- Row.newBuilder()
- .addContents(boxBuilder)
- .addContents(image))
+ .setRow(Row.newBuilder().addContents(boxBuilder).addContents(image))
.build();
FrameLayout layout = renderer(fingerprintedLayout(root)).inflate();
@@ -5059,7 +5208,8 @@
assertThat(secondImage.getLeft()).isEqualTo(secondImageLeft);
}
- @Test public void inflate_box_withVisibleModifier() {
+ @Test
+ public void inflate_box_withVisibleModifier() {
final String protoResId = "android";
final String boolKey = "bool-key";
@@ -5226,20 +5376,18 @@
ContainerDimension.newBuilder().setLinearDimension(dp(100.f).build()).build();
ContainerDimension innerBoxSize =
ContainerDimension.newBuilder().setLinearDimension(dp(60.f).build()).build();
- Box.Builder boxBuilder = Box.newBuilder()
- .setWidth(expand())
- .setHeight(wrap())
- .setModifiers(
- Modifiers.newBuilder()
- .setTransformation(
- transformation)
- .build())
- .addContents(
- LayoutElement.newBuilder()
- .setBox(
- Box.newBuilder()
- .setWidth(innerBoxSize)
- .setHeight(innerBoxSize)));
+ Box.Builder boxBuilder =
+ Box.newBuilder()
+ .setWidth(expand())
+ .setHeight(wrap())
+ .setModifiers(
+ Modifiers.newBuilder().setTransformation(transformation).build())
+ .addContents(
+ LayoutElement.newBuilder()
+ .setBox(
+ Box.newBuilder()
+ .setWidth(innerBoxSize)
+ .setHeight(innerBoxSize)));
LayoutElement root =
LayoutElement.newBuilder()
.setBox(
@@ -5657,7 +5805,7 @@
renderer.computeMutation(
getRenderedMetadata(inflatedViewParent),
fingerprintedLayout(textFadeIn("World")));
- ListenableFuture<Void> applyMutationFuture =
+ ListenableFuture<RenderingArtifact> applyMutationFuture =
renderer.mRenderer.applyMutation(inflatedViewParent, mutation);
// Idle for running code for starting animations.
@@ -5689,7 +5837,7 @@
getRenderedMetadata(inflatedViewParent),
fingerprintedLayout(
getTextElementWithExitAnimation("World", /* iterations= */ 0)));
- ListenableFuture<Void> applyMutationFuture =
+ ListenableFuture<RenderingArtifact> applyMutationFuture =
renderer.mRenderer.applyMutation(inflatedViewParent, mutation);
assertThat(mDataPipeline.getRunningAnimationsCount()).isEqualTo(0);
@@ -5715,7 +5863,7 @@
getRenderedMetadata(inflatedViewParent),
fingerprintedLayout(
getTextElementWithExitAnimation("World", /* iterations= */ 1)));
- ListenableFuture<Void> applyMutationFuture =
+ ListenableFuture<RenderingArtifact> applyMutationFuture =
renderer.mRenderer.applyMutation(inflatedViewParent, mutation);
assertThat(mDataPipeline.getRunningAnimationsCount()).isEqualTo(0);
@@ -5738,7 +5886,7 @@
getRenderedMetadata(inflatedViewParent),
fingerprintedLayout(
getTextElementWithExitAnimation("World", /* iterations= */ 1)));
- ListenableFuture<Void> applyMutationFuture =
+ ListenableFuture<RenderingArtifact> applyMutationFuture =
renderer.mRenderer.applyMutation(inflatedViewParent, mutation);
assertThat(mDataPipeline.getRunningAnimationsCount()).isEqualTo(0);
@@ -5764,7 +5912,7 @@
getRenderedMetadata(inflatedViewParent),
fingerprintedLayout(
getTextElementWithExitAnimation("World", /* iterations= */ 10)));
- ListenableFuture<Void> applyMutationFuture =
+ ListenableFuture<RenderingArtifact> applyMutationFuture =
renderer.mRenderer.applyMutation(inflatedViewParent, mutation);
shadowOf(getMainLooper()).idleFor(Duration.ofMillis(100));
@@ -5792,7 +5940,7 @@
getRenderedMetadata(inflatedViewParent),
fingerprintedLayout(
getTextElementWithExitAnimation("World", /* iterations= */ 10)));
- ListenableFuture<Void> applyMutationFuture =
+ ListenableFuture<RenderingArtifact> applyMutationFuture =
renderer.mRenderer.applyMutation(inflatedViewParent, mutation);
shadowOf(getMainLooper()).idle();
@@ -5821,7 +5969,7 @@
fingerprintedLayout(
getMultipleTextElementWithExitAnimation(
Arrays.asList("Hello"), /* iterations= */ 10)));
- ListenableFuture<Void> applyMutationFuture =
+ ListenableFuture<RenderingArtifact> applyMutationFuture =
renderer.mRenderer.applyMutation(inflatedViewParent, mutation);
shadowOf(getMainLooper()).idleFor(Duration.ofMillis(100));
@@ -5850,7 +5998,7 @@
getRenderedMetadata(inflatedViewParent),
fingerprintedLayout(
getTextElementWithExitAnimation("World", /* iterations= */ 10)));
- ListenableFuture<Void> applyMutationFuture =
+ ListenableFuture<RenderingArtifact> applyMutationFuture =
renderer.mRenderer.applyMutation(inflatedViewParent, mutation);
shadowOf(getMainLooper()).idleFor(Duration.ofMillis(100));
@@ -5863,7 +6011,7 @@
getTextElementWithExitAnimation(
"Second mutation", /* iterations= */ 10)));
- ListenableFuture<Void> applySecondMutationFuture =
+ ListenableFuture<RenderingArtifact> applySecondMutationFuture =
renderer.mRenderer.applyMutation(inflatedViewParent, secondMutation);
// the previous mutation should be finished
@@ -6222,9 +6370,12 @@
private static Spacer.Builder buildExpandedSpacer(int widthWeight, int heightWeight) {
return Spacer.newBuilder()
- .setWidth(SpacerDimension.newBuilder().setExpandedDimension(expandWithWeight(widthWeight)))
+ .setWidth(
+ SpacerDimension.newBuilder()
+ .setExpandedDimension(expandWithWeight(widthWeight)))
.setHeight(
- SpacerDimension.newBuilder().setExpandedDimension(expandWithWeight(heightWeight)));
+ SpacerDimension.newBuilder()
+ .setExpandedDimension(expandWithWeight(heightWeight)));
}
private static ExpandedDimensionProp expandWithWeight(int weight) {
@@ -6255,4 +6406,15 @@
.addContents(LayoutElement.newBuilder().setSpacer(spacer)))
.build());
}
+
+ private static Text createTextWithVisibility(
+ String text, String id, Action action, boolean visibility) {
+ return Text.newBuilder()
+ .setText(string(text))
+ .setModifiers(
+ Modifiers.newBuilder()
+ .setVisible(BoolProp.newBuilder().setValue(visibility))
+ .setClickable(Clickable.newBuilder().setId(id).setOnClick(action)))
+ .build();
+ }
}
diff --git a/wear/tiles/tiles-testing/build.gradle b/wear/tiles/tiles-testing/build.gradle
index a85c803f..f14b743 100644
--- a/wear/tiles/tiles-testing/build.gradle
+++ b/wear/tiles/tiles-testing/build.gradle
@@ -54,6 +54,7 @@
testImplementation(libs.testRules)
testImplementation(libs.robolectric)
testImplementation(libs.truth)
+ testImplementation(files("../../wear_sdk/wear-sdk.jar"))
}
android {
diff --git a/wear/tiles/tiles/build.gradle b/wear/tiles/tiles/build.gradle
index 42e6c85..aff1a6e 100644
--- a/wear/tiles/tiles/build.gradle
+++ b/wear/tiles/tiles/build.gradle
@@ -35,6 +35,8 @@
api(project(":wear:protolayout:protolayout-expression"))
api(libs.guavaListenableFuture)
+ compileOnly files("../../wear_sdk/wear-sdk.jar")
+
implementation("androidx.annotation:annotation-experimental:1.4.0")
implementation("androidx.concurrent:concurrent-futures:1.1.0")
implementation(project(":wear:tiles:tiles-proto"))
diff --git a/wear/tiles/tiles/src/main/AndroidManifest.xml b/wear/tiles/tiles/src/main/AndroidManifest.xml
index 3b4ff38..69678eb 100644
--- a/wear/tiles/tiles/src/main/AndroidManifest.xml
+++ b/wear/tiles/tiles/src/main/AndroidManifest.xml
@@ -1,5 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+ <application>
+ <uses-library
+ android:name="wear-sdk"
+ android:required="false"/>
+ </application>
<queries>
<intent>
<action android:name="androidx.wear.tiles.action.BIND_UPDATE_REQUESTER" />
diff --git a/wear/tiles/tiles/src/main/java/androidx/wear/tiles/TileService.java b/wear/tiles/tiles/src/main/java/androidx/wear/tiles/TileService.java
index fb88bb2..9c90ec8f 100644
--- a/wear/tiles/tiles/src/main/java/androidx/wear/tiles/TileService.java
+++ b/wear/tiles/tiles/src/main/java/androidx/wear/tiles/TileService.java
@@ -21,15 +21,21 @@
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
+import android.os.OutcomeReceiver;
import android.os.RemoteException;
import android.os.StrictMode;
import android.util.Log;
+import androidx.annotation.DoNotInline;
import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import androidx.annotation.RestrictTo;
import androidx.annotation.VisibleForTesting;
import androidx.concurrent.futures.CallbackToFutureAdapter;
import androidx.concurrent.futures.ResolvableFuture;
@@ -50,6 +56,9 @@
import androidx.wear.tiles.proto.TileProto;
import com.google.common.util.concurrent.ListenableFuture;
+import com.google.wear.Sdk;
+import com.google.wear.services.tiles.TileInstance;
+import com.google.wear.services.tiles.TilesManager;
import java.lang.ref.WeakReference;
import java.time.Duration;
@@ -133,6 +142,8 @@
private static final TimeSourceClockImpl sTimeSourceClock = new TimeSourceClockImpl();
+ private static Boolean sUseWearSdkImpl;
+
/**
* Called when the system is requesting a new timeline from this Tile Provider. The returned
* future must complete after at most 10 seconds from the moment this method is called (exact
@@ -273,15 +284,17 @@
* changed by the time the result is received. {@link TileService#onTileAddEvent} and {@link
* TileService#onTileRemoveEvent} should be used instead for live updates.
*
- * <p>This method may not always return all tiles present in the carousel. The possibly omitted
- * tiles being the pre-installed tiles, all tiles if the user has cleared the app data, or the
- * tiles a user hasn't visited in the last 60 days, while tiles removed by an app update may be
- * shown as active for 60 days afterwards.
+ * Compatibility behavior:
+ * <p>On SDKs older than U, this method is a best-effort to match platform behavior, but may
+ * not always return all tiles present in the carousel. The possibly omitted tiles being the
+ * pre-installed tiles, all tiles if the user has cleared the app data, or the tiles a user
+ * hasn't visited in the last 60 days, while tiles removed by an app update may be shown as
+ * active for 60 days afterwards.
*
* @param context The application context.
* @param executor The executor on which methods should be invoked. To dispatch events through
* the main thread of your application, you can use {@link
- * android.content.Context#getMainExecutor()}.
+ * Context#getMainExecutor()}.
* @return A list of {@link ActiveTileIdentifier} for the tiles belonging to the passed {@code
* context} present in the carousel, or a value based on platform-specific fallback
* behavior.
@@ -289,17 +302,22 @@
@NonNull
public static ListenableFuture<List<ActiveTileIdentifier>> getActiveTilesAsync(
@NonNull Context context, @NonNull Executor executor) {
- return getActiveTilesAsync(context, executor, sTimeSourceClock);
+ if (useWearSdkImpl(context)
+ && Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ return Api34Impl.getActiveTilesAsync(Sdk.getWearManager(context, TilesManager.class),
+ executor);
+ }
+ return getActiveTilesAsyncLegacy(context, executor, sTimeSourceClock);
}
@VisibleForTesting
@NonNull
- static ListenableFuture<List<ActiveTileIdentifier>> getActiveTilesAsync(
+ static ListenableFuture<List<ActiveTileIdentifier>> getActiveTilesAsyncLegacy(
@NonNull Context context,
@NonNull Executor executor,
@NonNull TimeSourceClock timeSourceClock) {
- return readActiveTilesSharedPref(
- getActiveTilesSharedPreferences(context),
+ return readActiveTilesSharedPrefLegacy(
+ getActiveTilesSharedPrefLegacy(context),
context.getPackageName(),
executor,
timeSourceClock);
@@ -353,7 +371,7 @@
+ requestParams.getVersion());
return;
}
- tileService.markTileAsActive(tileId);
+ tileService.markTileAsActiveLegacy(tileId);
TileRequest tileRequest;
try {
@@ -434,7 +452,7 @@
+ requestParams.getVersion());
return;
}
- tileService.markTileAsActive(tileId);
+ tileService.markTileAsActiveLegacy(tileId);
ResourcesRequest req;
@@ -526,7 +544,7 @@
TileAddEvent.fromProto(
EventProto.TileAddEvent.parseFrom(
data.getContents()));
- tileService.markTileAsActive(evt.getTileId());
+ tileService.markTileAsActiveLegacy(evt.getTileId());
tileService.onTileAddEvent(evt);
} catch (InvalidProtocolBufferException ex) {
Log.e(TAG, "Error deserializing TileAddEvent payload.", ex);
@@ -556,7 +574,7 @@
EventProto.TileRemoveEvent.parseFrom(
data.getContents()));
- tileService.markTileAsInactive(evt.getTileId());
+ tileService.markTileAsInactiveLegacy(evt.getTileId());
tileService.onTileRemoveEvent(evt);
} catch (InvalidProtocolBufferException ex) {
Log.e(TAG, "Error deserializing TileRemoveEvent payload.", ex);
@@ -585,7 +603,7 @@
TileEnterEvent.fromProto(
EventProto.TileEnterEvent.parseFrom(
data.getContents()));
- tileService.markTileAsActive(evt.getTileId());
+ tileService.markTileAsActiveLegacy(evt.getTileId());
tileService.onTileEnterEvent(evt);
} catch (InvalidProtocolBufferException ex) {
Log.e(TAG, "Error deserializing TileEnterEvent payload.", ex);
@@ -614,7 +632,7 @@
TileLeaveEvent.fromProto(
EventProto.TileLeaveEvent.parseFrom(
data.getContents()));
- tileService.markTileAsActive(evt.getTileId());
+ tileService.markTileAsActiveLegacy(evt.getTileId());
tileService.onTileLeaveEvent(evt);
} catch (InvalidProtocolBufferException ex) {
Log.e(TAG, "Error deserializing TileLeaveEvent payload.", ex);
@@ -632,6 +650,75 @@
}
}
+ private static <T> ListenableFuture<T> createFailedFuture(@NonNull Throwable throwable) {
+ ResolvableFuture<T> errorFuture = ResolvableFuture.create();
+ errorFuture.setException(throwable);
+ return errorFuture;
+ }
+
+ private static boolean packageNameMatches(
+ String packageName, List<ActiveTileIdentifier> activeTileIdentifiers) {
+ return activeTileIdentifiers.stream()
+ .allMatch(i -> i.getComponentName().getPackageName().equals(packageName));
+ }
+
+ private static Boolean useWearSdkImpl(Context context) {
+ if (sUseWearSdkImpl == null) {
+ setUseWearSdkImpl(context);
+ }
+ return sUseWearSdkImpl;
+ }
+
+ private static void setUseWearSdkImpl(Context context) {
+ if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)
+ && Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ sUseWearSdkImpl = (Sdk.getWearManager(context, TilesManager.class) != null);
+ return;
+ }
+ sUseWearSdkImpl = false;
+ }
+
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ @VisibleForTesting
+ public static void setUseWearSdkImpl(boolean value) {
+ sUseWearSdkImpl = value;
+ }
+
+ @RequiresApi(34)
+ private static class Api34Impl {
+ @DoNotInline
+ @NonNull
+ static ListenableFuture<List<ActiveTileIdentifier>> getActiveTilesAsync(
+ @NonNull TilesManager tilesManager, @NonNull Executor executor) {
+ return CallbackToFutureAdapter.getFuture(
+ completer -> {
+ tilesManager.getActiveTiles(executor,
+ new OutcomeReceiver<List<TileInstance>, Exception>() {
+ @Override
+ public void onResult(List<TileInstance> tileInstanceList) {
+ completer.set(tileInstanceToActiveTileIdentifier(
+ tileInstanceList));
+ }
+
+ @Override
+ public void onError(
+ @NonNull Exception error) {
+ completer.setException(error.getCause());
+ }
+ });
+ return "getActiveTilesAsync";
+ });
+ }
+ }
+
+ private static List<ActiveTileIdentifier> tileInstanceToActiveTileIdentifier(
+ @NonNull List<TileInstance> tileInstanceList) {
+ return tileInstanceList.stream().map(
+ i -> new ActiveTileIdentifier(i.getTileProvider().getComponentName(),
+ i.getId())).collect(
+ Collectors.toList());
+ }
+
/**
* Mark tile instance as active by adding it to the {@code ACTIVE_TILES_SHARED_PREF_NAME} shared
* preferences if it doesn't already exist. If the tile instance is already present the
@@ -642,16 +729,20 @@
* TileService#onTileRequest}, {@link TileService#onTileResourcesRequest} when an interaction
* with the tile is observed, indicating its presence in the carousel.
*/
- private void markTileAsActive(int tileId) {
- ComponentName componentName = new ComponentName(this, this.getClass().getName());
- SharedPreferences sharedPref = getActiveTilesSharedPreferences(this);
- cleanupActiveTilesSharedPref(sharedPref, getTimeSourceClock());
- String key = new ActiveTileIdentifier(componentName, tileId).flattenToString();
- if (sharedPref.contains(key)
- && !timestampNeedsUpdate(sharedPref.getLong(key, -1L), getTimeSourceClock())) {
- return;
+ private void markTileAsActiveLegacy(int tileId) {
+ if (!useWearSdkImpl(this)) {
+ ComponentName componentName = new ComponentName(this, this.getClass().getName());
+ SharedPreferences sharedPref = getActiveTilesSharedPrefLegacy(this);
+ cleanupActiveTilesSharedPrefLegacy(sharedPref, getTimeSourceClock());
+ String key = new ActiveTileIdentifier(componentName, tileId).flattenToString();
+ if (sharedPref.contains(key)
+ && !timestampNeedsUpdateLegacy(sharedPref.getLong(key, -1L),
+ getTimeSourceClock())) {
+ return;
+ }
+ sharedPref.edit().putLong(key,
+ getTimeSourceClock().getCurrentTimestampMillis()).apply();
}
- sharedPref.edit().putLong(key, getTimeSourceClock().getCurrentTimestampMillis()).apply();
}
/**
@@ -661,15 +752,18 @@
* <p>This method is called from {@link TileService#onTileRemoveEvent} when a tile instance is
* removed from the carousel.
*/
- private void markTileAsInactive(int tileId) {
- SharedPreferences sharedPref = getActiveTilesSharedPreferences(this);
- String key =
- new ActiveTileIdentifier(new ComponentName(this, this.getClass().getName()), tileId)
- .flattenToString();
- if (!sharedPref.contains(key)) {
- return;
+ private void markTileAsInactiveLegacy(int tileId) {
+ if (!useWearSdkImpl(this)) {
+ SharedPreferences sharedPref = getActiveTilesSharedPrefLegacy(this);
+ String key =
+ new ActiveTileIdentifier(new ComponentName(this, this.getClass().getName()),
+ tileId)
+ .flattenToString();
+ if (!sharedPref.contains(key)) {
+ return;
+ }
+ sharedPref.edit().remove(key).apply();
}
- sharedPref.edit().remove(key).apply();
}
/**
@@ -682,13 +776,14 @@
* <p>This method is called on any user interactions with the tiles and before the
* SharedPreferences are read.
*/
- private static void cleanupActiveTilesSharedPref(
+ private static void cleanupActiveTilesSharedPrefLegacy(
@NonNull SharedPreferences activeTilesSharedPref,
@NonNull TimeSourceClock timeSourceClock) {
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
try {
for (String key : activeTilesSharedPref.getAll().keySet()) {
- if (isTileInactive(activeTilesSharedPref.getLong(key, -1L), timeSourceClock)) {
+ if (isTileInactiveLegacy(activeTilesSharedPref.getLong(key, -1L),
+ timeSourceClock)) {
activeTilesSharedPref.edit().remove(key).apply();
}
}
@@ -697,7 +792,7 @@
}
}
- private static ListenableFuture<List<ActiveTileIdentifier>> readActiveTilesSharedPref(
+ private static ListenableFuture<List<ActiveTileIdentifier>> readActiveTilesSharedPrefLegacy(
@NonNull SharedPreferences activeTilesSharedPref,
@NonNull String packageName,
@NonNull Executor executor,
@@ -707,7 +802,7 @@
executor.execute(
() -> {
if (activeTilesSharedPref != null) {
- cleanupActiveTilesSharedPref(
+ cleanupActiveTilesSharedPrefLegacy(
activeTilesSharedPref, timeSourceClock);
List<ActiveTileIdentifier> activeTilesList =
activeTilesSharedPref.getAll().entrySet().stream()
@@ -733,11 +828,11 @@
}
});
- return "readActiveTilesSharedPref";
+ return "readActiveTilesSharedPrefLegacy";
});
}
- private static SharedPreferences getActiveTilesSharedPreferences(@NonNull Context context) {
+ private static SharedPreferences getActiveTilesSharedPrefLegacy(@NonNull Context context) {
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
try {
return context.getSharedPreferences(ACTIVE_TILES_SHARED_PREF_NAME, MODE_PRIVATE);
@@ -751,7 +846,7 @@
* UPDATE_TILE_TIMESTAMP_PERIOD_MS}. Returns false if the timestamp has been updated in the past
* {@code UPDATE_TILE_TIMESTAMP_PERIOD_MS} or if the current time cannot be obtained.
*/
- private static boolean timestampNeedsUpdate(
+ private static boolean timestampNeedsUpdateLegacy(
long timestampMs, @NonNull TimeSourceClock timeSourceClock) {
return timeSourceClock.getCurrentTimestampMillis() - timestampMs
>= UPDATE_TILE_TIMESTAMP_PERIOD_MS;
@@ -762,17 +857,11 @@
* INACTIVE_TILE_PERIOD_MS}. Returns false if the timestamp has been updated in the past {@code
* INACTIVE_TILE_PERIOD_MS} or if the current time cannot be obtained.
*/
- private static boolean isTileInactive(
+ private static boolean isTileInactiveLegacy(
long timestampMs, @NonNull TimeSourceClock timeSourceClock) {
return timeSourceClock.getCurrentTimestampMillis() - timestampMs >= INACTIVE_TILE_PERIOD_MS;
}
- private static boolean packageNameMatches(
- String packageName, List<ActiveTileIdentifier> activeTileIdentifiers) {
- return activeTileIdentifiers.stream()
- .allMatch(i -> i.getComponentName().getPackageName().equals(packageName));
- }
-
interface TimeSourceClock {
/** Returns time agnostic timestamp with the current time. */
long getCurrentTimestampMillis();
@@ -784,10 +873,4 @@
return System.currentTimeMillis();
}
}
-
- private static <T> ListenableFuture<T> createFailedFuture(@NonNull Throwable throwable) {
- ResolvableFuture<T> errorFuture = ResolvableFuture.create();
- errorFuture.setException(throwable);
- return errorFuture;
- }
}
diff --git a/wear/tiles/tiles/src/test/java/androidx/wear/tiles/TileServiceTest.java b/wear/tiles/tiles/src/test/java/androidx/wear/tiles/TileServiceTest.java
index f0bf0fe..b61490a 100644
--- a/wear/tiles/tiles/src/test/java/androidx/wear/tiles/TileServiceTest.java
+++ b/wear/tiles/tiles/src/test/java/androidx/wear/tiles/TileServiceTest.java
@@ -15,6 +15,8 @@
*/
package androidx.wear.tiles;
+import static androidx.wear.tiles.TileService.setUseWearSdkImpl;
+
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
@@ -155,17 +157,18 @@
mTestContext.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
assertThat(mSharedPreferences.getAll()).isEmpty();
sFakeTimeSourceClock.setCurrentTimestampMs(TIMESTAMP_MS);
+ TileService.setUseWearSdkImpl(false);
}
@Test
- public void getActiveTilesAsync_noActions_readEmptySharedPref() throws Exception {
+ public void getActiveTilesAsyncLegacy_noActions_readEmptySharedPref() throws Exception {
assertThat(mSharedPreferences.getAll()).isEmpty();
assertActiveTilesSnapshotIsEmpty();
}
@Test
- public void getActiveTilesAsync_onTileAdded_addTileToSharedPref() throws Exception {
+ public void getActiveTilesAsyncLegacy_onTileAdded_addTileToSharedPref() throws Exception {
assertFalse(mSharedPreferences.contains(FAKE_TILE_IDENTIFIER_1));
mTileProviderServiceStub.onTileAddEvent(
@@ -181,7 +184,7 @@
}
@Test
- public void getActiveTilesAsync_onTileEnter_addTileToSharedPref() throws Exception {
+ public void getActiveTilesAsyncLegacy_onTileEnter_addTileToSharedPref() throws Exception {
assertFalse(mSharedPreferences.contains(FAKE_TILE_IDENTIFIER_1));
mTileProviderServiceStub.onTileEnterEvent(
@@ -197,7 +200,7 @@
}
@Test
- public void getActiveTilesAsync_onTileLeave_addTileToSharedPref() throws Exception {
+ public void getActiveTilesAsyncLegacy_onTileLeave_addTileToSharedPref() throws Exception {
assertFalse(mSharedPreferences.contains(FAKE_TILE_IDENTIFIER_1));
mTileProviderServiceStub.onTileLeaveEvent(
@@ -213,7 +216,7 @@
}
@Test
- public void getActiveTilesAsync_onTileRequest_addTileToSharedPref() throws Exception {
+ public void getActiveTilesAsyncLegacy_onTileRequest_addTileToSharedPref() throws Exception {
assertFalse(mSharedPreferences.contains(FAKE_TILE_IDENTIFIER_1));
mTileProviderServiceStub.onTileRequest(
@@ -228,7 +231,8 @@
}
@Test
- public void getActiveTilesAsync_onTileResourcesRequest_addTileToSharedPref() throws Exception {
+ public void getActiveTilesAsyncLegacy_onTileResourcesRequest_addTileToSharedPref()
+ throws Exception {
assertFalse(mSharedPreferences.contains(FAKE_COMPAT_TILE_IDENTIFIER_2));
ResourcesRequestData resourcesRequestData =
@@ -246,7 +250,7 @@
}
@Test
- public void getActiveTilesAsync_addToSharedPref_doNothingIfAlreadyAddedRecently()
+ public void getActiveTilesAsyncLegacy_addToSharedPref_doNothingIfAlreadyAddedRecently()
throws Exception {
mSharedPreferences.edit().putLong(FAKE_TILE_IDENTIFIER_1, TIMESTAMP_MS_NO_UPDATE).commit();
assertTrue(mSharedPreferences.contains(FAKE_TILE_IDENTIFIER_1));
@@ -264,7 +268,7 @@
}
@Test
- public void getActiveTilesAsync_addToSharedPref_alreadyAddedTimestampNeedsUpdate()
+ public void getActiveTilesAsyncLegacy_addToSharedPref_alreadyAddedTimestampNeedsUpdate()
throws Exception {
mSharedPreferences
.edit()
@@ -285,7 +289,7 @@
}
@Test
- public void getActiveTilesAsync_onTileRemoved_removeFromSharedPref() throws Exception {
+ public void getActiveTilesAsyncLegacy_onTileRemoved_removeFromSharedPref() throws Exception {
mSharedPreferences.edit().putLong(FAKE_TILE_IDENTIFIER_1, TIMESTAMP_MS).commit();
assertTrue(mSharedPreferences.contains(FAKE_TILE_IDENTIFIER_1));
@@ -302,7 +306,7 @@
}
@Test
- public void getActiveTilesAsync_removeFromSharedPref_doNothingIfNotInSharedPref()
+ public void getActiveTilesAsyncLegacy_removeFromSharedPref_doNothingIfNotInSharedPref()
throws Exception {
assertFalse(mSharedPreferences.contains(FAKE_TILE_IDENTIFIER_1));
@@ -319,7 +323,8 @@
}
@Test
- public void getActiveTilesAsync_onTileAddedFromMultipleServicesFromSameApp() throws Exception {
+ public void getActiveTilesAsyncLegacy_onTileAddedFromMultipleServicesFromSameApp()
+ throws Exception {
assertFalse(mSharedPreferences.contains(FAKE_TILE_IDENTIFIER_1));
assertFalse(mSharedPreferences.contains(FAKE_COMPAT_TILE_IDENTIFIER_2));
@@ -342,7 +347,7 @@
TileAddEventData.VERSION_PROTOBUF));
shadowOf(Looper.getMainLooper()).idle();
List<ActiveTileIdentifier> result =
- TileService.getActiveTilesAsync(
+ TileService.getActiveTilesAsyncLegacy(
mTestContext, directExecutor(), sFakeTimeSourceClock)
.get();
@@ -357,7 +362,7 @@
}
@Test
- public void getActiveTilesAsync_afterEvent_readAllDataFromSharedPref() throws Exception {
+ public void getActiveTilesAsyncLegacy_afterEvent_readAllDataFromSharedPref() throws Exception {
mSharedPreferences
.edit()
.putLong(FAKE_COMPAT_TILE_IDENTIFIER_2, TIMESTAMP_MS_NO_UPDATE)
@@ -373,7 +378,7 @@
TileAddEventData.VERSION_PROTOBUF));
shadowOf(Looper.getMainLooper()).idle();
List<ActiveTileIdentifier> result =
- TileService.getActiveTilesAsync(
+ TileService.getActiveTilesAsyncLegacy(
mTestContext, directExecutor(), sFakeTimeSourceClock)
.get();
@@ -388,7 +393,7 @@
}
@Test
- public void getActiveTilesAsync_addToSharedPref_cleanupOldDataFromSharedPref()
+ public void getActiveTilesAsyncLegacy_addToSharedPref_cleanupOldDataFromSharedPref()
throws Exception {
mSharedPreferences
.edit()
@@ -409,7 +414,7 @@
}
@Test
- public void getActiveTilesAsync_readFromSharedPref_cleanupOldDataFromSharedPref()
+ public void getActiveTilesAsyncLegacy_readFromSharedPref_cleanupOldDataFromSharedPref()
throws Exception {
mSharedPreferences.edit().putLong(FAKE_TILE_IDENTIFIER_1, TIMESTAMP_MS).commit();
mSharedPreferences
@@ -423,14 +428,14 @@
}
@Test
- public void getActiveTilesAsync_overriddenSharedPreferences_throwsException() {
+ public void getActiveTilesAsyncLegacy_overriddenSharedPreferences_throwsException() {
FakeContext fakeContext =
new FakeContext(mTestContext, mTestContext.getPackageName(), null);
ExecutionException thrownException =
assertThrows(
ExecutionException.class,
() ->
- TileService.getActiveTilesAsync(
+ TileService.getActiveTilesAsyncLegacy(
fakeContext, directExecutor(), sFakeTimeSourceClock)
.get());
@@ -438,7 +443,7 @@
}
@Test
- public void getActiveTilesAsync_overriddenPackageName_throwsException() {
+ public void getActiveTilesAsyncLegacy_overriddenPackageName_throwsException() {
mSharedPreferences.edit().putLong(FAKE_TILE_IDENTIFIER_1, TIMESTAMP_MS).commit();
assertTrue(mSharedPreferences.contains(FAKE_TILE_IDENTIFIER_1));
FakeContext fakeContext =
@@ -451,7 +456,7 @@
assertThrows(
ExecutionException.class,
() ->
- TileService.getActiveTilesAsync(
+ TileService.getActiveTilesAsyncLegacy(
fakeContext, directExecutor(), sFakeTimeSourceClock)
.get());
@@ -461,7 +466,7 @@
}
@Test
- public void getActiveTilesAsync_notAllPackageNamesMatching_throwsException() {
+ public void getActiveTilesAsyncLegacy_notAllPackageNamesMatching_throwsException() {
String fakeTileIdentifierWrongPackage =
new ActiveTileIdentifier(
new ComponentName(
@@ -477,7 +482,7 @@
assertThrows(
ExecutionException.class,
() ->
- TileService.getActiveTilesAsync(
+ TileService.getActiveTilesAsyncLegacy(
mTestContext,
directExecutor(),
sFakeTimeSourceClock)
@@ -493,6 +498,43 @@
}
@Test
+ public void getActiveTilesAsync_useWearSdkImplTrue_doNotAddTileToSharedPref()
+ throws Exception {
+ setUseWearSdkImpl(true);
+ assertTrue(mSharedPreferences.getAll().isEmpty());
+
+ mTileProviderServiceStub.onTileRemoveEvent(
+ new TileRemoveEventData(
+ EventProto.TileRemoveEvent.newBuilder()
+ .setTileId(TILE_ID_1)
+ .build()
+ .toByteArray(),
+ TileRemoveEventData.VERSION_PROTOBUF));
+ shadowOf(Looper.getMainLooper()).idle();
+
+ assertTrue(mSharedPreferences.getAll().isEmpty());
+ }
+
+ @Test
+ public void getActiveTilesAsync_useWearSdkImplTrue_doNotChangeSharedPref()
+ throws Exception {
+ setUseWearSdkImpl(true);
+ mSharedPreferences.edit().putLong(FAKE_TILE_IDENTIFIER_1, TIMESTAMP_MS).commit();
+ assertTrue(mSharedPreferences.contains(FAKE_TILE_IDENTIFIER_1));
+
+ mTileProviderServiceStub.onTileRemoveEvent(
+ new TileRemoveEventData(
+ EventProto.TileRemoveEvent.newBuilder()
+ .setTileId(TILE_ID_1)
+ .build()
+ .toByteArray(),
+ TileRemoveEventData.VERSION_PROTOBUF));
+ shadowOf(Looper.getMainLooper()).idle();
+
+ assertTrue(mSharedPreferences.contains(FAKE_TILE_IDENTIFIER_1));
+ }
+
+ @Test
public void tileService_tileRequest() throws Exception {
ArgumentCaptor<TileData> tileCaptor = ArgumentCaptor.forClass(TileData.class);
@@ -809,7 +851,7 @@
private void assertActiveTilesSnapshot(@NonNull String tileIdentifier, long timestampMs)
throws Exception {
List<ActiveTileIdentifier> result =
- TileService.getActiveTilesAsync(
+ TileService.getActiveTilesAsyncLegacy(
mTestContext, directExecutor(), sFakeTimeSourceClock)
.get();
@@ -819,7 +861,7 @@
private void assertActiveTilesSnapshotIsEmpty() throws Exception {
List<ActiveTileIdentifier> result =
- TileService.getActiveTilesAsync(
+ TileService.getActiveTilesAsyncLegacy(
mTestContext, directExecutor(), sFakeTimeSourceClock)
.get();
diff --git a/wear/watchface/watchface-style/src/main/java/androidx/wear/watchface/style/CurrentUserStyleRepository.kt b/wear/watchface/watchface-style/src/main/java/androidx/wear/watchface/style/CurrentUserStyleRepository.kt
index 4a563e0..2d88c40 100644
--- a/wear/watchface/watchface-style/src/main/java/androidx/wear/watchface/style/CurrentUserStyleRepository.kt
+++ b/wear/watchface/watchface-style/src/main/java/androidx/wear/watchface/style/CurrentUserStyleRepository.kt
@@ -49,12 +49,13 @@
*
* To modify the user style, you should call [toMutableUserStyle] and construct a new [UserStyle]
* instance with [MutableUserStyle.toUserStyle].
- *
+ */
+public class UserStyle
+/**
* @param selectedOptions The [UserStyleSetting.Option] selected for each [UserStyleSetting]
* @param copySelectedOptions Whether to create a copy of the provided [selectedOptions]. If
* `false`, no mutable copy of the [selectedOptions] map should be retained outside this class.
*/
-public class UserStyle
private constructor(
selectedOptions: Map<UserStyleSetting, UserStyleSetting.Option>,
copySelectedOptions: Boolean
@@ -70,6 +71,8 @@
*
* A copy of the [selectedOptions] map will be created, so that changed to the map will not be
* reflected by this object.
+ *
+ * @param selectedOptions The [UserStyleSetting.Option] selected for each [UserStyleSetting]
*/
public constructor(
selectedOptions: Map<UserStyleSetting, UserStyleSetting.Option>
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlot.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlot.kt
index 5d3c6df..93e468f 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlot.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlot.kt
@@ -131,6 +131,7 @@
* @param boundsType The [ComplicationSlotBoundsTypeIntDef] of the complication
* @param zonedDateTime The [ZonedDateTime] to render the highlight with
* @param color The color to render the highlight with
+ * @param boundingArc Optional [BoundingArc] defining the geometry of an edge complication
*/
@ComplicationExperimental
public fun drawHighlight(
@@ -633,8 +634,12 @@
* @param defaultDataSourcePolicy The [DefaultComplicationDataSourcePolicy] used to select
* the initial complication data source when the watch is first installed.
* @param bounds The complication's [ComplicationSlotBounds]. Its likely the bounding rect
- * will be much larger than the complication and shouldn't directly be used for hit
+ * will have a much larger area than [boundingArc] and shouldn't directly be used for hit
* testing.
+ * @param boundingArc The [BoundingArc] defining the geometry of the edge complication.
+ * @param complicationTapFilter The [ComplicationTapFilter] used to determine whether or not
+ * a tap hit the complication. The default [ComplicationTapFilter] uses [boundingArc] to
+ * perform hit testing.
*/
@JvmStatic
@JvmOverloads
diff --git a/window/window/src/main/java/androidx/window/embedding/SafeActivityEmbeddingComponentProvider.kt b/window/window/src/main/java/androidx/window/embedding/SafeActivityEmbeddingComponentProvider.kt
index f980f1e..c13634f 100644
--- a/window/window/src/main/java/androidx/window/embedding/SafeActivityEmbeddingComponentProvider.kt
+++ b/window/window/src/main/java/androidx/window/embedding/SafeActivityEmbeddingComponentProvider.kt
@@ -17,6 +17,7 @@
package androidx.window.embedding
import android.app.Activity
+import android.content.Intent
import androidx.annotation.VisibleForTesting
import androidx.window.SafeWindowExtensionsProvider
import androidx.window.core.ConsumerAdapter
@@ -25,6 +26,13 @@
import androidx.window.extensions.core.util.function.Consumer
import androidx.window.extensions.core.util.function.Function
import androidx.window.extensions.embedding.ActivityEmbeddingComponent
+import androidx.window.extensions.embedding.ActivityRule
+import androidx.window.extensions.embedding.ActivityStack
+import androidx.window.extensions.embedding.SplitAttributes
+import androidx.window.extensions.embedding.SplitAttributes.SplitType
+import androidx.window.extensions.embedding.SplitInfo
+import androidx.window.extensions.embedding.SplitPairRule
+import androidx.window.extensions.embedding.SplitPlaceholderRule
import androidx.window.reflection.ReflectionUtils.doesReturn
import androidx.window.reflection.ReflectionUtils.isPublic
import androidx.window.reflection.ReflectionUtils.validateReflection
@@ -79,34 +87,43 @@
* - [ActivityEmbeddingComponent.setEmbeddingRules]
* - [ActivityEmbeddingComponent.isActivityEmbedded]
* - [ActivityEmbeddingComponent.setSplitInfoCallback] with [java.util.function.Consumer]
- * and following classes: TODO(b/268583307) : add guard function for those classes
- * - [androidx.window.extensions.embedding.ActivityRule]
- * - [androidx.window.extensions.embedding.SplitPairRule]
- * - [androidx.window.extensions.embedding.SplitPlaceholderRule]
- * - [androidx.window.extensions.embedding.SplitInfo]
+ * and following classes:
+ * - [ActivityRule]
+ * - [SplitInfo]
+ * - [SplitPairRule]
+ * - [SplitPlaceholderRule]
*/
@VisibleForTesting
internal fun hasValidVendorApiLevel1(): Boolean {
return isMethodSetEmbeddingRulesValid() &&
isMethodIsActivityEmbeddedValid() &&
- isMethodSetSplitInfoCallbackJavaConsumerValid()
+ isMethodSetSplitInfoCallbackJavaConsumerValid() &&
+ isClassActivityRuleValid() &&
+ isClassSplitInfoValid() &&
+ isClassSplitPairRuleValid() &&
+ isClassSplitPlaceholderRuleValid()
}
/**
- * [WindowExtensions.VENDOR_API_LEVEL_2] includes the following methods
+ * Vendor API level 2 includes the following methods:
* - [ActivityEmbeddingComponent.setSplitInfoCallback] with [Consumer]
* - [ActivityEmbeddingComponent.clearSplitInfoCallback]
* - [ActivityEmbeddingComponent.setSplitAttributesCalculator]
* - [ActivityEmbeddingComponent.clearSplitAttributesCalculator]
- * and following classes: TODO(b/268583307) : add guard function for those classes
- * - [androidx.window.extensions.embedding.SplitAttributes]
+ * - [SplitInfo.getSplitAttributes]
+ * and following classes:
+ * - [SplitAttributes]
+ * - [SplitAttributes.SplitType]
*/
@VisibleForTesting
internal fun hasValidVendorApiLevel2(): Boolean {
return hasValidVendorApiLevel1() &&
isMethodSetSplitInfoCallbackWindowConsumerValid() &&
isMethodClearSplitInfoCallbackValid() &&
- isMethodSplitAttributesCalculatorValid()
+ isMethodSplitAttributesCalculatorValid() &&
+ isMethodGetSplitAttributesValid() &&
+ isClassSplitAttributesValid() &&
+ isClassSplitTypeValid()
}
private fun isMethodSetEmbeddingRulesValid(): Boolean {
@@ -155,6 +172,62 @@
}
}
+ private fun isMethodGetSplitAttributesValid(): Boolean =
+ validateReflection("SplitInfo#getSplitAttributes is not valid") {
+ val splitInfoClass = SplitInfo::class.java
+ val getSplitAttributesMethod = splitInfoClass.getMethod("getSplitAttributes")
+ getSplitAttributesMethod.isPublic &&
+ getSplitAttributesMethod.doesReturn(SplitAttributes::class.java)
+ }
+
+ private fun isClassSplitAttributesValid(): Boolean =
+ validateReflection("Class SplitAttributes is not valid") {
+ val splitAttributesClass = SplitAttributes::class.java
+ val getLayoutDirectionMethod =
+ splitAttributesClass.getMethod("getLayoutDirection")
+ val getSplitTypeMethod = splitAttributesClass.getMethod("getSplitType")
+ val splitAttributesBuilderClass = SplitAttributes.Builder::class.java
+ val setSplitTypeMethod = splitAttributesBuilderClass.getMethod(
+ "setSplitType",
+ SplitType::class.java
+ )
+ val setLayoutDirectionMethod = splitAttributesBuilderClass.getMethod(
+ "setLayoutDirection",
+ Int::class.java
+ )
+ getLayoutDirectionMethod.isPublic &&
+ getLayoutDirectionMethod.doesReturn(Int::class.java) &&
+ getSplitTypeMethod.isPublic &&
+ getSplitTypeMethod.doesReturn(SplitType::class.java) &&
+ setSplitTypeMethod.isPublic && setLayoutDirectionMethod.isPublic
+ }
+
+ private fun isClassSplitTypeValid(): Boolean =
+ validateReflection("Class SplitAttributes.SplitType is not valid") {
+ val ratioSplitTypeClass = SplitType.RatioSplitType::class.java
+ val ratioSplitTypeConstructor =
+ ratioSplitTypeClass.getDeclaredConstructor(Float::class.java)
+ val getRatioMethod = ratioSplitTypeClass.getMethod("getRatio")
+ val splitEquallyMethod = ratioSplitTypeClass.getMethod("splitEqually")
+ val hingeSplitTypeClass = SplitType.HingeSplitType::class.java
+ val hingeSplitTypeConstructor =
+ hingeSplitTypeClass.getDeclaredConstructor(SplitType::class.java)
+ val getFallbackSplitTypeMethod =
+ hingeSplitTypeClass.getMethod("getFallbackSplitType")
+ val expandContainersSplitTypeClass = SplitType.ExpandContainersSplitType::class.java
+ val expandContainersSplitTypeConstructor =
+ expandContainersSplitTypeClass.getDeclaredConstructor()
+ ratioSplitTypeConstructor.isPublic &&
+ getRatioMethod.isPublic &&
+ getRatioMethod.doesReturn(Float::class.java) &&
+ hingeSplitTypeConstructor.isPublic &&
+ splitEquallyMethod.isPublic &&
+ splitEquallyMethod.doesReturn(SplitType.RatioSplitType::class.java) &&
+ getFallbackSplitTypeMethod.isPublic &&
+ getFallbackSplitTypeMethod.doesReturn(SplitType::class.java) &&
+ expandContainersSplitTypeConstructor.isPublic
+ }
+
private fun isMethodSetSplitInfoCallbackJavaConsumerValid(): Boolean {
return validateReflection("ActivityEmbeddingComponent#setSplitInfoCallback is not valid") {
val consumerClass =
@@ -165,6 +238,68 @@
}
}
+ private fun isClassActivityRuleValid(): Boolean =
+ validateReflection("Class ActivityRule is not valid") {
+ val activityRuleClass = ActivityRule::class.java
+ val shouldAlwaysExpandMethod = activityRuleClass.getMethod("shouldAlwaysExpand")
+ val activityRuleBuilderClass = ActivityRule.Builder::class.java
+ val setShouldAlwaysExpandMethod = activityRuleBuilderClass.getMethod(
+ "setShouldAlwaysExpand",
+ Boolean::class.java
+ )
+ shouldAlwaysExpandMethod.isPublic &&
+ shouldAlwaysExpandMethod.doesReturn(Boolean::class.java) &&
+ setShouldAlwaysExpandMethod.isPublic
+ }
+
+ private fun isClassSplitInfoValid(): Boolean =
+ validateReflection("Class SplitInfo is not valid") {
+ val splitInfoClass = SplitInfo::class.java
+ val getPrimaryActivityStackMethod =
+ splitInfoClass.getMethod("getPrimaryActivityStack")
+ val getSecondaryActivityStackMethod =
+ splitInfoClass.getMethod("getSecondaryActivityStack")
+ val getSplitRatioMethod = splitInfoClass.getMethod("getSplitRatio")
+ getPrimaryActivityStackMethod.isPublic &&
+ getPrimaryActivityStackMethod.doesReturn(ActivityStack::class.java) &&
+ getSecondaryActivityStackMethod.isPublic &&
+ getSecondaryActivityStackMethod.doesReturn(ActivityStack::class.java) &&
+ getSplitRatioMethod.isPublic &&
+ getSplitRatioMethod.doesReturn(Float::class.java)
+ }
+
+ private fun isClassSplitPairRuleValid(): Boolean =
+ validateReflection("Class SplitPairRule is not valid") {
+ val splitPairRuleClass = SplitPairRule::class.java
+ val getFinishPrimaryWithSecondaryMethod =
+ splitPairRuleClass.getMethod("getFinishPrimaryWithSecondary")
+ val getFinishSecondaryWithPrimaryMethod =
+ splitPairRuleClass.getMethod("getFinishSecondaryWithPrimary")
+ val shouldClearTopMethod = splitPairRuleClass.getMethod("shouldClearTop")
+ getFinishPrimaryWithSecondaryMethod.isPublic &&
+ getFinishPrimaryWithSecondaryMethod.doesReturn(Int::class.java) &&
+ getFinishSecondaryWithPrimaryMethod.isPublic &&
+ getFinishSecondaryWithPrimaryMethod.doesReturn(Int::class.java) &&
+ shouldClearTopMethod.isPublic &&
+ shouldClearTopMethod.doesReturn(Boolean::class.java)
+ }
+
+ private fun isClassSplitPlaceholderRuleValid(): Boolean =
+ validateReflection("Class SplitPlaceholderRule is not valid") {
+ val splitPlaceholderRuleClass = SplitPlaceholderRule::class.java
+ val getPlaceholderIntentMethod =
+ splitPlaceholderRuleClass.getMethod("getPlaceholderIntent")
+ val isStickyMethod = splitPlaceholderRuleClass.getMethod("isSticky")
+ val getFinishPrimaryWithSecondaryMethod =
+ splitPlaceholderRuleClass.getMethod("getFinishPrimaryWithSecondary")
+ getPlaceholderIntentMethod.isPublic &&
+ getPlaceholderIntentMethod.doesReturn(Intent::class.java) &&
+ isStickyMethod.isPublic &&
+ isStickyMethod.doesReturn(Boolean::class.java)
+ getFinishPrimaryWithSecondaryMethod.isPublic &&
+ getFinishPrimaryWithSecondaryMethod.doesReturn(Int::class.java)
+ }
+
private fun isMethodSetSplitInfoCallbackWindowConsumerValid(): Boolean {
return validateReflection("ActivityEmbeddingComponent#setSplitInfoCallback is not valid") {
val setSplitInfoCallbackMethod = activityEmbeddingComponentClass.getMethod(
diff --git a/window/window/src/main/java/androidx/window/reflection/ReflectionUtils.kt b/window/window/src/main/java/androidx/window/reflection/ReflectionUtils.kt
index ed8b7ee..48c03e6 100644
--- a/window/window/src/main/java/androidx/window/reflection/ReflectionUtils.kt
+++ b/window/window/src/main/java/androidx/window/reflection/ReflectionUtils.kt
@@ -17,6 +17,7 @@
package androidx.window.reflection
import android.util.Log
+import java.lang.reflect.Constructor
import java.lang.reflect.Method
import java.lang.reflect.Modifier
import kotlin.reflect.KClass
@@ -60,6 +61,14 @@
}
/**
+ * Checks if a constructor has public modifier
+ */
+ internal val Constructor<*>.isPublic: Boolean
+ get() {
+ return Modifier.isPublic(modifiers)
+ }
+
+ /**
* Checks if a method has public modifier
*/
internal val Method.isPublic: Boolean