Merge "Deprecate MissingMethodFlags to preserve invocation order"
This commit is contained in:
committed by
Android (Google) Code Review
commit
6676af25d0
@@ -32,7 +32,6 @@ import android.view.InputChannel;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputBinding;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
import android.view.inputmethod.InputConnectionInspector;
|
||||
import android.view.inputmethod.InputMethod;
|
||||
import android.view.inputmethod.InputMethodSession;
|
||||
import android.view.inputmethod.InputMethodSubtype;
|
||||
@@ -190,10 +189,8 @@ class IInputMethodWrapper extends IInputMethod.Stub
|
||||
final EditorInfo info = (EditorInfo) args.arg3;
|
||||
final CancellationGroup cancellationGroup = (CancellationGroup) args.arg4;
|
||||
final boolean restarting = args.argi5 == 1;
|
||||
final int missingMethod = args.argi6;
|
||||
final InputConnection ic = inputContext != null
|
||||
? new RemoteInputConnection(
|
||||
mTarget, inputContext, missingMethod, cancellationGroup)
|
||||
? new RemoteInputConnection(mTarget, inputContext, cancellationGroup)
|
||||
: null;
|
||||
info.makeCompatible(mTargetSdkVersion);
|
||||
inputMethod.dispatchStartInputWithToken(ic, info, restarting, startInputToken);
|
||||
@@ -295,11 +292,8 @@ class IInputMethodWrapper extends IInputMethod.Stub
|
||||
Log.e(TAG, "bindInput must be paired with unbindInput.");
|
||||
}
|
||||
mCancellationGroup = new CancellationGroup();
|
||||
// This IInputContext is guaranteed to implement all the methods.
|
||||
final int missingMethodFlags = 0;
|
||||
InputConnection ic = new RemoteInputConnection(mTarget,
|
||||
IInputContext.Stub.asInterface(binding.getConnectionToken()), missingMethodFlags,
|
||||
mCancellationGroup);
|
||||
IInputContext.Stub.asInterface(binding.getConnectionToken()), mCancellationGroup);
|
||||
InputBinding nu = new InputBinding(ic, binding);
|
||||
mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_INPUT_CONTEXT, nu));
|
||||
}
|
||||
@@ -320,14 +314,13 @@ class IInputMethodWrapper extends IInputMethod.Stub
|
||||
@BinderThread
|
||||
@Override
|
||||
public void startInput(IBinder startInputToken, IInputContext inputContext,
|
||||
@InputConnectionInspector.MissingMethodFlags final int missingMethods,
|
||||
EditorInfo attribute, boolean restarting) {
|
||||
if (mCancellationGroup == null) {
|
||||
Log.e(TAG, "startInput must be called after bindInput.");
|
||||
mCancellationGroup = new CancellationGroup();
|
||||
}
|
||||
mCaller.executeOrSendMessage(mCaller.obtainMessageOOOOII(DO_START_INPUT, startInputToken,
|
||||
inputContext, attribute, mCancellationGroup, restarting ? 1 : 0, missingMethods));
|
||||
inputContext, attribute, mCancellationGroup, restarting ? 1 : 0, 0 /* unused */));
|
||||
}
|
||||
|
||||
@BinderThread
|
||||
|
||||
@@ -29,8 +29,6 @@ import android.view.inputmethod.CorrectionInfo;
|
||||
import android.view.inputmethod.ExtractedText;
|
||||
import android.view.inputmethod.ExtractedTextRequest;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
import android.view.inputmethod.InputConnectionInspector;
|
||||
import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags;
|
||||
import android.view.inputmethod.InputContentInfo;
|
||||
import android.view.inputmethod.SurroundingText;
|
||||
|
||||
@@ -87,9 +85,6 @@ final class RemoteInputConnection implements InputConnection {
|
||||
@NonNull
|
||||
private final InputMethodServiceInternalHolder mImsInternal;
|
||||
|
||||
@MissingMethodFlags
|
||||
private final int mMissingMethods;
|
||||
|
||||
/**
|
||||
* Signaled when the system decided to take away IME focus from the target app.
|
||||
*
|
||||
@@ -101,11 +96,9 @@ final class RemoteInputConnection implements InputConnection {
|
||||
|
||||
RemoteInputConnection(
|
||||
@NonNull WeakReference<InputMethodServiceInternal> inputMethodService,
|
||||
IInputContext inputContext, @MissingMethodFlags int missingMethods,
|
||||
@NonNull CancellationGroup cancellationGroup) {
|
||||
IInputContext inputContext, @NonNull CancellationGroup cancellationGroup) {
|
||||
mImsInternal = new InputMethodServiceInternalHolder(inputMethodService);
|
||||
mInvoker = IInputContextInvoker.create(inputContext);
|
||||
mMissingMethods = missingMethods;
|
||||
mCancellationGroup = cancellationGroup;
|
||||
}
|
||||
|
||||
@@ -163,10 +156,6 @@ final class RemoteInputConnection implements InputConnection {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isMethodMissing(MissingMethodFlags.GET_SELECTED_TEXT)) {
|
||||
// This method is not implemented.
|
||||
return null;
|
||||
}
|
||||
final CompletableFuture<CharSequence> value = mInvoker.getSelectedText(flags);
|
||||
final CharSequence result = CompletableFutureUtil.getResultOrNull(
|
||||
value, TAG, "getSelectedText()", mCancellationGroup, MAX_WAIT_TIME_MILLIS);
|
||||
@@ -200,10 +189,6 @@ final class RemoteInputConnection implements InputConnection {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isMethodMissing(MissingMethodFlags.GET_SURROUNDING_TEXT)) {
|
||||
// This method is not implemented.
|
||||
return null;
|
||||
}
|
||||
final CompletableFuture<SurroundingText> value = mInvoker.getSurroundingText(beforeLength,
|
||||
afterLength, flags);
|
||||
final SurroundingText result = CompletableFutureUtil.getResultOrNull(
|
||||
@@ -284,10 +269,6 @@ final class RemoteInputConnection implements InputConnection {
|
||||
|
||||
@AnyThread
|
||||
public boolean commitCorrection(CorrectionInfo correctionInfo) {
|
||||
if (isMethodMissing(MissingMethodFlags.COMMIT_CORRECTION)) {
|
||||
// This method is not implemented.
|
||||
return false;
|
||||
}
|
||||
return mInvoker.commitCorrection(correctionInfo);
|
||||
}
|
||||
|
||||
@@ -308,10 +289,6 @@ final class RemoteInputConnection implements InputConnection {
|
||||
|
||||
@AnyThread
|
||||
public boolean setComposingRegion(int start, int end) {
|
||||
if (isMethodMissing(MissingMethodFlags.SET_COMPOSING_REGION)) {
|
||||
// This method is not implemented.
|
||||
return false;
|
||||
}
|
||||
return mInvoker.setComposingRegion(start, end);
|
||||
}
|
||||
|
||||
@@ -360,10 +337,6 @@ final class RemoteInputConnection implements InputConnection {
|
||||
|
||||
@AnyThread
|
||||
public boolean deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) {
|
||||
if (isMethodMissing(MissingMethodFlags.DELETE_SURROUNDING_TEXT_IN_CODE_POINTS)) {
|
||||
// This method is not implemented.
|
||||
return false;
|
||||
}
|
||||
return mInvoker.deleteSurroundingTextInCodePoints(beforeLength, afterLength);
|
||||
}
|
||||
|
||||
@@ -389,11 +362,6 @@ final class RemoteInputConnection implements InputConnection {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isMethodMissing(MissingMethodFlags.REQUEST_CURSOR_UPDATES)) {
|
||||
// This method is not implemented.
|
||||
return false;
|
||||
}
|
||||
|
||||
final InputMethodServiceInternal ims = mImsInternal.getAndWarnIfNull();
|
||||
if (ims == null) {
|
||||
return false;
|
||||
@@ -423,11 +391,6 @@ final class RemoteInputConnection implements InputConnection {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isMethodMissing(MissingMethodFlags.COMMIT_CONTENT)) {
|
||||
// This method is not implemented.
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((flags & InputConnection.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
|
||||
final InputMethodServiceInternal imsInternal = mImsInternal.getAndWarnIfNull();
|
||||
if (imsInternal == null) {
|
||||
@@ -450,17 +413,10 @@ final class RemoteInputConnection implements InputConnection {
|
||||
return mInvoker.setImeConsumesInput(imeConsumesInput);
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
private boolean isMethodMissing(@MissingMethodFlags final int methodFlag) {
|
||||
return (mMissingMethods & methodFlag) == methodFlag;
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RemoteInputConnection{idHash=#"
|
||||
+ Integer.toHexString(System.identityHashCode(this))
|
||||
+ " mMissingMethods="
|
||||
+ InputConnectionInspector.getMissingMethodFlagsAsString(mMissingMethods) + "}";
|
||||
+ Integer.toHexString(System.identityHashCode(this)) + "}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,10 +274,7 @@ public interface InputConnection {
|
||||
*
|
||||
* @param flags Supplies additional options controlling how the text is
|
||||
* returned. May be either {@code 0} or {@link #GET_TEXT_WITH_STYLES}.
|
||||
* @return the text that is currently selected, if any, or null if
|
||||
* no text is selected. In {@link android.os.Build.VERSION_CODES#N} and
|
||||
* later, returns false when the target application does not implement
|
||||
* this method.
|
||||
* @return the text that is currently selected, if any, or {@code null} if no text is selected.
|
||||
*/
|
||||
CharSequence getSelectedText(int flags);
|
||||
|
||||
@@ -483,8 +480,9 @@ public interface InputConnection {
|
||||
* If this is greater than the number of existing characters between the cursor and
|
||||
* the end of the text, then this method does not fail but deletes all the characters in
|
||||
* that range.
|
||||
* @return true on success, false if the input connection is no longer valid. Returns
|
||||
* {@code false} when the target application does not implement this method.
|
||||
* @return {@code true} on success, {@code false} if the input connection is no longer valid.
|
||||
* Before Android {@link android.os.Build.VERSION_CODES#TIRAMISU}, this API returned
|
||||
* {@code false} when the target application does not implement this method.
|
||||
*/
|
||||
boolean deleteSurroundingTextInCodePoints(int beforeLength, int afterLength);
|
||||
|
||||
@@ -573,9 +571,10 @@ public interface InputConnection {
|
||||
*
|
||||
* @param start the position in the text at which the composing region begins
|
||||
* @param end the position in the text at which the composing region ends
|
||||
* @return true on success, false if the input connection is no longer
|
||||
* valid. In {@link android.os.Build.VERSION_CODES#N} and later, false is returned when the
|
||||
* target application does not implement this method.
|
||||
* @return {@code true} on success, {@code false} if the input connection is no longer valid.
|
||||
* Since Android {@link android.os.Build.VERSION_CODES#N} until
|
||||
* {@link android.os.Build.VERSION_CODES#TIRAMISU}, this API returned {@code false} when
|
||||
* the target application does not implement this method.
|
||||
*/
|
||||
boolean setComposingRegion(int start, int end);
|
||||
|
||||
@@ -686,9 +685,10 @@ public interface InputConnection {
|
||||
* in progress.</p>
|
||||
*
|
||||
* @param correctionInfo Detailed information about the correction.
|
||||
* @return true on success, false if the input connection is no longer valid.
|
||||
* In {@link android.os.Build.VERSION_CODES#N} and later, returns false
|
||||
* when the target application does not implement this method.
|
||||
* @return {@code true} on success, {@code false} if the input connection is no longer valid.
|
||||
* Since Android {@link android.os.Build.VERSION_CODES#N} until
|
||||
* {@link android.os.Build.VERSION_CODES#TIRAMISU}, this API returned {@code false} when
|
||||
* the target application does not implement this method.
|
||||
*/
|
||||
boolean commitCorrection(CorrectionInfo correctionInfo);
|
||||
|
||||
@@ -924,10 +924,11 @@ public interface InputConnection {
|
||||
* {@link #CURSOR_UPDATE_MONITOR}. Pass {@code 0} to disable the effect of
|
||||
* {@link #CURSOR_UPDATE_MONITOR}.
|
||||
* @return {@code true} if the request is scheduled. {@code false} to indicate that when the
|
||||
* application will not call
|
||||
* {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)}.
|
||||
* In {@link android.os.Build.VERSION_CODES#N} and later, returns {@code false} also when the
|
||||
* target application does not implement this method.
|
||||
* application will not call {@link InputMethodManager#updateCursorAnchorInfo(
|
||||
* android.view.View, CursorAnchorInfo)}.
|
||||
* Since Android {@link android.os.Build.VERSION_CODES#N} until
|
||||
* {@link android.os.Build.VERSION_CODES#TIRAMISU}, this API returned {@code false} when
|
||||
* the target application does not implement this method.
|
||||
*/
|
||||
boolean requestCursorUpdates(int cursorUpdateMode);
|
||||
|
||||
|
||||
@@ -1,293 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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 android.view.inputmethod;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Bundle;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final class InputConnectionInspector {
|
||||
|
||||
@Retention(SOURCE)
|
||||
@IntDef({MissingMethodFlags.GET_SELECTED_TEXT,
|
||||
MissingMethodFlags.SET_COMPOSING_REGION,
|
||||
MissingMethodFlags.COMMIT_CORRECTION,
|
||||
MissingMethodFlags.REQUEST_CURSOR_UPDATES,
|
||||
MissingMethodFlags.DELETE_SURROUNDING_TEXT_IN_CODE_POINTS,
|
||||
MissingMethodFlags.GET_HANDLER,
|
||||
MissingMethodFlags.CLOSE_CONNECTION,
|
||||
MissingMethodFlags.COMMIT_CONTENT,
|
||||
MissingMethodFlags.GET_SURROUNDING_TEXT
|
||||
})
|
||||
public @interface MissingMethodFlags {
|
||||
/**
|
||||
* {@link InputConnection#getSelectedText(int)} is available in
|
||||
* {@link android.os.Build.VERSION_CODES#GINGERBREAD} and later.
|
||||
*/
|
||||
int GET_SELECTED_TEXT = 1 << 0;
|
||||
/**
|
||||
* {@link InputConnection#setComposingRegion(int, int)} is available in
|
||||
* {@link android.os.Build.VERSION_CODES#GINGERBREAD} and later.
|
||||
*/
|
||||
int SET_COMPOSING_REGION = 1 << 1;
|
||||
/**
|
||||
* {@link InputConnection#commitCorrection(CorrectionInfo)} is available in
|
||||
* {@link android.os.Build.VERSION_CODES#HONEYCOMB} and later.
|
||||
*/
|
||||
int COMMIT_CORRECTION = 1 << 2;
|
||||
/**
|
||||
* {@link InputConnection#requestCursorUpdates(int)} is available in
|
||||
* {@link android.os.Build.VERSION_CODES#LOLLIPOP} and later.
|
||||
*/
|
||||
int REQUEST_CURSOR_UPDATES = 1 << 3;
|
||||
/**
|
||||
* {@link InputConnection#deleteSurroundingTextInCodePoints(int, int)}} is available in
|
||||
* {@link android.os.Build.VERSION_CODES#N} and later.
|
||||
*/
|
||||
int DELETE_SURROUNDING_TEXT_IN_CODE_POINTS = 1 << 4;
|
||||
/**
|
||||
* {@link InputConnection#deleteSurroundingTextInCodePoints(int, int)}} is available in
|
||||
* {@link android.os.Build.VERSION_CODES#N} and later.
|
||||
*/
|
||||
int GET_HANDLER = 1 << 5;
|
||||
/**
|
||||
* {@link InputConnection#closeConnection()}} is available in
|
||||
* {@link android.os.Build.VERSION_CODES#N} and later.
|
||||
*/
|
||||
int CLOSE_CONNECTION = 1 << 6;
|
||||
/**
|
||||
* {@link InputConnection#commitContent(InputContentInfo, int, Bundle)} is available in
|
||||
* {@link android.os.Build.VERSION_CODES#N} MR-1 and later.
|
||||
*/
|
||||
int COMMIT_CONTENT = 1 << 7;
|
||||
/**
|
||||
* {@link InputConnection#getSurroundingText(int, int, int)} is available in
|
||||
* {@link android.os.Build.VERSION_CODES#S} and later.
|
||||
*/
|
||||
int GET_SURROUNDING_TEXT = 1 << 8;
|
||||
}
|
||||
|
||||
private static final Map<Class, Integer> sMissingMethodsMap = Collections.synchronizedMap(
|
||||
new WeakHashMap<>());
|
||||
|
||||
@MissingMethodFlags
|
||||
public static int getMissingMethodFlags(@Nullable final InputConnection ic) {
|
||||
if (ic == null) {
|
||||
return 0;
|
||||
}
|
||||
// Optimization for a known class.
|
||||
if (ic instanceof BaseInputConnection) {
|
||||
return 0;
|
||||
}
|
||||
// Optimization for a known class.
|
||||
if (ic instanceof InputConnectionWrapper) {
|
||||
return ((InputConnectionWrapper) ic).getMissingMethodFlags();
|
||||
}
|
||||
return getMissingMethodFlagsInternal(ic.getClass());
|
||||
}
|
||||
|
||||
@MissingMethodFlags
|
||||
public static int getMissingMethodFlagsInternal(@NonNull final Class clazz) {
|
||||
final Integer cachedFlags = sMissingMethodsMap.get(clazz);
|
||||
if (cachedFlags != null) {
|
||||
return cachedFlags;
|
||||
}
|
||||
int flags = 0;
|
||||
if (!hasGetSelectedText(clazz)) {
|
||||
flags |= MissingMethodFlags.GET_SELECTED_TEXT;
|
||||
}
|
||||
if (!hasSetComposingRegion(clazz)) {
|
||||
flags |= MissingMethodFlags.SET_COMPOSING_REGION;
|
||||
}
|
||||
if (!hasCommitCorrection(clazz)) {
|
||||
flags |= MissingMethodFlags.COMMIT_CORRECTION;
|
||||
}
|
||||
if (!hasRequestCursorUpdate(clazz)) {
|
||||
flags |= MissingMethodFlags.REQUEST_CURSOR_UPDATES;
|
||||
}
|
||||
if (!hasDeleteSurroundingTextInCodePoints(clazz)) {
|
||||
flags |= MissingMethodFlags.DELETE_SURROUNDING_TEXT_IN_CODE_POINTS;
|
||||
}
|
||||
if (!hasGetHandler(clazz)) {
|
||||
flags |= MissingMethodFlags.GET_HANDLER;
|
||||
}
|
||||
if (!hasCloseConnection(clazz)) {
|
||||
flags |= MissingMethodFlags.CLOSE_CONNECTION;
|
||||
}
|
||||
if (!hasCommitContent(clazz)) {
|
||||
flags |= MissingMethodFlags.COMMIT_CONTENT;
|
||||
}
|
||||
if (!hasGetSurroundingText(clazz)) {
|
||||
flags |= MissingMethodFlags.GET_SURROUNDING_TEXT;
|
||||
}
|
||||
sMissingMethodsMap.put(clazz, flags);
|
||||
return flags;
|
||||
}
|
||||
|
||||
private static boolean hasGetSelectedText(@NonNull final Class clazz) {
|
||||
try {
|
||||
final Method method = clazz.getMethod("getSelectedText", int.class);
|
||||
return !Modifier.isAbstract(method.getModifiers());
|
||||
} catch (NoSuchMethodException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasSetComposingRegion(@NonNull final Class clazz) {
|
||||
try {
|
||||
final Method method = clazz.getMethod("setComposingRegion", int.class, int.class);
|
||||
return !Modifier.isAbstract(method.getModifiers());
|
||||
} catch (NoSuchMethodException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasCommitCorrection(@NonNull final Class clazz) {
|
||||
try {
|
||||
final Method method = clazz.getMethod("commitCorrection", CorrectionInfo.class);
|
||||
return !Modifier.isAbstract(method.getModifiers());
|
||||
} catch (NoSuchMethodException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasRequestCursorUpdate(@NonNull final Class clazz) {
|
||||
try {
|
||||
final Method method = clazz.getMethod("requestCursorUpdates", int.class);
|
||||
return !Modifier.isAbstract(method.getModifiers());
|
||||
} catch (NoSuchMethodException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasDeleteSurroundingTextInCodePoints(@NonNull final Class clazz) {
|
||||
try {
|
||||
final Method method = clazz.getMethod("deleteSurroundingTextInCodePoints", int.class,
|
||||
int.class);
|
||||
return !Modifier.isAbstract(method.getModifiers());
|
||||
} catch (NoSuchMethodException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasGetHandler(@NonNull final Class clazz) {
|
||||
try {
|
||||
final Method method = clazz.getMethod("getHandler");
|
||||
return !Modifier.isAbstract(method.getModifiers());
|
||||
} catch (NoSuchMethodException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasCloseConnection(@NonNull final Class clazz) {
|
||||
try {
|
||||
final Method method = clazz.getMethod("closeConnection");
|
||||
return !Modifier.isAbstract(method.getModifiers());
|
||||
} catch (NoSuchMethodException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasCommitContent(@NonNull final Class clazz) {
|
||||
try {
|
||||
final Method method = clazz.getMethod("commitContent", InputContentInfo.class,
|
||||
int.class, Bundle.class);
|
||||
return !Modifier.isAbstract(method.getModifiers());
|
||||
} catch (NoSuchMethodException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasGetSurroundingText(@NonNull final Class clazz) {
|
||||
try {
|
||||
final Method method = clazz.getMethod("getSurroundingText", int.class, int.class,
|
||||
int.class);
|
||||
return !Modifier.isAbstract(method.getModifiers());
|
||||
} catch (NoSuchMethodException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getMissingMethodFlagsAsString(@MissingMethodFlags final int flags) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
boolean isEmpty = true;
|
||||
if ((flags & MissingMethodFlags.GET_SELECTED_TEXT) != 0) {
|
||||
sb.append("getSelectedText(int)");
|
||||
isEmpty = false;
|
||||
}
|
||||
if ((flags & MissingMethodFlags.SET_COMPOSING_REGION) != 0) {
|
||||
if (!isEmpty) {
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append("setComposingRegion(int, int)");
|
||||
isEmpty = false;
|
||||
}
|
||||
if ((flags & MissingMethodFlags.COMMIT_CORRECTION) != 0) {
|
||||
if (!isEmpty) {
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append("commitCorrection(CorrectionInfo)");
|
||||
isEmpty = false;
|
||||
}
|
||||
if ((flags & MissingMethodFlags.REQUEST_CURSOR_UPDATES) != 0) {
|
||||
if (!isEmpty) {
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append("requestCursorUpdate(int)");
|
||||
isEmpty = false;
|
||||
}
|
||||
if ((flags & MissingMethodFlags.DELETE_SURROUNDING_TEXT_IN_CODE_POINTS) != 0) {
|
||||
if (!isEmpty) {
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append("deleteSurroundingTextInCodePoints(int, int)");
|
||||
isEmpty = false;
|
||||
}
|
||||
if ((flags & MissingMethodFlags.GET_HANDLER) != 0) {
|
||||
if (!isEmpty) {
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append("getHandler()");
|
||||
}
|
||||
if ((flags & MissingMethodFlags.CLOSE_CONNECTION) != 0) {
|
||||
if (!isEmpty) {
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append("closeConnection()");
|
||||
}
|
||||
if ((flags & MissingMethodFlags.COMMIT_CONTENT) != 0) {
|
||||
if (!isEmpty) {
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append("commitContent(InputContentInfo, Bundle)");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -30,8 +30,6 @@ import com.android.internal.util.Preconditions;
|
||||
public class InputConnectionWrapper implements InputConnection {
|
||||
private InputConnection mTarget;
|
||||
final boolean mMutable;
|
||||
@InputConnectionInspector.MissingMethodFlags
|
||||
private int mMissingMethodFlags;
|
||||
|
||||
/**
|
||||
* Initializes a wrapper.
|
||||
@@ -46,7 +44,6 @@ public class InputConnectionWrapper implements InputConnection {
|
||||
public InputConnectionWrapper(InputConnection target, boolean mutable) {
|
||||
mMutable = mutable;
|
||||
mTarget = target;
|
||||
mMissingMethodFlags = InputConnectionInspector.getMissingMethodFlags(target);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,15 +60,6 @@ public class InputConnectionWrapper implements InputConnection {
|
||||
throw new SecurityException("not mutable");
|
||||
}
|
||||
mTarget = target;
|
||||
mMissingMethodFlags = InputConnectionInspector.getMissingMethodFlags(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@InputConnectionInspector.MissingMethodFlags
|
||||
public int getMissingMethodFlags() {
|
||||
return mMissingMethodFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -683,7 +683,6 @@ public final class InputMethodManager {
|
||||
windowFlags,
|
||||
null,
|
||||
null,
|
||||
0 /* missingMethodFlags */,
|
||||
mCurRootView.mContext.getApplicationInfo().targetSdkVersion);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
@@ -1938,7 +1937,6 @@ public final class InputMethodManager {
|
||||
mServedInputConnection = null;
|
||||
}
|
||||
RemoteInputConnectionImpl servedInputConnection;
|
||||
final int missingMethodFlags;
|
||||
if (ic != null) {
|
||||
mCursorSelStart = tba.initialSelStart;
|
||||
mCursorSelEnd = tba.initialSelEnd;
|
||||
@@ -1946,19 +1944,17 @@ public final class InputMethodManager {
|
||||
mCursorCandEnd = -1;
|
||||
mCursorRect.setEmpty();
|
||||
mCursorAnchorInfo = null;
|
||||
missingMethodFlags = InputConnectionInspector.getMissingMethodFlags(ic);
|
||||
if ((missingMethodFlags & InputConnectionInspector.MissingMethodFlags.GET_HANDLER)
|
||||
!= 0) {
|
||||
// InputConnection#getHandler() is not implemented.
|
||||
icHandler = null;
|
||||
} else {
|
||||
icHandler = ic.getHandler();
|
||||
Handler handler = null;
|
||||
try {
|
||||
handler = ic.getHandler();
|
||||
} catch (AbstractMethodError ignored) {
|
||||
// TODO(b/199934664): See if we can remove this by providing a default impl.
|
||||
}
|
||||
icHandler = handler;
|
||||
servedInputConnection = new RemoteInputConnectionImpl(
|
||||
icHandler != null ? icHandler.getLooper() : vh.getLooper(), ic, this, view);
|
||||
} else {
|
||||
servedInputConnection = null;
|
||||
missingMethodFlags = 0;
|
||||
icHandler = null;
|
||||
}
|
||||
mServedInputConnection = servedInputConnection;
|
||||
@@ -1971,7 +1967,7 @@ public final class InputMethodManager {
|
||||
try {
|
||||
res = mService.startInputOrWindowGainedFocus(
|
||||
startInputReason, mClient, windowGainingFocus, startInputFlags,
|
||||
softInputMode, windowFlags, tba, servedInputConnection, missingMethodFlags,
|
||||
softInputMode, windowFlags, tba, servedInputConnection,
|
||||
view.getContext().getApplicationInfo().targetSdkVersion);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
|
||||
@@ -38,8 +38,6 @@ import android.view.inputmethod.CorrectionInfo;
|
||||
import android.view.inputmethod.DumpableInputConnection;
|
||||
import android.view.inputmethod.ExtractedTextRequest;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
import android.view.inputmethod.InputConnectionInspector;
|
||||
import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags;
|
||||
import android.view.inputmethod.InputContentInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
@@ -145,10 +143,10 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub {
|
||||
if (ic == null) {
|
||||
return;
|
||||
}
|
||||
@MissingMethodFlags
|
||||
final int missingMethods = InputConnectionInspector.getMissingMethodFlags(ic);
|
||||
if ((missingMethods & MissingMethodFlags.CLOSE_CONNECTION) == 0) {
|
||||
try {
|
||||
ic.closeConnection();
|
||||
} catch (AbstractMethodError ignored) {
|
||||
// TODO(b/199934664): See if we can remove this by providing a default impl.
|
||||
}
|
||||
} finally {
|
||||
synchronized (mLock) {
|
||||
@@ -260,7 +258,12 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub {
|
||||
Log.w(TAG, "getSelectedText on inactive InputConnection");
|
||||
return null;
|
||||
}
|
||||
return ic.getSelectedText(flags);
|
||||
try {
|
||||
return ic.getSelectedText(flags);
|
||||
} catch (AbstractMethodError ignored) {
|
||||
// TODO(b/199934664): See if we can remove this by providing a default impl.
|
||||
return null;
|
||||
}
|
||||
}, useImeTracing() ? result -> buildGetSelectedTextProto(flags, result) : null);
|
||||
}
|
||||
|
||||
@@ -335,7 +338,11 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub {
|
||||
Log.w(TAG, "commitCorrection on inactive InputConnection");
|
||||
return;
|
||||
}
|
||||
ic.commitCorrection(info);
|
||||
try {
|
||||
ic.commitCorrection(info);
|
||||
} catch (AbstractMethodError ignored) {
|
||||
// TODO(b/199934664): See if we can remove this by providing a default impl.
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -383,7 +390,11 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub {
|
||||
Log.w(TAG, "setComposingRegion on inactive InputConnection");
|
||||
return;
|
||||
}
|
||||
ic.setComposingRegion(start, end);
|
||||
try {
|
||||
ic.setComposingRegion(start, end);
|
||||
} catch (AbstractMethodError ignored) {
|
||||
// TODO(b/199934664): See if we can remove this by providing a default impl.
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -467,7 +478,11 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub {
|
||||
Log.w(TAG, "deleteSurroundingTextInCodePoints on inactive InputConnection");
|
||||
return;
|
||||
}
|
||||
ic.deleteSurroundingTextInCodePoints(beforeLength, afterLength);
|
||||
try {
|
||||
ic.deleteSurroundingTextInCodePoints(beforeLength, afterLength);
|
||||
} catch (AbstractMethodError ignored) {
|
||||
// TODO(b/199934664): See if we can remove this by providing a default impl.
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -532,7 +547,12 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub {
|
||||
// requestCursorUpdates() is not currently supported across displays.
|
||||
return false;
|
||||
}
|
||||
return ic.requestCursorUpdates(cursorUpdateMode);
|
||||
try {
|
||||
return ic.requestCursorUpdates(cursorUpdateMode);
|
||||
} catch (AbstractMethodError ignored) {
|
||||
// TODO(b/199934664): See if we can remove this by providing a default impl.
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -549,7 +569,12 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub {
|
||||
Log.w(TAG, "commitContent with invalid inputContentInfo=" + inputContentInfo);
|
||||
return false;
|
||||
}
|
||||
return ic.commitContent(inputContentInfo, flags, opts);
|
||||
try {
|
||||
return ic.commitContent(inputContentInfo, flags, opts);
|
||||
} catch (AbstractMethodError ignored) {
|
||||
// TODO(b/199934664): See if we can remove this by providing a default impl.
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ oneway interface IInputMethod {
|
||||
|
||||
void unbindInput();
|
||||
|
||||
void startInput(in IBinder startInputToken, in IInputContext inputContext, int missingMethods,
|
||||
void startInput(in IBinder startInputToken, in IInputContext inputContext,
|
||||
in EditorInfo attribute, boolean restarting);
|
||||
|
||||
void createSession(in InputChannel channel, IInputSessionCallback callback);
|
||||
|
||||
@@ -54,7 +54,6 @@ interface IInputMethodManager {
|
||||
/* @StartInputFlags */ int startInputFlags,
|
||||
/* @android.view.WindowManager.LayoutParams.SoftInputModeFlags */ int softInputMode,
|
||||
int windowFlags, in EditorInfo attribute, IInputContext inputContext,
|
||||
/* @InputConnectionInspector.MissingMethodFlags */ int missingMethodFlags,
|
||||
int unverifiedTargetSdkVersion);
|
||||
|
||||
void showInputMethodPickerFromClient(in IInputMethodClient client,
|
||||
|
||||
@@ -136,8 +136,6 @@ import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InlineSuggestionsRequest;
|
||||
import android.view.inputmethod.InputBinding;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
import android.view.inputmethod.InputConnectionInspector;
|
||||
import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags;
|
||||
import android.view.inputmethod.InputMethod;
|
||||
import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceFileProto;
|
||||
import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto;
|
||||
@@ -511,14 +509,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
*/
|
||||
IInputContext mCurInputContext;
|
||||
|
||||
/**
|
||||
* The missing method flags for the input context last provided by the current client.
|
||||
*
|
||||
* @see android.view.inputmethod.InputConnectionInspector.MissingMethodFlags
|
||||
*/
|
||||
@MissingMethodFlags
|
||||
int mCurInputContextMissingMethods;
|
||||
|
||||
/**
|
||||
* The attributes last provided by the current client.
|
||||
*/
|
||||
@@ -2313,7 +2303,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
|
||||
final SessionState session = mCurClient.curSession;
|
||||
executeOrSendMessage(session.method, mCaller.obtainMessageIIOOOO(
|
||||
MSG_START_INPUT, mCurInputContextMissingMethods, initial ? 0 : 1 /* restarting */,
|
||||
MSG_START_INPUT, 0 /* unused */, initial ? 0 : 1 /* restarting */,
|
||||
startInputToken, session, mCurInputContext, mCurAttribute));
|
||||
if (mShowRequested) {
|
||||
if (DEBUG) Slog.v(TAG, "Attach new input asks to show input");
|
||||
@@ -2331,8 +2321,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
@GuardedBy("mMethodMap")
|
||||
@NonNull
|
||||
InputBindResult startInputUncheckedLocked(@NonNull ClientState cs, IInputContext inputContext,
|
||||
@MissingMethodFlags int missingMethods, @NonNull EditorInfo attribute,
|
||||
@StartInputFlags int startInputFlags, @StartInputReason int startInputReason) {
|
||||
@NonNull EditorInfo attribute, @StartInputFlags int startInputFlags,
|
||||
@StartInputReason int startInputReason) {
|
||||
// If no method is currently selected, do nothing.
|
||||
if (mCurMethodId == null) {
|
||||
return InputBindResult.NO_IME;
|
||||
@@ -2389,7 +2379,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
if (mCurSeq <= 0) mCurSeq = 1;
|
||||
mCurClient = cs;
|
||||
mCurInputContext = inputContext;
|
||||
mCurInputContextMissingMethods = missingMethods;
|
||||
mCurAttribute = attribute;
|
||||
|
||||
// Check if the input method is changing.
|
||||
@@ -3274,10 +3263,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
@StartInputReason int startInputReason, IInputMethodClient client, IBinder windowToken,
|
||||
@StartInputFlags int startInputFlags, @SoftInputModeFlags int softInputMode,
|
||||
int windowFlags, @Nullable EditorInfo attribute, IInputContext inputContext,
|
||||
@MissingMethodFlags int missingMethods, int unverifiedTargetSdkVersion) {
|
||||
int unverifiedTargetSdkVersion) {
|
||||
return startInputOrWindowGainedFocusInternal(startInputReason, client, windowToken,
|
||||
startInputFlags, softInputMode, windowFlags, attribute, inputContext,
|
||||
missingMethods, unverifiedTargetSdkVersion);
|
||||
unverifiedTargetSdkVersion);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -3285,7 +3274,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
@StartInputReason int startInputReason, IInputMethodClient client, IBinder windowToken,
|
||||
@StartInputFlags int startInputFlags, @SoftInputModeFlags int softInputMode,
|
||||
int windowFlags, @Nullable EditorInfo attribute, @Nullable IInputContext inputContext,
|
||||
@MissingMethodFlags int missingMethods, int unverifiedTargetSdkVersion) {
|
||||
int unverifiedTargetSdkVersion) {
|
||||
if (windowToken == null) {
|
||||
Slog.e(TAG, "windowToken cannot be null.");
|
||||
return InputBindResult.NULL;
|
||||
@@ -3321,8 +3310,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
try {
|
||||
result = startInputOrWindowGainedFocusInternalLocked(startInputReason,
|
||||
client, windowToken, startInputFlags, softInputMode, windowFlags,
|
||||
attribute, inputContext, missingMethods, unverifiedTargetSdkVersion,
|
||||
userId);
|
||||
attribute, inputContext, unverifiedTargetSdkVersion, userId);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
@@ -3348,15 +3336,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
@StartInputReason int startInputReason, IInputMethodClient client,
|
||||
@NonNull IBinder windowToken, @StartInputFlags int startInputFlags,
|
||||
@SoftInputModeFlags int softInputMode, int windowFlags, EditorInfo attribute,
|
||||
IInputContext inputContext, @MissingMethodFlags int missingMethods,
|
||||
int unverifiedTargetSdkVersion, @UserIdInt int userId) {
|
||||
IInputContext inputContext, int unverifiedTargetSdkVersion, @UserIdInt int userId) {
|
||||
if (DEBUG) {
|
||||
Slog.v(TAG, "startInputOrWindowGainedFocusInternalLocked: reason="
|
||||
+ InputMethodDebug.startInputReasonToString(startInputReason)
|
||||
+ " client=" + client.asBinder()
|
||||
+ " inputContext=" + inputContext
|
||||
+ " missingMethods="
|
||||
+ InputConnectionInspector.getMissingMethodFlagsAsString(missingMethods)
|
||||
+ " attribute=" + attribute
|
||||
+ " startInputFlags="
|
||||
+ InputMethodDebug.startInputFlagsToString(startInputFlags)
|
||||
@@ -3437,8 +3422,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
+ InputMethodDebug.startInputReasonToString(startInputReason));
|
||||
}
|
||||
if (attribute != null) {
|
||||
return startInputUncheckedLocked(cs, inputContext, missingMethods,
|
||||
attribute, startInputFlags, startInputReason);
|
||||
return startInputUncheckedLocked(cs, inputContext, attribute, startInputFlags,
|
||||
startInputReason);
|
||||
}
|
||||
return new InputBindResult(
|
||||
InputBindResult.ResultCode.SUCCESS_REPORT_WINDOW_FOCUS_ONLY,
|
||||
@@ -3478,8 +3463,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
// UI for input.
|
||||
if (isTextEditor && attribute != null
|
||||
&& shouldRestoreImeVisibility(windowToken, softInputMode)) {
|
||||
res = startInputUncheckedLocked(cs, inputContext, missingMethods, attribute,
|
||||
startInputFlags, startInputReason);
|
||||
res = startInputUncheckedLocked(cs, inputContext, attribute, startInputFlags,
|
||||
startInputReason);
|
||||
showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null,
|
||||
SoftInputShowHideReason.SHOW_RESTORE_IME_VISIBILITY);
|
||||
return res;
|
||||
@@ -3517,8 +3502,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
// is more room for the target window + IME.
|
||||
if (DEBUG) Slog.v(TAG, "Unspecified window will show input");
|
||||
if (attribute != null) {
|
||||
res = startInputUncheckedLocked(cs, inputContext, missingMethods,
|
||||
attribute, startInputFlags, startInputReason);
|
||||
res = startInputUncheckedLocked(cs, inputContext, attribute,
|
||||
startInputFlags, startInputReason);
|
||||
didStart = true;
|
||||
}
|
||||
showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null,
|
||||
@@ -3548,8 +3533,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
if (InputMethodUtils.isSoftInputModeStateVisibleAllowed(
|
||||
unverifiedTargetSdkVersion, startInputFlags)) {
|
||||
if (attribute != null) {
|
||||
res = startInputUncheckedLocked(cs, inputContext, missingMethods,
|
||||
attribute, startInputFlags, startInputReason);
|
||||
res = startInputUncheckedLocked(cs, inputContext, attribute,
|
||||
startInputFlags, startInputReason);
|
||||
didStart = true;
|
||||
}
|
||||
showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null,
|
||||
@@ -3567,8 +3552,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
unverifiedTargetSdkVersion, startInputFlags)) {
|
||||
if (!sameWindowFocused) {
|
||||
if (attribute != null) {
|
||||
res = startInputUncheckedLocked(cs, inputContext, missingMethods,
|
||||
attribute, startInputFlags, startInputReason);
|
||||
res = startInputUncheckedLocked(cs, inputContext, attribute,
|
||||
startInputFlags, startInputReason);
|
||||
didStart = true;
|
||||
}
|
||||
showCurrentInputLocked(windowToken, InputMethodManager.SHOW_IMPLICIT, null,
|
||||
@@ -3596,8 +3581,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
SoftInputShowHideReason.HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR);
|
||||
}
|
||||
}
|
||||
res = startInputUncheckedLocked(cs, inputContext, missingMethods, attribute,
|
||||
startInputFlags, startInputReason);
|
||||
res = startInputUncheckedLocked(cs, inputContext, attribute, startInputFlags,
|
||||
startInputReason);
|
||||
} else {
|
||||
res = InputBindResult.NULL_EDITOR_INFO;
|
||||
}
|
||||
@@ -4363,7 +4348,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
// ---------------------------------------------------------
|
||||
|
||||
case MSG_START_INPUT: {
|
||||
final int missingMethods = msg.arg1;
|
||||
final boolean restarting = msg.arg2 != 0;
|
||||
args = (SomeArgs) msg.obj;
|
||||
final IBinder startInputToken = (IBinder) args.arg1;
|
||||
@@ -4372,8 +4356,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
final EditorInfo editorInfo = (EditorInfo) args.arg4;
|
||||
try {
|
||||
setEnabledSessionInHandlerThread(session);
|
||||
session.method.startInput(startInputToken, inputContext, missingMethods,
|
||||
editorInfo, restarting);
|
||||
session.method.startInput(startInputToken, inputContext, editorInfo,
|
||||
restarting);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
args.recycle();
|
||||
|
||||
Reference in New Issue
Block a user