diff --git a/core/java/com/android/internal/infra/AndroidFuture.java b/core/java/com/android/internal/infra/AndroidFuture.java index d78bd73b080b3..b250578c8454f 100644 --- a/core/java/com/android/internal/infra/AndroidFuture.java +++ b/core/java/com/android/internal/infra/AndroidFuture.java @@ -531,6 +531,12 @@ public class AndroidFuture extends CompletableFuture implements Parcelable try { AndroidFuture.this.complete((T) resultContainer.get()); } catch (Throwable t) { + // If resultContainer was completed exceptionally, get() wraps the + // underlying exception in an ExecutionException. Unwrap it now to avoid + // double-layering ExecutionExceptions. + if (t instanceof ExecutionException && t.getCause() != null) { + t = t.getCause(); + } completeExceptionally(t); } } 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 9002c2c6b184b..ffc925ff82cd7 100644 --- a/core/tests/coretests/src/com/android/internal/infra/AndroidFutureTest.java +++ b/core/tests/coretests/src/com/android/internal/infra/AndroidFutureTest.java @@ -111,7 +111,7 @@ public class AndroidFutureTest { } @Test - public void testWriteToParcel_Exceptionally() throws Exception { + public void testWriteToParcel_Exception() throws Exception { Parcel parcel = Parcel.obtain(); AndroidFuture future1 = new AndroidFuture<>(); future1.completeExceptionally(new UnsupportedOperationException()); @@ -123,4 +123,30 @@ public class AndroidFutureTest { expectThrows(ExecutionException.class, future2::get); assertThat(executionException.getCause()).isInstanceOf(UnsupportedOperationException.class); } + + @Test + public void testWriteToParcel_Incomplete() throws Exception { + Parcel parcel = Parcel.obtain(); + AndroidFuture future1 = new AndroidFuture<>(); + future1.writeToParcel(parcel, 0); + + parcel.setDataPosition(0); + AndroidFuture future2 = AndroidFuture.CREATOR.createFromParcel(parcel); + future2.complete(5); + assertThat(future1.get()).isEqualTo(5); + } + + @Test + public void testWriteToParcel_Incomplete_Exception() throws Exception { + Parcel parcel = Parcel.obtain(); + AndroidFuture future1 = new AndroidFuture<>(); + future1.writeToParcel(parcel, 0); + + parcel.setDataPosition(0); + AndroidFuture future2 = AndroidFuture.CREATOR.createFromParcel(parcel); + future2.completeExceptionally(new UnsupportedOperationException()); + ExecutionException executionException = + expectThrows(ExecutionException.class, future1::get); + assertThat(executionException.getCause()).isInstanceOf(UnsupportedOperationException.class); + } }