Merge "Incorporate API feedback: CAI requestCursorUpdates()" into tm-dev

This commit is contained in:
TreeHugger Robot
2022-03-03 13:27:04 +00:00
committed by Android (Google) Code Review
12 changed files with 145 additions and 12 deletions

View File

@@ -52951,6 +52951,7 @@ package android.view.inputmethod {
method public default boolean performSpellCheck();
method public boolean reportFullscreenMode(boolean);
method public boolean requestCursorUpdates(int);
method public default boolean requestCursorUpdates(int, int);
method public boolean sendKeyEvent(android.view.KeyEvent);
method public boolean setComposingRegion(int, int);
method public default boolean setComposingRegion(int, int, @Nullable android.view.inputmethod.TextAttribute);

View File

@@ -433,6 +433,26 @@ public final class RemoteInputConnection implements InputConnection {
mCancellationGroup, MAX_WAIT_TIME_MILLIS);
}
@Override
@AnyThread
public boolean requestCursorUpdates(@CursorUpdateMode int cursorUpdateMode,
@CursorUpdateFilter int cursorUpdateFilter) {
if (mCancellationGroup.isCanceled()) {
return false;
}
final InputMethodServiceInternal ims = mImsInternal.getAndWarnIfNull();
if (ims == null) {
return false;
}
final int displayId = ims.getContext().getDisplayId();
final CompletableFuture<Boolean> value =
mInvoker.requestCursorUpdates(cursorUpdateMode, cursorUpdateFilter, displayId);
return CompletableFutureUtil.getResultOrFalse(value, TAG, "requestCursorUpdates()",
mCancellationGroup, MAX_WAIT_TIME_MILLIS);
}
@AnyThread
public Handler getHandler() {
// Nothing should happen when called from input method.

View File

@@ -575,7 +575,9 @@ public final class CursorAnchorInfo implements Parcelable {
}
/**
* Returns {@link EditorBoundsInfo} editor related bounds.
* Returns {@link EditorBoundsInfo} for the current editor, or {@code null} if IME is not
* subscribed with {@link InputConnection#CURSOR_UPDATE_FILTER_EDITOR_BOUNDS}
* or {@link InputConnection#CURSOR_UPDATE_MONITOR}.
*/
@Nullable
public EditorBoundsInfo getEditorBoundsInfo() {

View File

@@ -30,13 +30,13 @@ import java.util.Objects;
public final class EditorBoundsInfo implements Parcelable {
/**
* Container of rectangular position of Editor in the current window.
* The bounding box of the of currently focused text editor in local coordinates.
*/
private final RectF mEditorBounds;
/**
* Container of rectangular position of Editor with additional padding around for initiating
* Stylus Handwriting in the current window.
* The bounding box of the of currently focused text editor with additional padding around it
* for initiating Stylus Handwriting in the current window.
*/
private final RectF mHandwritingBounds;

View File

@@ -1042,6 +1042,23 @@ public interface InputConnection {
*/
int CURSOR_UPDATE_FILTER_INSERTION_MARKER = 1 << 4;
/**
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {CURSOR_UPDATE_IMMEDIATE, CURSOR_UPDATE_MONITOR}, flag = true,
prefix = { "CURSOR_UPDATE_" })
@interface CursorUpdateMode{}
/**
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {CURSOR_UPDATE_FILTER_EDITOR_BOUNDS, CURSOR_UPDATE_FILTER_CHARACTER_BOUNDS,
CURSOR_UPDATE_FILTER_INSERTION_MARKER}, flag = true,
prefix = { "CURSOR_UPDATE_FILTER_" })
@interface CursorUpdateFilter{}
/**
* Called by the input method to ask the editor for calling back
* {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} to
@@ -1062,6 +1079,34 @@ public interface InputConnection {
*/
boolean requestCursorUpdates(int cursorUpdateMode);
/**
* Called by the input method to ask the editor for calling back
* {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} to
* notify cursor/anchor locations.
*
* @param cursorUpdateMode combination of update modes:
* {@link #CURSOR_UPDATE_IMMEDIATE}, {@link #CURSOR_UPDATE_MONITOR}
* @param cursorUpdateFilter any combination of data filters:
* {@link #CURSOR_UPDATE_FILTER_CHARACTER_BOUNDS}, {@link #CURSOR_UPDATE_FILTER_EDITOR_BOUNDS},
* {@link #CURSOR_UPDATE_FILTER_INSERTION_MARKER}.
*
* <p>Pass {@code 0} to disable them. However, if an unknown flag is provided, request will be
* rejected and method will return {@code false}.</p>
* @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)}.
* 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.
*/
default boolean requestCursorUpdates(@CursorUpdateMode int cursorUpdateMode,
@CursorUpdateFilter int cursorUpdateFilter) {
if (cursorUpdateFilter == 0) {
return requestCursorUpdates(cursorUpdateMode);
}
return false;
}
/**
* Called by the system to enable application developers to specify a dedicated thread on which
* {@link InputConnection} methods are called back.

View File

@@ -1936,8 +1936,8 @@ public final class InputMethodManager {
// TODO (b/210039666): Pipe IME displayId from InputBindResult and use it here.
// instead of mDisplayId.
mServedInputConnection.requestCursorUpdatesFromImm(
CURSOR_UPDATE_IMMEDIATE | CURSOR_UPDATE_MONITOR
| CURSOR_UPDATE_FILTER_EDITOR_BOUNDS,
CURSOR_UPDATE_IMMEDIATE | CURSOR_UPDATE_MONITOR,
CURSOR_UPDATE_FILTER_EDITOR_BOUNDS,
mDisplayId);
}

View File

@@ -6179,6 +6179,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
return getTarget().requestCursorUpdates(cursorUpdateMode);
}
@Override
public boolean requestCursorUpdates(int cursorUpdateMode, int cursorUpdateFilter) {
return getTarget().requestCursorUpdates(cursorUpdateMode, cursorUpdateFilter);
}
@Override
public Handler getHandler() {
return getTarget().getHandler();

View File

@@ -204,6 +204,13 @@ public final class EditableInputConnection extends BaseInputConnection
return success;
}
@Override
public boolean requestCursorUpdates(
@CursorUpdateMode int cursorUpdateMode, @CursorUpdateFilter int cursorUpdateFilter) {
// TODO(b/210039666): use separate attrs for updateMode and updateFilter.
return requestCursorUpdates(cursorUpdateMode | cursorUpdateFilter);
}
@Override
public boolean requestCursorUpdates(int cursorUpdateMode) {
if (DEBUG) Log.v(TAG, "requestUpdateCursorAnchorInfo " + cursorUpdateMode);

View File

@@ -602,6 +602,30 @@ public final class IInputContextInvoker {
return future;
}
/**
* Invokes {@link IInputContext#requestCursorUpdatesWithFilter(InputConnectionCommandHeader,
* int, int, int, AndroidFuture)}.
*
* @param cursorUpdateMode {@code cursorUpdateMode} parameter to be passed.
* @param cursorUpdateFilter {@code cursorUpdateFilter} parameter to be passed.
* @param imeDisplayId the display ID that is associated with the IME.
* @return {@link AndroidFuture<Boolean>} that can be used to retrieve the invocation
* result. {@link RemoteException} will be treated as an error.
*/
@AnyThread
@NonNull
public AndroidFuture<Boolean> requestCursorUpdates(int cursorUpdateMode, int cursorUpdateFilter,
int imeDisplayId) {
final AndroidFuture<Boolean> future = new AndroidFuture<>();
try {
mIInputContext.requestCursorUpdatesWithFilter(createHeader(), cursorUpdateMode,
cursorUpdateFilter, imeDisplayId, future);
} catch (RemoteException e) {
future.completeExceptionally(e);
}
return future;
}
/**
* Invokes {@link IInputContext#commitContent(InputConnectionCommandHeader, InputContentInfo,
* int, Bundle, AndroidFuture)}.

View File

@@ -935,17 +935,20 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub {
* Dispatches {@link InputConnection#requestCursorUpdates(int)}.
*
* <p>This method is intended to be called only from {@link InputMethodManager}.</p>
* @param cursorUpdateMode the mode for {@link InputConnection#requestCursorUpdates(int)}
* @param cursorUpdateMode the mode for {@link InputConnection#requestCursorUpdates(int, int)}
* @param cursorUpdateFilter the filter for
* {@link InputConnection#requestCursorUpdates(int, int)}
* @param imeDisplayId displayId on which IME is displayed.
*/
@Dispatching(cancellable = true)
public void requestCursorUpdatesFromImm(int cursorUpdateMode, int imeDisplayId) {
public void requestCursorUpdatesFromImm(int cursorUpdateMode, int cursorUpdateFilter,
int imeDisplayId) {
final int currentSessionId = mCurrentSessionId.get();
dispatchWithTracing("requestCursorUpdatesFromImm", () -> {
if (currentSessionId != mCurrentSessionId.get()) {
return; // cancelled
}
requestCursorUpdatesInternal(cursorUpdateMode, imeDisplayId);
requestCursorUpdatesInternal(cursorUpdateMode, cursorUpdateFilter, imeDisplayId);
});
}
@@ -957,11 +960,28 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub {
if (header.mSessionId != mCurrentSessionId.get()) {
return false; // cancelled
}
return requestCursorUpdatesInternal(cursorUpdateMode, imeDisplayId);
return requestCursorUpdatesInternal(
cursorUpdateMode, 0 /* cursorUpdateFilter */, imeDisplayId);
});
}
private boolean requestCursorUpdatesInternal(int cursorUpdateMode, int imeDisplayId) {
@Dispatching(cancellable = true)
@Override
public void requestCursorUpdatesWithFilter(InputConnectionCommandHeader header,
int cursorUpdateMode, int cursorUpdateFilter, int imeDisplayId,
AndroidFuture future /* T=Boolean */) {
dispatchWithTracing("requestCursorUpdates", future, () -> {
if (header.mSessionId != mCurrentSessionId.get()) {
return false; // cancelled
}
return requestCursorUpdatesInternal(
cursorUpdateMode, cursorUpdateFilter, imeDisplayId);
});
}
private boolean requestCursorUpdatesInternal(
@InputConnection.CursorUpdateMode int cursorUpdateMode,
@InputConnection.CursorUpdateFilter int cursorUpdateFilter, int imeDisplayId) {
final InputConnection ic = getInputConnection();
if (ic == null || !isActive()) {
Log.w(TAG, "requestCursorAnchorInfo on inactive InputConnection");
@@ -972,7 +992,7 @@ public final class RemoteInputConnectionImpl extends IInputContext.Stub {
return false;
}
try {
return ic.requestCursorUpdates(cursorUpdateMode);
return ic.requestCursorUpdates(cursorUpdateMode, cursorUpdateFilter);
} catch (AbstractMethodError ignored) {
// TODO(b/199934664): See if we can remove this by providing a default impl.
return false;

View File

@@ -98,6 +98,10 @@ import com.android.internal.inputmethod.InputConnectionCommandHeader;
void requestCursorUpdates(in InputConnectionCommandHeader header, int cursorUpdateMode,
int imeDisplayId, in AndroidFuture future /* T=Boolean */);
void requestCursorUpdatesWithFilter(in InputConnectionCommandHeader header,
int cursorUpdateMode, int cursorUpdateFilter, int imeDisplayId,
in AndroidFuture future /* T=Boolean */);
void commitContent(in InputConnectionCommandHeader header, in InputContentInfo inputContentInfo,
int flags, in Bundle opts, in AndroidFuture future /* T=Boolean */);

View File

@@ -548,6 +548,11 @@ public class ViewInputConnectionTest {
return false;
}
@Override
public boolean requestCursorUpdates(int cursorUpdateMode, int cursorUpdateFilter) {
return false;
}
@Override
public Handler getHandler() {
return null;