Make IInputMethodManager to oneway (1/N)
Isolate the Completable class from the CancellationGroup class because not all Completable objects could be cancelled. So we don’t need to always hold a final CancellationGroup in Completable class. If the Completable object could be cancelled, pass it as parameter when doing await. Bug: 163453493 Test: Manual test with keyboard Test: atest CtsInputMethodTestCases Change-Id: If79810d5acc36b5a8c6a2c7cfcabeb4d0ebed197
This commit is contained in:
@@ -24,11 +24,10 @@ import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* A utility class, which works as both a factory class of completable objects and a cancellation
|
||||
* signal to cancel all the completable objects created by this object.
|
||||
* A utility class, which works as both a factory class of a cancellation signal to cancel
|
||||
* all the completable objects.
|
||||
*/
|
||||
public final class CancellationGroup {
|
||||
private final Object mLock = new Object();
|
||||
@@ -46,274 +45,8 @@ public final class CancellationGroup {
|
||||
@GuardedBy("mLock")
|
||||
private boolean mCanceled = false;
|
||||
|
||||
/**
|
||||
* An inner class to consolidate completable object types supported by
|
||||
* {@link CancellationGroup}.
|
||||
*/
|
||||
public static final class Completable {
|
||||
|
||||
/**
|
||||
* Not intended to be instantiated.
|
||||
*/
|
||||
private Completable() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class of all the completable types supported by {@link CancellationGroup}.
|
||||
*/
|
||||
protected static class ValueBase {
|
||||
/**
|
||||
* {@link CountDownLatch} to be signaled to unblock {@link #await(int, TimeUnit)}.
|
||||
*/
|
||||
private final CountDownLatch mLatch = new CountDownLatch(1);
|
||||
|
||||
/**
|
||||
* {@link CancellationGroup} to which this completable object belongs.
|
||||
*/
|
||||
@NonNull
|
||||
private final CancellationGroup mParentGroup;
|
||||
|
||||
/**
|
||||
* Lock {@link Object} to guard complete operations within this class.
|
||||
*/
|
||||
protected final Object mValueLock = new Object();
|
||||
|
||||
/**
|
||||
* {@code true} after {@link #onComplete()} gets called.
|
||||
*/
|
||||
@GuardedBy("mValueLock")
|
||||
protected boolean mHasValue = false;
|
||||
|
||||
/**
|
||||
* Base constructor.
|
||||
*
|
||||
* @param parentGroup {@link CancellationGroup} to which this completable object
|
||||
* belongs.
|
||||
*/
|
||||
protected ValueBase(@NonNull CancellationGroup parentGroup) {
|
||||
mParentGroup = parentGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link true} if {@link #onComplete()} gets called already.
|
||||
*/
|
||||
@AnyThread
|
||||
public boolean hasValue() {
|
||||
synchronized (mValueLock) {
|
||||
return mHasValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by subclasses to signale {@link #mLatch}.
|
||||
*/
|
||||
@AnyThread
|
||||
protected void onComplete() {
|
||||
mLatch.countDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Blocks the calling thread until at least one of the following conditions is met.
|
||||
*
|
||||
* <p>
|
||||
* <ol>
|
||||
* <li>This object becomes ready to return the value.</li>
|
||||
* <li>{@link CancellationGroup#cancelAll()} gets called.</li>
|
||||
* <li>The given timeout period has passed.</li>
|
||||
* </ol>
|
||||
* </p>
|
||||
*
|
||||
* <p>The caller can distinguish the case 1 and case 2 by calling {@link #hasValue()}.
|
||||
* Note that the return value of {@link #hasValue()} can change from {@code false} to
|
||||
* {@code true} at any time, even after this methods finishes with returning
|
||||
* {@code true}.</p>
|
||||
*
|
||||
* @param timeout length of the timeout.
|
||||
* @param timeUnit unit of {@code timeout}.
|
||||
* @return {@code false} if and only if the given timeout period has passed. Otherwise
|
||||
* {@code true}.
|
||||
*/
|
||||
@AnyThread
|
||||
public boolean await(int timeout, @NonNull TimeUnit timeUnit) {
|
||||
if (!mParentGroup.registerLatch(mLatch)) {
|
||||
// Already canceled when this method gets called.
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return mLatch.await(timeout, timeUnit);
|
||||
} catch (InterruptedException e) {
|
||||
return true;
|
||||
} finally {
|
||||
mParentGroup.unregisterLatch(mLatch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Completable object of integer primitive.
|
||||
*/
|
||||
public static final class Int extends ValueBase {
|
||||
@GuardedBy("mValueLock")
|
||||
private int mValue = 0;
|
||||
|
||||
private Int(@NonNull CancellationGroup factory) {
|
||||
super(factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify when a value is set to this completable object.
|
||||
*
|
||||
* @param value value to be set.
|
||||
*/
|
||||
@AnyThread
|
||||
void onComplete(int value) {
|
||||
synchronized (mValueLock) {
|
||||
if (mHasValue) {
|
||||
throw new UnsupportedOperationException(
|
||||
"onComplete() cannot be called multiple times");
|
||||
}
|
||||
mValue = value;
|
||||
mHasValue = true;
|
||||
}
|
||||
onComplete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return value associated with this object.
|
||||
* @throws UnsupportedOperationException when called while {@link #hasValue()} returns
|
||||
* {@code false}.
|
||||
*/
|
||||
@AnyThread
|
||||
public int getValue() {
|
||||
synchronized (mValueLock) {
|
||||
if (!mHasValue) {
|
||||
throw new UnsupportedOperationException(
|
||||
"getValue() is allowed only if hasValue() returns true");
|
||||
}
|
||||
return mValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class of completable object types.
|
||||
*
|
||||
* @param <T> type associated with this completable object.
|
||||
*/
|
||||
public static class Values<T> extends ValueBase {
|
||||
@GuardedBy("mValueLock")
|
||||
@Nullable
|
||||
private T mValue = null;
|
||||
|
||||
protected Values(@NonNull CancellationGroup factory) {
|
||||
super(factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify when a value is set to this completable value object.
|
||||
*
|
||||
* @param value value to be set.
|
||||
*/
|
||||
@AnyThread
|
||||
void onComplete(@Nullable T value) {
|
||||
synchronized (mValueLock) {
|
||||
if (mHasValue) {
|
||||
throw new UnsupportedOperationException(
|
||||
"onComplete() cannot be called multiple times");
|
||||
}
|
||||
mValue = value;
|
||||
mHasValue = true;
|
||||
}
|
||||
onComplete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return value associated with this object.
|
||||
* @throws UnsupportedOperationException when called while {@link #hasValue()} returns
|
||||
* {@code false}.
|
||||
*/
|
||||
@AnyThread
|
||||
@Nullable
|
||||
public T getValue() {
|
||||
synchronized (mValueLock) {
|
||||
if (!mHasValue) {
|
||||
throw new UnsupportedOperationException(
|
||||
"getValue() is allowed only if hasValue() returns true");
|
||||
}
|
||||
return mValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Completable object of {@link java.lang.CharSequence}.
|
||||
*/
|
||||
public static final class CharSequence extends Values<java.lang.CharSequence> {
|
||||
private CharSequence(@NonNull CancellationGroup factory) {
|
||||
super(factory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Completable object of {@link android.view.inputmethod.ExtractedText}.
|
||||
*/
|
||||
public static final class ExtractedText
|
||||
extends Values<android.view.inputmethod.ExtractedText> {
|
||||
private ExtractedText(@NonNull CancellationGroup factory) {
|
||||
super(factory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Completable object of {@link android.view.inputmethod.SurroundingText}.
|
||||
*/
|
||||
public static final class SurroundingText
|
||||
extends Values<android.view.inputmethod.SurroundingText> {
|
||||
private SurroundingText(@NonNull CancellationGroup factory) {
|
||||
super(factory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an instance of {@link Completable.Int} that is associated with this
|
||||
* {@link CancellationGroup}.
|
||||
*/
|
||||
@AnyThread
|
||||
public Completable.Int createCompletableInt() {
|
||||
return new Completable.Int(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an instance of {@link Completable.CharSequence} that is associated with this
|
||||
* {@link CancellationGroup}.
|
||||
*/
|
||||
@AnyThread
|
||||
public Completable.CharSequence createCompletableCharSequence() {
|
||||
return new Completable.CharSequence(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an instance of {@link Completable.ExtractedText} that is associated with this
|
||||
* {@link CancellationGroup}.
|
||||
*/
|
||||
@AnyThread
|
||||
public Completable.ExtractedText createCompletableExtractedText() {
|
||||
return new Completable.ExtractedText(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an instance of {@link Completable.SurroundingText} that is associated with this
|
||||
* {@link CancellationGroup}.
|
||||
*/
|
||||
@AnyThread
|
||||
public Completable.SurroundingText createCompletableSurroundingText() {
|
||||
return new Completable.SurroundingText(this);
|
||||
}
|
||||
|
||||
|
||||
@AnyThread
|
||||
private boolean registerLatch(@NonNull CountDownLatch latch) {
|
||||
boolean registerLatch(@NonNull CountDownLatch latch) {
|
||||
synchronized (mLock) {
|
||||
if (mCanceled) {
|
||||
return false;
|
||||
@@ -329,7 +62,7 @@ public final class CancellationGroup {
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
private void unregisterLatch(@NonNull CountDownLatch latch) {
|
||||
void unregisterLatch(@NonNull CountDownLatch latch) {
|
||||
synchronized (mLock) {
|
||||
if (mLatchList != null) {
|
||||
mLatchList.remove(latch);
|
||||
|
||||
278
core/java/com/android/internal/inputmethod/Completable.java
Normal file
278
core/java/com/android/internal/inputmethod/Completable.java
Normal file
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* 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.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* An class to consolidate completable object types supported by
|
||||
* {@link CancellationGroup}.
|
||||
*/
|
||||
public final class Completable {
|
||||
|
||||
/**
|
||||
* Not intended to be instantiated.
|
||||
*/
|
||||
private Completable() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class of all the completable types supported by {@link CancellationGroup}.
|
||||
*/
|
||||
protected static class ValueBase {
|
||||
/**
|
||||
* {@link CountDownLatch} to be signaled to unblock
|
||||
* {@link #await(int, TimeUnit, CancellationGroup)}.
|
||||
*/
|
||||
private final CountDownLatch mLatch = new CountDownLatch(1);
|
||||
|
||||
/**
|
||||
* Lock {@link Object} to guard complete operations within this class.
|
||||
*/
|
||||
protected final Object mValueLock = new Object();
|
||||
|
||||
/**
|
||||
* {@code true} after {@link #onComplete()} gets called.
|
||||
*/
|
||||
@GuardedBy("mValueLock")
|
||||
protected boolean mHasValue = false;
|
||||
|
||||
/**
|
||||
* @return {@link true} if {@link #onComplete()} gets called already.
|
||||
*/
|
||||
@AnyThread
|
||||
public boolean hasValue() {
|
||||
synchronized (mValueLock) {
|
||||
return mHasValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by subclasses to signale {@link #mLatch}.
|
||||
*/
|
||||
@AnyThread
|
||||
protected void onComplete() {
|
||||
mLatch.countDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Blocks the calling thread until at least one of the following conditions is met.
|
||||
*
|
||||
* <p>
|
||||
* <ol>
|
||||
* <li>This object becomes ready to return the value.</li>
|
||||
* <li>{@link CancellationGroup#cancelAll()} gets called.</li>
|
||||
* <li>The given timeout period has passed.</li>
|
||||
* </ol>
|
||||
* </p>
|
||||
*
|
||||
* <p>The caller can distinguish the case 1 and case 2 by calling {@link #hasValue()}.
|
||||
* Note that the return value of {@link #hasValue()} can change from {@code false} to
|
||||
* {@code true} at any time, even after this methods finishes with returning
|
||||
* {@code true}.</p>
|
||||
*
|
||||
* @param timeout length of the timeout.
|
||||
* @param timeUnit unit of {@code timeout}.
|
||||
* @param cancellationGroup {@link CancellationGroup} to cancel completable objects.
|
||||
* @return {@code false} if and only if the given timeout period has passed. Otherwise
|
||||
* {@code true}.
|
||||
*/
|
||||
@AnyThread
|
||||
public boolean await(int timeout, @NonNull TimeUnit timeUnit,
|
||||
@Nullable CancellationGroup cancellationGroup) {
|
||||
if (cancellationGroup == null) {
|
||||
return awaitInner(timeout, timeUnit);
|
||||
}
|
||||
|
||||
if (!cancellationGroup.registerLatch(mLatch)) {
|
||||
// Already canceled when this method gets called.
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return awaitInner(timeout, timeUnit);
|
||||
} finally {
|
||||
cancellationGroup.unregisterLatch(mLatch);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean awaitInner(int timeout, @NonNull TimeUnit timeUnit) {
|
||||
try {
|
||||
return mLatch.await(timeout, timeUnit);
|
||||
} catch (InterruptedException e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Completable object of integer primitive.
|
||||
*/
|
||||
public static final class Int extends ValueBase {
|
||||
@GuardedBy("mValueLock")
|
||||
private int mValue = 0;
|
||||
|
||||
/**
|
||||
* Notify when a value is set to this completable object.
|
||||
*
|
||||
* @param value value to be set.
|
||||
*/
|
||||
@AnyThread
|
||||
void onComplete(int value) {
|
||||
synchronized (mValueLock) {
|
||||
if (mHasValue) {
|
||||
throw new UnsupportedOperationException(
|
||||
"onComplete() cannot be called multiple times");
|
||||
}
|
||||
mValue = value;
|
||||
mHasValue = true;
|
||||
}
|
||||
onComplete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return value associated with this object.
|
||||
* @throws UnsupportedOperationException when called while {@link #hasValue()} returns
|
||||
* {@code false}.
|
||||
*/
|
||||
@AnyThread
|
||||
public int getValue() {
|
||||
synchronized (mValueLock) {
|
||||
if (!mHasValue) {
|
||||
throw new UnsupportedOperationException(
|
||||
"getValue() is allowed only if hasValue() returns true");
|
||||
}
|
||||
return mValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class of completable object types.
|
||||
*
|
||||
* @param <T> type associated with this completable object.
|
||||
*/
|
||||
public static class Values<T> extends ValueBase {
|
||||
@GuardedBy("mValueLock")
|
||||
@Nullable
|
||||
private T mValue = null;
|
||||
|
||||
/**
|
||||
* Notify when a value is set to this completable value object.
|
||||
*
|
||||
* @param value value to be set.
|
||||
*/
|
||||
@AnyThread
|
||||
void onComplete(@Nullable T value) {
|
||||
synchronized (mValueLock) {
|
||||
if (mHasValue) {
|
||||
throw new UnsupportedOperationException(
|
||||
"onComplete() cannot be called multiple times");
|
||||
}
|
||||
mValue = value;
|
||||
mHasValue = true;
|
||||
}
|
||||
onComplete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return value associated with this object.
|
||||
* @throws UnsupportedOperationException when called while {@link #hasValue()} returns
|
||||
* {@code false}.
|
||||
*/
|
||||
@AnyThread
|
||||
@Nullable
|
||||
public T getValue() {
|
||||
synchronized (mValueLock) {
|
||||
if (!mHasValue) {
|
||||
throw new UnsupportedOperationException(
|
||||
"getValue() is allowed only if hasValue() returns true");
|
||||
}
|
||||
return mValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an instance of {@link Completable.Int}.
|
||||
*/
|
||||
public static Completable.Int createInt() {
|
||||
return new Completable.Int();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an instance of {@link Completable.Boolean}.
|
||||
*/
|
||||
public static Completable.Boolean createBoolean() {
|
||||
return new Completable.Boolean();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an instance of {@link Completable.CharSequence}.
|
||||
*/
|
||||
public static Completable.CharSequence createCharSequence() {
|
||||
return new Completable.CharSequence();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an instance of {@link Completable.ExtractedText}.
|
||||
*/
|
||||
public static Completable.ExtractedText createExtractedText() {
|
||||
return new Completable.ExtractedText();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an instance of {@link Completable.SurroundingText}.
|
||||
*/
|
||||
public static Completable.SurroundingText createSurroundingText() {
|
||||
return new Completable.SurroundingText();
|
||||
}
|
||||
|
||||
/**
|
||||
* Completable object of {@link java.lang.Boolean}.
|
||||
*/
|
||||
public static final class Boolean extends Values<java.lang.Boolean> { }
|
||||
|
||||
/**
|
||||
* Completable object of {@link java.lang.CharSequence}.
|
||||
*/
|
||||
public static final class CharSequence extends Values<java.lang.CharSequence> { }
|
||||
|
||||
/**
|
||||
* Completable object of {@link android.view.inputmethod.ExtractedText}.
|
||||
*/
|
||||
public static final class ExtractedText
|
||||
extends Values<android.view.inputmethod.ExtractedText> { }
|
||||
|
||||
/**
|
||||
* Completable object of {@link android.view.inputmethod.SurroundingText}.
|
||||
*/
|
||||
public static final class SurroundingText
|
||||
extends Values<android.view.inputmethod.SurroundingText> { }
|
||||
|
||||
/**
|
||||
* Completable object of {@link com.android.internal.view.InputBindResult}.
|
||||
*/
|
||||
public static final class InputBindResult
|
||||
extends Values<com.android.internal.view.InputBindResult> { }
|
||||
}
|
||||
@@ -26,7 +26,7 @@ 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 CancellationGroup.Completable}.
|
||||
* associated with completable objects defined in {@link Completable}.
|
||||
*/
|
||||
public final class ResultCallbacks {
|
||||
|
||||
@@ -50,22 +50,22 @@ public final class ResultCallbacks {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates {@link IIntResultCallback.Stub} that is to set
|
||||
* {@link CancellationGroup.Completable.Int} when receiving the result.
|
||||
* Creates {@link IIntResultCallback.Stub} that is to set {@link Completable.Int} when receiving
|
||||
* the result.
|
||||
*
|
||||
* @param value {@link CancellationGroup.Completable.Int} to be set when receiving the result.
|
||||
* @param value {@link Completable.Int} 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 of(@NonNull CancellationGroup.Completable.Int value) {
|
||||
final AtomicReference<WeakReference<CancellationGroup.Completable.Int>>
|
||||
public static IIntResultCallback.Stub of(@NonNull Completable.Int value) {
|
||||
final AtomicReference<WeakReference<Completable.Int>>
|
||||
atomicRef = new AtomicReference<>(new WeakReference<>(value));
|
||||
|
||||
return new IIntResultCallback.Stub() {
|
||||
@BinderThread
|
||||
@Override
|
||||
public void onResult(int result) {
|
||||
final CancellationGroup.Completable.Int value = unwrap(atomicRef);
|
||||
final Completable.Int value = unwrap(atomicRef);
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
@@ -76,24 +76,23 @@ public final class ResultCallbacks {
|
||||
|
||||
/**
|
||||
* Creates {@link ICharSequenceResultCallback.Stub} that is to set
|
||||
* {@link CancellationGroup.Completable.CharSequence} when receiving the result.
|
||||
* {@link Completable.CharSequence} when receiving the result.
|
||||
*
|
||||
* @param value {@link CancellationGroup.Completable.CharSequence} to be set when receiving the
|
||||
* result.
|
||||
* @param value {@link Completable.CharSequence} 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 of(
|
||||
@NonNull CancellationGroup.Completable.CharSequence value) {
|
||||
final AtomicReference<WeakReference<CancellationGroup.Completable.CharSequence>> atomicRef =
|
||||
@NonNull Completable.CharSequence value) {
|
||||
final AtomicReference<WeakReference<Completable.CharSequence>> atomicRef =
|
||||
new AtomicReference<>(new WeakReference<>(value));
|
||||
|
||||
return new ICharSequenceResultCallback.Stub() {
|
||||
@BinderThread
|
||||
@Override
|
||||
public void onResult(CharSequence result) {
|
||||
final CancellationGroup.Completable.CharSequence value = unwrap(atomicRef);
|
||||
final Completable.CharSequence value = unwrap(atomicRef);
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
@@ -104,24 +103,23 @@ public final class ResultCallbacks {
|
||||
|
||||
/**
|
||||
* Creates {@link IExtractedTextResultCallback.Stub} that is to set
|
||||
* {@link CancellationGroup.Completable.ExtractedText} when receiving the result.
|
||||
* {@link Completable.ExtractedText} when receiving the result.
|
||||
*
|
||||
* @param value {@link CancellationGroup.Completable.ExtractedText} to be set when receiving the
|
||||
* result.
|
||||
* @param value {@link Completable.ExtractedText} 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 of(
|
||||
@NonNull CancellationGroup.Completable.ExtractedText value) {
|
||||
final AtomicReference<WeakReference<CancellationGroup.Completable.ExtractedText>>
|
||||
@NonNull Completable.ExtractedText value) {
|
||||
final AtomicReference<WeakReference<Completable.ExtractedText>>
|
||||
atomicRef = new AtomicReference<>(new WeakReference<>(value));
|
||||
|
||||
return new IExtractedTextResultCallback.Stub() {
|
||||
@BinderThread
|
||||
@Override
|
||||
public void onResult(android.view.inputmethod.ExtractedText result) {
|
||||
final CancellationGroup.Completable.ExtractedText value = unwrap(atomicRef);
|
||||
final Completable.ExtractedText value = unwrap(atomicRef);
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
@@ -132,24 +130,23 @@ public final class ResultCallbacks {
|
||||
|
||||
/**
|
||||
* Creates {@link ISurroundingTextResultCallback.Stub} that is to set
|
||||
* {@link CancellationGroup.Completable.SurroundingText} when receiving the result.
|
||||
* {@link Completable.SurroundingText} when receiving the result.
|
||||
*
|
||||
* @param value {@link CancellationGroup.Completable.SurroundingText} to be set when receiving
|
||||
* the result.
|
||||
* @param value {@link Completable.SurroundingText} 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 of(
|
||||
@NonNull CancellationGroup.Completable.SurroundingText value) {
|
||||
final AtomicReference<WeakReference<CancellationGroup.Completable.SurroundingText>>
|
||||
@NonNull Completable.SurroundingText value) {
|
||||
final AtomicReference<WeakReference<Completable.SurroundingText>>
|
||||
atomicRef = new AtomicReference<>(new WeakReference<>(value));
|
||||
|
||||
return new ISurroundingTextResultCallback.Stub() {
|
||||
@BinderThread
|
||||
@Override
|
||||
public void onResult(android.view.inputmethod.SurroundingText result) {
|
||||
final CancellationGroup.Completable.SurroundingText value = unwrap(atomicRef);
|
||||
final Completable.SurroundingText value = unwrap(atomicRef);
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import android.view.inputmethod.InputContentInfo;
|
||||
import android.view.inputmethod.SurroundingText;
|
||||
|
||||
import com.android.internal.inputmethod.CancellationGroup;
|
||||
import com.android.internal.inputmethod.Completable;
|
||||
import com.android.internal.inputmethod.ResultCallbacks;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
@@ -84,9 +85,10 @@ public class InputConnectionWrapper implements InputConnection {
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
private static int getResultOrZero(@NonNull CancellationGroup.Completable.Int value,
|
||||
@NonNull String methodName) {
|
||||
final boolean timedOut = value.await(MAX_WAIT_TIME_MILLIS, TimeUnit.MILLISECONDS);
|
||||
private static int getResultOrZero(@NonNull Completable.Int value, @NonNull String methodName,
|
||||
@Nullable CancellationGroup cancellationGroup) {
|
||||
final boolean timedOut =
|
||||
value.await(MAX_WAIT_TIME_MILLIS, TimeUnit.MILLISECONDS, cancellationGroup);
|
||||
if (value.hasValue()) {
|
||||
return value.getValue();
|
||||
}
|
||||
@@ -96,9 +98,10 @@ public class InputConnectionWrapper implements InputConnection {
|
||||
|
||||
@AnyThread
|
||||
@Nullable
|
||||
private static <T> T getResultOrNull(@NonNull CancellationGroup.Completable.Values<T> value,
|
||||
@NonNull String methodName) {
|
||||
final boolean timedOut = value.await(MAX_WAIT_TIME_MILLIS, TimeUnit.MILLISECONDS);
|
||||
private static <T> T getResultOrNull(@NonNull Completable.Values<T> value,
|
||||
@NonNull String methodName, @Nullable CancellationGroup cancellationGroup) {
|
||||
final boolean timedOut =
|
||||
value.await(MAX_WAIT_TIME_MILLIS, TimeUnit.MILLISECONDS, cancellationGroup);
|
||||
if (value.hasValue()) {
|
||||
return value.getValue();
|
||||
}
|
||||
@@ -112,14 +115,13 @@ public class InputConnectionWrapper implements InputConnection {
|
||||
return null;
|
||||
}
|
||||
|
||||
final CancellationGroup.Completable.CharSequence value =
|
||||
mCancellationGroup.createCompletableCharSequence();
|
||||
final Completable.CharSequence value = Completable.createCharSequence();
|
||||
try {
|
||||
mIInputContext.getTextAfterCursor(length, flags, ResultCallbacks.of(value));
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
return getResultOrNull(value, "getTextAfterCursor()");
|
||||
return getResultOrNull(value, "getTextAfterCursor()", mCancellationGroup);
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
@@ -128,14 +130,13 @@ public class InputConnectionWrapper implements InputConnection {
|
||||
return null;
|
||||
}
|
||||
|
||||
final CancellationGroup.Completable.CharSequence value =
|
||||
mCancellationGroup.createCompletableCharSequence();
|
||||
final Completable.CharSequence value = Completable.createCharSequence();
|
||||
try {
|
||||
mIInputContext.getTextBeforeCursor(length, flags, ResultCallbacks.of(value));
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
return getResultOrNull(value, "getTextBeforeCursor()");
|
||||
return getResultOrNull(value, "getTextBeforeCursor()", mCancellationGroup);
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
@@ -148,14 +149,13 @@ public class InputConnectionWrapper implements InputConnection {
|
||||
// This method is not implemented.
|
||||
return null;
|
||||
}
|
||||
final CancellationGroup.Completable.CharSequence value =
|
||||
mCancellationGroup.createCompletableCharSequence();
|
||||
final Completable.CharSequence value = Completable.createCharSequence();
|
||||
try {
|
||||
mIInputContext.getSelectedText(flags, ResultCallbacks.of(value));
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
return getResultOrNull(value, "getSelectedText()");
|
||||
return getResultOrNull(value, "getSelectedText()", mCancellationGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,15 +179,14 @@ public class InputConnectionWrapper implements InputConnection {
|
||||
// This method is not implemented.
|
||||
return null;
|
||||
}
|
||||
final CancellationGroup.Completable.SurroundingText value =
|
||||
mCancellationGroup.createCompletableSurroundingText();
|
||||
final Completable.SurroundingText value = Completable.createSurroundingText();
|
||||
try {
|
||||
mIInputContext.getSurroundingText(beforeLength, afterLength, flags,
|
||||
ResultCallbacks.of(value));
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
return getResultOrNull(value, "getSurroundingText()");
|
||||
return getResultOrNull(value, "getSurroundingText()", mCancellationGroup);
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
@@ -196,14 +195,13 @@ public class InputConnectionWrapper implements InputConnection {
|
||||
return 0;
|
||||
}
|
||||
|
||||
final CancellationGroup.Completable.Int value =
|
||||
mCancellationGroup.createCompletableInt();
|
||||
final Completable.Int value = Completable.createInt();
|
||||
try {
|
||||
mIInputContext.getCursorCapsMode(reqModes, ResultCallbacks.of(value));
|
||||
} catch (RemoteException e) {
|
||||
return 0;
|
||||
}
|
||||
return getResultOrZero(value, "getCursorCapsMode()");
|
||||
return getResultOrZero(value, "getCursorCapsMode()", mCancellationGroup);
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
@@ -212,14 +210,13 @@ public class InputConnectionWrapper implements InputConnection {
|
||||
return null;
|
||||
}
|
||||
|
||||
final CancellationGroup.Completable.ExtractedText value =
|
||||
mCancellationGroup.createCompletableExtractedText();
|
||||
final Completable.ExtractedText value = Completable.createExtractedText();
|
||||
try {
|
||||
mIInputContext.getExtractedText(request, flags, ResultCallbacks.of(value));
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
return getResultOrNull(value, "getExtractedText()");
|
||||
return getResultOrNull(value, "getExtractedText()", mCancellationGroup);
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
@@ -423,14 +420,14 @@ public class InputConnectionWrapper implements InputConnection {
|
||||
// This method is not implemented.
|
||||
return false;
|
||||
}
|
||||
final CancellationGroup.Completable.Int value = mCancellationGroup.createCompletableInt();
|
||||
final Completable.Int value = Completable.createInt();
|
||||
try {
|
||||
mIInputContext.requestUpdateCursorAnchorInfo(cursorUpdateMode,
|
||||
ResultCallbacks.of(value));
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
return getResultOrZero(value, "requestUpdateCursorAnchorInfo()") != 0;
|
||||
return getResultOrZero(value, "requestUpdateCursorAnchorInfo()", mCancellationGroup) != 0;
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
@@ -464,13 +461,13 @@ public class InputConnectionWrapper implements InputConnection {
|
||||
inputMethodService.exposeContent(inputContentInfo, this);
|
||||
}
|
||||
|
||||
final CancellationGroup.Completable.Int value = mCancellationGroup.createCompletableInt();
|
||||
final Completable.Int value = Completable.createInt();
|
||||
try {
|
||||
mIInputContext.commitContent(inputContentInfo, flags, opts, ResultCallbacks.of(value));
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
return getResultOrZero(value, "commitContent()") != 0;
|
||||
return getResultOrZero(value, "commitContent()", mCancellationGroup) != 0;
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
|
||||
Reference in New Issue
Block a user