Create new StreamScope interface

PiperOrigin-RevId: 247988091
Change-Id: I0cb5e5f19f6df423e7c26c1b234c97be3de05850
diff --git a/src/main/java/com/google/android/libraries/feed/api/client/scope/BUILD b/src/main/java/com/google/android/libraries/feed/api/client/scope/BUILD
index 8b788d5..5f4acae 100644
--- a/src/main/java/com/google/android/libraries/feed/api/client/scope/BUILD
+++ b/src/main/java/com/google/android/libraries/feed/api/client/scope/BUILD
@@ -6,6 +6,7 @@
     name = "processscope",
     srcs = ["ProcessScope.java"],
     deps = [
+        ":streamscopebuilder",
         "//src/main/java/com/google/android/libraries/feed/api/client/knowncontent",
         "//src/main/java/com/google/android/libraries/feed/api/client/lifecycle",
         "//src/main/java/com/google/android/libraries/feed/api/client/requestmanager",
@@ -15,7 +16,6 @@
         "//src/main/java/com/google/android/libraries/feed/api/host/stream",
         "//src/main/java/com/google/android/libraries/feed/api/internal/actionmanager",
         "//src/main/java/com/google/android/libraries/feed/api/internal/protocoladapter",
-        "//src/main/java/com/google/android/libraries/feed/api/scope:feedstreamscope",
         "//src/main/java/com/google/android/libraries/feed/api/sessionmanager",
         "//src/main/java/com/google/android/libraries/feed/basicstream",
         "//src/main/java/com/google/android/libraries/feed/common/concurrent",
@@ -65,3 +65,44 @@
         "@maven//:com_android_support_support_annotations",
     ],
 )
+
+android_library(
+    name = "streamscope",
+    srcs = ["StreamScope.java"],
+    deps = [
+        "//src/main/java/com/google/android/libraries/feed/api/internal/modelprovider",
+        "//src/main/java/com/google/android/libraries/feed/api/stream",
+    ],
+)
+
+android_library(
+    name = "streamscopebuilder",
+    srcs = ["StreamScopeBuilder.java"],
+    deps = [
+        ":streamscope",
+        "//src/main/java/com/google/android/libraries/feed/api/host/action",
+        "//src/main/java/com/google/android/libraries/feed/api/host/config",
+        "//src/main/java/com/google/android/libraries/feed/api/host/imageloader",
+        "//src/main/java/com/google/android/libraries/feed/api/host/logging",
+        "//src/main/java/com/google/android/libraries/feed/api/host/offlineindicator",
+        "//src/main/java/com/google/android/libraries/feed/api/host/stream",
+        "//src/main/java/com/google/android/libraries/feed/api/internal/actionmanager",
+        "//src/main/java/com/google/android/libraries/feed/api/internal/actionparser",
+        "//src/main/java/com/google/android/libraries/feed/api/internal/common",
+        "//src/main/java/com/google/android/libraries/feed/api/internal/knowncontent",
+        "//src/main/java/com/google/android/libraries/feed/api/internal/modelprovider",
+        "//src/main/java/com/google/android/libraries/feed/api/internal/protocoladapter",
+        "//src/main/java/com/google/android/libraries/feed/api/internal/sessionmanager",
+        "//src/main/java/com/google/android/libraries/feed/api/internal/stream",
+        "//src/main/java/com/google/android/libraries/feed/api/scope:feedstreamscope",
+        "//src/main/java/com/google/android/libraries/feed/api/stream",
+        "//src/main/java/com/google/android/libraries/feed/common",
+        "//src/main/java/com/google/android/libraries/feed/common/concurrent",
+        "//src/main/java/com/google/android/libraries/feed/common/protoextensions",
+        "//src/main/java/com/google/android/libraries/feed/common/time",
+        "//src/main/java/com/google/android/libraries/feed/feedactionparser",
+        "//src/main/java/com/google/android/libraries/feed/feedmodelprovider",
+        "//src/main/java/com/google/android/libraries/feed/piet/host",
+        "@com_google_code_findbugs_jsr305//jar",
+    ],
+)
diff --git a/src/main/java/com/google/android/libraries/feed/api/client/scope/ProcessScope.java b/src/main/java/com/google/android/libraries/feed/api/client/scope/ProcessScope.java
index b73c869..e8cdfb0 100644
--- a/src/main/java/com/google/android/libraries/feed/api/client/scope/ProcessScope.java
+++ b/src/main/java/com/google/android/libraries/feed/api/client/scope/ProcessScope.java
@@ -27,7 +27,6 @@
 import com.google.android.libraries.feed.api.host.stream.TooltipApi;
 import com.google.android.libraries.feed.api.internal.actionmanager.ActionManager;
 import com.google.android.libraries.feed.api.internal.protocoladapter.ProtocolAdapter;
-import com.google.android.libraries.feed.api.scope.FeedStreamScope;
 import com.google.android.libraries.feed.api.sessionmanager.SessionManager;
 import com.google.android.libraries.feed.common.concurrent.TaskQueue;
 import com.google.android.libraries.feed.common.protoextensions.FeedExtensionRegistry;
@@ -63,8 +62,8 @@
   @Deprecated
   FeedExtensionRegistry getFeedExtensionRegistry();
 
-  /** Returns a {@link FeedStreamScope.Builder}. */
-  FeedStreamScope.Builder createFeedStreamScopeBuilder(
+  /** Returns a {@link StreamScopeBuilder.Builder}. */
+  StreamScopeBuilder createStreamScopeBuilder(
       Context context,
       ImageLoaderApi imageLoaderApi,
       ActionApi actionApi,
@@ -74,3 +73,4 @@
       OfflineIndicatorApi offlineIndicatorApi,
       TooltipApi tooltipApi);
 }
+
diff --git a/src/main/java/com/google/android/libraries/feed/api/client/scope/StreamScope.java b/src/main/java/com/google/android/libraries/feed/api/client/scope/StreamScope.java
new file mode 100644
index 0000000..cf944b9
--- /dev/null
+++ b/src/main/java/com/google/android/libraries/feed/api/client/scope/StreamScope.java
@@ -0,0 +1,28 @@
+// Copyright 2018 The Feed Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.android.libraries.feed.api.client.scope;
+
+import com.google.android.libraries.feed.api.internal.modelprovider.ModelProviderFactory;
+import com.google.android.libraries.feed.api.stream.Stream;
+
+/** Allows interacting with the Feed library on a per-stream level */
+public interface StreamScope {
+
+  /** Returns the current {@link Stream}. */
+  Stream getStream();
+
+  /** Returns the current {@link ModelProviderFactory}. */
+  ModelProviderFactory getModelProviderFactory();
+}
diff --git a/src/main/java/com/google/android/libraries/feed/api/client/scope/StreamScopeBuilder.java b/src/main/java/com/google/android/libraries/feed/api/client/scope/StreamScopeBuilder.java
new file mode 100644
index 0000000..3b52039
--- /dev/null
+++ b/src/main/java/com/google/android/libraries/feed/api/client/scope/StreamScopeBuilder.java
@@ -0,0 +1,210 @@
+// Copyright 2018 The Feed Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.android.libraries.feed.api.client.scope;
+
+import android.content.Context;
+import com.google.android.libraries.feed.api.host.action.ActionApi;
+import com.google.android.libraries.feed.api.host.config.ApplicationInfo;
+import com.google.android.libraries.feed.api.host.config.Configuration;
+import com.google.android.libraries.feed.api.host.config.DebugBehavior;
+import com.google.android.libraries.feed.api.host.imageloader.ImageLoaderApi;
+import com.google.android.libraries.feed.api.host.logging.BasicLoggingApi;
+import com.google.android.libraries.feed.api.host.offlineindicator.OfflineIndicatorApi;
+import com.google.android.libraries.feed.api.host.stream.CardConfiguration;
+import com.google.android.libraries.feed.api.host.stream.SnackbarApi;
+import com.google.android.libraries.feed.api.host.stream.StreamConfiguration;
+import com.google.android.libraries.feed.api.host.stream.TooltipApi;
+import com.google.android.libraries.feed.api.host.stream.TooltipSupportedApi;
+import com.google.android.libraries.feed.api.internal.actionmanager.ActionManager;
+import com.google.android.libraries.feed.api.internal.actionparser.ActionParserFactory;
+import com.google.android.libraries.feed.api.internal.common.ThreadUtils;
+import com.google.android.libraries.feed.api.internal.knowncontent.FeedKnownContent;
+import com.google.android.libraries.feed.api.internal.modelprovider.ModelProviderFactory;
+import com.google.android.libraries.feed.api.internal.protocoladapter.ProtocolAdapter;
+import com.google.android.libraries.feed.api.internal.sessionmanager.FeedSessionManager;
+import com.google.android.libraries.feed.api.internal.stream.BasicStreamFactory;
+import com.google.android.libraries.feed.api.internal.stream.StreamFactory;
+import com.google.android.libraries.feed.api.scope.FeedStreamScope;
+import com.google.android.libraries.feed.api.stream.Stream;
+import com.google.android.libraries.feed.common.Validators;
+import com.google.android.libraries.feed.common.concurrent.MainThreadRunner;
+import com.google.android.libraries.feed.common.concurrent.TaskQueue;
+import com.google.android.libraries.feed.common.protoextensions.FeedExtensionRegistry;
+import com.google.android.libraries.feed.common.time.Clock;
+import com.google.android.libraries.feed.common.time.TimingUtils;
+import com.google.android.libraries.feed.feedactionparser.FeedActionParserFactory;
+import com.google.android.libraries.feed.feedmodelprovider.FeedModelProviderFactory;
+import com.google.android.libraries.feed.piet.host.CustomElementProvider;
+import com.google.android.libraries.feed.piet.host.HostBindingProvider;
+import com.google.android.libraries.feed.piet.host.ThrowingCustomElementProvider;
+
+/** A builder that creates a {@link StreamScope}. */
+public final class StreamScopeBuilder {
+
+  // Required external dependencies.
+  private final Context context;
+  private final ActionApi actionApi;
+  private final ImageLoaderApi imageLoaderApi;
+
+  private final ProtocolAdapter protocolAdapter;
+  private final FeedSessionManager feedSessionManager;
+  private final ThreadUtils threadUtils;
+  private final TimingUtils timingUtils;
+  private final TaskQueue taskQueue;
+  private final MainThreadRunner mainThreadRunner;
+  private final Clock clock;
+  private final ActionManager actionManager;
+  private final CardConfiguration cardConfiguration;
+  private final StreamConfiguration streamConfiguration;
+  private final DebugBehavior debugBehavior;
+  private final Configuration config;
+  private final SnackbarApi snackbarApi;
+  private final BasicLoggingApi basicLoggingApi;
+  private final OfflineIndicatorApi offlineIndicatorApi;
+  private final FeedKnownContent feedKnownContent;
+  private final TooltipApi tooltipApi;
+  private final ApplicationInfo applicationInfo;
+  private final FeedExtensionRegistry feedExtensionRegistry;
+  private boolean isBackgroundDark;
+
+  // Optional internal components to override the default implementations.
+  /*@MonotonicNonNull*/ private ActionParserFactory actionParserFactory;
+  /*@MonotonicNonNull*/ private ModelProviderFactory modelProviderFactory;
+  /*@MonotonicNonNull*/ private Stream stream;
+  /*@MonotonicNonNull*/ private StreamFactory streamFactory;
+  /*@MonotonicNonNull*/ private CustomElementProvider customElementProvider;
+  /*@MonotonicNonNull*/ private HostBindingProvider hostBindingProvider;
+
+  /** Construct this builder using {@link ProcessScope#createStreamScopeBuilder} */
+  public StreamScopeBuilder(
+      Context context,
+      ActionApi actionApi,
+      ImageLoaderApi imageLoaderApi,
+      ProtocolAdapter protocolAdapter,
+      FeedSessionManager feedSessionManager,
+      ThreadUtils threadUtils,
+      TimingUtils timingUtils,
+      TaskQueue taskQueue,
+      MainThreadRunner mainThreadRunner,
+      Clock clock,
+      DebugBehavior debugBehavior,
+      StreamConfiguration streamConfiguration,
+      CardConfiguration cardConfiguration,
+      ActionManager actionManager,
+      Configuration config,
+      SnackbarApi snackbarApi,
+      BasicLoggingApi basicLoggingApi,
+      OfflineIndicatorApi offlineIndicatorApi,
+      FeedKnownContent feedKnownContent,
+      TooltipApi tooltipApi,
+      TooltipSupportedApi tooltipSupportedApi,
+      ApplicationInfo applicationInfo,
+      FeedExtensionRegistry feedExtensionRegistry) {
+    this.context = context;
+    this.actionApi = actionApi;
+    this.imageLoaderApi = imageLoaderApi;
+    this.protocolAdapter = protocolAdapter;
+    this.feedSessionManager = feedSessionManager;
+    this.threadUtils = threadUtils;
+    this.timingUtils = timingUtils;
+    this.taskQueue = taskQueue;
+    this.mainThreadRunner = mainThreadRunner;
+    this.streamConfiguration = streamConfiguration;
+    this.cardConfiguration = cardConfiguration;
+    this.clock = clock;
+    this.debugBehavior = debugBehavior;
+    this.actionManager = actionManager;
+    this.config = config;
+    this.snackbarApi = snackbarApi;
+    this.basicLoggingApi = basicLoggingApi;
+    this.offlineIndicatorApi = offlineIndicatorApi;
+    this.feedKnownContent = feedKnownContent;
+    this.tooltipApi = tooltipApi;
+    this.applicationInfo = applicationInfo;
+    this.feedExtensionRegistry = feedExtensionRegistry;
+  }
+
+  public StreamScopeBuilder setIsBackgroundDark(boolean isBackgroundDark) {
+    this.isBackgroundDark = isBackgroundDark;
+    return this;
+  }
+
+  public StreamScopeBuilder setStreamFactory(StreamFactory streamFactory) {
+    this.streamFactory = streamFactory;
+    return this;
+  }
+
+  public StreamScopeBuilder setModelProviderFactory(ModelProviderFactory modelProviderFactory) {
+    this.modelProviderFactory = modelProviderFactory;
+    return this;
+  }
+
+  public StreamScopeBuilder setCustomElementProvider(CustomElementProvider customElementProvider) {
+    this.customElementProvider = customElementProvider;
+    return this;
+  }
+
+  public StreamScopeBuilder setHostBindingProvider(HostBindingProvider hostBindingProvider) {
+    this.hostBindingProvider = hostBindingProvider;
+    return this;
+  }
+
+  public StreamScope build() {
+    if (modelProviderFactory == null) {
+      modelProviderFactory =
+          new FeedModelProviderFactory(
+              feedSessionManager, threadUtils, timingUtils, taskQueue, mainThreadRunner, config);
+    }
+    if (actionParserFactory == null) {
+      actionParserFactory = new FeedActionParserFactory(protocolAdapter, basicLoggingApi);
+    }
+    if (customElementProvider == null) {
+      customElementProvider = new ThrowingCustomElementProvider();
+    }
+    if (hostBindingProvider == null) {
+      hostBindingProvider = new HostBindingProvider();
+    }
+    if (streamFactory == null) {
+      streamFactory = new BasicStreamFactory();
+    }
+    stream =
+        streamFactory.build(
+            Validators.checkNotNull(actionParserFactory),
+            context,
+            applicationInfo.getBuildType(),
+            cardConfiguration,
+            imageLoaderApi,
+            Validators.checkNotNull(customElementProvider),
+            debugBehavior,
+            clock,
+            Validators.checkNotNull(modelProviderFactory),
+            Validators.checkNotNull(hostBindingProvider),
+            offlineIndicatorApi,
+            config,
+            actionApi,
+            actionManager,
+            snackbarApi,
+            streamConfiguration,
+            feedExtensionRegistry,
+            basicLoggingApi,
+            mainThreadRunner,
+            isBackgroundDark,
+            tooltipApi,
+            threadUtils,
+            feedKnownContent);
+    return new FeedStreamScope(
+        Validators.checkNotNull(stream), Validators.checkNotNull(modelProviderFactory));
+  }
+}
diff --git a/src/main/java/com/google/android/libraries/feed/api/scope/BUILD b/src/main/java/com/google/android/libraries/feed/api/scope/BUILD
index b3e8759..cd19b80 100644
--- a/src/main/java/com/google/android/libraries/feed/api/scope/BUILD
+++ b/src/main/java/com/google/android/libraries/feed/api/scope/BUILD
@@ -26,12 +26,12 @@
     name = "feedprocessscope",
     srcs = ["FeedProcessScope.java"],
     deps = [
-        ":feedstreamscope",
         ":scope",
         "//src/main/java/com/google/android/libraries/feed/api/client/knowncontent",
         "//src/main/java/com/google/android/libraries/feed/api/client/lifecycle",
         "//src/main/java/com/google/android/libraries/feed/api/client/requestmanager",
         "//src/main/java/com/google/android/libraries/feed/api/client/scope:processscope",
+        "//src/main/java/com/google/android/libraries/feed/api/client/scope:streamscopebuilder",
         "//src/main/java/com/google/android/libraries/feed/api/host/action",
         "//src/main/java/com/google/android/libraries/feed/api/host/config",
         "//src/main/java/com/google/android/libraries/feed/api/host/imageloader",
@@ -58,29 +58,9 @@
     name = "feedstreamscope",
     srcs = ["FeedStreamScope.java"],
     deps = [
-        "//src/main/java/com/google/android/libraries/feed/api/host/action",
-        "//src/main/java/com/google/android/libraries/feed/api/host/config",
-        "//src/main/java/com/google/android/libraries/feed/api/host/imageloader",
-        "//src/main/java/com/google/android/libraries/feed/api/host/logging",
-        "//src/main/java/com/google/android/libraries/feed/api/host/offlineindicator",
-        "//src/main/java/com/google/android/libraries/feed/api/host/stream",
-        "//src/main/java/com/google/android/libraries/feed/api/internal/actionmanager",
-        "//src/main/java/com/google/android/libraries/feed/api/internal/actionparser",
-        "//src/main/java/com/google/android/libraries/feed/api/internal/common",
-        "//src/main/java/com/google/android/libraries/feed/api/internal/knowncontent",
+        "//src/main/java/com/google/android/libraries/feed/api/client/scope:streamscope",
         "//src/main/java/com/google/android/libraries/feed/api/internal/modelprovider",
-        "//src/main/java/com/google/android/libraries/feed/api/internal/protocoladapter",
-        "//src/main/java/com/google/android/libraries/feed/api/internal/sessionmanager",
-        "//src/main/java/com/google/android/libraries/feed/api/internal/stream",
         "//src/main/java/com/google/android/libraries/feed/api/stream",
         "//src/main/java/com/google/android/libraries/feed/basicstream",
-        "//src/main/java/com/google/android/libraries/feed/common",
-        "//src/main/java/com/google/android/libraries/feed/common/concurrent",
-        "//src/main/java/com/google/android/libraries/feed/common/protoextensions",
-        "//src/main/java/com/google/android/libraries/feed/common/time",
-        "//src/main/java/com/google/android/libraries/feed/feedactionparser",
-        "//src/main/java/com/google/android/libraries/feed/feedmodelprovider",
-        "//src/main/java/com/google/android/libraries/feed/piet/host",
-        "@com_google_code_findbugs_jsr305//jar",
     ],
 )
diff --git a/src/main/java/com/google/android/libraries/feed/api/scope/FeedProcessScope.java b/src/main/java/com/google/android/libraries/feed/api/scope/FeedProcessScope.java
index 745e76e..a4d3466 100644
--- a/src/main/java/com/google/android/libraries/feed/api/scope/FeedProcessScope.java
+++ b/src/main/java/com/google/android/libraries/feed/api/scope/FeedProcessScope.java
@@ -19,6 +19,7 @@
 import com.google.android.libraries.feed.api.client.lifecycle.AppLifecycleListener;
 import com.google.android.libraries.feed.api.client.requestmanager.RequestManager;
 import com.google.android.libraries.feed.api.client.scope.ProcessScope;
+import com.google.android.libraries.feed.api.client.scope.StreamScopeBuilder;
 import com.google.android.libraries.feed.api.host.action.ActionApi;
 import com.google.android.libraries.feed.api.host.config.ApplicationInfo;
 import com.google.android.libraries.feed.api.host.config.Configuration;
@@ -78,46 +79,6 @@
   private final TooltipSupportedApi tooltipSupportedApi;
   private final ApplicationInfo applicationInfo;
 
-  /**
-   * Return a {@link Builder} to create a FeedProcessScope
-   *
-   * <p>This is called by hosts so it must be public
-   */
-  public FeedStreamScope.Builder createFeedStreamScopeBuilder(
-      Context context,
-      ImageLoaderApi imageLoaderApi,
-      ActionApi actionApi,
-      StreamConfiguration streamConfiguration,
-      CardConfiguration cardConfiguration,
-      SnackbarApi snackbarApi,
-      OfflineIndicatorApi offlineIndicatorApi,
-      TooltipApi tooltipApi) {
-    return new FeedStreamScope.Builder(
-        context,
-        actionApi,
-        imageLoaderApi,
-        protocolAdapter,
-        feedSessionManager,
-        threadUtils,
-        timingUtils,
-        taskQueue,
-        mainThreadRunner,
-        clock,
-        debugBehavior,
-        streamConfiguration,
-        cardConfiguration,
-        actionManager,
-        configuration,
-        snackbarApi,
-        basicLoggingApi,
-        offlineIndicatorApi,
-        feedKnownContent,
-        tooltipApi,
-        tooltipSupportedApi,
-        applicationInfo,
-        feedExtensionRegistry);
-  }
-
   /** Created through the {@link Builder}. */
   public FeedProcessScope(
       BasicLoggingApi basicLoggingApi,
@@ -229,4 +190,45 @@
   public FeedExtensionRegistry getFeedExtensionRegistry() {
     return feedExtensionRegistry;
   }
+
+  /**
+   * Return a {@link Builder} to create a FeedProcessScope
+   *
+   * <p>This is called by hosts so it must be public
+   */
+  @Override
+  public StreamScopeBuilder createStreamScopeBuilder(
+      Context context,
+      ImageLoaderApi imageLoaderApi,
+      ActionApi actionApi,
+      StreamConfiguration streamConfiguration,
+      CardConfiguration cardConfiguration,
+      SnackbarApi snackbarApi,
+      OfflineIndicatorApi offlineIndicatorApi,
+      TooltipApi tooltipApi) {
+    return new StreamScopeBuilder(
+        context,
+        actionApi,
+        imageLoaderApi,
+        protocolAdapter,
+        feedSessionManager,
+        threadUtils,
+        timingUtils,
+        taskQueue,
+        mainThreadRunner,
+        clock,
+        debugBehavior,
+        streamConfiguration,
+        cardConfiguration,
+        actionManager,
+        configuration,
+        snackbarApi,
+        basicLoggingApi,
+        offlineIndicatorApi,
+        feedKnownContent,
+        tooltipApi,
+        tooltipSupportedApi,
+        applicationInfo,
+        feedExtensionRegistry);
+  }
 }
diff --git a/src/main/java/com/google/android/libraries/feed/api/scope/FeedStreamScope.java b/src/main/java/com/google/android/libraries/feed/api/scope/FeedStreamScope.java
index 72c9579..0a1e7e2 100644
--- a/src/main/java/com/google/android/libraries/feed/api/scope/FeedStreamScope.java
+++ b/src/main/java/com/google/android/libraries/feed/api/scope/FeedStreamScope.java
@@ -14,43 +14,20 @@
 
 package com.google.android.libraries.feed.api.scope;
 
-import android.content.Context;
-import com.google.android.libraries.feed.api.host.action.ActionApi;
-import com.google.android.libraries.feed.api.host.config.ApplicationInfo;
-import com.google.android.libraries.feed.api.host.config.Configuration;
-import com.google.android.libraries.feed.api.host.config.DebugBehavior;
-import com.google.android.libraries.feed.api.host.imageloader.ImageLoaderApi;
-import com.google.android.libraries.feed.api.host.logging.BasicLoggingApi;
-import com.google.android.libraries.feed.api.host.offlineindicator.OfflineIndicatorApi;
-import com.google.android.libraries.feed.api.host.stream.CardConfiguration;
-import com.google.android.libraries.feed.api.host.stream.SnackbarApi;
-import com.google.android.libraries.feed.api.host.stream.StreamConfiguration;
-import com.google.android.libraries.feed.api.host.stream.TooltipApi;
-import com.google.android.libraries.feed.api.host.stream.TooltipSupportedApi;
-import com.google.android.libraries.feed.api.internal.actionmanager.ActionManager;
-import com.google.android.libraries.feed.api.internal.actionparser.ActionParserFactory;
-import com.google.android.libraries.feed.api.internal.common.ThreadUtils;
-import com.google.android.libraries.feed.api.internal.knowncontent.FeedKnownContent;
+import com.google.android.libraries.feed.api.client.scope.StreamScope;
 import com.google.android.libraries.feed.api.internal.modelprovider.ModelProviderFactory;
-import com.google.android.libraries.feed.api.internal.protocoladapter.ProtocolAdapter;
-import com.google.android.libraries.feed.api.internal.sessionmanager.FeedSessionManager;
-import com.google.android.libraries.feed.api.internal.stream.BasicStreamFactory;
-import com.google.android.libraries.feed.api.internal.stream.StreamFactory;
 import com.google.android.libraries.feed.api.stream.Stream;
-import com.google.android.libraries.feed.common.Validators;
-import com.google.android.libraries.feed.common.concurrent.MainThreadRunner;
-import com.google.android.libraries.feed.common.concurrent.TaskQueue;
-import com.google.android.libraries.feed.common.protoextensions.FeedExtensionRegistry;
-import com.google.android.libraries.feed.common.time.Clock;
-import com.google.android.libraries.feed.common.time.TimingUtils;
-import com.google.android.libraries.feed.feedactionparser.FeedActionParserFactory;
-import com.google.android.libraries.feed.feedmodelprovider.FeedModelProviderFactory;
-import com.google.android.libraries.feed.piet.host.CustomElementProvider;
-import com.google.android.libraries.feed.piet.host.HostBindingProvider;
-import com.google.android.libraries.feed.piet.host.ThrowingCustomElementProvider;
 
 /** Per-stream instance of the feed library. */
-public final class FeedStreamScope {
+public final class FeedStreamScope implements StreamScope {
+
+  private final Stream stream;
+  private final ModelProviderFactory modelProviderFactory;
+
+  public FeedStreamScope(Stream stream, ModelProviderFactory modelProviderFactory) {
+    this.stream = stream;
+    this.modelProviderFactory = modelProviderFactory;
+  }
 
   public Stream getStream() {
     return stream;
@@ -59,170 +36,4 @@
   public ModelProviderFactory getModelProviderFactory() {
     return modelProviderFactory;
   }
-
-  /** A builder that creates a {@link FeedStreamScope}. */
-  public static final class Builder {
-    /** Construct this builder using {@link FeedProcessScope#createFeedStreamScopeBuilder} */
-    Builder(
-        Context context,
-        ActionApi actionApi,
-        ImageLoaderApi imageLoaderApi,
-        ProtocolAdapter protocolAdapter,
-        FeedSessionManager feedSessionManager,
-        ThreadUtils threadUtils,
-        TimingUtils timingUtils,
-        TaskQueue taskQueue,
-        MainThreadRunner mainThreadRunner,
-        Clock clock,
-        DebugBehavior debugBehavior,
-        StreamConfiguration streamConfiguration,
-        CardConfiguration cardConfiguration,
-        ActionManager actionManager,
-        Configuration config,
-        SnackbarApi snackbarApi,
-        BasicLoggingApi basicLoggingApi,
-        OfflineIndicatorApi offlineIndicatorApi,
-        FeedKnownContent feedKnownContent,
-        TooltipApi tooltipApi,
-        TooltipSupportedApi tooltipSupportedApi,
-        ApplicationInfo applicationInfo,
-        FeedExtensionRegistry feedExtensionRegistry) {
-      this.context = context;
-      this.actionApi = actionApi;
-      this.imageLoaderApi = imageLoaderApi;
-      this.protocolAdapter = protocolAdapter;
-      this.feedSessionManager = feedSessionManager;
-      this.threadUtils = threadUtils;
-      this.timingUtils = timingUtils;
-      this.taskQueue = taskQueue;
-      this.mainThreadRunner = mainThreadRunner;
-      this.streamConfiguration = streamConfiguration;
-      this.cardConfiguration = cardConfiguration;
-      this.clock = clock;
-      this.debugBehavior = debugBehavior;
-      this.actionManager = actionManager;
-      this.config = config;
-      this.snackbarApi = snackbarApi;
-      this.basicLoggingApi = basicLoggingApi;
-      this.offlineIndicatorApi = offlineIndicatorApi;
-      this.feedKnownContent = feedKnownContent;
-      this.tooltipApi = tooltipApi;
-      this.applicationInfo = applicationInfo;
-      this.feedExtensionRegistry = feedExtensionRegistry;
-    }
-
-    public Builder setIsBackgroundDark(boolean isBackgroundDark) {
-      this.isBackgroundDark = isBackgroundDark;
-      return this;
-    }
-
-    public Builder setStreamFactory(StreamFactory streamFactory) {
-      this.streamFactory = streamFactory;
-      return this;
-    }
-
-    public Builder setModelProviderFactory(ModelProviderFactory modelProviderFactory) {
-      this.modelProviderFactory = modelProviderFactory;
-      return this;
-    }
-
-    public Builder setCustomElementProvider(CustomElementProvider customElementProvider) {
-      this.customElementProvider = customElementProvider;
-      return this;
-    }
-
-    public Builder setHostBindingProvider(HostBindingProvider hostBindingProvider) {
-      this.hostBindingProvider = hostBindingProvider;
-      return this;
-    }
-
-    public FeedStreamScope build() {
-      if (modelProviderFactory == null) {
-        modelProviderFactory =
-            new FeedModelProviderFactory(
-                feedSessionManager, threadUtils, timingUtils, taskQueue, mainThreadRunner, config);
-      }
-      if (actionParserFactory == null) {
-        actionParserFactory = new FeedActionParserFactory(protocolAdapter, basicLoggingApi);
-      }
-      if (customElementProvider == null) {
-        customElementProvider = new ThrowingCustomElementProvider();
-      }
-      if (hostBindingProvider == null) {
-        hostBindingProvider = new HostBindingProvider();
-      }
-      if (streamFactory == null) {
-        streamFactory = new BasicStreamFactory();
-      }
-      stream =
-          streamFactory.build(
-              Validators.checkNotNull(actionParserFactory),
-              context,
-              applicationInfo.getBuildType(),
-              cardConfiguration,
-              imageLoaderApi,
-              Validators.checkNotNull(customElementProvider),
-              debugBehavior,
-              clock,
-              Validators.checkNotNull(modelProviderFactory),
-              Validators.checkNotNull(hostBindingProvider),
-              offlineIndicatorApi,
-              config,
-              actionApi,
-              actionManager,
-              snackbarApi,
-              streamConfiguration,
-              feedExtensionRegistry,
-              basicLoggingApi,
-              mainThreadRunner,
-              isBackgroundDark,
-              tooltipApi,
-              threadUtils,
-              feedKnownContent);
-      return new FeedStreamScope(
-          Validators.checkNotNull(stream), Validators.checkNotNull(modelProviderFactory));
-    }
-
-    // Required external dependencies.
-    private final Context context;
-    private final ActionApi actionApi;
-    private final ImageLoaderApi imageLoaderApi;
-
-    private final ProtocolAdapter protocolAdapter;
-    private final FeedSessionManager feedSessionManager;
-    private final ThreadUtils threadUtils;
-    private final TimingUtils timingUtils;
-    private final TaskQueue taskQueue;
-    private final MainThreadRunner mainThreadRunner;
-    private final Clock clock;
-    private final ActionManager actionManager;
-    private final CardConfiguration cardConfiguration;
-    private final StreamConfiguration streamConfiguration;
-    private final DebugBehavior debugBehavior;
-    private final Configuration config;
-    private final SnackbarApi snackbarApi;
-    private final BasicLoggingApi basicLoggingApi;
-    private final OfflineIndicatorApi offlineIndicatorApi;
-    private final FeedKnownContent feedKnownContent;
-    private final TooltipApi tooltipApi;
-    private final ApplicationInfo applicationInfo;
-    private final FeedExtensionRegistry feedExtensionRegistry;
-    private boolean isBackgroundDark;
-
-    // Optional internal components to override the default implementations.
-    /*@MonotonicNonNull*/ private ActionParserFactory actionParserFactory;
-    /*@MonotonicNonNull*/ private ModelProviderFactory modelProviderFactory;
-    /*@MonotonicNonNull*/ private Stream stream;
-    /*@MonotonicNonNull*/ private StreamFactory streamFactory;
-    /*@MonotonicNonNull*/ private CustomElementProvider customElementProvider;
-    /*@MonotonicNonNull*/ private HostBindingProvider hostBindingProvider;
-  }
-
-  private FeedStreamScope(Stream stream, ModelProviderFactory modelProviderFactory) {
-    this.stream = stream;
-    this.modelProviderFactory = modelProviderFactory;
-  }
-
-  private final Stream stream;
-  private final ModelProviderFactory modelProviderFactory;
 }
diff --git a/src/test/java/com/google/android/libraries/feed/api/client/scope/BUILD b/src/test/java/com/google/android/libraries/feed/api/client/scope/BUILD
index 0349d4f..82800ca 100644
--- a/src/test/java/com/google/android/libraries/feed/api/client/scope/BUILD
+++ b/src/test/java/com/google/android/libraries/feed/api/client/scope/BUILD
@@ -30,3 +30,40 @@
         "@robolectric//bazel:android-all",
     ],
 )
+
+android_local_test(
+    name = "StreamScopeBuilderTest",
+    size = "small",
+    timeout = "moderate",
+    srcs = ["StreamScopeBuilderTest.java"],
+    aapt_version = "aapt2",
+    manifest_values = DEFAULT_ANDROID_LOCAL_TEST_MANIFEST,
+    deps = [
+        "//src/main/java/com/google/android/libraries/feed/api/client/scope:streamscope",
+        "//src/main/java/com/google/android/libraries/feed/api/client/scope:streamscopebuilder",
+        "//src/main/java/com/google/android/libraries/feed/api/host/action",
+        "//src/main/java/com/google/android/libraries/feed/api/host/config",
+        "//src/main/java/com/google/android/libraries/feed/api/host/imageloader",
+        "//src/main/java/com/google/android/libraries/feed/api/host/logging",
+        "//src/main/java/com/google/android/libraries/feed/api/host/offlineindicator",
+        "//src/main/java/com/google/android/libraries/feed/api/host/stream",
+        "//src/main/java/com/google/android/libraries/feed/api/internal/actionmanager",
+        "//src/main/java/com/google/android/libraries/feed/api/internal/common",
+        "//src/main/java/com/google/android/libraries/feed/api/internal/knowncontent",
+        "//src/main/java/com/google/android/libraries/feed/api/internal/modelprovider",
+        "//src/main/java/com/google/android/libraries/feed/api/internal/protocoladapter",
+        "//src/main/java/com/google/android/libraries/feed/api/internal/sessionmanager",
+        "//src/main/java/com/google/android/libraries/feed/api/internal/stream",
+        "//src/main/java/com/google/android/libraries/feed/api/stream",
+        "//src/main/java/com/google/android/libraries/feed/common/concurrent",
+        "//src/main/java/com/google/android/libraries/feed/common/protoextensions",
+        "//src/main/java/com/google/android/libraries/feed/common/time",
+        "//src/main/java/com/google/android/libraries/feed/common/time/testing",
+        "//src/main/java/com/google/android/libraries/feed/piet/host",
+        "//third_party:robolectric",
+        "@com_google_protobuf_javalite//:protobuf_java_lite",
+        "@maven//:com_google_truth_truth",
+        "@maven//:org_mockito_mockito_core",
+        "@robolectric//bazel:android-all",
+    ],
+)
diff --git a/src/test/java/com/google/android/libraries/feed/api/scope/FeedStreamScopeTest.java b/src/test/java/com/google/android/libraries/feed/api/client/scope/StreamScopeBuilderTest.java
similarity index 95%
rename from src/test/java/com/google/android/libraries/feed/api/scope/FeedStreamScopeTest.java
rename to src/test/java/com/google/android/libraries/feed/api/client/scope/StreamScopeBuilderTest.java
index a9d6731..16c1ce9 100644
--- a/src/test/java/com/google/android/libraries/feed/api/scope/FeedStreamScopeTest.java
+++ b/src/test/java/com/google/android/libraries/feed/api/client/scope/StreamScopeBuilderTest.java
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package com.google.android.libraries.feed.api.scope;
+package com.google.android.libraries.feed.api.client.scope;
 
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -44,7 +44,6 @@
 import com.google.android.libraries.feed.api.internal.protocoladapter.ProtocolAdapter;
 import com.google.android.libraries.feed.api.internal.sessionmanager.FeedSessionManager;
 import com.google.android.libraries.feed.api.internal.stream.StreamFactory;
-import com.google.android.libraries.feed.api.scope.FeedStreamScope.Builder;
 import com.google.android.libraries.feed.api.stream.Stream;
 import com.google.android.libraries.feed.common.concurrent.MainThreadRunner;
 import com.google.android.libraries.feed.common.concurrent.TaskQueue;
@@ -61,9 +60,9 @@
 import org.robolectric.Robolectric;
 import org.robolectric.RobolectricTestRunner;
 
-/** Tests for {@link FeedStreamScope}. */
+/** Tests for {@link StreamScopeBuilder}. */
 @RunWith(RobolectricTestRunner.class)
-public class FeedStreamScopeTest {
+public class StreamScopeBuilderTest {
 
   @BuildType private static final int BUILD_TYPE = BuildType.ALPHA;
   public static final DebugBehavior DEBUG_BEHAVIOR = DebugBehavior.VERBOSE;
@@ -116,8 +115,8 @@
 
   @Test
   public void testBasicBuild() {
-    FeedStreamScope streamScope =
-        new Builder(
+    StreamScope streamScope =
+        new StreamScopeBuilder(
                 context,
                 actionApi,
                 imageLoaderApi,
@@ -148,8 +147,8 @@
 
   @Test
   public void testComplexBuild() {
-    FeedStreamScope streamScope =
-        new Builder(
+    StreamScope streamScope =
+        new StreamScopeBuilder(
                 context,
                 actionApi,
                 imageLoaderApi,
@@ -185,8 +184,8 @@
   public void testStreamFactoryBuild() {
     setupStreamFactory(stream);
 
-    FeedStreamScope streamScope =
-        new Builder(
+    StreamScope streamScope =
+        new StreamScopeBuilder(
                 context,
                 actionApi,
                 imageLoaderApi,
diff --git a/src/test/java/com/google/android/libraries/feed/api/scope/BUILD b/src/test/java/com/google/android/libraries/feed/api/scope/BUILD
index 5905731..2547a00 100644
--- a/src/test/java/com/google/android/libraries/feed/api/scope/BUILD
+++ b/src/test/java/com/google/android/libraries/feed/api/scope/BUILD
@@ -60,39 +60,3 @@
         "@robolectric//bazel:android-all",
     ],
 )
-
-android_local_test(
-    name = "FeedStreamScopeTest",
-    size = "small",
-    timeout = "moderate",
-    srcs = ["FeedStreamScopeTest.java"],
-    aapt_version = "aapt2",
-    manifest_values = DEFAULT_ANDROID_LOCAL_TEST_MANIFEST,
-    deps = [
-        "//src/main/java/com/google/android/libraries/feed/api/host/action",
-        "//src/main/java/com/google/android/libraries/feed/api/host/config",
-        "//src/main/java/com/google/android/libraries/feed/api/host/imageloader",
-        "//src/main/java/com/google/android/libraries/feed/api/host/logging",
-        "//src/main/java/com/google/android/libraries/feed/api/host/offlineindicator",
-        "//src/main/java/com/google/android/libraries/feed/api/host/stream",
-        "//src/main/java/com/google/android/libraries/feed/api/internal/actionmanager",
-        "//src/main/java/com/google/android/libraries/feed/api/internal/common",
-        "//src/main/java/com/google/android/libraries/feed/api/internal/knowncontent",
-        "//src/main/java/com/google/android/libraries/feed/api/internal/modelprovider",
-        "//src/main/java/com/google/android/libraries/feed/api/internal/protocoladapter",
-        "//src/main/java/com/google/android/libraries/feed/api/internal/sessionmanager",
-        "//src/main/java/com/google/android/libraries/feed/api/internal/stream",
-        "//src/main/java/com/google/android/libraries/feed/api/scope:feedstreamscope",
-        "//src/main/java/com/google/android/libraries/feed/api/stream",
-        "//src/main/java/com/google/android/libraries/feed/common/concurrent",
-        "//src/main/java/com/google/android/libraries/feed/common/protoextensions",
-        "//src/main/java/com/google/android/libraries/feed/common/time",
-        "//src/main/java/com/google/android/libraries/feed/common/time/testing",
-        "//src/main/java/com/google/android/libraries/feed/piet/host",
-        "//third_party:robolectric",
-        "@com_google_protobuf_javalite//:protobuf_java_lite",
-        "@maven//:com_google_truth_truth",
-        "@maven//:org_mockito_mockito_core",
-        "@robolectric//bazel:android-all",
-    ],
-)