Merge "Update Resource Builders." into androidx-main
diff --git a/wear/protolayout/protolayout-proto/src/main/proto/resources.proto b/wear/protolayout/protolayout-proto/src/main/proto/resources.proto
index 3284bee..23b453c 100644
--- a/wear/protolayout/protolayout-proto/src/main/proto/resources.proto
+++ b/wear/protolayout/protolayout-proto/src/main/proto/resources.proto
@@ -66,34 +66,31 @@
 // resource ID. The animation is started with given trigger, fire and forget.
 message AndroidAnimatedImageResourceByResId {
   // The format for the animated image.
-  AnimatedImageFormat format = 1;
+  AnimatedImageFormat animated_image_format = 1;
 
   // The Android resource ID, e.g. R.drawable.foo.
   int32 resource_id = 2;
 
   // The trigger to start the animation.
-  Trigger trigger = 3;
+  Trigger start_trigger = 3;
 }
 
 // A seekable animated image resource that maps to an Android drawable by
 // resource ID. The animation progress is bound to the provided dynamic float.
 message AndroidSeekableAnimatedImageResourceByResId {
   // The format for the animated image.
-  AnimatedImageFormat format = 1;
+  AnimatedImageFormat animated_image_format = 1;
 
   // The Android resource ID, e.g. R.drawable.foo
   int32 resource_id = 2;
 
-  // A dynamic float, normally transformed from certain states with the data
-  // binding pipeline, controls the progress of the animation. Its value is
-  // required to fall in the range of [0.0, 1.0], any values outside this range
-  // would be clamped.
-  //
-  // Typically, AnimatableFixedFloat or AnimatableDynamicFloat is used for this
-  // progress. With AnimatableFixedFloat, the animation is played from progress
-  // of its from_value to to_value; with AnimatableDynamicFloat, the animation
-  // is set from progress 0 to its first value once it is available, it then
-  // plays from current progress to the new value on subsequent updates.
+  // A DynamicFloat, normally transformed from certain states with the data
+  // binding pipeline to control the progress of the animation. Its value is
+  // required to fall in the range of [0.0, 1.0]. Any values outside this range
+  // would be clamped. When the first value of the DynamicFloat arrives, the
+  // animation starts from progress 0 to that value. After that it plays from
+  // current progress to the new value on subsequent updates. If not set, the
+  // animation will play on load (similar to a non-seekable animated).
   androidx.wear.protolayout.expression.proto.DynamicFloat progress = 3;
 }
 
diff --git a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ResourceBuilders.java b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ResourceBuilders.java
index 76dbb60..071b698 100644
--- a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ResourceBuilders.java
+++ b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/ResourceBuilders.java
@@ -35,6 +35,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
@@ -117,18 +118,35 @@
         public int getResourceId() {
             return mImpl.getResourceId();
         }
-
+        /**
+         * Creates a new wrapper instance from the proto.
+         *
+         * @hide
+         */
+        @RestrictTo(Scope.LIBRARY_GROUP)
         @NonNull
-        static AndroidImageResourceByResId fromProto(
+        public static AndroidImageResourceByResId fromProto(
                 @NonNull ResourceProto.AndroidImageResourceByResId proto) {
             return new AndroidImageResourceByResId(proto);
         }
 
+        /**
+         * Returns the internal proto instance.
+         *
+         * @hide
+         */
+        @RestrictTo(Scope.LIBRARY_GROUP)
         @NonNull
-        ResourceProto.AndroidImageResourceByResId toProto() {
+        public ResourceProto.AndroidImageResourceByResId toProto() {
             return mImpl;
         }
 
+        @Override
+        @NonNull
+        public String toString() {
+            return "AndroidImageResourceByResId{" + "resourceId=" + getResourceId() + "}";
+        }
+
         /** Builder for {@link AndroidImageResourceByResId} */
         public static final class Builder {
             private final ResourceProto.AndroidImageResourceByResId.Builder mImpl =
@@ -213,17 +231,44 @@
         public int getFormat() {
             return mImpl.getFormat().getNumber();
         }
-
+        /**
+         * Creates a new wrapper instance from the proto.
+         *
+         * @hide
+         */
+        @RestrictTo(Scope.LIBRARY_GROUP)
         @NonNull
-        static InlineImageResource fromProto(@NonNull ResourceProto.InlineImageResource proto) {
+        public static InlineImageResource fromProto(
+                @NonNull ResourceProto.InlineImageResource proto) {
             return new InlineImageResource(proto);
         }
 
+        /**
+         * Returns the internal proto instance.
+         *
+         * @hide
+         */
+        @RestrictTo(Scope.LIBRARY_GROUP)
         @NonNull
-        ResourceProto.InlineImageResource toProto() {
+        public ResourceProto.InlineImageResource toProto() {
             return mImpl;
         }
 
+        @Override
+        @NonNull
+        public String toString() {
+            return "InlineImageResource{"
+                    + "data="
+                    + Arrays.toString(getData())
+                    + ", widthPx="
+                    + getWidthPx()
+                    + ", heightPx="
+                    + getHeightPx()
+                    + ", format="
+                    + getFormat()
+                    + "}";
+        }
+
         /** Builder for {@link InlineImageResource} */
         public static final class Builder {
             private final ResourceProto.InlineImageResource.Builder mImpl =
@@ -309,7 +354,7 @@
          */
         @AnimatedImageFormat
         public int getAnimatedImageFormat() {
-            return mImpl.getFormat().getNumber();
+            return mImpl.getAnimatedImageFormat().getNumber();
         }
 
         /**
@@ -329,24 +374,48 @@
          */
         @Nullable
         public Trigger getStartTrigger() {
-            if (mImpl.hasTrigger()) {
-                return TriggerBuilders.triggerFromProto(mImpl.getTrigger());
+            if (mImpl.hasStartTrigger()) {
+                return TriggerBuilders.triggerFromProto(mImpl.getStartTrigger());
             } else {
                 return null;
             }
         }
-
+        /**
+         * Creates a new wrapper instance from the proto.
+         *
+         * @hide
+         */
+        @RestrictTo(Scope.LIBRARY_GROUP)
         @NonNull
-        static AndroidAnimatedImageResourceByResId fromProto(
+        public static AndroidAnimatedImageResourceByResId fromProto(
                 @NonNull ResourceProto.AndroidAnimatedImageResourceByResId proto) {
             return new AndroidAnimatedImageResourceByResId(proto);
         }
 
+        /**
+         * Returns the internal proto instance.
+         *
+         * @hide
+         */
+        @RestrictTo(Scope.LIBRARY_GROUP)
         @NonNull
-        ResourceProto.AndroidAnimatedImageResourceByResId toProto() {
+        public ResourceProto.AndroidAnimatedImageResourceByResId toProto() {
             return mImpl;
         }
 
+        @Override
+        @NonNull
+        public String toString() {
+            return "AndroidAnimatedImageResourceByResId{"
+                    + "animatedImageFormat="
+                    + getAnimatedImageFormat()
+                    + ", resourceId="
+                    + getResourceId()
+                    + ", startTrigger="
+                    + getStartTrigger()
+                    + "}";
+        }
+
         /** Builder for {@link AndroidAnimatedImageResourceByResId} */
         public static final class Builder {
             private final ResourceProto.AndroidAnimatedImageResourceByResId.Builder mImpl =
@@ -360,8 +429,9 @@
              * @since 1.2
              */
             @NonNull
-            public Builder setAnimatedImageFormat(@AnimatedImageFormat int format) {
-                mImpl.setFormat(ResourceProto.AnimatedImageFormat.forNumber(format));
+            public Builder setAnimatedImageFormat(@AnimatedImageFormat int animatedImageFormat) {
+                mImpl.setAnimatedImageFormat(
+                        ResourceProto.AnimatedImageFormat.forNumber(animatedImageFormat));
                 return this;
             }
 
@@ -382,8 +452,8 @@
              * @since 1.2
              */
             @NonNull
-            public Builder setStartTrigger(@NonNull Trigger trigger) {
-                mImpl.setTrigger(trigger.toTriggerProto());
+            public Builder setStartTrigger(@NonNull Trigger startTrigger) {
+                mImpl.setStartTrigger(startTrigger.toTriggerProto());
                 return this;
             }
 
@@ -416,7 +486,7 @@
          */
         @AnimatedImageFormat
         public int getAnimatedImageFormat() {
-            return mImpl.getFormat().getNumber();
+            return mImpl.getAnimatedImageFormat().getNumber();
         }
 
         /**
@@ -430,13 +500,14 @@
         }
 
         /**
-         * Gets a {@link DynamicFloat}, normally transformed from certain states with the data
-         * binding pipeline to control the progress of the animation. Its value is required to fall
-         * in the range of [0.0, 1.0]. Any values outside this range would be clamped. When the
-         * first value of the {@link DynamicFloat} arrives, the animation starts from progress 0 to
-         * that value. After that it plays from current progress to the new value on subsequent
-         * updates.
-         * If not set, the animation will play on load (similar to a non-seekable animated).
+         * Gets a {@link androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat},
+         * normally transformed from certain states with the data binding pipeline to control the
+         * progress of the animation. Its value is required to fall in the range of [0.0, 1.0]. Any
+         * values outside this range would be clamped. When the first value of the {@link
+         * androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat} arrives, the animation
+         * starts from progress 0 to that value. After that it plays from current progress to the
+         * new value on subsequent updates. If not set, the animation will play on load (similar to
+         * a non-seekable animated).
          *
          * @since 1.2
          */
@@ -448,18 +519,42 @@
                 return null;
             }
         }
-
+        /**
+         * Creates a new wrapper instance from the proto.
+         *
+         * @hide
+         */
+        @RestrictTo(Scope.LIBRARY_GROUP)
         @NonNull
-        static AndroidSeekableAnimatedImageResourceByResId fromProto(
+        public static AndroidSeekableAnimatedImageResourceByResId fromProto(
                 @NonNull ResourceProto.AndroidSeekableAnimatedImageResourceByResId proto) {
             return new AndroidSeekableAnimatedImageResourceByResId(proto);
         }
 
+        /**
+         * Returns the internal proto instance.
+         *
+         * @hide
+         */
+        @RestrictTo(Scope.LIBRARY_GROUP)
         @NonNull
-        ResourceProto.AndroidSeekableAnimatedImageResourceByResId toProto() {
+        public ResourceProto.AndroidSeekableAnimatedImageResourceByResId toProto() {
             return mImpl;
         }
 
+        @Override
+        @NonNull
+        public String toString() {
+            return "AndroidSeekableAnimatedImageResourceByResId{"
+                    + "animatedImageFormat="
+                    + getAnimatedImageFormat()
+                    + ", resourceId="
+                    + getResourceId()
+                    + ", progress="
+                    + getProgress()
+                    + "}";
+        }
+
         /** Builder for {@link AndroidSeekableAnimatedImageResourceByResId} */
         public static final class Builder {
             private final ResourceProto.AndroidSeekableAnimatedImageResourceByResId.Builder mImpl =
@@ -473,8 +568,9 @@
              * @since 1.2
              */
             @NonNull
-            public Builder setAnimatedImageFormat(@AnimatedImageFormat int format) {
-                mImpl.setFormat(ResourceProto.AnimatedImageFormat.forNumber(format));
+            public Builder setAnimatedImageFormat(@AnimatedImageFormat int animatedImageFormat) {
+                mImpl.setAnimatedImageFormat(
+                        ResourceProto.AnimatedImageFormat.forNumber(animatedImageFormat));
                 return this;
             }
 
@@ -490,13 +586,14 @@
             }
 
             /**
-             * Sets a {@link DynamicFloat}, normally transformed from certain states with the data
-             * binding pipeline to control the progress of the animation. Its value is required to
-             * fall in the range of [0.0, 1.0]. Any values outside this range would be clamped. When
-             * the first value of the {@link DynamicFloat} arrives, the animation starts from
-             * progress 0 to that value. After that it plays from current progress to the new value
-             * on subsequent updates.
-             * If not set, the animation will play on load (similar to a non-seekable animated).
+             * Sets a {@link androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat},
+             * normally transformed from certain states with the data binding pipeline to control
+             * the progress of the animation. Its value is required to fall in the range of [0.0,
+             * 1.0]. Any values outside this range would be clamped. When the first value of the
+             * {@link androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat} arrives,
+             * the animation starts from progress 0 to that value. After that it plays from current
+             * progress to the new value on subsequent updates. If not set, the animation will play
+             * on load (similar to a non-seekable animated).
              *
              * @since 1.2
              */
@@ -587,17 +684,43 @@
                 return null;
             }
         }
-
+        /**
+         * Creates a new wrapper instance from the proto.
+         *
+         * @hide
+         */
+        @RestrictTo(Scope.LIBRARY_GROUP)
         @NonNull
-        static ImageResource fromProto(@NonNull ResourceProto.ImageResource proto) {
+        public static ImageResource fromProto(@NonNull ResourceProto.ImageResource proto) {
             return new ImageResource(proto);
         }
 
+        /**
+         * Returns the internal proto instance.
+         *
+         * @hide
+         */
+        @RestrictTo(Scope.LIBRARY_GROUP)
         @NonNull
-        ResourceProto.ImageResource toProto() {
+        public ResourceProto.ImageResource toProto() {
             return mImpl;
         }
 
+        @Override
+        @NonNull
+        public String toString() {
+            return "ImageResource{"
+                    + "androidResourceByResId="
+                    + getAndroidResourceByResId()
+                    + ", inlineResource="
+                    + getInlineResource()
+                    + ", androidAnimatedResourceByResId="
+                    + getAndroidAnimatedResourceByResId()
+                    + ", androidSeekableAnimatedResourceByResId="
+                    + getAndroidSeekableAnimatedResourceByResId()
+                    + "}";
+        }
+
         /** Builder for {@link ImageResource} */
         public static final class Builder {
             private final ResourceProto.ImageResource.Builder mImpl =
@@ -710,8 +833,14 @@
             return Collections.unmodifiableMap(map);
         }
 
+        /**
+         * Creates a new wrapper instance from the proto.
+         *
+         * @hide
+         */
+        @RestrictTo(Scope.LIBRARY_GROUP)
         @NonNull
-        static Resources fromProto(@NonNull ResourceProto.Resources proto) {
+        public static Resources fromProto(@NonNull ResourceProto.Resources proto) {
             return new Resources(proto);
         }
 
@@ -726,6 +855,17 @@
             return mImpl;
         }
 
+        @Override
+        @NonNull
+        public String toString() {
+            return "Resources{"
+                    + "version="
+                    + getVersion()
+                    + ", idToImageMapping="
+                    + getIdToImageMapping()
+                    + "}";
+        }
+
         /** Builder for {@link Resources} */
         public static final class Builder {
             private final ResourceProto.Resources.Builder mImpl =
diff --git a/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/ResourceBuildersTest.java b/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/ResourceBuildersTest.java
index 59f2df8..2b6348d 100644
--- a/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/ResourceBuildersTest.java
+++ b/wear/protolayout/protolayout/src/test/java/androidx/wear/protolayout/ResourceBuildersTest.java
@@ -44,8 +44,8 @@
         ResourceProto.AndroidAnimatedImageResourceByResId avdProto = avd.toProto();
 
         assertThat(avdProto.getResourceId()).isEqualTo(RESOURCE_ID);
-        assertThat(avdProto.getFormat().getNumber()).isEqualTo(FORMAT);
-        assertThat(avdProto.getTrigger().hasOnLoadTrigger()).isTrue();
+        assertThat(avdProto.getAnimatedImageFormat().getNumber()).isEqualTo(FORMAT);
+        assertThat(avdProto.getStartTrigger().hasOnLoadTrigger()).isTrue();
     }
 
     @Test
@@ -61,7 +61,7 @@
         ResourceProto.AndroidSeekableAnimatedImageResourceByResId avdProto = avd.toProto();
 
         assertThat(avdProto.getResourceId()).isEqualTo(RESOURCE_ID);
-        assertThat(avdProto.getFormat().getNumber()).isEqualTo(FORMAT);
+        assertThat(avdProto.getAnimatedImageFormat().getNumber()).isEqualTo(FORMAT);
         assertThat(avdProto.getProgress().getStateSource().getSourceKey()).isEqualTo(stateKey);
     }
 }
diff --git a/wear/tiles/tiles/src/main/java/androidx/wear/tiles/ResourceBuilders.java b/wear/tiles/tiles/src/main/java/androidx/wear/tiles/ResourceBuilders.java
index b062133..03390ef 100644
--- a/wear/tiles/tiles/src/main/java/androidx/wear/tiles/ResourceBuilders.java
+++ b/wear/tiles/tiles/src/main/java/androidx/wear/tiles/ResourceBuilders.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * Copyright 2021-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.
@@ -18,8 +18,6 @@
 
 import static androidx.annotation.Dimension.PX;
 
-import static java.util.stream.Collectors.toMap;
-
 import android.annotation.SuppressLint;
 
 import androidx.annotation.Dimension;
@@ -36,7 +34,9 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Map;
+import java.util.Map.Entry;
 
 /** Builders for the resources for a layout. */
 public final class ResourceBuilders {
@@ -347,12 +347,31 @@
          */
         @NonNull
         public Map<String, ImageResource> getIdToImageMapping() {
-            return Collections.unmodifiableMap(
-                    mImpl.getIdToImageMap().entrySet().stream()
-                            .collect(
-                                    toMap(
-                                            Map.Entry::getKey,
-                                            f -> ImageResource.fromProto(f.getValue()))));
+            Map<String, ImageResource> map = new HashMap<>();
+            for (Entry<String, ResourceProto.ImageResource> entry :
+                    mImpl.getIdToImageMap().entrySet()) {
+                map.put(entry.getKey(), ImageResource.fromProto(entry.getValue()));
+            }
+            return Collections.unmodifiableMap(map);
+        }
+
+        /** Converts to byte array representation. */
+        @NonNull
+        @TilesExperimental
+        public byte[] toByteArray() {
+            return mImpl.toByteArray();
+        }
+
+        /** Converts from byte array representation. */
+        @SuppressWarnings("ProtoParseWithRegistry")
+        @Nullable
+        @TilesExperimental
+        public static Resources fromByteArray(@NonNull byte[] byteArray) {
+            try {
+                return fromProto(ResourceProto.Resources.parseFrom(byteArray));
+            } catch (InvalidProtocolBufferException e) {
+                return null;
+            }
         }
 
         /** @hide */
@@ -369,24 +388,6 @@
             return mImpl;
         }
 
-        /** Converts to byte array representation. */
-        @TilesExperimental
-        @NonNull
-        public byte[] toByteArray() {
-            return mImpl.toByteArray();
-        }
-
-        /** Converts from byte array representation. */
-        @TilesExperimental
-        @Nullable
-        public static Resources fromByteArray(@NonNull byte[] byteArray) {
-            try {
-                return fromProto(ResourceProto.Resources.parseFrom(byteArray));
-            } catch (InvalidProtocolBufferException e) {
-                return null;
-            }
-        }
-
         /** Builder for {@link Resources} */
         public static final class Builder {
             private final ResourceProto.Resources.Builder mImpl =