Remove the consumer pattern for some synchronous methods that can return a
result.

PiperOrigin-RevId: 258256627
Change-Id: I200b7d3c9e42e4e7a7037563fa0c991708ed8112
diff --git a/src/main/java/com/google/android/libraries/feed/api/internal/sessionmanager/FeedSessionManager.java b/src/main/java/com/google/android/libraries/feed/api/internal/sessionmanager/FeedSessionManager.java
index 982d624..a901f70 100644
--- a/src/main/java/com/google/android/libraries/feed/api/internal/sessionmanager/FeedSessionManager.java
+++ b/src/main/java/com/google/android/libraries/feed/api/internal/sessionmanager/FeedSessionManager.java
@@ -93,11 +93,10 @@
       /*@Nullable*/ String sessionId, @RequestReason int requestReason, UiContext uiContext);
 
   /**
-   * Returns a List of {@link StreamPayload} for each of the keys. This operation may perform disk
-   * reads, therefore the payloads are returned through a consumer. The returned values will contain
-   * both the payload and the content id of the payload.
+   * Returns a List of {@link StreamPayload} for each of the keys. This must be called on the
+   * background thread.
    */
-  void getStreamFeatures(List<String> contentIds, Consumer<Result<List<PayloadWithId>>> consumer);
+  Result<List<PayloadWithId>> getStreamFeatures(List<String> contentIds);
 
   /**
    * Return the shared state. This operation will be fast, so it can be called on the UI Thread.
diff --git a/src/main/java/com/google/android/libraries/feed/feedmodelprovider/FeedModelProvider.java b/src/main/java/com/google/android/libraries/feed/feedmodelprovider/FeedModelProvider.java
index e3bcdab..6bb79a8 100644
--- a/src/main/java/com/google/android/libraries/feed/feedmodelprovider/FeedModelProvider.java
+++ b/src/main/java/com/google/android/libraries/feed/feedmodelprovider/FeedModelProvider.java
@@ -36,14 +36,12 @@
 import com.google.android.libraries.feed.api.internal.modelprovider.TokenCompleted;
 import com.google.android.libraries.feed.api.internal.modelprovider.TokenCompletedObserver;
 import com.google.android.libraries.feed.api.internal.sessionmanager.FeedSessionManager;
-import com.google.android.libraries.feed.common.Result;
 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.concurrent.TaskQueue.TaskType;
 import com.google.android.libraries.feed.common.feedobservable.FeedObservable;
 import com.google.android.libraries.feed.common.functional.Committer;
-import com.google.android.libraries.feed.common.functional.Consumer;
 import com.google.android.libraries.feed.common.functional.Predicate;
 import com.google.android.libraries.feed.common.logging.Dumpable;
 import com.google.android.libraries.feed.common.logging.Dumper;
@@ -647,16 +645,13 @@
             }
           }
 
-          bindChildrenAndTokens(
-              childrenToBind,
-              (result) -> {
-                if (result.isSuccessful()) {
-                  mutationHandler.postMutation();
-                } else {
-                  Logger.e(TAG, "bindChildrenAndTokens failed, not processing mutation");
-                  invalidate();
-                }
-              });
+          boolean success = bindChildrenAndTokens(childrenToBind);
+          if (success) {
+            mutationHandler.postMutation();
+          } else {
+            Logger.e(TAG, "bindChildrenAndTokens failed, not processing mutation");
+            invalidate();
+          }
           timeTracker.stop("", "modelProviderCommit");
           StreamToken token =
               (change.mutationContext != null)
@@ -793,10 +788,9 @@
         }
       };
 
-  private void bindChildrenAndTokens(
-      List<UpdatableModelChild> childrenToBind, Consumer<Result<Void>> consumer) {
+  private boolean bindChildrenAndTokens(List<UpdatableModelChild> childrenToBind) {
     // Bind the unbound children
-    modelChildBinder.bindChildren(childrenToBind, consumer);
+    boolean success = modelChildBinder.bindChildren(childrenToBind);
 
     synchronized (lock) {
       // Track any tokens we added to the tree
@@ -817,6 +811,8 @@
         }
       }
     }
+
+    return success;
   }
 
   private boolean shouldInsertSyntheticToken() {
@@ -951,20 +947,21 @@
       SyntheticTokenTracker tokenTracker = new SyntheticTokenTracker(currentRoot, pos, pageSize);
       List<UpdatableModelChild> childrenToBind = tokenTracker.insertToken();
       List<UpdatableModelChild> cursorSublist = rootChildren.subList(pos, rootChildren.size());
-      bindChildrenAndTokens(
-          childrenToBind,
-          (bindingCount) -> {
-            ModelCursorImpl cursor = new ModelCursorImpl(streamToken.getParentId(), cursorSublist);
 
-            TokenCompleted tokenCompleted = new TokenCompleted(cursor);
-            mainThreadRunner.execute(
-                TAG + " onTokenChange",
-                () -> {
-                  List<TokenCompletedObserver> observerList = token.getObserversToNotify();
-                  for (TokenCompletedObserver observer : observerList) {
-                    observer.onTokenCompleted(tokenCompleted);
-                  }
-                });
+      boolean success = bindChildrenAndTokens(childrenToBind);
+      if (!success) {
+        Logger.e(TAG, "bindChildren was unsuccessful");
+      }
+
+      ModelCursorImpl cursor = new ModelCursorImpl(streamToken.getParentId(), cursorSublist);
+      TokenCompleted tokenCompleted = new TokenCompleted(cursor);
+      mainThreadRunner.execute(
+          TAG + " onTokenChange",
+          () -> {
+            List<TokenCompletedObserver> observerList = token.getObserversToNotify();
+            for (TokenCompletedObserver observer : observerList) {
+              observer.onTokenCompleted(tokenCompleted);
+            }
           });
     }
 
diff --git a/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/ModelChildBinder.java b/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/ModelChildBinder.java
index ebd4e15..16f1761 100644
--- a/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/ModelChildBinder.java
+++ b/src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal/ModelChildBinder.java
@@ -19,7 +19,6 @@
 import com.google.android.libraries.feed.api.internal.modelprovider.ModelChild.Type;
 import com.google.android.libraries.feed.api.internal.sessionmanager.FeedSessionManager;
 import com.google.android.libraries.feed.common.Result;
-import com.google.android.libraries.feed.common.functional.Consumer;
 import com.google.android.libraries.feed.common.logging.Logger;
 import com.google.android.libraries.feed.common.time.TimingUtils;
 import com.google.android.libraries.feed.common.time.TimingUtils.ElapsedTimeTracker;
@@ -50,8 +49,7 @@
     this.timingUtils = timingUtils;
   }
 
-  public void bindChildren(
-      List<UpdatableModelChild> childrenToBind, Consumer<Result<Void>> consumer) {
+  public boolean bindChildren(List<UpdatableModelChild> childrenToBind) {
     ElapsedTimeTracker timeTracker = timingUtils.getElapsedTimeTracker(TAG);
     Map<String, UpdatableModelChild> bindingChildren = new HashMap<>();
     List<String> contentIds = new ArrayList<>();
@@ -60,47 +58,45 @@
       contentIds.add(key);
       bindingChildren.put(key, child);
     }
-    feedSessionManager.getStreamFeatures(
-        contentIds,
-        results -> {
-          if (!results.isSuccessful()) {
-            // If we failed, it's likely that this ModelProvider will soon be invalidated by the
-            // FeedSessionManager
-            Logger.e(TAG, "Unable to get the stream features.");
-            consumer.accept(Result.failure());
+
+    Result<List<PayloadWithId>> results = feedSessionManager.getStreamFeatures(contentIds);
+    if (!results.isSuccessful()) {
+      // If we failed, it's likely that this ModelProvider will soon be invalidated by the
+      // FeedSessionManager
+      Logger.e(TAG, "Unable to get the stream features.");
+      return false;
+    }
+    List<PayloadWithId> payloads = results.getValue();
+    if (contentIds.size() > payloads.size()) {
+      Logger.e(
+          TAG,
+          "Didn't find all of the unbound content, found %s, expected %s",
+          payloads.size(),
+          contentIds.size());
+    }
+    for (PayloadWithId childPayload : payloads) {
+      String key = childPayload.contentId;
+      UpdatableModelChild child = bindingChildren.get(key);
+      if (child != null) {
+        StreamPayload payload = childPayload.payload;
+        if (child.getType() == Type.UNBOUND) {
+          if (payload.hasStreamFeature()) {
+            child.bindFeature(
+                new UpdatableModelFeature(payload.getStreamFeature(), cursorProvider));
+          } else if (payload.hasStreamToken()) {
+            child.bindToken(new UpdatableModelToken(payload.getStreamToken(), false));
+            continue;
+          } else {
+            Logger.e(TAG, "Unsupported Payload Type");
           }
-          List<PayloadWithId> payloads = results.getValue();
-          if (contentIds.size() > payloads.size()) {
-            Logger.e(
-                TAG,
-                "Didn't find all of the unbound content, found %s, expected %s",
-                payloads.size(),
-                contentIds.size());
-          }
-          for (PayloadWithId childPayload : payloads) {
-            String key = childPayload.contentId;
-            UpdatableModelChild child = bindingChildren.get(key);
-            if (child != null) {
-              StreamPayload payload = childPayload.payload;
-              if (child.getType() == Type.UNBOUND) {
-                if (payload.hasStreamFeature()) {
-                  child.bindFeature(
-                      new UpdatableModelFeature(payload.getStreamFeature(), cursorProvider));
-                } else if (payload.hasStreamToken()) {
-                  child.bindToken(new UpdatableModelToken(payload.getStreamToken(), false));
-                  continue;
-                } else {
-                  Logger.e(TAG, "Unsupported Payload Type");
-                }
-                child.updateFeature(childPayload.payload);
-              } else {
-                child.updateFeature(payload);
-              }
-            }
-          }
-          // TODO: log an error if any children are still left unbounded.
-          timeTracker.stop("", "bindingChildren", "childrenToBind", childrenToBind.size());
-          consumer.accept(Result.success(null));
-        });
+          child.updateFeature(childPayload.payload);
+        } else {
+          child.updateFeature(payload);
+        }
+      }
+    }
+    // TODO: log an error if any children are still left unbounded.
+    timeTracker.stop("", "bindingChildren", "childrenToBind", childrenToBind.size());
+    return true;
   }
 }
diff --git a/src/main/java/com/google/android/libraries/feed/feedsessionmanager/FeedSessionManagerImpl.java b/src/main/java/com/google/android/libraries/feed/feedsessionmanager/FeedSessionManagerImpl.java
index e361f52..6e9cf4c 100644
--- a/src/main/java/com/google/android/libraries/feed/feedsessionmanager/FeedSessionManagerImpl.java
+++ b/src/main/java/com/google/android/libraries/feed/feedsessionmanager/FeedSessionManagerImpl.java
@@ -619,8 +619,7 @@
   }
 
   @Override
-  public void getStreamFeatures(
-      List<String> contentIds, Consumer<Result<List<PayloadWithId>>> consumer) {
+  public Result<List<PayloadWithId>> getStreamFeatures(List<String> contentIds) {
     threadUtils.checkNotMainThread();
     List<PayloadWithId> results = new ArrayList<>();
     List<String> cacheMisses = new ArrayList<>();
@@ -641,7 +640,7 @@
       } else {
         // since we couldn't populate the content, switch to ephemeral mode
         switchToEphemeralMode("Unable to get the payloads in getStreamFeatures");
-        consumer.accept(Result.failure());
+        return Result.failure();
       }
     }
     Logger.i(
@@ -650,7 +649,7 @@
         contentIds.size(),
         cacheMisses.size(),
         contentSize);
-    consumer.accept(Result.success(results));
+    return Result.success(results);
   }
 
   @Override
diff --git a/src/test/java/com/google/android/libraries/feed/feedmodelprovider/BUILD b/src/test/java/com/google/android/libraries/feed/feedmodelprovider/BUILD
index 2b29cf3..9dad351 100644
--- a/src/test/java/com/google/android/libraries/feed/feedmodelprovider/BUILD
+++ b/src/test/java/com/google/android/libraries/feed/feedmodelprovider/BUILD
@@ -43,7 +43,6 @@
         "//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/concurrent/testing",
-        "//src/main/java/com/google/android/libraries/feed/common/functional",
         "//src/main/java/com/google/android/libraries/feed/common/time",
         "//src/main/java/com/google/android/libraries/feed/feedmodelprovider",
         "//src/main/java/com/google/android/libraries/feed/feedmodelprovider/internal",
diff --git a/src/test/java/com/google/android/libraries/feed/feedmodelprovider/FeedModelProviderTest.java b/src/test/java/com/google/android/libraries/feed/feedmodelprovider/FeedModelProviderTest.java
index 8638d4b..f1ceacd 100644
--- a/src/test/java/com/google/android/libraries/feed/feedmodelprovider/FeedModelProviderTest.java
+++ b/src/test/java/com/google/android/libraries/feed/feedmodelprovider/FeedModelProviderTest.java
@@ -49,7 +49,6 @@
 import com.google.android.libraries.feed.common.Result;
 import com.google.android.libraries.feed.common.concurrent.TaskQueue;
 import com.google.android.libraries.feed.common.concurrent.testing.FakeMainThreadRunner;
-import com.google.android.libraries.feed.common.functional.Consumer;
 import com.google.android.libraries.feed.common.time.TimingUtils;
 import com.google.android.libraries.feed.feedmodelprovider.FeedModelProvider.InitializeModel;
 import com.google.android.libraries.feed.feedmodelprovider.FeedModelProvider.TokenMutation;
@@ -100,16 +99,7 @@
   public void setUp() {
     initMocks(this);
     childBindings.clear();
-    doAnswer(
-            invocation -> {
-              @SuppressWarnings("unchecked")
-              Consumer<Result<List<PayloadWithId>>> consumer =
-                  (Consumer<Result<List<PayloadWithId>>>) invocation.getArguments()[1];
-              consumer.accept(Result.success(childBindings));
-              return null;
-            })
-        .when(feedSessionManager)
-        .getStreamFeatures(any(), any());
+    when(feedSessionManager.getStreamFeatures(any())).thenReturn(Result.success(childBindings));
     fakeMainThreadRunner = FakeMainThreadRunner.runTasksImmediately();
   }