From 0c1f2a1189fc5cb268be028275b2d889a0daf493 Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Tue, 31 Aug 2021 15:15:33 -0700 Subject: [PATCH] Propagate exceptions in RemoteInputConnectionImpl Previously there were cases where we failed to invoke callback used to implement sync APIs in InputConnection if app's InputConnection failed due to exceptions, while the IME was still waiting for the callback. Although such an exception usually triggers an app crash, which eventually triggers IInputMethodWrapper#unbindInput() to unblock IME's waiting operation [1], there is no reason to not propagate the failure through the callback object itself to minimize the blocking time. This CL just makes it happen. Note that there is no observable behavior change in the IME client app. What this CL does is just completing the callback request before letting an exception go, which will never change the fate of the IME client process. [1]: Ic65a95eb5d0fd56f505a02fd9083bcf6694b6734 f87f75088899d0f7513132e0f397b0edbf373d71 Fix: 195699814 Test: atest CtsInputMethodTestCases:InputConnectionHandlerTest Change-Id: I5b88333cfad3cbafe311c6262fa00eff893cd8f1 --- .../inputmethod/RemoteInputConnectionImpl.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java index 74211fb974df2..fc299febef3ed 100644 --- a/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java +++ b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java @@ -752,6 +752,15 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub { private void dispatch(@NonNull AndroidFuture untypedFuture, @NonNull Supplier supplier) { @SuppressWarnings("unchecked") final AndroidFuture future = untypedFuture; - dispatch(() -> future.complete(supplier.get())); + dispatch(() -> { + final T result; + try { + result = supplier.get(); + } catch (Throwable throwable) { + future.completeExceptionally(throwable); + throw throwable; + } + future.complete(result); + }); } }