Loading core/java/com/android/internal/inputmethod/CallbackUtils.java +14 −1 Original line number Diff line number Diff line Loading @@ -45,8 +45,21 @@ public final class CallbackUtils { @AnyThread public static void onResult(@NonNull IInputBindResultResultCallback callback, @NonNull Supplier<InputBindResult> resultSupplier) { InputBindResult result = null; Throwable exception = null; try { callback.onResult(resultSupplier.get()); result = resultSupplier.get(); } catch (Throwable throwable) { exception = throwable; } try { if (exception != null) { callback.onError(ThrowableHolder.of(exception)); return; } callback.onResult(result); } catch (RemoteException ignored) { } } } core/java/com/android/internal/inputmethod/Completable.java +137 −31 Original line number Diff line number Diff line Loading @@ -16,13 +16,17 @@ package com.android.internal.inputmethod; import static java.lang.annotation.RetentionPolicy.SOURCE; import android.annotation.AnyThread; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.util.Log; import com.android.internal.annotations.GuardedBy; import java.lang.annotation.Retention; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; Loading Loading @@ -51,21 +55,100 @@ public final class Completable { /** * Lock {@link Object} to guard complete operations within this class. */ protected final Object mValueLock = new Object(); protected final Object mStateLock = new Object(); /** * {@code true} after {@link #onComplete()} gets called. * Indicates the completion state of this object. */ @GuardedBy("mValueLock") protected boolean mHasValue = false; @GuardedBy("mStateLock") @CompletionState protected int mState = CompletionState.NOT_COMPLETED; /** * @return {@link true} if {@link #onComplete()} gets called already. * {@link Throwable} message passed to {@link #onError(ThrowableHolder)}. * * <p>This is not {@code null} only when {@link #mState} is * {@link CompletionState#COMPLETED_WITH_ERROR}.</p> */ @GuardedBy("mStateLock") @Nullable protected String mMessage = null; @Retention(SOURCE) @IntDef({ CompletionState.NOT_COMPLETED, CompletionState.COMPLETED_WITH_VALUE, CompletionState.COMPLETED_WITH_ERROR}) protected @interface CompletionState { /** * This object is not completed yet. */ int NOT_COMPLETED = 0; /** * This object is already completed with a value. */ int COMPLETED_WITH_VALUE = 1; /** * This object is already completed with an error. */ int COMPLETED_WITH_ERROR = 2; } /** * Converts the given {@link CompletionState} into a human-readable string. * * @param state {@link CompletionState} to be converted. * @return a human-readable {@link String} for the given {@code state}. */ @AnyThread protected static String stateToString(@CompletionState int state) { switch (state) { case CompletionState.NOT_COMPLETED: return "NOT_COMPLETED"; case CompletionState.COMPLETED_WITH_VALUE: return "COMPLETED_WITH_VALUE"; case CompletionState.COMPLETED_WITH_ERROR: return "COMPLETED_WITH_ERROR"; default: return "Unknown(value=" + state + ")"; } } /** * @return {@link true} if {@link #onComplete()} gets called and {@link #mState} is * {@link CompletionState#COMPLETED_WITH_VALUE} . */ @AnyThread public boolean hasValue() { synchronized (mValueLock) { return mHasValue; synchronized (mStateLock) { return mState == CompletionState.COMPLETED_WITH_VALUE; } } /** * Provides the base implementation of {@code getValue()} for derived classes. * * <p>Must be called after acquiring {@link #mStateLock}.</p> * * @throws RuntimeException when {@link #mState} is * {@link CompletionState#COMPLETED_WITH_ERROR}. * @throws UnsupportedOperationException when {@link #mState} is not * {@link CompletionState#COMPLETED_WITH_VALUE} and * {@link CompletionState#COMPLETED_WITH_ERROR}. */ @GuardedBy("mStateLock") protected void enforceGetValueLocked() { switch (mState) { case CompletionState.NOT_COMPLETED: throw new UnsupportedOperationException( "getValue() is allowed only if hasValue() returns true"); case CompletionState.COMPLETED_WITH_VALUE: return; case CompletionState.COMPLETED_WITH_ERROR: throw new RuntimeException(mMessage); default: throw new UnsupportedOperationException( "getValue() is not allowed on state=" + stateToString(mState)); } } Loading @@ -77,6 +160,27 @@ public final class Completable { mLatch.countDown(); } /** * Notify when exception happened. * * @param throwableHolder contains the {@link Throwable} object when exception happened. */ @AnyThread protected void onError(ThrowableHolder throwableHolder) { synchronized (mStateLock) { switch (mState) { case CompletionState.NOT_COMPLETED: mMessage = throwableHolder.getMessage(); mState = CompletionState.COMPLETED_WITH_ERROR; break; default: throw new UnsupportedOperationException( "onError() is not allowed on state=" + stateToString(mState)); } } onComplete(); } /** * Blocks the calling thread until at least one of the following conditions is met. * Loading Loading @@ -140,7 +244,7 @@ public final class Completable { * Completable object of integer primitive. */ public static final class Int extends ValueBase { @GuardedBy("mValueLock") @GuardedBy("mStateLock") private int mValue = 0; /** Loading @@ -150,29 +254,30 @@ public final class Completable { */ @AnyThread void onComplete(int value) { synchronized (mValueLock) { if (mHasValue) { synchronized (mStateLock) { switch (mState) { case CompletionState.NOT_COMPLETED: mValue = value; mState = CompletionState.COMPLETED_WITH_VALUE; break; default: throw new UnsupportedOperationException( "onComplete() cannot be called multiple times"); "onComplete() is not allowed on state=" + stateToString(mState)); } mValue = value; mHasValue = true; } onComplete(); } /** * @return value associated with this object. * @throws RuntimeException when called while {@link #onError} happened. * @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"); } synchronized (mStateLock) { enforceGetValueLocked(); return mValue; } } Loading @@ -184,7 +289,7 @@ public final class Completable { * @param <T> type associated with this completable object. */ public static class Values<T> extends ValueBase { @GuardedBy("mValueLock") @GuardedBy("mStateLock") @Nullable private T mValue = null; Loading @@ -195,30 +300,31 @@ public final class Completable { */ @AnyThread void onComplete(@Nullable T value) { synchronized (mValueLock) { if (mHasValue) { synchronized (mStateLock) { switch (mState) { case CompletionState.NOT_COMPLETED: mValue = value; mState = CompletionState.COMPLETED_WITH_VALUE; break; default: throw new UnsupportedOperationException( "onComplete() cannot be called multiple times"); "onComplete() is not allowed on state=" + stateToString(mState)); } mValue = value; mHasValue = true; } onComplete(); } /** * @return value associated with this object. * @throws RuntimeException when called while {@link #onError} happened * @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"); } synchronized (mStateLock) { enforceGetValueLocked(); return mValue; } } Loading core/java/com/android/internal/inputmethod/IInputBindResultResultCallback.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -17,7 +17,9 @@ package com.android.internal.inputmethod; import com.android.internal.view.InputBindResult; import com.android.internal.inputmethod.ThrowableHolder; oneway interface IInputBindResultResultCallback { void onResult(in InputBindResult result); void onError(in ThrowableHolder exception); } No newline at end of file core/java/com/android/internal/inputmethod/ResultCallbacks.java +10 −0 Original line number Diff line number Diff line Loading @@ -181,6 +181,16 @@ public final class ResultCallbacks { } value.onComplete(result); } @BinderThread @Override public void onError(ThrowableHolder throwableHolder) { final Completable.InputBindResult value = unwrap(atomicRef); if (value == null) { return; } value.onError(throwableHolder); } }; } } core/java/com/android/internal/inputmethod/ThrowableHolder.aidl 0 → 100644 +19 −0 Original line number Diff line number Diff line /* * Copyright (C) 2008 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; parcelable ThrowableHolder; No newline at end of file Loading
core/java/com/android/internal/inputmethod/CallbackUtils.java +14 −1 Original line number Diff line number Diff line Loading @@ -45,8 +45,21 @@ public final class CallbackUtils { @AnyThread public static void onResult(@NonNull IInputBindResultResultCallback callback, @NonNull Supplier<InputBindResult> resultSupplier) { InputBindResult result = null; Throwable exception = null; try { callback.onResult(resultSupplier.get()); result = resultSupplier.get(); } catch (Throwable throwable) { exception = throwable; } try { if (exception != null) { callback.onError(ThrowableHolder.of(exception)); return; } callback.onResult(result); } catch (RemoteException ignored) { } } }
core/java/com/android/internal/inputmethod/Completable.java +137 −31 Original line number Diff line number Diff line Loading @@ -16,13 +16,17 @@ package com.android.internal.inputmethod; import static java.lang.annotation.RetentionPolicy.SOURCE; import android.annotation.AnyThread; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.util.Log; import com.android.internal.annotations.GuardedBy; import java.lang.annotation.Retention; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; Loading Loading @@ -51,21 +55,100 @@ public final class Completable { /** * Lock {@link Object} to guard complete operations within this class. */ protected final Object mValueLock = new Object(); protected final Object mStateLock = new Object(); /** * {@code true} after {@link #onComplete()} gets called. * Indicates the completion state of this object. */ @GuardedBy("mValueLock") protected boolean mHasValue = false; @GuardedBy("mStateLock") @CompletionState protected int mState = CompletionState.NOT_COMPLETED; /** * @return {@link true} if {@link #onComplete()} gets called already. * {@link Throwable} message passed to {@link #onError(ThrowableHolder)}. * * <p>This is not {@code null} only when {@link #mState} is * {@link CompletionState#COMPLETED_WITH_ERROR}.</p> */ @GuardedBy("mStateLock") @Nullable protected String mMessage = null; @Retention(SOURCE) @IntDef({ CompletionState.NOT_COMPLETED, CompletionState.COMPLETED_WITH_VALUE, CompletionState.COMPLETED_WITH_ERROR}) protected @interface CompletionState { /** * This object is not completed yet. */ int NOT_COMPLETED = 0; /** * This object is already completed with a value. */ int COMPLETED_WITH_VALUE = 1; /** * This object is already completed with an error. */ int COMPLETED_WITH_ERROR = 2; } /** * Converts the given {@link CompletionState} into a human-readable string. * * @param state {@link CompletionState} to be converted. * @return a human-readable {@link String} for the given {@code state}. */ @AnyThread protected static String stateToString(@CompletionState int state) { switch (state) { case CompletionState.NOT_COMPLETED: return "NOT_COMPLETED"; case CompletionState.COMPLETED_WITH_VALUE: return "COMPLETED_WITH_VALUE"; case CompletionState.COMPLETED_WITH_ERROR: return "COMPLETED_WITH_ERROR"; default: return "Unknown(value=" + state + ")"; } } /** * @return {@link true} if {@link #onComplete()} gets called and {@link #mState} is * {@link CompletionState#COMPLETED_WITH_VALUE} . */ @AnyThread public boolean hasValue() { synchronized (mValueLock) { return mHasValue; synchronized (mStateLock) { return mState == CompletionState.COMPLETED_WITH_VALUE; } } /** * Provides the base implementation of {@code getValue()} for derived classes. * * <p>Must be called after acquiring {@link #mStateLock}.</p> * * @throws RuntimeException when {@link #mState} is * {@link CompletionState#COMPLETED_WITH_ERROR}. * @throws UnsupportedOperationException when {@link #mState} is not * {@link CompletionState#COMPLETED_WITH_VALUE} and * {@link CompletionState#COMPLETED_WITH_ERROR}. */ @GuardedBy("mStateLock") protected void enforceGetValueLocked() { switch (mState) { case CompletionState.NOT_COMPLETED: throw new UnsupportedOperationException( "getValue() is allowed only if hasValue() returns true"); case CompletionState.COMPLETED_WITH_VALUE: return; case CompletionState.COMPLETED_WITH_ERROR: throw new RuntimeException(mMessage); default: throw new UnsupportedOperationException( "getValue() is not allowed on state=" + stateToString(mState)); } } Loading @@ -77,6 +160,27 @@ public final class Completable { mLatch.countDown(); } /** * Notify when exception happened. * * @param throwableHolder contains the {@link Throwable} object when exception happened. */ @AnyThread protected void onError(ThrowableHolder throwableHolder) { synchronized (mStateLock) { switch (mState) { case CompletionState.NOT_COMPLETED: mMessage = throwableHolder.getMessage(); mState = CompletionState.COMPLETED_WITH_ERROR; break; default: throw new UnsupportedOperationException( "onError() is not allowed on state=" + stateToString(mState)); } } onComplete(); } /** * Blocks the calling thread until at least one of the following conditions is met. * Loading Loading @@ -140,7 +244,7 @@ public final class Completable { * Completable object of integer primitive. */ public static final class Int extends ValueBase { @GuardedBy("mValueLock") @GuardedBy("mStateLock") private int mValue = 0; /** Loading @@ -150,29 +254,30 @@ public final class Completable { */ @AnyThread void onComplete(int value) { synchronized (mValueLock) { if (mHasValue) { synchronized (mStateLock) { switch (mState) { case CompletionState.NOT_COMPLETED: mValue = value; mState = CompletionState.COMPLETED_WITH_VALUE; break; default: throw new UnsupportedOperationException( "onComplete() cannot be called multiple times"); "onComplete() is not allowed on state=" + stateToString(mState)); } mValue = value; mHasValue = true; } onComplete(); } /** * @return value associated with this object. * @throws RuntimeException when called while {@link #onError} happened. * @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"); } synchronized (mStateLock) { enforceGetValueLocked(); return mValue; } } Loading @@ -184,7 +289,7 @@ public final class Completable { * @param <T> type associated with this completable object. */ public static class Values<T> extends ValueBase { @GuardedBy("mValueLock") @GuardedBy("mStateLock") @Nullable private T mValue = null; Loading @@ -195,30 +300,31 @@ public final class Completable { */ @AnyThread void onComplete(@Nullable T value) { synchronized (mValueLock) { if (mHasValue) { synchronized (mStateLock) { switch (mState) { case CompletionState.NOT_COMPLETED: mValue = value; mState = CompletionState.COMPLETED_WITH_VALUE; break; default: throw new UnsupportedOperationException( "onComplete() cannot be called multiple times"); "onComplete() is not allowed on state=" + stateToString(mState)); } mValue = value; mHasValue = true; } onComplete(); } /** * @return value associated with this object. * @throws RuntimeException when called while {@link #onError} happened * @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"); } synchronized (mStateLock) { enforceGetValueLocked(); return mValue; } } Loading
core/java/com/android/internal/inputmethod/IInputBindResultResultCallback.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -17,7 +17,9 @@ package com.android.internal.inputmethod; import com.android.internal.view.InputBindResult; import com.android.internal.inputmethod.ThrowableHolder; oneway interface IInputBindResultResultCallback { void onResult(in InputBindResult result); void onError(in ThrowableHolder exception); } No newline at end of file
core/java/com/android/internal/inputmethod/ResultCallbacks.java +10 −0 Original line number Diff line number Diff line Loading @@ -181,6 +181,16 @@ public final class ResultCallbacks { } value.onComplete(result); } @BinderThread @Override public void onError(ThrowableHolder throwableHolder) { final Completable.InputBindResult value = unwrap(atomicRef); if (value == null) { return; } value.onError(throwableHolder); } }; } }
core/java/com/android/internal/inputmethod/ThrowableHolder.aidl 0 → 100644 +19 −0 Original line number Diff line number Diff line /* * Copyright (C) 2008 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; parcelable ThrowableHolder; No newline at end of file