From b2d09de1f9131c0e87356441a46db709eb27a828 Mon Sep 17 00:00:00 2001 From: Yohei Yukawa Date: Sun, 29 Aug 2021 13:30:03 -0700 Subject: [PATCH] Use AndroidFuture instead This CL replaces our inhouse utility classes in favor of an existing alternative AndroidFuture, which allows us to remove 8 files in total. Several downsides are: * We lose compile-time type checking in the remote end, because AIDL does not support generics. * AndroidFuture does not support any raw Binder interfaces. For instance, AndroidFuture would crash due to java.lang.ClassCastException at run time. You must use IBinder instead and manually create a stub object in the receiver side. * Data transfer would be a bit slower for primitive types and much more slower for Parcelable types, because AndroidFuture internally uses Parcel.{read,write}Value(), which is known to be around 4x slower than Parcel.{read,write}TypedObject() for Parcelable objects [1][2]. * When you find an AndroidFuture on a code, you have to figure out whether the code is running on the source side or remote side. If you are on the source side, what you see on that object is an aggregation of the computations on both the source and remote ends, which is probably easy to understand. If you are on the remote side, however, you will never observe any computation result in the source side. What you can observe in the remote side remains to be your local data that is specific to your remote process. Other than above, there should be no observable semantic change in this CL. [1]: https://developer.android.com/reference/android/os/Parcel [2]: I29548ce6c2e5886f0e90a5dc70d8e9ecc0fb25a8 b293d933e0297dc9a5b8b0c7f8ca939bd8f53267 Bug: 192412909 Bug: 195699814 Test: presubmit Change-Id: I74657826a99b11ca1f86932f8f41cca6e449cc8a --- .../internal/inputmethod/CallbackUtils.java | 140 --------- .../inputmethod/IBooleanResultCallback.aidl | 24 -- .../ICharSequenceResultCallback.aidl | 21 -- .../IExtractedTextResultCallback.aidl | 23 -- .../IInputContentUriTokenResultCallback.aidl | 25 -- .../inputmethod/IInputContextInvoker.java | 103 ++++--- .../IInputMethodPrivilegedOperations.aidl | 21 +- .../ISurroundingTextResultCallback.aidl | 23 -- .../inputmethod/IVoidResultCallback.aidl | 24 -- .../InputMethodPrivilegedOperations.java | 62 ++-- .../RemoteInputConnectionImpl.java | 92 +++--- .../internal/inputmethod/ResultCallbacks.java | 275 ------------------ .../android/internal/view/IInputContext.aidl | 36 +-- .../InputMethodManagerService.java | 95 ++++-- 14 files changed, 210 insertions(+), 754 deletions(-) delete mode 100644 core/java/com/android/internal/inputmethod/CallbackUtils.java delete mode 100644 core/java/com/android/internal/inputmethod/IBooleanResultCallback.aidl delete mode 100644 core/java/com/android/internal/inputmethod/ICharSequenceResultCallback.aidl delete mode 100644 core/java/com/android/internal/inputmethod/IExtractedTextResultCallback.aidl delete mode 100644 core/java/com/android/internal/inputmethod/IInputContentUriTokenResultCallback.aidl delete mode 100644 core/java/com/android/internal/inputmethod/ISurroundingTextResultCallback.aidl delete mode 100644 core/java/com/android/internal/inputmethod/IVoidResultCallback.aidl delete mode 100644 core/java/com/android/internal/inputmethod/ResultCallbacks.java diff --git a/core/java/com/android/internal/inputmethod/CallbackUtils.java b/core/java/com/android/internal/inputmethod/CallbackUtils.java deleted file mode 100644 index aca761de54d46..0000000000000 --- a/core/java/com/android/internal/inputmethod/CallbackUtils.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * 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.android.internal.inputmethod; - -import android.annotation.NonNull; -import android.os.RemoteException; - -import java.util.function.BooleanSupplier; -import java.util.function.IntSupplier; -import java.util.function.Supplier; - -/** - * Defines a set of helper methods to callback corresponding results in {@link ResultCallbacks}. - */ -public final class CallbackUtils { - - /** - * Not intended to be instantiated. - */ - private CallbackUtils() { - } - - /** - * A utility method using given {@link IBooleanResultCallback} to callback the result. - * - * @param callback {@link IBooleanResultCallback} to be called back. - * @param resultSupplier the supplier from which the result is provided. - */ - public static void onResult(@NonNull IBooleanResultCallback callback, - @NonNull BooleanSupplier resultSupplier) { - boolean result = false; - Throwable exception = null; - - try { - result = resultSupplier.getAsBoolean(); - } catch (Throwable throwable) { - exception = throwable; - } - - try { - if (exception != null) { - callback.onError(ThrowableHolder.of(exception)); - return; - } - callback.onResult(result); - } catch (RemoteException ignored) { } - } - - /** - * A utility method using given {@link IIntResultCallback} to callback the result. - * - * @param callback {@link IIntResultCallback} to be called back. - * @param resultSupplier the supplier from which the result is provided. - */ - public static void onResult(@NonNull IIntResultCallback callback, - @NonNull IntSupplier resultSupplier) { - int result = 0; - Throwable exception = null; - - try { - result = resultSupplier.getAsInt(); - } catch (Throwable throwable) { - exception = throwable; - } - - try { - if (exception != null) { - callback.onError(ThrowableHolder.of(exception)); - return; - } - callback.onResult(result); - } catch (RemoteException ignored) { } - } - - /** - * A utility method using given {@link IVoidResultCallback} to callback the result. - * - * @param callback {@link IVoidResultCallback} to be called back. - * @param runnable to execute the given method - */ - public static void onResult(@NonNull IVoidResultCallback callback, - @NonNull Runnable runnable) { - Throwable exception = null; - - try { - runnable.run(); - } catch (Throwable throwable) { - exception = throwable; - } - - try { - if (exception != null) { - callback.onError(ThrowableHolder.of(exception)); - return; - } - callback.onResult(); - } catch (RemoteException ignored) { } - } - - /** - * A utility method using given {@link IInputContentUriTokenResultCallback} to callback the - * result. - * - * @param callback {@link IInputContentUriTokenResultCallback} to be called back. - * @param resultSupplier the supplier from which the result is provided. - */ - public static void onResult(@NonNull IInputContentUriTokenResultCallback callback, - @NonNull Supplier resultSupplier) { - IInputContentUriToken result = null; - Throwable exception = null; - - try { - result = resultSupplier.get(); - } catch (Throwable throwable) { - exception = throwable; - } - - try { - if (exception != null) { - callback.onError(ThrowableHolder.of(exception)); - return; - } - callback.onResult(result); - } catch (RemoteException ignored) { } - } -} diff --git a/core/java/com/android/internal/inputmethod/IBooleanResultCallback.aidl b/core/java/com/android/internal/inputmethod/IBooleanResultCallback.aidl deleted file mode 100644 index 6daeb3f27414a..0000000000000 --- a/core/java/com/android/internal/inputmethod/IBooleanResultCallback.aidl +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * 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.android.internal.inputmethod; - -import com.android.internal.inputmethod.ThrowableHolder; - -oneway interface IBooleanResultCallback { - void onResult(boolean result); - void onError(in ThrowableHolder exception); -} \ No newline at end of file diff --git a/core/java/com/android/internal/inputmethod/ICharSequenceResultCallback.aidl b/core/java/com/android/internal/inputmethod/ICharSequenceResultCallback.aidl deleted file mode 100644 index da56fd045e57d..0000000000000 --- a/core/java/com/android/internal/inputmethod/ICharSequenceResultCallback.aidl +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * 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.android.internal.inputmethod; - -oneway interface ICharSequenceResultCallback { - void onResult(in CharSequence result); -} diff --git a/core/java/com/android/internal/inputmethod/IExtractedTextResultCallback.aidl b/core/java/com/android/internal/inputmethod/IExtractedTextResultCallback.aidl deleted file mode 100644 index b603f6adc2d27..0000000000000 --- a/core/java/com/android/internal/inputmethod/IExtractedTextResultCallback.aidl +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * 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.android.internal.inputmethod; - -import android.view.inputmethod.ExtractedText; - -oneway interface IExtractedTextResultCallback { - void onResult(in ExtractedText result); -} diff --git a/core/java/com/android/internal/inputmethod/IInputContentUriTokenResultCallback.aidl b/core/java/com/android/internal/inputmethod/IInputContentUriTokenResultCallback.aidl deleted file mode 100644 index 779acb5a57b40..0000000000000 --- a/core/java/com/android/internal/inputmethod/IInputContentUriTokenResultCallback.aidl +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * 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.android.internal.inputmethod; - -import com.android.internal.inputmethod.IInputContentUriToken; -import com.android.internal.inputmethod.ThrowableHolder; - -oneway interface IInputContentUriTokenResultCallback { - void onResult(in IInputContentUriToken result); - void onError(in ThrowableHolder exception); -} \ No newline at end of file diff --git a/core/java/com/android/internal/inputmethod/IInputContextInvoker.java b/core/java/com/android/internal/inputmethod/IInputContextInvoker.java index 783d54d077b6a..0cbdc132e66fb 100644 --- a/core/java/com/android/internal/inputmethod/IInputContextInvoker.java +++ b/core/java/com/android/internal/inputmethod/IInputContextInvoker.java @@ -28,14 +28,14 @@ import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputContentInfo; import android.view.inputmethod.SurroundingText; +import com.android.internal.infra.AndroidFuture; import com.android.internal.view.IInputContext; import java.util.Objects; -import java.util.concurrent.CompletableFuture; /** * A stateless wrapper of {@link com.android.internal.view.IInputContext} to encapsulate boilerplate - * code around {@link CompletableFuture} and {@link RemoteException}. + * code around {@link AndroidFuture} and {@link RemoteException}. */ public final class IInputContextInvoker { @@ -63,19 +63,19 @@ public final class IInputContextInvoker { * * @param length {@code length} parameter to be passed. * @param flags {@code flags} parameter to be passed. - * @return {@link CompletableFuture} that can be used to retrieve the invocation + * @return {@link AndroidFuture} that can be used to retrieve the invocation * result. {@link RemoteException} will be treated as an error. */ @AnyThread @NonNull - public CompletableFuture getTextAfterCursor(int length, int flags) { - final CompletableFuture value = new CompletableFuture<>(); + public AndroidFuture getTextAfterCursor(int length, int flags) { + final AndroidFuture future = new AndroidFuture<>(); try { - mIInputContext.getTextAfterCursor(length, flags, ResultCallbacks.ofCharSequence(value)); + mIInputContext.getTextAfterCursor(length, flags, future); } catch (RemoteException e) { - value.completeExceptionally(e); + future.completeExceptionally(e); } - return value; + return future; } /** @@ -83,39 +83,38 @@ public final class IInputContextInvoker { * * @param length {@code length} parameter to be passed. * @param flags {@code flags} parameter to be passed. - * @return {@link CompletableFuture} that can be used to retrieve the invocation + * @return {@link AndroidFuture} that can be used to retrieve the invocation * result. {@link RemoteException} will be treated as an error. */ @AnyThread @NonNull - public CompletableFuture getTextBeforeCursor(int length, int flags) { - final CompletableFuture value = new CompletableFuture<>(); + public AndroidFuture getTextBeforeCursor(int length, int flags) { + final AndroidFuture future = new AndroidFuture<>(); try { - mIInputContext.getTextBeforeCursor(length, flags, - ResultCallbacks.ofCharSequence(value)); + mIInputContext.getTextBeforeCursor(length, flags, future); } catch (RemoteException e) { - value.completeExceptionally(e); + future.completeExceptionally(e); } - return value; + return future; } /** * Invokes {@link IInputContext#getSelectedText(int, ICharSequenceResultCallback)}. * * @param flags {@code flags} parameter to be passed. - * @return {@link CompletableFuture} that can be used to retrieve the invocation + * @return {@link AndroidFuture} that can be used to retrieve the invocation * result. {@link RemoteException} will be treated as an error. */ @AnyThread @NonNull - public CompletableFuture getSelectedText(int flags) { - final CompletableFuture value = new CompletableFuture<>(); + public AndroidFuture getSelectedText(int flags) { + final AndroidFuture future = new AndroidFuture<>(); try { - mIInputContext.getSelectedText(flags, ResultCallbacks.ofCharSequence(value)); + mIInputContext.getSelectedText(flags, future); } catch (RemoteException e) { - value.completeExceptionally(e); + future.completeExceptionally(e); } - return value; + return future; } /** @@ -125,40 +124,39 @@ public final class IInputContextInvoker { * @param beforeLength {@code beforeLength} parameter to be passed. * @param afterLength {@code afterLength} parameter to be passed. * @param flags {@code flags} parameter to be passed. - * @return {@link CompletableFuture} that can be used to retrieve the + * @return {@link AndroidFuture} that can be used to retrieve the * invocation result. {@link RemoteException} will be treated as an error. */ @AnyThread @NonNull - public CompletableFuture getSurroundingText(int beforeLength, int afterLength, + public AndroidFuture getSurroundingText(int beforeLength, int afterLength, int flags) { - final CompletableFuture value = new CompletableFuture<>(); + final AndroidFuture future = new AndroidFuture<>(); try { - mIInputContext.getSurroundingText(beforeLength, afterLength, flags, - ResultCallbacks.ofSurroundingText(value)); + mIInputContext.getSurroundingText(beforeLength, afterLength, flags, future); } catch (RemoteException e) { - value.completeExceptionally(e); + future.completeExceptionally(e); } - return value; + return future; } /** * Invokes {@link IInputContext#getCursorCapsMode(int, IIntResultCallback)}. * * @param reqModes {@code reqModes} parameter to be passed. - * @return {@link CompletableFuture} that can be used to retrieve the invocation + * @return {@link AndroidFuture} that can be used to retrieve the invocation * result. {@link RemoteException} will be treated as an error. */ @AnyThread @NonNull - public CompletableFuture getCursorCapsMode(int reqModes) { - final CompletableFuture value = new CompletableFuture<>(); + public AndroidFuture getCursorCapsMode(int reqModes) { + final AndroidFuture future = new AndroidFuture<>(); try { - mIInputContext.getCursorCapsMode(reqModes, ResultCallbacks.ofInteger(value)); + mIInputContext.getCursorCapsMode(reqModes, future); } catch (RemoteException e) { - value.completeExceptionally(e); + future.completeExceptionally(e); } - return value; + return future; } /** @@ -167,20 +165,20 @@ public final class IInputContextInvoker { * * @param request {@code request} parameter to be passed. * @param flags {@code flags} parameter to be passed. - * @return {@link CompletableFuture} that can be used to retrieve the invocation + * @return {@link AndroidFuture} that can be used to retrieve the invocation * result. {@link RemoteException} will be treated as an error. */ @AnyThread @NonNull - public CompletableFuture getExtractedText(ExtractedTextRequest request, + public AndroidFuture getExtractedText(ExtractedTextRequest request, int flags) { - final CompletableFuture value = new CompletableFuture<>(); + final AndroidFuture future = new AndroidFuture<>(); try { - mIInputContext.getExtractedText(request, flags, ResultCallbacks.ofExtractedText(value)); + mIInputContext.getExtractedText(request, flags, future); } catch (RemoteException e) { - value.completeExceptionally(e); + future.completeExceptionally(e); } - return value; + return future; } /** @@ -479,19 +477,19 @@ public final class IInputContextInvoker { * Invokes {@link IInputContext#requestCursorUpdates(int, IIntResultCallback)}. * * @param cursorUpdateMode {@code cursorUpdateMode} parameter to be passed. - * @return {@link CompletableFuture} that can be used to retrieve the invocation + * @return {@link AndroidFuture} that can be used to retrieve the invocation * result. {@link RemoteException} will be treated as an error. */ @AnyThread @NonNull - public CompletableFuture requestCursorUpdates(int cursorUpdateMode) { - final CompletableFuture value = new CompletableFuture<>(); + public AndroidFuture requestCursorUpdates(int cursorUpdateMode) { + final AndroidFuture future = new AndroidFuture<>(); try { - mIInputContext.requestCursorUpdates(cursorUpdateMode, ResultCallbacks.ofBoolean(value)); + mIInputContext.requestCursorUpdates(cursorUpdateMode, future); } catch (RemoteException e) { - value.completeExceptionally(e); + future.completeExceptionally(e); } - return value; + return future; } /** @@ -501,21 +499,20 @@ public final class IInputContextInvoker { * @param inputContentInfo {@code inputContentInfo} parameter to be passed. * @param flags {@code flags} parameter to be passed. * @param opts {@code opts} parameter to be passed. - * @return {@link CompletableFuture} that can be used to retrieve the invocation + * @return {@link AndroidFuture} that can be used to retrieve the invocation * result. {@link RemoteException} will be treated as an error. */ @AnyThread @NonNull - public CompletableFuture commitContent(InputContentInfo inputContentInfo, int flags, + public AndroidFuture commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) { - final CompletableFuture value = new CompletableFuture<>(); + final AndroidFuture future = new AndroidFuture<>(); try { - mIInputContext.commitContent(inputContentInfo, flags, opts, - ResultCallbacks.ofBoolean(value)); + mIInputContext.commitContent(inputContentInfo, flags, opts, future); } catch (RemoteException e) { - value.completeExceptionally(e); + future.completeExceptionally(e); } - return value; + return future; } /** diff --git a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl index 36943e3bd5917..9d0f209d8b2dd 100644 --- a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl +++ b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl @@ -19,10 +19,7 @@ package com.android.internal.inputmethod; import android.net.Uri; import android.view.inputmethod.InputMethodSubtype; -import com.android.internal.inputmethod.IBooleanResultCallback; -import com.android.internal.inputmethod.IInputContentUriToken; -import com.android.internal.inputmethod.IInputContentUriTokenResultCallback; -import com.android.internal.inputmethod.IVoidResultCallback; +import com.android.internal.infra.AndroidFuture; /** * Defines priviledged operations that only the current IME is allowed to call. @@ -32,17 +29,17 @@ oneway interface IInputMethodPrivilegedOperations { void setImeWindowStatusAsync(int vis, int backDisposition); void reportStartInputAsync(in IBinder startInputToken); void createInputContentUriToken(in Uri contentUri, in String packageName, - in IInputContentUriTokenResultCallback resultCallback); + in AndroidFuture future /* T=IBinder */); void reportFullscreenModeAsync(boolean fullscreen); - void setInputMethod(String id, in IVoidResultCallback resultCallback); + void setInputMethod(String id, in AndroidFuture future /* T=Void */); void setInputMethodAndSubtype(String id, in InputMethodSubtype subtype, - in IVoidResultCallback resultCallback); - void hideMySoftInput(int flags, in IVoidResultCallback resultCallback); - void showMySoftInput(int flags, in IVoidResultCallback resultCallback); + in AndroidFuture future /* T=Void */); + void hideMySoftInput(int flags, in AndroidFuture future /* T=Void */); + void showMySoftInput(int flags, in AndroidFuture future /* T=Void */); void updateStatusIconAsync(String packageName, int iconId); - void switchToPreviousInputMethod(in IBooleanResultCallback resultCallback); - void switchToNextInputMethod(boolean onlyCurrentIme, in IBooleanResultCallback resultCallback); - void shouldOfferSwitchingToNextInputMethod(in IBooleanResultCallback resultCallback); + void switchToPreviousInputMethod(in AndroidFuture future /* T=Boolean */); + void switchToNextInputMethod(boolean onlyCurrentIme, in AndroidFuture future /* T=Boolean */); + void shouldOfferSwitchingToNextInputMethod(in AndroidFuture future /* T=Boolean */); void notifyUserActionAsync(); void applyImeVisibilityAsync(IBinder showOrHideInputToken, boolean setVisible); } diff --git a/core/java/com/android/internal/inputmethod/ISurroundingTextResultCallback.aidl b/core/java/com/android/internal/inputmethod/ISurroundingTextResultCallback.aidl deleted file mode 100644 index 6c4f3d58ed028..0000000000000 --- a/core/java/com/android/internal/inputmethod/ISurroundingTextResultCallback.aidl +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * 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.android.internal.inputmethod; - -import android.view.inputmethod.SurroundingText; - -oneway interface ISurroundingTextResultCallback { - void onResult(in SurroundingText result); -} \ No newline at end of file diff --git a/core/java/com/android/internal/inputmethod/IVoidResultCallback.aidl b/core/java/com/android/internal/inputmethod/IVoidResultCallback.aidl deleted file mode 100644 index 0b25a2b886c9a..0000000000000 --- a/core/java/com/android/internal/inputmethod/IVoidResultCallback.aidl +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * 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.android.internal.inputmethod; - -import com.android.internal.inputmethod.ThrowableHolder; - -oneway interface IVoidResultCallback { - void onResult(); - void onError(in ThrowableHolder exception); -} \ No newline at end of file diff --git a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java index c0785abdc7fb6..d4cc376385b88 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java +++ b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java @@ -28,9 +28,9 @@ import android.view.View; import android.view.inputmethod.InputMethodSubtype; import com.android.internal.annotations.GuardedBy; +import com.android.internal.infra.AndroidFuture; import java.util.Objects; -import java.util.concurrent.CompletableFuture; /** * A utility class to take care of boilerplate code around IPCs. @@ -143,7 +143,7 @@ public final class InputMethodPrivilegedOperations { /** * Calls {@link IInputMethodPrivilegedOperations#createInputContentUriToken(Uri, String, - * IInputContentUriTokenResultCallback)}. + * AndroidFuture)}. * * @param contentUri Content URI to which a temporary read permission should be granted * @param packageName Indicates what package needs to have a temporary read permission @@ -157,10 +157,9 @@ public final class InputMethodPrivilegedOperations { return null; } try { - final CompletableFuture value = new CompletableFuture<>(); - ops.createInputContentUriToken(contentUri, packageName, - ResultCallbacks.ofIInputContentUriToken(value)); - return CompletableFutureUtil.getResult(value); + final AndroidFuture future = new AndroidFuture<>(); + ops.createInputContentUriToken(contentUri, packageName, future); + return IInputContentUriToken.Stub.asInterface(CompletableFutureUtil.getResult(future)); } catch (RemoteException e) { // For historical reasons, this error was silently ignored. // Note that the caller already logs error so we do not need additional Log.e() here. @@ -207,7 +206,7 @@ public final class InputMethodPrivilegedOperations { } /** - * Calls {@link IInputMethodPrivilegedOperations#setInputMethod(String, IVoidResultCallback)}. + * Calls {@link IInputMethodPrivilegedOperations#setInputMethod(String, AndroidFuture)}. * * @param id IME ID of the IME to switch to * @see android.view.inputmethod.InputMethodInfo#getId() @@ -219,9 +218,9 @@ public final class InputMethodPrivilegedOperations { return; } try { - final CompletableFuture value = new CompletableFuture<>(); - ops.setInputMethod(id, ResultCallbacks.ofVoid(value)); - CompletableFutureUtil.getResult(value); + final AndroidFuture future = new AndroidFuture<>(); + ops.setInputMethod(id, future); + CompletableFutureUtil.getResult(future); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -229,7 +228,7 @@ public final class InputMethodPrivilegedOperations { /** * Calls {@link IInputMethodPrivilegedOperations#setInputMethodAndSubtype(String, - * InputMethodSubtype, IVoidResultCallback)} + * InputMethodSubtype, AndroidFuture)} * * @param id IME ID of the IME to switch to * @param subtype {@link InputMethodSubtype} to switch to @@ -242,9 +241,9 @@ public final class InputMethodPrivilegedOperations { return; } try { - final CompletableFuture value = new CompletableFuture<>(); - ops.setInputMethodAndSubtype(id, subtype, ResultCallbacks.ofVoid(value)); - CompletableFutureUtil.getResult(value); + final AndroidFuture future = new AndroidFuture<>(); + ops.setInputMethodAndSubtype(id, subtype, future); + CompletableFutureUtil.getResult(future); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -264,16 +263,16 @@ public final class InputMethodPrivilegedOperations { return; } try { - final CompletableFuture value = new CompletableFuture<>(); - ops.hideMySoftInput(flags, ResultCallbacks.ofVoid(value)); - CompletableFutureUtil.getResult(value); + final AndroidFuture future = new AndroidFuture<>(); + ops.hideMySoftInput(flags, future); + CompletableFutureUtil.getResult(future); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** - * Calls {@link IInputMethodPrivilegedOperations#showMySoftInput(int, IVoidResultCallback)} + * Calls {@link IInputMethodPrivilegedOperations#showMySoftInput(int, AndroidFuture)} * * @param flags additional operating flags * @see android.view.inputmethod.InputMethodManager#SHOW_IMPLICIT @@ -286,17 +285,16 @@ public final class InputMethodPrivilegedOperations { return; } try { - final CompletableFuture value = new CompletableFuture<>(); - ops.showMySoftInput(flags, ResultCallbacks.ofVoid(value)); - CompletableFutureUtil.getResult(value); + final AndroidFuture future = new AndroidFuture<>(); + ops.showMySoftInput(flags, future); + CompletableFutureUtil.getResult(future); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** - * Calls {@link IInputMethodPrivilegedOperations#switchToPreviousInputMethod( - * IBooleanResultCallback)} + * Calls {@link IInputMethodPrivilegedOperations#switchToPreviousInputMethod(AndroidFuture)} * * @return {@code true} if handled */ @@ -307,8 +305,8 @@ public final class InputMethodPrivilegedOperations { return false; } try { - final CompletableFuture value = new CompletableFuture<>(); - ops.switchToPreviousInputMethod(ResultCallbacks.ofBoolean(value)); + final AndroidFuture value = new AndroidFuture<>(); + ops.switchToPreviousInputMethod(value); return CompletableFutureUtil.getResult(value); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -330,9 +328,9 @@ public final class InputMethodPrivilegedOperations { return false; } try { - final CompletableFuture value = new CompletableFuture<>(); - ops.switchToNextInputMethod(onlyCurrentIme, ResultCallbacks.ofBoolean(value)); - return CompletableFutureUtil.getResult(value); + final AndroidFuture future = new AndroidFuture<>(); + ops.switchToNextInputMethod(onlyCurrentIme, future); + return CompletableFutureUtil.getResult(future); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -340,7 +338,7 @@ public final class InputMethodPrivilegedOperations { /** * Calls {@link IInputMethodPrivilegedOperations#shouldOfferSwitchingToNextInputMethod( - * IBooleanResultCallback)} + * AndroidFuture)} * * @return {@code true} if the IEM should offer a way to globally switch IME */ @@ -351,9 +349,9 @@ public final class InputMethodPrivilegedOperations { return false; } try { - final CompletableFuture value = new CompletableFuture<>(); - ops.shouldOfferSwitchingToNextInputMethod(ResultCallbacks.ofBoolean(value)); - return CompletableFutureUtil.getResult(value); + final AndroidFuture future = new AndroidFuture<>(); + ops.shouldOfferSwitchingToNextInputMethod(future); + return CompletableFutureUtil.getResult(future); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java index 0c2701219ef45..2d0b3f9e50256 100644 --- a/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java +++ b/core/java/com/android/internal/inputmethod/RemoteInputConnectionImpl.java @@ -21,7 +21,6 @@ import android.annotation.Nullable; import android.os.Bundle; import android.os.Handler; import android.os.Looper; -import android.os.RemoteException; import android.os.Trace; import android.util.Log; import android.util.proto.ProtoOutputStream; @@ -40,6 +39,7 @@ import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.SurroundingText; import com.android.internal.annotations.GuardedBy; +import com.android.internal.infra.AndroidFuture; import com.android.internal.view.IInputContext; import java.lang.ref.WeakReference; @@ -220,7 +220,10 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub { } @Override - public void getTextAfterCursor(int length, int flags, ICharSequenceResultCallback callback) { + public void getTextAfterCursor(int length, int flags, + AndroidFuture future /* T=CharSequence */) { + @SuppressWarnings("unchecked") + final AndroidFuture typedFuture = future; dispatch(() -> { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getTextAfterCursor"); try { @@ -238,12 +241,7 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub { ImeTracing.getInstance().triggerClientDump( TAG + "#getTextAfterCursor", mParentInputMethodManager, icProto); } - try { - callback.onResult(result); - } catch (RemoteException e) { - Log.w(TAG, "Failed to return the result to getTextAfterCursor()." - + " result=" + result, e); - } + typedFuture.complete(result); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } @@ -251,7 +249,10 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub { } @Override - public void getTextBeforeCursor(int length, int flags, ICharSequenceResultCallback callback) { + public void getTextBeforeCursor(int length, int flags, + AndroidFuture future /* T=CharSequence */) { + @SuppressWarnings("unchecked") + final AndroidFuture typedFuture = future; dispatch(() -> { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getTextBeforeCursor"); try { @@ -269,12 +270,7 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub { ImeTracing.getInstance().triggerClientDump( TAG + "#getTextBeforeCursor", mParentInputMethodManager, icProto); } - try { - callback.onResult(result); - } catch (RemoteException e) { - Log.w(TAG, "Failed to return the result to getTextBeforeCursor()." - + " result=" + result, e); - } + typedFuture.complete(result); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } @@ -282,7 +278,9 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub { } @Override - public void getSelectedText(int flags, ICharSequenceResultCallback callback) { + public void getSelectedText(int flags, AndroidFuture future /* T=CharSequence */) { + @SuppressWarnings("unchecked") + final AndroidFuture typedFuture = future; dispatch(() -> { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getSelectedText"); try { @@ -300,12 +298,7 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub { ImeTracing.getInstance().triggerClientDump( TAG + "#getSelectedText", mParentInputMethodManager, icProto); } - try { - callback.onResult(result); - } catch (RemoteException e) { - Log.w(TAG, "Failed to return the result to getSelectedText()." - + " result=" + result, e); - } + typedFuture.complete(result); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } @@ -314,7 +307,9 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub { @Override public void getSurroundingText(int beforeLength, int afterLength, int flags, - ISurroundingTextResultCallback callback) { + AndroidFuture future /* T=SurroundingText */) { + @SuppressWarnings("unchecked") + final AndroidFuture typedFuture = future; dispatch(() -> { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getSurroundingText"); try { @@ -332,12 +327,7 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub { ImeTracing.getInstance().triggerClientDump( TAG + "#getSurroundingText", mParentInputMethodManager, icProto); } - try { - callback.onResult(result); - } catch (RemoteException e) { - Log.w(TAG, "Failed to return the result to getSurroundingText()." - + " result=" + result, e); - } + typedFuture.complete(result); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } @@ -345,7 +335,9 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub { } @Override - public void getCursorCapsMode(int reqModes, IIntResultCallback callback) { + public void getCursorCapsMode(int reqModes, AndroidFuture future /* T=Integer */) { + @SuppressWarnings("unchecked") + final AndroidFuture typedFuture = future; dispatch(() -> { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getCursorCapsMode"); try { @@ -363,12 +355,7 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub { ImeTracing.getInstance().triggerClientDump( TAG + "#getCursorCapsMode", mParentInputMethodManager, icProto); } - try { - callback.onResult(result); - } catch (RemoteException e) { - Log.w(TAG, "Failed to return the result to getCursorCapsMode()." - + " result=" + result, e); - } + typedFuture.complete(result); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } @@ -377,7 +364,9 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub { @Override public void getExtractedText(ExtractedTextRequest request, int flags, - IExtractedTextResultCallback callback) { + AndroidFuture future /* T=ExtractedText */) { + @SuppressWarnings("unchecked") + final AndroidFuture typedFuture = future; dispatch(() -> { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getExtractedText"); try { @@ -395,12 +384,7 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub { ImeTracing.getInstance().triggerClientDump( TAG + "#getExtractedText", mParentInputMethodManager, icProto); } - try { - callback.onResult(result); - } catch (RemoteException e) { - Log.w(TAG, "Failed to return the result to getExtractedText()." - + " result=" + result, e); - } + typedFuture.complete(result); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } @@ -710,7 +694,9 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub { } @Override - public void requestCursorUpdates(int cursorUpdateMode, IBooleanResultCallback callback) { + public void requestCursorUpdates(int cursorUpdateMode, AndroidFuture future /* T=Boolean */) { + @SuppressWarnings("unchecked") + final AndroidFuture typedFuture = future; dispatch(() -> { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#requestCursorUpdates"); try { @@ -722,12 +708,7 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub { } else { result = ic.requestCursorUpdates(cursorUpdateMode); } - try { - callback.onResult(result); - } catch (RemoteException e) { - Log.w(TAG, "Failed to return the result to requestCursorUpdates()." - + " result=" + result, e); - } + typedFuture.complete(result); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } @@ -736,7 +717,9 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub { @Override public void commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts, - IBooleanResultCallback callback) { + AndroidFuture future /* T=Boolean */) { + @SuppressWarnings("unchecked") + final AndroidFuture typedFuture = future; dispatch(() -> { Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#commitContent"); try { @@ -754,12 +737,7 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub { result = ic.commitContent(inputContentInfo, flags, opts); } } - try { - callback.onResult(result); - } catch (RemoteException e) { - Log.w(TAG, "Failed to return the result to commitContent()." - + " result=" + result, e); - } + typedFuture.complete(result); } finally { Trace.traceEnd(Trace.TRACE_TAG_INPUT); } diff --git a/core/java/com/android/internal/inputmethod/ResultCallbacks.java b/core/java/com/android/internal/inputmethod/ResultCallbacks.java deleted file mode 100644 index 8aef54b3b1d38..0000000000000 --- a/core/java/com/android/internal/inputmethod/ResultCallbacks.java +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * 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.android.internal.inputmethod; - -import android.annotation.AnyThread; -import android.annotation.BinderThread; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.view.inputmethod.ExtractedText; -import android.view.inputmethod.SurroundingText; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.atomic.AtomicReference; - -/** - * Defines a set of factory methods to create {@link android.os.IBinder}-based callbacks that are - * associated with completable objects defined in {@link CompletableFuture}. - */ -public final class ResultCallbacks { - - /** - * Not intended to be instantiated. - */ - private ResultCallbacks() { - } - - private static final class LightweightThrowable extends RuntimeException { - LightweightThrowable(@Nullable ThrowableHolder throwableHolder) { - super(throwableHolder != null ? throwableHolder.getMessage() : null, - null, false, false); - } - } - - @AnyThread - @Nullable - private static T unwrap(@NonNull AtomicReference atomicRef) { - // Only the first caller will receive the non-null original object. - return atomicRef.getAndSet(null); - } - - /** - * Creates {@link IIntResultCallback.Stub} that is to set {@link CompletableFuture} - * when receiving the result. - * - * @param value {@link CompletableFuture} to be set when receiving the result. - * @return {@link IIntResultCallback.Stub} that can be passed as a binder IPC parameter. - */ - @AnyThread - public static IIntResultCallback.Stub ofInteger(@NonNull CompletableFuture value) { - final AtomicReference> atomicRef = new AtomicReference<>(value); - - return new IIntResultCallback.Stub() { - @BinderThread - @Override - public void onResult(int result) { - final CompletableFuture value = unwrap(atomicRef); - if (value == null) { - return; - } - value.complete(result); - } - - @BinderThread - @Override - public void onError(ThrowableHolder throwableHolder) { - final CompletableFuture value = unwrap(atomicRef); - if (value == null) { - return; - } - value.completeExceptionally(new LightweightThrowable(throwableHolder)); - } - }; - } - - /** - * Creates {@link ICharSequenceResultCallback.Stub} that is to set - * {@link CompletableFuture} when receiving the result. - * - * @param value {@link CompletableFuture} to be set when receiving the result. - * @return {@link ICharSequenceResultCallback.Stub} that can be passed as a binder IPC - * parameter. - */ - @AnyThread - public static ICharSequenceResultCallback.Stub ofCharSequence( - @NonNull CompletableFuture value) { - final AtomicReference> atomicRef = - new AtomicReference<>(value); - - return new ICharSequenceResultCallback.Stub() { - @BinderThread - @Override - public void onResult(CharSequence result) { - final CompletableFuture value = unwrap(atomicRef); - if (value == null) { - return; - } - value.complete(result); - } - }; - } - - /** - * Creates {@link IExtractedTextResultCallback.Stub} that is to set - * {@link CompletableFuture} when receiving the result. - * - * @param value {@link CompletableFuture} to be set when receiving the result. - * @return {@link IExtractedTextResultCallback.Stub} that can be passed as a binder IPC - * parameter. - */ - @AnyThread - public static IExtractedTextResultCallback.Stub ofExtractedText( - @NonNull CompletableFuture value) { - final AtomicReference> atomicRef = - new AtomicReference<>(value); - - return new IExtractedTextResultCallback.Stub() { - @BinderThread - @Override - public void onResult(android.view.inputmethod.ExtractedText result) { - final CompletableFuture value = unwrap(atomicRef); - if (value == null) { - return; - } - value.complete(result); - } - }; - } - - /** - * Creates {@link ISurroundingTextResultCallback.Stub} that is to set - * {@link CompletableFuture} when receiving the result. - * - * @param value {@link CompletableFuture} to be set when receiving the result. - * @return {@link ISurroundingTextResultCallback.Stub} that can be passed as a binder IPC - * parameter. - */ - @AnyThread - public static ISurroundingTextResultCallback.Stub ofSurroundingText( - @NonNull CompletableFuture value) { - final AtomicReference> atomicRef = - new AtomicReference<>(value); - - return new ISurroundingTextResultCallback.Stub() { - @BinderThread - @Override - public void onResult(android.view.inputmethod.SurroundingText result) { - final CompletableFuture value = unwrap(atomicRef); - if (value == null) { - return; - } - value.complete(result); - } - }; - } - - /** - * Creates {@link IBooleanResultCallback.Stub} that is to set {@link CompletableFuture} - * when receiving the result. - * - * @param value {@link CompletableFuture} to be set when receiving the result. - * @return {@link IBooleanResultCallback.Stub} that can be passed as a binder IPC parameter. - */ - @AnyThread - public static IBooleanResultCallback.Stub ofBoolean(@NonNull CompletableFuture value) { - final AtomicReference> atomicRef = new AtomicReference<>(value); - - return new IBooleanResultCallback.Stub() { - @BinderThread - @Override - public void onResult(boolean result) { - final CompletableFuture value = unwrap(atomicRef); - if (value == null) { - return; - } - value.complete(result); - } - - @BinderThread - @Override - public void onError(ThrowableHolder throwableHolder) { - final CompletableFuture value = unwrap(atomicRef); - if (value == null) { - return; - } - value.completeExceptionally(new LightweightThrowable(throwableHolder)); - } - }; - } - - /** - * Creates {@link IVoidResultCallback.Stub} that is to set {@link CompletableFuture} when - * receiving the result. - * - * @param value {@link CompletableFuture} to be set when receiving the result. - * @return {@link IVoidResultCallback.Stub} that can be passed as a binder IPC parameter. - */ - @AnyThread - public static IVoidResultCallback.Stub ofVoid(@NonNull CompletableFuture value) { - final AtomicReference> atomicRef = new AtomicReference<>(value); - - return new IVoidResultCallback.Stub() { - @BinderThread - @Override - public void onResult() { - final CompletableFuture value = unwrap(atomicRef); - if (value == null) { - return; - } - value.complete(null); - } - - @BinderThread - @Override - public void onError(ThrowableHolder throwableHolder) { - final CompletableFuture value = unwrap(atomicRef); - if (value == null) { - return; - } - value.completeExceptionally(new LightweightThrowable(throwableHolder)); - } - }; - } - - /** - * Creates {@link IInputContentUriTokenResultCallback.Stub} that is to set - * {@link CompletableFuture} when receiving the result. - * - * @param value {@link CompletableFuture} to be set when receiving the - * result. - * @return {@link IInputContentUriTokenResultCallback.Stub} that can be passed as a binder IPC - * parameter. - */ - @AnyThread - public static IInputContentUriTokenResultCallback.Stub ofIInputContentUriToken( - @NonNull CompletableFuture value) { - final AtomicReference> - atomicRef = new AtomicReference<>(value); - - return new IInputContentUriTokenResultCallback.Stub() { - @BinderThread - @Override - public void onResult(IInputContentUriToken result) { - final CompletableFuture value = unwrap(atomicRef); - if (value == null) { - return; - } - value.complete(result); - } - - @BinderThread - @Override - public void onError(ThrowableHolder throwableHolder) { - final CompletableFuture value = unwrap(atomicRef); - if (value == null) { - return; - } - value.completeExceptionally(new LightweightThrowable(throwableHolder)); - } - }; - } -} diff --git a/core/java/com/android/internal/view/IInputContext.aidl b/core/java/com/android/internal/view/IInputContext.aidl index dd42c40edb493..12a98c17b3f01 100644 --- a/core/java/com/android/internal/view/IInputContext.aidl +++ b/core/java/com/android/internal/view/IInputContext.aidl @@ -23,11 +23,7 @@ import android.view.inputmethod.CorrectionInfo; import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputContentInfo; -import com.android.internal.inputmethod.IBooleanResultCallback; -import com.android.internal.inputmethod.ICharSequenceResultCallback; -import com.android.internal.inputmethod.IExtractedTextResultCallback; -import com.android.internal.inputmethod.IIntResultCallback; -import com.android.internal.inputmethod.ISurroundingTextResultCallback; +import com.android.internal.infra.AndroidFuture; /** * Interface from an input method to the application, allowing it to perform @@ -35,14 +31,14 @@ import com.android.internal.inputmethod.ISurroundingTextResultCallback; * {@hide} */ oneway interface IInputContext { - void getTextBeforeCursor(int length, int flags, ICharSequenceResultCallback callback); + void getTextBeforeCursor(int length, int flags, in AndroidFuture future /* T=CharSequence */); - void getTextAfterCursor(int length, int flags, ICharSequenceResultCallback callback); + void getTextAfterCursor(int length, int flags, in AndroidFuture future /* T=CharSequence */); - void getCursorCapsMode(int reqModes, IIntResultCallback callback); + void getCursorCapsMode(int reqModes, in AndroidFuture future /* T=Integer */); void getExtractedText(in ExtractedTextRequest request, int flags, - IExtractedTextResultCallback callback); + in AndroidFuture future /* T=ExtractedText */); void deleteSurroundingText(int beforeLength, int afterLength); void deleteSurroundingTextInCodePoints(int beforeLength, int afterLength); @@ -50,7 +46,7 @@ import com.android.internal.inputmethod.ISurroundingTextResultCallback; void setComposingText(CharSequence text, int newCursorPosition); void finishComposingText(); - + void commitText(CharSequence text, int newCursorPosition); void commitCompletion(in CompletionInfo completion); @@ -58,34 +54,34 @@ import com.android.internal.inputmethod.ISurroundingTextResultCallback; void commitCorrection(in CorrectionInfo correction); void setSelection(int start, int end); - + void performEditorAction(int actionCode); - + void performContextMenuAction(int id); - + void beginBatchEdit(); - + void endBatchEdit(); void sendKeyEvent(in KeyEvent event); - + void clearMetaKeyStates(int states); - + void performSpellCheck(); void performPrivateCommand(String action, in Bundle data); void setComposingRegion(int start, int end); - void getSelectedText(int flags, ICharSequenceResultCallback callback); + void getSelectedText(int flags, in AndroidFuture future /* T=CharSequence */); - void requestCursorUpdates(int cursorUpdateMode, IBooleanResultCallback callback); + void requestCursorUpdates(int cursorUpdateMode, in AndroidFuture future /* T=Boolean */); void commitContent(in InputContentInfo inputContentInfo, int flags, in Bundle opts, - IBooleanResultCallback callback); + in AndroidFuture future /* T=Boolean */); void getSurroundingText(int beforeLength, int afterLength, int flags, - ISurroundingTextResultCallback callback); + in AndroidFuture future /* T=SurroundingText */); void setImeConsumesInput(boolean imeConsumesInput); } diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 62b36d0ab4683..5888b989864f5 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -152,12 +152,9 @@ import android.view.inputmethod.InputMethodSubtype; import com.android.internal.annotations.GuardedBy; import com.android.internal.compat.IPlatformCompat; import com.android.internal.content.PackageMonitor; -import com.android.internal.inputmethod.CallbackUtils; -import com.android.internal.inputmethod.IBooleanResultCallback; +import com.android.internal.infra.AndroidFuture; import com.android.internal.inputmethod.IInputContentUriToken; -import com.android.internal.inputmethod.IInputContentUriTokenResultCallback; import com.android.internal.inputmethod.IInputMethodPrivilegedOperations; -import com.android.internal.inputmethod.IVoidResultCallback; import com.android.internal.inputmethod.ImeTracing; import com.android.internal.inputmethod.InputBindResult; import com.android.internal.inputmethod.InputMethodDebug; @@ -5842,9 +5839,15 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @BinderThread @Override public void createInputContentUriToken(Uri contentUri, String packageName, - IInputContentUriTokenResultCallback resultCallback) { - CallbackUtils.onResult(resultCallback, - () -> mImms.createInputContentUriToken(mToken, contentUri, packageName)); + AndroidFuture future /* T=IBinder */) { + @SuppressWarnings("unchecked") + final AndroidFuture typedFuture = future; + try { + typedFuture.complete(mImms.createInputContentUriToken( + mToken, contentUri, packageName).asBinder()); + } catch (Throwable e) { + typedFuture.completeExceptionally(e); + } } @BinderThread @@ -5855,28 +5858,55 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @BinderThread @Override - public void setInputMethod(String id, IVoidResultCallback resultCallback) { - CallbackUtils.onResult(resultCallback, () -> mImms.setInputMethod(mToken, id)); + public void setInputMethod(String id, AndroidFuture future /* T=Void */) { + @SuppressWarnings("unchecked") + final AndroidFuture typedFuture = future; + try { + mImms.setInputMethod(mToken, id); + typedFuture.complete(null); + } catch (Throwable e) { + typedFuture.completeExceptionally(e); + } } @BinderThread @Override public void setInputMethodAndSubtype(String id, InputMethodSubtype subtype, - IVoidResultCallback resultCallback) { - CallbackUtils.onResult(resultCallback, - () -> mImms.setInputMethodAndSubtype(mToken, id, subtype)); + AndroidFuture future /* T=Void */) { + @SuppressWarnings("unchecked") + final AndroidFuture typedFuture = future; + try { + mImms.setInputMethodAndSubtype(mToken, id, subtype); + typedFuture.complete(null); + } catch (Throwable e) { + typedFuture.completeExceptionally(e); + } } @BinderThread @Override - public void hideMySoftInput(int flags, IVoidResultCallback resultCallback) { - CallbackUtils.onResult(resultCallback, () -> mImms.hideMySoftInput(mToken, flags)); + public void hideMySoftInput(int flags, AndroidFuture future /* T=Void */) { + @SuppressWarnings("unchecked") + final AndroidFuture typedFuture = future; + try { + mImms.hideMySoftInput(mToken, flags); + typedFuture.complete(null); + } catch (Throwable e) { + typedFuture.completeExceptionally(e); + } } @BinderThread @Override - public void showMySoftInput(int flags, IVoidResultCallback resultCallback) { - CallbackUtils.onResult(resultCallback, () -> mImms.showMySoftInput(mToken, flags)); + public void showMySoftInput(int flags, AndroidFuture future /* T=Void */) { + @SuppressWarnings("unchecked") + final AndroidFuture typedFuture = future; + try { + mImms.showMySoftInput(mToken, flags); + typedFuture.complete(null); + } catch (Throwable e) { + typedFuture.completeExceptionally(e); + } } @BinderThread @@ -5887,24 +5917,39 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @BinderThread @Override - public void switchToPreviousInputMethod(IBooleanResultCallback resultCallback) { - CallbackUtils.onResult(resultCallback, () -> mImms.switchToPreviousInputMethod(mToken)); + public void switchToPreviousInputMethod(AndroidFuture future /* T=Boolean */) { + @SuppressWarnings("unchecked") + final AndroidFuture typedFuture = future; + try { + typedFuture.complete(mImms.switchToPreviousInputMethod(mToken)); + } catch (Throwable e) { + typedFuture.completeExceptionally(e); + } } @BinderThread @Override public void switchToNextInputMethod(boolean onlyCurrentIme, - IBooleanResultCallback resultCallback) { - CallbackUtils.onResult(resultCallback, - () -> mImms.switchToNextInputMethod(mToken, onlyCurrentIme)); + AndroidFuture future /* T=Boolean */) { + @SuppressWarnings("unchecked") + final AndroidFuture typedFuture = future; + try { + typedFuture.complete(mImms.switchToNextInputMethod(mToken, onlyCurrentIme)); + } catch (Throwable e) { + typedFuture.completeExceptionally(e); + } } @BinderThread @Override - public void shouldOfferSwitchingToNextInputMethod( - IBooleanResultCallback resultCallback) { - CallbackUtils.onResult(resultCallback, - () -> mImms.shouldOfferSwitchingToNextInputMethod(mToken)); + public void shouldOfferSwitchingToNextInputMethod(AndroidFuture future /* T=Boolean */) { + @SuppressWarnings("unchecked") + final AndroidFuture typedFuture = future; + try { + typedFuture.complete(mImms.shouldOfferSwitchingToNextInputMethod(mToken)); + } catch (Throwable e) { + typedFuture.completeExceptionally(e); + } } @BinderThread