Add InputConnection app and service dump
This change dumps information through IME tracing for the getter methods
exposed by the InputConnection interface. The dump is done through the
ImeTracing interface and is triggered by events in the wrapper classes
used to handle InputConnection implementations corresponding to:
- different apps
- InputMethodService
The new data is available under inputConnectionCall in the clients
output proto.
Bug: 154348613
Test: flash a device
start IME tracing by calling "adb shell ime tracing start"
end IME tracing by calling "adb shell ime tracing stop"
pull generated trace files and visualize in Winscope
or start tracing directly through ADB Connect and visualize traces
Change-Id: Iabd6af1b858803030848a0ef5e7dd9ecfc562716
This commit is contained in:
@@ -199,10 +199,11 @@ public abstract class AbstractInputMethodService extends Service
|
||||
* Dumps the internal state of IME to a protocol buffer output stream.
|
||||
*
|
||||
* @param proto ProtoOutputStream to dump data to.
|
||||
* @param icProto {@link InputConnection} call data in proto format.
|
||||
* @hide
|
||||
*/
|
||||
@SuppressWarnings("HiddenAbstractMethod")
|
||||
public abstract void dumpProtoInternal(ProtoOutputStream proto);
|
||||
public abstract void dumpProtoInternal(ProtoOutputStream proto, ProtoOutputStream icProto);
|
||||
|
||||
/**
|
||||
* Implement this to handle {@link android.os.Binder#dump Binder.dump()}
|
||||
|
||||
@@ -25,6 +25,7 @@ import static android.inputmethodservice.InputMethodServiceProto.EXTRACTED_TOKEN
|
||||
import static android.inputmethodservice.InputMethodServiceProto.EXTRACT_VIEW_HIDDEN;
|
||||
import static android.inputmethodservice.InputMethodServiceProto.FULLSCREEN_APPLIED;
|
||||
import static android.inputmethodservice.InputMethodServiceProto.INPUT_BINDING;
|
||||
import static android.inputmethodservice.InputMethodServiceProto.INPUT_CONNECTION_CALL;
|
||||
import static android.inputmethodservice.InputMethodServiceProto.INPUT_EDITOR_INFO;
|
||||
import static android.inputmethodservice.InputMethodServiceProto.INPUT_STARTED;
|
||||
import static android.inputmethodservice.InputMethodServiceProto.INPUT_VIEW_STARTED;
|
||||
@@ -742,7 +743,8 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
return;
|
||||
}
|
||||
ImeTracing.getInstance().triggerServiceDump(
|
||||
"InputMethodService.InputMethodImpl#hideSoftInput", InputMethodService.this);
|
||||
"InputMethodService.InputMethodImpl#hideSoftInput", InputMethodService.this,
|
||||
null /* icProto */);
|
||||
final boolean wasVisible = isInputViewShown();
|
||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.hideSoftInput");
|
||||
|
||||
@@ -798,7 +800,8 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
}
|
||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.showSoftInput");
|
||||
ImeTracing.getInstance().triggerServiceDump(
|
||||
"InputMethodService.InputMethodImpl#showSoftInput", InputMethodService.this);
|
||||
"InputMethodService.InputMethodImpl#showSoftInput", InputMethodService.this,
|
||||
null /* icProto */);
|
||||
final boolean wasVisible = isInputViewShown();
|
||||
if (dispatchOnShowInputRequested(flags, false)) {
|
||||
|
||||
@@ -2182,7 +2185,8 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
return;
|
||||
}
|
||||
|
||||
ImeTracing.getInstance().triggerServiceDump("InputMethodService#showWindow", this);
|
||||
ImeTracing.getInstance().triggerServiceDump("InputMethodService#showWindow", this,
|
||||
null /* icProto */);
|
||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.showWindow");
|
||||
mDecorViewWasVisible = mDecorViewVisible;
|
||||
mInShowWindow = true;
|
||||
@@ -2260,7 +2264,8 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
*/
|
||||
private void applyVisibilityInInsetsConsumerIfNecessary(boolean setVisible) {
|
||||
ImeTracing.getInstance().triggerServiceDump(
|
||||
"InputMethodService#applyVisibilityInInsetsConsumerIfNecessary", this);
|
||||
"InputMethodService#applyVisibilityInInsetsConsumerIfNecessary", this,
|
||||
null /* icProto */);
|
||||
mPrivOps.applyImeVisibility(setVisible
|
||||
? mCurShowInputToken : mCurHideInputToken, setVisible);
|
||||
}
|
||||
@@ -2285,7 +2290,8 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
|
||||
public void hideWindow() {
|
||||
if (DEBUG) Log.v(TAG, "CALL: hideWindow");
|
||||
ImeTracing.getInstance().triggerServiceDump("InputMethodService#hideWindow", this);
|
||||
ImeTracing.getInstance().triggerServiceDump("InputMethodService#hideWindow", this,
|
||||
null /* icProto */);
|
||||
mWindowVisible = false;
|
||||
finishViews(false /* finishingInput */);
|
||||
if (mDecorViewVisible) {
|
||||
@@ -2356,7 +2362,8 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
|
||||
void doFinishInput() {
|
||||
if (DEBUG) Log.v(TAG, "CALL: doFinishInput");
|
||||
ImeTracing.getInstance().triggerServiceDump("InputMethodService#doFinishInput", this);
|
||||
ImeTracing.getInstance().triggerServiceDump("InputMethodService#doFinishInput", this,
|
||||
null /* icProto */);
|
||||
finishViews(true /* finishingInput */);
|
||||
if (mInputStarted) {
|
||||
mInlineSuggestionSessionController.notifyOnFinishInput();
|
||||
@@ -2372,7 +2379,8 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
if (!restarting && mInputStarted) {
|
||||
doFinishInput();
|
||||
}
|
||||
ImeTracing.getInstance().triggerServiceDump("InputMethodService#doStartInput", this);
|
||||
ImeTracing.getInstance().triggerServiceDump("InputMethodService#doStartInput", this,
|
||||
null /* icProto */);
|
||||
mInputStarted = true;
|
||||
mStartedInputConnection = ic;
|
||||
mInputEditorInfo = attribute;
|
||||
@@ -2531,7 +2539,8 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
* @param flags Provides additional operating flags.
|
||||
*/
|
||||
public void requestHideSelf(int flags) {
|
||||
ImeTracing.getInstance().triggerServiceDump("InputMethodService#requestHideSelf", this);
|
||||
ImeTracing.getInstance().triggerServiceDump("InputMethodService#requestHideSelf", this,
|
||||
null /* icProto */);
|
||||
mPrivOps.hideMySoftInput(flags);
|
||||
}
|
||||
|
||||
@@ -2544,7 +2553,8 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
* @param flags Provides additional operating flags.
|
||||
*/
|
||||
public final void requestShowSelf(int flags) {
|
||||
ImeTracing.getInstance().triggerServiceDump("InputMethodService#requestShowSelf", this);
|
||||
ImeTracing.getInstance().triggerServiceDump("InputMethodService#requestShowSelf", this,
|
||||
null /* icProto */);
|
||||
mPrivOps.showMySoftInput(flags);
|
||||
}
|
||||
|
||||
@@ -3364,7 +3374,7 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
* @hide
|
||||
*/
|
||||
@Override
|
||||
public final void dumpProtoInternal(ProtoOutputStream proto) {
|
||||
public final void dumpProtoInternal(ProtoOutputStream proto, ProtoOutputStream icProto) {
|
||||
final long token = proto.start(InputMethodServiceTraceProto.INPUT_METHOD_SERVICE);
|
||||
mWindow.dumpDebug(proto, SOFT_INPUT_WINDOW);
|
||||
proto.write(VIEWS_CREATED, mViewsCreated);
|
||||
@@ -3393,6 +3403,9 @@ public class InputMethodService extends AbstractInputMethodService {
|
||||
proto.write(STATUS_ICON, mStatusIcon);
|
||||
mTmpInsets.dumpDebug(proto, LAST_COMPUTED_INSETS);
|
||||
proto.write(SETTINGS_OBSERVER, Objects.toString(mSettingsObserver));
|
||||
if (icProto != null) {
|
||||
proto.write(INPUT_CONNECTION_CALL, icProto.getBytes());
|
||||
}
|
||||
proto.end(token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,15 +110,20 @@ public abstract class ImeTracing {
|
||||
*
|
||||
* @param where Place where the trace was triggered.
|
||||
* @param immInstance The {@link InputMethodManager} instance to dump.
|
||||
* @param icProto {@link android.view.inputmethod.InputConnection} call data in proto format.
|
||||
*/
|
||||
public abstract void triggerClientDump(String where, InputMethodManager immInstance);
|
||||
public abstract void triggerClientDump(String where, InputMethodManager immInstance,
|
||||
ProtoOutputStream icProto);
|
||||
|
||||
/**
|
||||
* Starts a proto dump of the currently connected InputMethodService information.
|
||||
*
|
||||
* @param where Place where the trace was triggered.
|
||||
* @param service The {@link android.inputmethodservice.InputMethodService} to be dumped.
|
||||
* @param icProto {@link android.view.inputmethod.InputConnection} call data in proto format.
|
||||
*/
|
||||
public abstract void triggerServiceDump(String where, AbstractInputMethodService service);
|
||||
public abstract void triggerServiceDump(String where, AbstractInputMethodService service,
|
||||
ProtoOutputStream icProto);
|
||||
|
||||
/**
|
||||
* Starts a proto dump of the InputMethodManagerService information.
|
||||
|
||||
@@ -45,7 +45,8 @@ class ImeTracingClientImpl extends ImeTracing {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void triggerClientDump(String where, @NonNull InputMethodManager immInstance) {
|
||||
public void triggerClientDump(String where, @NonNull InputMethodManager immInstance,
|
||||
ProtoOutputStream icProto) {
|
||||
if (!isEnabled() || !isAvailable()) {
|
||||
return;
|
||||
}
|
||||
@@ -59,7 +60,7 @@ class ImeTracingClientImpl extends ImeTracing {
|
||||
|
||||
try {
|
||||
ProtoOutputStream proto = new ProtoOutputStream();
|
||||
immInstance.dumpDebug(proto);
|
||||
immInstance.dumpDebug(proto, icProto);
|
||||
sendToService(proto.getBytes(), IME_TRACING_FROM_CLIENT, where);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Exception while sending ime-related client dump to server", e);
|
||||
@@ -69,7 +70,8 @@ class ImeTracingClientImpl extends ImeTracing {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void triggerServiceDump(String where, @NonNull AbstractInputMethodService service) {
|
||||
public void triggerServiceDump(String where, @NonNull AbstractInputMethodService service,
|
||||
ProtoOutputStream icProto) {
|
||||
if (!isEnabled() || !isAvailable()) {
|
||||
return;
|
||||
}
|
||||
@@ -83,7 +85,7 @@ class ImeTracingClientImpl extends ImeTracing {
|
||||
|
||||
try {
|
||||
ProtoOutputStream proto = new ProtoOutputStream();
|
||||
service.dumpProtoInternal(proto);
|
||||
service.dumpProtoInternal(proto, icProto);
|
||||
sendToService(proto.getBytes(), IME_TRACING_FROM_IMS, where);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Exception while sending ime-related service dump to server", e);
|
||||
|
||||
@@ -133,12 +133,14 @@ class ImeTracingServerImpl extends ImeTracing {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void triggerClientDump(String where, InputMethodManager immInstance) {
|
||||
public void triggerClientDump(String where, InputMethodManager immInstance,
|
||||
ProtoOutputStream icProto) {
|
||||
// Intentionally left empty, this is implemented in ImeTracingClientImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void triggerServiceDump(String where, AbstractInputMethodService service) {
|
||||
public void triggerServiceDump(String where, AbstractInputMethodService service,
|
||||
ProtoOutputStream icProto) {
|
||||
// Intentionally left empty, this is implemented in ImeTracingClientImpl
|
||||
}
|
||||
|
||||
|
||||
231
core/java/android/util/imetracing/InputConnectionHelper.java
Normal file
231
core/java/android/util/imetracing/InputConnectionHelper.java
Normal file
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* 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 android.util.imetracing;
|
||||
|
||||
import static android.view.inputmethod.InputConnectionCallProto.GET_CURSOR_CAPS_MODE;
|
||||
import static android.view.inputmethod.InputConnectionCallProto.GET_EXTRACTED_TEXT;
|
||||
import static android.view.inputmethod.InputConnectionCallProto.GET_SELECTED_TEXT;
|
||||
import static android.view.inputmethod.InputConnectionCallProto.GET_SURROUNDING_TEXT;
|
||||
import static android.view.inputmethod.InputConnectionCallProto.GET_TEXT_AFTER_CURSOR;
|
||||
import static android.view.inputmethod.InputConnectionCallProto.GET_TEXT_BEFORE_CURSOR;
|
||||
import static android.view.inputmethod.InputConnectionCallProto.GetExtractedText.REQUEST;
|
||||
|
||||
import android.annotation.IntRange;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
import android.view.inputmethod.ExtractedText;
|
||||
import android.view.inputmethod.ExtractedTextRequest;
|
||||
import android.view.inputmethod.InputConnectionCallProto.GetCursorCapsMode;
|
||||
import android.view.inputmethod.InputConnectionCallProto.GetExtractedText;
|
||||
import android.view.inputmethod.InputConnectionCallProto.GetSelectedText;
|
||||
import android.view.inputmethod.InputConnectionCallProto.GetSurroundingText;
|
||||
import android.view.inputmethod.InputConnectionCallProto.GetTextAfterCursor;
|
||||
import android.view.inputmethod.InputConnectionCallProto.GetTextBeforeCursor;
|
||||
import android.view.inputmethod.SurroundingText;
|
||||
|
||||
/**
|
||||
* Helper class for constructing {@link android.view.inputmethod.InputConnection} dumps, which are
|
||||
* integrated into {@link ImeTracing}.
|
||||
* @hide
|
||||
*/
|
||||
public class InputConnectionHelper {
|
||||
static final String TAG = "InputConnectionHelper";
|
||||
public static final boolean DUMP_TEXT = false;
|
||||
|
||||
private InputConnectionHelper() {}
|
||||
|
||||
/**
|
||||
* Builder for InputConnectionCallProto to hold
|
||||
* {@link android.view.inputmethod.InputConnection#getTextAfterCursor(int, int)} data.
|
||||
*
|
||||
* @param length The expected length of the text. This must be non-negative.
|
||||
* @param flags Supplies additional options controlling how the text is
|
||||
* returned. May be either {@code 0} or
|
||||
* {@link android.view.inputmethod.InputConnection#GET_TEXT_WITH_STYLES}.
|
||||
* @param result The text after the cursor position; the length of the
|
||||
* returned text might be less than <var>length</var>.
|
||||
* @return ProtoOutputStream holding the InputConnectionCallProto data.
|
||||
*/
|
||||
public static ProtoOutputStream buildGetTextAfterCursorProto(@IntRange(from = 0) int length,
|
||||
int flags, @Nullable CharSequence result) {
|
||||
ProtoOutputStream proto = new ProtoOutputStream();
|
||||
final long token = proto.start(GET_TEXT_AFTER_CURSOR);
|
||||
proto.write(GetTextAfterCursor.LENGTH, length);
|
||||
proto.write(GetTextAfterCursor.FLAGS, flags);
|
||||
if (result == null) {
|
||||
proto.write(GetTextAfterCursor.RESULT, "null result");
|
||||
} else if (DUMP_TEXT) {
|
||||
proto.write(GetTextAfterCursor.RESULT, result.toString());
|
||||
}
|
||||
proto.end(token);
|
||||
return proto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for InputConnectionCallProto to hold
|
||||
* {@link android.view.inputmethod.InputConnection#getTextBeforeCursor(int, int)} data.
|
||||
*
|
||||
* @param length The expected length of the text. This must be non-negative.
|
||||
* @param flags Supplies additional options controlling how the text is
|
||||
* returned. May be either {@code 0} or
|
||||
* {@link android.view.inputmethod.InputConnection#GET_TEXT_WITH_STYLES}.
|
||||
* @param result The text before the cursor position; the length of the
|
||||
* returned text might be less than <var>length</var>.
|
||||
* @return ProtoOutputStream holding the InputConnectionCallProto data.
|
||||
*/
|
||||
public static ProtoOutputStream buildGetTextBeforeCursorProto(@IntRange(from = 0) int length,
|
||||
int flags, @Nullable CharSequence result) {
|
||||
ProtoOutputStream proto = new ProtoOutputStream();
|
||||
final long token = proto.start(GET_TEXT_BEFORE_CURSOR);
|
||||
proto.write(GetTextBeforeCursor.LENGTH, length);
|
||||
proto.write(GetTextBeforeCursor.FLAGS, flags);
|
||||
if (result == null) {
|
||||
proto.write(GetTextBeforeCursor.RESULT, "null result");
|
||||
} else if (DUMP_TEXT) {
|
||||
proto.write(GetTextBeforeCursor.RESULT, result.toString());
|
||||
}
|
||||
proto.end(token);
|
||||
return proto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for InputConnectionCallProto to hold
|
||||
* {@link android.view.inputmethod.InputConnection#getSelectedText(int)} data.
|
||||
*
|
||||
* @param flags Supplies additional options controlling how the text is
|
||||
* returned. May be either {@code 0} or
|
||||
* {@link android.view.inputmethod.InputConnection#GET_TEXT_WITH_STYLES}.
|
||||
* @param result 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 ProtoOutputStream holding the InputConnectionCallProto data.
|
||||
*/
|
||||
public static ProtoOutputStream buildGetSelectedTextProto(int flags,
|
||||
@Nullable CharSequence result) {
|
||||
ProtoOutputStream proto = new ProtoOutputStream();
|
||||
final long token = proto.start(GET_SELECTED_TEXT);
|
||||
proto.write(GetSelectedText.FLAGS, flags);
|
||||
if (result == null) {
|
||||
proto.write(GetSelectedText.RESULT, "null result");
|
||||
} else if (DUMP_TEXT) {
|
||||
proto.write(GetSelectedText.RESULT, result.toString());
|
||||
}
|
||||
proto.end(token);
|
||||
return proto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for InputConnectionCallProto to hold
|
||||
* {@link android.view.inputmethod.InputConnection#getSurroundingText(int, int, int)} data.
|
||||
*
|
||||
* @param beforeLength The expected length of the text before the cursor.
|
||||
* @param afterLength The expected length of the text after the cursor.
|
||||
* @param flags Supplies additional options controlling how the text is
|
||||
* returned. May be either {@code 0} or
|
||||
* {@link android.view.inputmethod.InputConnection#GET_TEXT_WITH_STYLES}.
|
||||
* @param result an {@link android.view.inputmethod.SurroundingText} object describing the
|
||||
* surrounding text and state of selection, or null if the input connection is no longer valid,
|
||||
* or the editor can't comply with the request for some reason, or the application does not
|
||||
* implement this method. The length of the returned text might be less than the sum of
|
||||
* <var>beforeLength</var> and <var>afterLength</var> .
|
||||
* @return ProtoOutputStream holding the InputConnectionCallProto data.
|
||||
*/
|
||||
public static ProtoOutputStream buildGetSurroundingTextProto(@IntRange(from = 0)
|
||||
int beforeLength, @IntRange(from = 0) int afterLength, int flags,
|
||||
@Nullable SurroundingText result) {
|
||||
ProtoOutputStream proto = new ProtoOutputStream();
|
||||
final long token = proto.start(GET_SURROUNDING_TEXT);
|
||||
proto.write(GetSurroundingText.BEFORE_LENGTH, beforeLength);
|
||||
proto.write(GetSurroundingText.AFTER_LENGTH, afterLength);
|
||||
proto.write(GetSurroundingText.FLAGS, flags);
|
||||
if (result == null) {
|
||||
final long token_result = proto.start(GetSurroundingText.RESULT);
|
||||
proto.write(GetSurroundingText.SurroundingText.TEXT, "null result");
|
||||
proto.end(token_result);
|
||||
} else if (DUMP_TEXT) {
|
||||
final long token_result = proto.start(GetSurroundingText.RESULT);
|
||||
proto.write(GetSurroundingText.SurroundingText.TEXT, result.getText().toString());
|
||||
proto.write(GetSurroundingText.SurroundingText.SELECTION_START,
|
||||
result.getSelectionStart());
|
||||
proto.write(GetSurroundingText.SurroundingText.SELECTION_END,
|
||||
result.getSelectionEnd());
|
||||
proto.write(GetSurroundingText.SurroundingText.OFFSET, result.getOffset());
|
||||
proto.end(token_result);
|
||||
}
|
||||
proto.end(token);
|
||||
return proto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for InputConnectionCallProto to hold
|
||||
* {@link android.view.inputmethod.InputConnection#getCursorCapsMode(int)} data.
|
||||
*
|
||||
* @param reqModes The desired modes to retrieve, as defined by
|
||||
* {@link android.text.TextUtils#getCapsMode TextUtils.getCapsMode}.
|
||||
* @param result the caps mode flags that are in effect at the current
|
||||
* cursor position. See TYPE_TEXT_FLAG_CAPS_* in {@link android.text.InputType}.
|
||||
* @return ProtoOutputStream holding the InputConnectionCallProto data.
|
||||
*/
|
||||
public static ProtoOutputStream buildGetCursorCapsModeProto(int reqModes, int result) {
|
||||
ProtoOutputStream proto = new ProtoOutputStream();
|
||||
final long token = proto.start(GET_CURSOR_CAPS_MODE);
|
||||
proto.write(GetCursorCapsMode.REQ_MODES, reqModes);
|
||||
if (DUMP_TEXT) {
|
||||
proto.write(GetCursorCapsMode.RESULT, result);
|
||||
}
|
||||
proto.end(token);
|
||||
return proto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for InputConnectionCallProto to hold
|
||||
* {@link android.view.inputmethod.InputConnection#getExtractedText(ExtractedTextRequest, int)}
|
||||
* data.
|
||||
*
|
||||
* @param request Description of how the text should be returned.
|
||||
* {@link android.view.inputmethod.ExtractedTextRequest}
|
||||
* @param flags Additional options to control the client, either {@code 0} or
|
||||
* {@link android.view.inputmethod.InputConnection#GET_EXTRACTED_TEXT_MONITOR}.
|
||||
* @param result an {@link android.view.inputmethod.ExtractedText}
|
||||
* object describing the state of the text view and containing the
|
||||
* extracted text itself, or null if the input connection is no
|
||||
* longer valid of the editor can't comply with the request for
|
||||
* some reason.
|
||||
* @return ProtoOutputStream holding the InputConnectionCallProto data.
|
||||
*/
|
||||
public static ProtoOutputStream buildGetExtractedTextProto(@NonNull ExtractedTextRequest
|
||||
request, int flags, @Nullable ExtractedText result) {
|
||||
ProtoOutputStream proto = new ProtoOutputStream();
|
||||
final long token = proto.start(GET_EXTRACTED_TEXT);
|
||||
final long token_request = proto.start(REQUEST);
|
||||
proto.write(GetExtractedText.ExtractedTextRequest.TOKEN, request.token);
|
||||
proto.write(GetExtractedText.ExtractedTextRequest.FLAGS, request.flags);
|
||||
proto.write(GetExtractedText.ExtractedTextRequest.HINT_MAX_LINES, request.hintMaxLines);
|
||||
proto.write(GetExtractedText.ExtractedTextRequest.HINT_MAX_CHARS, request.hintMaxChars);
|
||||
proto.end(token_request);
|
||||
proto.write(GetExtractedText.FLAGS, flags);
|
||||
if (result == null) {
|
||||
proto.write(GetExtractedText.RESULT, "null result");
|
||||
} else if (DUMP_TEXT) {
|
||||
proto.write(GetExtractedText.RESULT, result.text.toString());
|
||||
}
|
||||
proto.end(token);
|
||||
return proto;
|
||||
}
|
||||
}
|
||||
@@ -829,7 +829,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
}
|
||||
if (fromIme) {
|
||||
ImeTracing.getInstance().triggerClientDump("InsetsController#show",
|
||||
mHost.getInputMethodManager());
|
||||
mHost.getInputMethodManager(), null /* icProto */);
|
||||
Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.showRequestFromApiToImeReady", 0);
|
||||
Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.showRequestFromIme", 0);
|
||||
} else {
|
||||
@@ -886,7 +886,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
void hide(@InsetsType int types, boolean fromIme) {
|
||||
if (fromIme) {
|
||||
ImeTracing.getInstance().triggerClientDump("InsetsController#hide",
|
||||
mHost.getInputMethodManager());
|
||||
mHost.getInputMethodManager(), null /* icProto */);
|
||||
Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.hideRequestFromIme", 0);
|
||||
} else {
|
||||
Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.hideRequestFromApi", 0);
|
||||
@@ -928,7 +928,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
if (fromIme) {
|
||||
ImeTracing.getInstance().triggerClientDump(
|
||||
"InsetsController#controlWindowInsetsAnimation",
|
||||
mHost.getInputMethodManager());
|
||||
mHost.getInputMethodManager(), null /* icProto */);
|
||||
}
|
||||
|
||||
controlAnimationUnchecked(types, cancellationSignal, listener, mFrame, fromIme, durationMs,
|
||||
@@ -1022,7 +1022,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
animationType, mHost.getTranslator());
|
||||
if ((typesReady & WindowInsets.Type.ime()) != 0) {
|
||||
ImeTracing.getInstance().triggerClientDump("InsetsAnimationControlImpl",
|
||||
mHost.getInputMethodManager());
|
||||
mHost.getInputMethodManager(), null /* icProto */);
|
||||
}
|
||||
mRunningAnimations.add(new RunningAnimation(runner, animationType));
|
||||
if (DEBUG) Log.d(TAG, "Animation added to runner. useInsetsAnimationThread: "
|
||||
@@ -1200,7 +1200,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
if (types.valueAt(j) == ITYPE_IME) {
|
||||
ImeTracing.getInstance().triggerClientDump(
|
||||
"InsetsSourceConsumer#notifyAnimationFinished",
|
||||
mHost.getInputMethodManager());
|
||||
mHost.getInputMethodManager(), null /* icProto */);
|
||||
}
|
||||
stateChanged |= getSourceConsumer(types.valueAt(j)).notifyAnimationFinished();
|
||||
}
|
||||
@@ -1345,7 +1345,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
boolean fromIme) {
|
||||
if ((types & ime()) != 0) {
|
||||
ImeTracing.getInstance().triggerClientDump("InsetsController#hideDirectly",
|
||||
mHost.getInputMethodManager());
|
||||
mHost.getInputMethodManager(), null /* icProto */);
|
||||
}
|
||||
final ArraySet<Integer> internalTypes = InsetsState.toInternalType(types);
|
||||
for (int i = internalTypes.size() - 1; i >= 0; i--) {
|
||||
@@ -1361,7 +1361,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
private void showDirectly(@InsetsType int types, boolean fromIme) {
|
||||
if ((types & ime()) != 0) {
|
||||
ImeTracing.getInstance().triggerClientDump("InsetsController#showDirectly",
|
||||
mHost.getInputMethodManager());
|
||||
mHost.getInputMethodManager(), null /* icProto */);
|
||||
}
|
||||
final ArraySet<Integer> internalTypes = InsetsState.toInternalType(types);
|
||||
for (int i = internalTypes.size() - 1; i >= 0; i--) {
|
||||
|
||||
@@ -9225,7 +9225,8 @@ public final class ViewRootImpl implements ViewParent,
|
||||
final ViewRootImpl viewAncestor = mViewAncestor.get();
|
||||
if (fromIme) {
|
||||
ImeTracing.getInstance().triggerClientDump("ViewRootImpl.W#showInsets",
|
||||
viewAncestor.getInsetsController().getHost().getInputMethodManager());
|
||||
viewAncestor.getInsetsController().getHost().getInputMethodManager(),
|
||||
null /* icProto */);
|
||||
}
|
||||
if (viewAncestor != null) {
|
||||
viewAncestor.showInsets(types, fromIme);
|
||||
@@ -9238,7 +9239,8 @@ public final class ViewRootImpl implements ViewParent,
|
||||
final ViewRootImpl viewAncestor = mViewAncestor.get();
|
||||
if (fromIme) {
|
||||
ImeTracing.getInstance().triggerClientDump("ViewRootImpl.W#hideInsets",
|
||||
viewAncestor.getInsetsController().getHost().getInputMethodManager());
|
||||
viewAncestor.getInsetsController().getHost().getInputMethodManager(),
|
||||
null /* icProto */);
|
||||
}
|
||||
if (viewAncestor != null) {
|
||||
viewAncestor.hideInsets(types, fromIme);
|
||||
|
||||
@@ -23,6 +23,7 @@ import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodCl
|
||||
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.EDITOR_INFO;
|
||||
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.IME_INSETS_SOURCE_CONSUMER;
|
||||
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.INPUT_CONNECTION;
|
||||
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.INPUT_CONNECTION_CALL;
|
||||
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.INPUT_METHOD_MANAGER;
|
||||
import static android.view.inputmethod.InputMethodEditorTraceProto.InputMethodClientsTraceProto.ClientSideProto.VIEW_ROOT_IMPL;
|
||||
import static android.view.inputmethod.InputMethodManagerProto.ACTIVE;
|
||||
@@ -579,7 +580,8 @@ public final class InputMethodManager {
|
||||
int windowFlags) {
|
||||
final View servedView;
|
||||
ImeTracing.getInstance().triggerClientDump(
|
||||
"InputMethodManager.DelegateImpl#startInput", InputMethodManager.this);
|
||||
"InputMethodManager.DelegateImpl#startInput", InputMethodManager.this,
|
||||
null /* icProto */);
|
||||
synchronized (mH) {
|
||||
mCurrentTextBoxAttribute = null;
|
||||
mCompletions = null;
|
||||
@@ -1016,6 +1018,11 @@ public final class InputMethodManager {
|
||||
return mParentInputMethodManager.mActive && !isFinished();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputMethodManager getIMM() {
|
||||
return mParentInputMethodManager;
|
||||
}
|
||||
|
||||
void deactivate() {
|
||||
if (isFinished()) {
|
||||
// This is a small performance optimization. Still only the 1st call of
|
||||
@@ -1713,7 +1720,8 @@ public final class InputMethodManager {
|
||||
* {@link #RESULT_HIDDEN}.
|
||||
*/
|
||||
public boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver) {
|
||||
ImeTracing.getInstance().triggerClientDump("InputMethodManager#showSoftInput", this);
|
||||
ImeTracing.getInstance().triggerClientDump("InputMethodManager#showSoftInput", this,
|
||||
null /* icProto */);
|
||||
// Re-dispatch if there is a context mismatch.
|
||||
final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
|
||||
if (fallbackImm != null) {
|
||||
@@ -1822,7 +1830,7 @@ public final class InputMethodManager {
|
||||
public boolean hideSoftInputFromWindow(IBinder windowToken, int flags,
|
||||
ResultReceiver resultReceiver) {
|
||||
ImeTracing.getInstance().triggerClientDump("InputMethodManager#hideSoftInputFromWindow",
|
||||
this);
|
||||
this, null /* icProto */);
|
||||
checkFocus();
|
||||
synchronized (mH) {
|
||||
final View servedView = getServedViewLocked();
|
||||
@@ -2228,7 +2236,8 @@ public final class InputMethodManager {
|
||||
* @hide
|
||||
*/
|
||||
public void notifyImeHidden(IBinder windowToken) {
|
||||
ImeTracing.getInstance().triggerClientDump("InputMethodManager#notifyImeHidden", this);
|
||||
ImeTracing.getInstance().triggerClientDump("InputMethodManager#notifyImeHidden", this,
|
||||
null /* icProto */);
|
||||
synchronized (mH) {
|
||||
try {
|
||||
if (mCurMethod != null && mCurRootView != null
|
||||
@@ -3296,7 +3305,7 @@ public final class InputMethodManager {
|
||||
for (String arg : args) {
|
||||
if (arg.equals(PROTO_ARG)) {
|
||||
final ProtoOutputStream proto = new ProtoOutputStream(fd);
|
||||
dumpDebug(proto);
|
||||
dumpDebug(proto, null /* icProto */);
|
||||
proto.flush();
|
||||
return true;
|
||||
}
|
||||
@@ -3309,10 +3318,11 @@ public final class InputMethodManager {
|
||||
* {@link ProtoOutputStream}.
|
||||
*
|
||||
* @param proto The proto stream to which the dumps are written.
|
||||
* @param icProto {@link InputConnection} call data in proto format.
|
||||
* @hide
|
||||
*/
|
||||
@GuardedBy("mH")
|
||||
public void dumpDebug(ProtoOutputStream proto) {
|
||||
public void dumpDebug(ProtoOutputStream proto, ProtoOutputStream icProto) {
|
||||
if (mCurMethod == null) {
|
||||
return;
|
||||
}
|
||||
@@ -3337,6 +3347,9 @@ public final class InputMethodManager {
|
||||
if (mServedInputConnectionWrapper != null) {
|
||||
mServedInputConnectionWrapper.dumpDebug(proto, INPUT_CONNECTION);
|
||||
}
|
||||
if (icProto != null) {
|
||||
proto.write(INPUT_CONNECTION_CALL, icProto.getBytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,9 @@ import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.os.Trace;
|
||||
import android.util.Log;
|
||||
import android.util.imetracing.ImeTracing;
|
||||
import android.util.imetracing.InputConnectionHelper;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.inputmethod.CompletionInfo;
|
||||
import android.view.inputmethod.CorrectionInfo;
|
||||
@@ -36,6 +39,7 @@ 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;
|
||||
import android.view.inputmethod.SurroundingText;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
@@ -124,7 +128,9 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected boolean isActive();
|
||||
protected abstract boolean isActive();
|
||||
|
||||
protected abstract InputMethodManager getIMM();
|
||||
|
||||
public void getTextAfterCursor(int length, int flags, ICharSequenceResultCallback callback) {
|
||||
dispatchMessage(mH.obtainMessage(DO_GET_TEXT_AFTER_CURSOR, length, flags, callback));
|
||||
@@ -264,6 +270,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
||||
}
|
||||
|
||||
void executeMessage(Message msg) {
|
||||
ProtoOutputStream icProto;
|
||||
switch (msg.what) {
|
||||
case DO_GET_TEXT_AFTER_CURSOR: {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#getTextAfterCursor");
|
||||
@@ -278,6 +285,12 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
||||
} else {
|
||||
result = ic.getTextAfterCursor(msg.arg1, msg.arg2);
|
||||
}
|
||||
if (ImeTracing.getInstance().isEnabled()) {
|
||||
icProto = InputConnectionHelper.buildGetTextAfterCursorProto(msg.arg1,
|
||||
msg.arg2, result);
|
||||
ImeTracing.getInstance().triggerClientDump(
|
||||
TAG + "#getTextAfterCursor", getIMM(), icProto);
|
||||
}
|
||||
try {
|
||||
callback.onResult(result);
|
||||
} catch (RemoteException e) {
|
||||
@@ -302,6 +315,12 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
||||
} else {
|
||||
result = ic.getTextBeforeCursor(msg.arg1, msg.arg2);
|
||||
}
|
||||
if (ImeTracing.getInstance().isEnabled()) {
|
||||
icProto = InputConnectionHelper.buildGetTextBeforeCursorProto(msg.arg1,
|
||||
msg.arg2, result);
|
||||
ImeTracing.getInstance().triggerClientDump(
|
||||
TAG + "#getTextBeforeCursor", getIMM(), icProto);
|
||||
}
|
||||
try {
|
||||
callback.onResult(result);
|
||||
} catch (RemoteException e) {
|
||||
@@ -326,6 +345,11 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
||||
} else {
|
||||
result = ic.getSelectedText(msg.arg1);
|
||||
}
|
||||
if (ImeTracing.getInstance().isEnabled()) {
|
||||
icProto = InputConnectionHelper.buildGetSelectedTextProto(msg.arg1, result);
|
||||
ImeTracing.getInstance().triggerClientDump(
|
||||
TAG + "#getSelectedText", getIMM(), icProto);
|
||||
}
|
||||
try {
|
||||
callback.onResult(result);
|
||||
} catch (RemoteException e) {
|
||||
@@ -354,6 +378,12 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
||||
} else {
|
||||
result = ic.getSurroundingText(beforeLength, afterLength, flags);
|
||||
}
|
||||
if (ImeTracing.getInstance().isEnabled()) {
|
||||
icProto = InputConnectionHelper.buildGetSurroundingTextProto(beforeLength,
|
||||
afterLength, flags, result);
|
||||
ImeTracing.getInstance().triggerClientDump(
|
||||
TAG + "#getSurroundingText", getIMM(), icProto);
|
||||
}
|
||||
try {
|
||||
callback.onResult(result);
|
||||
} catch (RemoteException e) {
|
||||
@@ -378,6 +408,12 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
||||
} else {
|
||||
result = ic.getCursorCapsMode(msg.arg1);
|
||||
}
|
||||
if (ImeTracing.getInstance().isEnabled()) {
|
||||
icProto = InputConnectionHelper.buildGetCursorCapsModeProto(msg.arg1,
|
||||
result);
|
||||
ImeTracing.getInstance().triggerClientDump(
|
||||
TAG + "#getCursorCapsMode", getIMM(), icProto);
|
||||
}
|
||||
try {
|
||||
callback.onResult(result);
|
||||
} catch (RemoteException e) {
|
||||
@@ -404,6 +440,12 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
||||
} else {
|
||||
result = ic.getExtractedText(request, msg.arg1);
|
||||
}
|
||||
if (ImeTracing.getInstance().isEnabled()) {
|
||||
icProto = InputConnectionHelper.buildGetExtractedTextProto(request,
|
||||
msg.arg1, result);
|
||||
ImeTracing.getInstance().triggerClientDump(
|
||||
TAG + "#getExtractedText", getIMM(), icProto);
|
||||
}
|
||||
try {
|
||||
callback.onResult(result);
|
||||
} catch (RemoteException e) {
|
||||
|
||||
@@ -24,6 +24,9 @@ import android.inputmethodservice.AbstractInputMethodService;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
import android.util.imetracing.ImeTracing;
|
||||
import android.util.imetracing.InputConnectionHelper;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.inputmethod.CompletionInfo;
|
||||
import android.view.inputmethod.CorrectionInfo;
|
||||
@@ -87,8 +90,18 @@ public class InputConnectionWrapper implements InputConnection {
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
return Completable.getResultOrNull(
|
||||
CharSequence result = Completable.getResultOrNull(
|
||||
value, TAG, "getTextAfterCursor()", mCancellationGroup, MAX_WAIT_TIME_MILLIS);
|
||||
|
||||
final AbstractInputMethodService inputMethodService = mInputMethodService.get();
|
||||
if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) {
|
||||
ProtoOutputStream icProto = InputConnectionHelper.buildGetTextAfterCursorProto(length,
|
||||
flags, result);
|
||||
ImeTracing.getInstance().triggerServiceDump(TAG + "#getTextAfterCursor",
|
||||
inputMethodService, icProto);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,8 +120,18 @@ public class InputConnectionWrapper implements InputConnection {
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
return Completable.getResultOrNull(
|
||||
CharSequence result = Completable.getResultOrNull(
|
||||
value, TAG, "getTextBeforeCursor()", mCancellationGroup, MAX_WAIT_TIME_MILLIS);
|
||||
|
||||
final AbstractInputMethodService inputMethodService = mInputMethodService.get();
|
||||
if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) {
|
||||
ProtoOutputStream icProto = InputConnectionHelper.buildGetTextBeforeCursorProto(length,
|
||||
flags, result);
|
||||
ImeTracing.getInstance().triggerServiceDump(TAG + "#getTextBeforeCursor",
|
||||
inputMethodService, icProto);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
@@ -127,8 +150,18 @@ public class InputConnectionWrapper implements InputConnection {
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
return Completable.getResultOrNull(
|
||||
CharSequence result = Completable.getResultOrNull(
|
||||
value, TAG, "getSelectedText()", mCancellationGroup, MAX_WAIT_TIME_MILLIS);
|
||||
|
||||
final AbstractInputMethodService inputMethodService = mInputMethodService.get();
|
||||
if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) {
|
||||
ProtoOutputStream icProto = InputConnectionHelper.buildGetSelectedTextProto(flags,
|
||||
result);
|
||||
ImeTracing.getInstance().triggerServiceDump(TAG + "#getSelectedText",
|
||||
inputMethodService, icProto);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,8 +194,18 @@ public class InputConnectionWrapper implements InputConnection {
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
return Completable.getResultOrNull(
|
||||
SurroundingText result = Completable.getResultOrNull(
|
||||
value, TAG, "getSurroundingText()", mCancellationGroup, MAX_WAIT_TIME_MILLIS);
|
||||
|
||||
final AbstractInputMethodService inputMethodService = mInputMethodService.get();
|
||||
if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) {
|
||||
ProtoOutputStream icProto = InputConnectionHelper.buildGetSurroundingTextProto(
|
||||
beforeLength, afterLength, flags, result);
|
||||
ImeTracing.getInstance().triggerServiceDump(TAG + "#getSurroundingText",
|
||||
inputMethodService, icProto);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
@@ -177,8 +220,18 @@ public class InputConnectionWrapper implements InputConnection {
|
||||
} catch (RemoteException e) {
|
||||
return 0;
|
||||
}
|
||||
return Completable.getResultOrZero(
|
||||
int result = Completable.getResultOrZero(
|
||||
value, TAG, "getCursorCapsMode()", mCancellationGroup, MAX_WAIT_TIME_MILLIS);
|
||||
|
||||
final AbstractInputMethodService inputMethodService = mInputMethodService.get();
|
||||
if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) {
|
||||
ProtoOutputStream icProto = InputConnectionHelper.buildGetCursorCapsModeProto(
|
||||
reqModes, result);
|
||||
ImeTracing.getInstance().triggerServiceDump(TAG + "#getCursorCapsMode",
|
||||
inputMethodService, icProto);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
@@ -193,8 +246,18 @@ public class InputConnectionWrapper implements InputConnection {
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
return Completable.getResultOrNull(
|
||||
ExtractedText result = Completable.getResultOrNull(
|
||||
value, TAG, "getExtractedText()", mCancellationGroup, MAX_WAIT_TIME_MILLIS);
|
||||
|
||||
final AbstractInputMethodService inputMethodService = mInputMethodService.get();
|
||||
if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) {
|
||||
ProtoOutputStream icProto = InputConnectionHelper.buildGetExtractedTextProto(
|
||||
request, flags, result);
|
||||
ImeTracing.getInstance().triggerServiceDump(TAG + "#getExtractedText",
|
||||
inputMethodService, icProto);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.text.Editable;
|
||||
import android.text.Selection;
|
||||
import android.text.method.KeyListener;
|
||||
import android.util.Log;
|
||||
import android.util.imetracing.InputConnectionHelper;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
import android.view.inputmethod.BaseInputConnection;
|
||||
import android.view.inputmethod.CompletionInfo;
|
||||
@@ -45,7 +46,6 @@ import android.widget.TextView;
|
||||
public class EditableInputConnection extends BaseInputConnection
|
||||
implements DumpableInputConnection {
|
||||
private static final boolean DEBUG = false;
|
||||
private static final boolean DUMP_TEXT = false;
|
||||
private static final String TAG = "EditableInputConnection";
|
||||
|
||||
private final TextView mTextView;
|
||||
@@ -243,7 +243,7 @@ public class EditableInputConnection extends BaseInputConnection
|
||||
final long token = proto.start(fieldId);
|
||||
CharSequence editableText = mTextView.getText();
|
||||
CharSequence selectedText = getSelectedText(0 /* flags */);
|
||||
if (DUMP_TEXT) {
|
||||
if (InputConnectionHelper.DUMP_TEXT) {
|
||||
if (editableText != null) {
|
||||
proto.write(EDITABLE_TEXT, editableText.toString());
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ syntax = "proto2";
|
||||
|
||||
import "frameworks/base/core/proto/android/inputmethodservice/softinputwindow.proto";
|
||||
import "frameworks/base/core/proto/android/view/inputmethod/editorinfo.proto";
|
||||
import "frameworks/base/core/proto/android/view/inputmethod/inputconnection.proto";
|
||||
|
||||
package android.inputmethodservice;
|
||||
|
||||
@@ -51,6 +52,7 @@ message InputMethodServiceProto {
|
||||
optional int32 status_icon = 25;
|
||||
optional InsetsProto last_computed_insets = 26;
|
||||
optional string settings_observer = 27;
|
||||
optional .android.view.inputmethod.InputConnectionCallProto input_connection_call = 28;
|
||||
|
||||
message InsetsProto {
|
||||
optional int32 content_top_insets = 1;
|
||||
|
||||
@@ -31,4 +31,68 @@ message InputConnectionProto {
|
||||
optional int32 selected_text_start = 3;
|
||||
optional int32 selected_text_end = 4;
|
||||
optional int32 cursor_caps_mode = 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows information about parameters and result for method calls to
|
||||
* {@link android.view.inputmethod.InputConnection}.
|
||||
*/
|
||||
message InputConnectionCallProto {
|
||||
oneof method_call {
|
||||
GetTextBeforeCursor get_text_before_cursor = 1;
|
||||
GetTextAfterCursor get_text_after_cursor = 2;
|
||||
GetSelectedText get_selected_text = 3;
|
||||
GetSurroundingText get_surrounding_text = 4;
|
||||
GetCursorCapsMode get_cursor_caps_mode = 5;
|
||||
GetExtractedText get_extracted_text = 6;
|
||||
}
|
||||
|
||||
message GetTextBeforeCursor {
|
||||
optional int32 length = 1;
|
||||
optional int32 flags = 2;
|
||||
optional string result = 3 [(.android.privacy).dest = DEST_LOCAL];
|
||||
}
|
||||
|
||||
message GetTextAfterCursor {
|
||||
optional int32 length = 1;
|
||||
optional int32 flags = 2;
|
||||
optional string result = 3 [(.android.privacy).dest = DEST_LOCAL];
|
||||
}
|
||||
|
||||
message GetSelectedText {
|
||||
optional int32 flags = 1;
|
||||
optional string result = 2 [(.android.privacy).dest = DEST_LOCAL];
|
||||
}
|
||||
|
||||
message GetSurroundingText {
|
||||
optional int32 before_length = 1;
|
||||
optional int32 after_length = 2;
|
||||
optional int32 flags = 3;
|
||||
optional SurroundingText result = 4;
|
||||
|
||||
message SurroundingText {
|
||||
optional string text = 1 [(.android.privacy).dest = DEST_LOCAL];
|
||||
optional int32 selection_start = 2;
|
||||
optional int32 selection_end = 3;
|
||||
optional int32 offset = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message GetCursorCapsMode {
|
||||
optional int32 req_modes = 1;
|
||||
optional int32 result = 2;
|
||||
}
|
||||
|
||||
message GetExtractedText {
|
||||
optional ExtractedTextRequest request = 1;
|
||||
optional int32 flags = 2;
|
||||
optional string result = 3 [(.android.privacy).dest = DEST_LOCAL];
|
||||
|
||||
message ExtractedTextRequest {
|
||||
optional int32 token = 1;
|
||||
optional int32 flags = 2;
|
||||
optional int32 hint_max_lines = 3;
|
||||
optional int32 hint_max_chars = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,7 @@ message InputMethodClientsTraceProto {
|
||||
optional EditorInfoProto editor_info = 6;
|
||||
optional ImeFocusControllerProto ime_focus_controller = 7;
|
||||
optional InputConnectionProto input_connection = 8;
|
||||
optional InputConnectionCallProto input_connection_call = 9;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user