Refactoring: Use builder pattern for  TileRenderer class.

RelNote:"Add a new constructor to TileRenderer that supprots a new
TileRenderer.Config class. Other constructor are deprecated."

BUG: 330301609
Change-Id: Iae7ff371c15610156f4757e76db818274cfed335
diff --git a/wear/tiles/tiles-renderer/api/current.txt b/wear/tiles/tiles-renderer/api/current.txt
index d4f5f16..7746fcc 100644
--- a/wear/tiles/tiles-renderer/api/current.txt
+++ b/wear/tiles/tiles-renderer/api/current.txt
@@ -46,11 +46,25 @@
     ctor @Deprecated public TileRenderer(android.content.Context, androidx.wear.tiles.LayoutElementBuilders.Layout, androidx.wear.tiles.ResourceBuilders.Resources, java.util.concurrent.Executor, androidx.wear.tiles.renderer.TileRenderer.LoadActionListener);
     ctor @Deprecated public TileRenderer(android.content.Context, androidx.wear.tiles.LayoutElementBuilders.Layout, @StyleRes int, androidx.wear.tiles.ResourceBuilders.Resources, java.util.concurrent.Executor, androidx.wear.tiles.renderer.TileRenderer.LoadActionListener);
     ctor public TileRenderer(android.content.Context, java.util.concurrent.Executor, java.util.function.Consumer<androidx.wear.protolayout.StateBuilders.State!>);
+    ctor public TileRenderer(androidx.wear.tiles.renderer.TileRenderer.Config);
     method @Deprecated public android.view.View? inflate(android.view.ViewGroup);
     method public com.google.common.util.concurrent.ListenableFuture<android.view.View!> inflateAsync(androidx.wear.protolayout.LayoutElementBuilders.Layout, androidx.wear.protolayout.ResourceBuilders.Resources, android.view.ViewGroup);
     method public void setState(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<?>!,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<?>!>);
   }
 
+  public static final class TileRenderer.Config {
+    method public java.util.concurrent.Executor getLoadActionExecutor();
+    method public java.util.function.Consumer<androidx.wear.protolayout.StateBuilders.State!> getLoadActionListener();
+    method public int getTilesTheme();
+    method public android.content.Context getUiContext();
+  }
+
+  public static final class TileRenderer.Config.Builder {
+    ctor public TileRenderer.Config.Builder(android.content.Context, java.util.concurrent.Executor, java.util.function.Consumer<androidx.wear.protolayout.StateBuilders.State!>);
+    method public androidx.wear.tiles.renderer.TileRenderer.Config build();
+    method public androidx.wear.tiles.renderer.TileRenderer.Config.Builder setTilesTheme(@StyleRes int);
+  }
+
   @Deprecated public static interface TileRenderer.LoadActionListener {
     method @Deprecated public void onClick(androidx.wear.tiles.StateBuilders.State);
   }
diff --git a/wear/tiles/tiles-renderer/api/restricted_current.txt b/wear/tiles/tiles-renderer/api/restricted_current.txt
index d4f5f16..7746fcc 100644
--- a/wear/tiles/tiles-renderer/api/restricted_current.txt
+++ b/wear/tiles/tiles-renderer/api/restricted_current.txt
@@ -46,11 +46,25 @@
     ctor @Deprecated public TileRenderer(android.content.Context, androidx.wear.tiles.LayoutElementBuilders.Layout, androidx.wear.tiles.ResourceBuilders.Resources, java.util.concurrent.Executor, androidx.wear.tiles.renderer.TileRenderer.LoadActionListener);
     ctor @Deprecated public TileRenderer(android.content.Context, androidx.wear.tiles.LayoutElementBuilders.Layout, @StyleRes int, androidx.wear.tiles.ResourceBuilders.Resources, java.util.concurrent.Executor, androidx.wear.tiles.renderer.TileRenderer.LoadActionListener);
     ctor public TileRenderer(android.content.Context, java.util.concurrent.Executor, java.util.function.Consumer<androidx.wear.protolayout.StateBuilders.State!>);
+    ctor public TileRenderer(androidx.wear.tiles.renderer.TileRenderer.Config);
     method @Deprecated public android.view.View? inflate(android.view.ViewGroup);
     method public com.google.common.util.concurrent.ListenableFuture<android.view.View!> inflateAsync(androidx.wear.protolayout.LayoutElementBuilders.Layout, androidx.wear.protolayout.ResourceBuilders.Resources, android.view.ViewGroup);
     method public void setState(java.util.Map<androidx.wear.protolayout.expression.AppDataKey<?>!,androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue<?>!>);
   }
 
+  public static final class TileRenderer.Config {
+    method public java.util.concurrent.Executor getLoadActionExecutor();
+    method public java.util.function.Consumer<androidx.wear.protolayout.StateBuilders.State!> getLoadActionListener();
+    method public int getTilesTheme();
+    method public android.content.Context getUiContext();
+  }
+
+  public static final class TileRenderer.Config.Builder {
+    ctor public TileRenderer.Config.Builder(android.content.Context, java.util.concurrent.Executor, java.util.function.Consumer<androidx.wear.protolayout.StateBuilders.State!>);
+    method public androidx.wear.tiles.renderer.TileRenderer.Config build();
+    method public androidx.wear.tiles.renderer.TileRenderer.Config.Builder setTilesTheme(@StyleRes int);
+  }
+
   @Deprecated public static interface TileRenderer.LoadActionListener {
     method @Deprecated public void onClick(androidx.wear.tiles.StateBuilders.State);
   }
diff --git a/wear/tiles/tiles-renderer/lint-baseline.xml b/wear/tiles/tiles-renderer/lint-baseline.xml
index 8294d8d..0177db4 100644
--- a/wear/tiles/tiles-renderer/lint-baseline.xml
+++ b/wear/tiles/tiles-renderer/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.4.0-alpha09" type="baseline" client="gradle" dependencies="false" name="AGP (8.4.0-alpha09)" variant="all" version="8.4.0-alpha09">
+<issues format="6" by="lint 8.4.0-alpha12" type="baseline" client="gradle" dependencies="false" name="AGP (8.4.0-alpha12)" variant="all" version="8.4.0-alpha12">
 
     <issue
         id="UnspecifiedRegisterReceiverFlag"
@@ -174,6 +174,96 @@
 
     <issue
         id="RestrictedApiAndroidX"
+        message="Layout can only be accessed from within the same library group (referenced groupId=`androidx.wear.protolayout` from groupId=`androidx.wear.tiles`)"
+        errorLine1="        @Nullable private final LayoutElementProto.Layout mLayout;"
+        errorLine2="                                ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/tiles/renderer/TileRenderer.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="Resources can only be accessed from within the same library group (referenced groupId=`androidx.wear.protolayout` from groupId=`androidx.wear.tiles`)"
+        errorLine1="        @Nullable private final ResourceProto.Resources mResources;"
+        errorLine2="                                ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/tiles/renderer/TileRenderer.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="Layout can only be accessed from within the same library group (referenced groupId=`androidx.wear.protolayout` from groupId=`androidx.wear.tiles`)"
+        errorLine1="                @Nullable LayoutElementProto.Layout layout,"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/tiles/renderer/TileRenderer.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="Resources can only be accessed from within the same library group (referenced groupId=`androidx.wear.protolayout` from groupId=`androidx.wear.tiles`)"
+        errorLine1="                @Nullable ResourceProto.Resources resources) {"
+        errorLine2="                          ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/tiles/renderer/TileRenderer.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="Layout can only be accessed from within the same library group (referenced groupId=`androidx.wear.protolayout` from groupId=`androidx.wear.tiles`)"
+        errorLine1="        public LayoutElementProto.Layout getLayout() {"
+        errorLine2="               ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/tiles/renderer/TileRenderer.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="Resources can only be accessed from within the same library group (referenced groupId=`androidx.wear.protolayout` from groupId=`androidx.wear.tiles`)"
+        errorLine1="        public ResourceProto.Resources getResources() {"
+        errorLine2="               ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/tiles/renderer/TileRenderer.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="Layout can only be accessed from within the same library group (referenced groupId=`androidx.wear.protolayout` from groupId=`androidx.wear.tiles`)"
+        errorLine1="            @Nullable private LayoutElementProto.Layout mLayout;"
+        errorLine2="                              ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/tiles/renderer/TileRenderer.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="Resources can only be accessed from within the same library group (referenced groupId=`androidx.wear.protolayout` from groupId=`androidx.wear.tiles`)"
+        errorLine1="            @Nullable private ResourceProto.Resources mResources;"
+        errorLine2="                              ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/tiles/renderer/TileRenderer.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="Layout can only be accessed from within the same library group (referenced groupId=`androidx.wear.protolayout` from groupId=`androidx.wear.tiles`)"
+        errorLine1="            public Builder setLayout(@NonNull LayoutElementProto.Layout layout) {"
+        errorLine2="                                              ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/tiles/renderer/TileRenderer.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
+        message="Resources can only be accessed from within the same library group (referenced groupId=`androidx.wear.protolayout` from groupId=`androidx.wear.tiles`)"
+        errorLine1="            public Builder setResources(@NonNull ResourceProto.Resources resources) {"
+        errorLine2="                                                 ~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/tiles/renderer/TileRenderer.java"/>
+    </issue>
+
+    <issue
+        id="RestrictedApiAndroidX"
         message="Timeline.toProto can only be called from within the same library group (referenced groupId=`androidx.wear.protolayout` from groupId=`androidx.wear.tiles`)"
         errorLine1="        mCache = new TilesTimelineCacheInternal(timeline.toProto());"
         errorLine2="                                                         ~~~~~~~">
diff --git a/wear/tiles/tiles-renderer/src/androidTest/java/androidx/wear/tiles/renderer/test/TileRendererGoldenTest.java b/wear/tiles/tiles-renderer/src/androidTest/java/androidx/wear/tiles/renderer/test/TileRendererGoldenTest.java
index c9dcd7b..763c021 100644
--- a/wear/tiles/tiles-renderer/src/androidTest/java/androidx/wear/tiles/renderer/test/TileRendererGoldenTest.java
+++ b/wear/tiles/tiles-renderer/src/androidTest/java/androidx/wear/tiles/renderer/test/TileRendererGoldenTest.java
@@ -41,6 +41,7 @@
 import androidx.wear.protolayout.proto.ResourceProto.Resources;
 import androidx.wear.protolayout.protobuf.ByteString;
 import androidx.wear.tiles.renderer.TileRenderer;
+import androidx.wear.tiles.renderer.TileRenderer.Config;
 
 import com.google.protobuf.TextFormat;
 
@@ -236,9 +237,11 @@
 
         TileRenderer renderer =
                 new TileRenderer(
-                        appContext,
-                        ContextCompat.getMainExecutor(getApplicationContext()),
-                        i -> {});
+                        new Config.Builder(
+                                        appContext,
+                                        ContextCompat.getMainExecutor(getApplicationContext()),
+                                        i -> {})
+                                .build());
 
         View firstChild =
                 renderer.inflateAsync(
diff --git a/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/renderer/TileRenderer.java b/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/renderer/TileRenderer.java
index 82e1946..92dfccf 100644
--- a/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/renderer/TileRenderer.java
+++ b/wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/renderer/TileRenderer.java
@@ -89,9 +89,9 @@
      * @param resources The resources for the Tile.
      * @param loadActionExecutor Executor for {@code loadActionListener}.
      * @param loadActionListener Listener for clicks that will cause the contents to be reloaded.
-     * @deprecated Use {@link #TileRenderer(Context, Executor, Consumer)} which accepts Layout and
-     *     Resources in {@link #inflateAsync(LayoutElementBuilders.Layout,
-     *     ResourceBuilders.Resources, ViewGroup)} method.
+     * @deprecated Use {@link #TileRenderer(Config)} which accepts Layout and Resources in {@link
+     *     #inflateAsync(LayoutElementBuilders.Layout, ResourceBuilders.Resources, ViewGroup)}
+     *     method.
      */
     @Deprecated
     public TileRenderer(
@@ -119,9 +119,9 @@
      * @param resources The resources for the Tile.
      * @param loadActionExecutor Executor for {@code loadActionListener}.
      * @param loadActionListener Listener for clicks that will cause the contents to be reloaded.
-     * @deprecated Use {@link #TileRenderer(Context, Executor, Consumer)} which accepts Layout and
-     *     Resources in {@link #inflateAsync(LayoutElementBuilders.Layout,
-     *     ResourceBuilders.Resources, ViewGroup)} method.
+     * @deprecated Use {@link #TileRenderer(Config)} which accepts Layout and Resources in {@link
+     *     #inflateAsync(LayoutElementBuilders.Layout, ResourceBuilders.Resources, ViewGroup)}
+     *     method.
      */
     @Deprecated
     public TileRenderer(
@@ -141,6 +141,10 @@
     }
 
     /**
+     * Constructor for {@link TileRenderer}.
+     *
+     * <p>It is recommended to use the new {@link #TileRenderer(Config)} constructor instead.
+     *
      * @param uiContext A {@link Context} suitable for interacting with the UI.
      * @param loadActionExecutor Executor for {@code loadActionListener}.
      * @param loadActionListener Listener for clicks that will cause the contents to be reloaded.
@@ -158,6 +162,21 @@
                 /* resources= */ null);
     }
 
+    /**
+     * Constructor for {@link TileRenderer}.
+     *
+     * @param config A {@link Config} to create a {@link TileRenderer} instance.
+     */
+    public TileRenderer(@NonNull Config config) {
+        this(
+                config.getUiContext(),
+                config.getTilesTheme(),
+                config.getLoadActionExecutor(),
+                config.getLoadActionListener(),
+                /* layout= */ null,
+                /* resources= */ null);
+    }
+
     private TileRenderer(
             @NonNull Context uiContext,
             @StyleRes int tilesTheme,
@@ -271,4 +290,93 @@
         ListenableFuture<Void> result = mInstance.renderAndAttach(layout, resources, parent);
         return FluentFuture.from(result).transform(ignored -> parent.getChildAt(0), mUiExecutor);
     }
+
+    /** Config class for {@link TileRenderer}. */
+    public static final class Config {
+        @NonNull private final Context mUiContext;
+        @NonNull private final Executor mLoadActionExecutor;
+        @NonNull private final Consumer<StateBuilders.State> mLoadActionListener;
+
+        @StyleRes int mTilesTheme;
+
+        Config(
+                @NonNull Context uiContext,
+                @NonNull Executor loadActionExecutor,
+                @NonNull Consumer<StateBuilders.State> loadActionListener,
+                @StyleRes int tilesTheme) {
+            this.mUiContext = uiContext;
+            this.mLoadActionExecutor = loadActionExecutor;
+            this.mLoadActionListener = loadActionListener;
+            this.mTilesTheme = tilesTheme;
+        }
+
+        /** Returns the {@link Context} suitable for interacting with the UI. */
+        @NonNull
+        public Context getUiContext() {
+            return mUiContext;
+        }
+
+        /** Returns the {@link Executor} for {@code loadActionListener}. */
+        @NonNull
+        public Executor getLoadActionExecutor() {
+            return mLoadActionExecutor;
+        }
+
+        /** Returns the Listener for clicks that will cause the contents to be reloaded. */
+        @NonNull
+        public Consumer<StateBuilders.State> getLoadActionListener() {
+            return mLoadActionListener;
+        }
+
+        /**
+         * Returns the theme to use for this Tile instance. This can be used to customise things
+         * like the default font family.
+         */
+        public int getTilesTheme() {
+            return mTilesTheme;
+        }
+
+        /** Builder class for {@link Config}. */
+        public static final class Builder {
+            @NonNull private final Context mUiContext;
+            @NonNull private final Executor mLoadActionExecutor;
+            @NonNull private final Consumer<StateBuilders.State> mLoadActionListener;
+
+            @StyleRes int mTilesTheme = 0; // Default theme.
+
+            /**
+             * Builder for the {@link Config} class.
+             *
+             * @param uiContext A {@link Context} suitable for interacting with the UI.
+             * @param loadActionExecutor Executor for {@code loadActionListener}.
+             * @param loadActionListener Listener for clicks that will cause the contents to be
+             *     reloaded.
+             */
+            public Builder(
+                    @NonNull Context uiContext,
+                    @NonNull Executor loadActionExecutor,
+                    @NonNull Consumer<StateBuilders.State> loadActionListener) {
+                this.mUiContext = uiContext;
+                this.mLoadActionExecutor = loadActionExecutor;
+                this.mLoadActionListener = loadActionListener;
+            }
+
+            /**
+             * Sets the theme to use for this Tile instance. This can be used to customise things
+             * like the default font family.
+             */
+            @NonNull
+            public Builder setTilesTheme(@StyleRes int tilesTheme) {
+                mTilesTheme = tilesTheme;
+                return this;
+            }
+
+            /** Builds {@link Config} object. */
+            @NonNull
+            public Config build() {
+                return new Config(
+                        mUiContext, mLoadActionExecutor, mLoadActionListener, mTilesTheme);
+            }
+        }
+    }
 }