diff --git a/core/java/com/android/internal/infra/AndroidFuture.java b/core/java/com/android/internal/infra/AndroidFuture.java index 0443ad03b6ea5..0835824f6b39b 100644 --- a/core/java/com/android/internal/infra/AndroidFuture.java +++ b/core/java/com/android/internal/infra/AndroidFuture.java @@ -455,7 +455,14 @@ public class AndroidFuture extends CompletableFuture implements Parcelable if (mSourceU != null) { // T done mResultT = (T) res; - mSourceU.whenComplete(this); + + // Subscribe to the second job completion. + mSourceU.whenComplete((r, e) -> { + // Mark the first job completion by setting mSourceU to null, so that next time + // the execution flow goes to the else case below. + mSourceU = null; + accept(r, e); + }); } else { // U done try { diff --git a/core/tests/coretests/src/com/android/internal/infra/AndroidFutureTest.java b/core/tests/coretests/src/com/android/internal/infra/AndroidFutureTest.java index a2bc77a71c909..3a272256e60e3 100644 --- a/core/tests/coretests/src/com/android/internal/infra/AndroidFutureTest.java +++ b/core/tests/coretests/src/com/android/internal/infra/AndroidFutureTest.java @@ -29,6 +29,7 @@ import org.junit.runner.RunWith; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; +import java.util.function.BiFunction; /** * Unit test for {@link AndroidFuture}. @@ -154,4 +155,35 @@ public class AndroidFutureTest { expectThrows(ExecutionException.class, future1::get); assertThat(executionException.getCause()).isInstanceOf(UnsupportedOperationException.class); } + + @Test + public void testThenCombine() throws Exception { + String nearFutureString = "near future comes"; + AndroidFuture nearFuture = AndroidFuture.supply(() -> nearFutureString); + String farFutureString = " before far future."; + AndroidFuture farFuture = AndroidFuture.supply(() -> farFutureString); + AndroidFuture combinedFuture = + nearFuture.thenCombine(farFuture, ((s1, s2) -> s1 + s2)); + + assertThat(combinedFuture.get()).isEqualTo(nearFutureString + farFutureString); + } + + @Test + public void testThenCombine_functionThrowingException() throws Exception { + String nearFutureString = "near future comes"; + AndroidFuture nearFuture = AndroidFuture.supply(() -> nearFutureString); + String farFutureString = " before far future."; + AndroidFuture farFuture = AndroidFuture.supply(() -> farFutureString); + UnsupportedOperationException exception = new UnsupportedOperationException( + "Unsupported operation exception thrown!"); + BiFunction throwingFunction = (s1, s2) -> { + throw exception; + }; + AndroidFuture combinedFuture = nearFuture.thenCombine(farFuture, throwingFunction); + + ExecutionException thrown = expectThrows(ExecutionException.class, + () -> combinedFuture.get()); + + assertThat(thrown.getCause()).isSameInstanceAs(exception); + } }