diff --git a/core/java/android/inputmethodservice/AbstractInputMethodService.java b/core/java/android/inputmethodservice/AbstractInputMethodService.java
index 7cf0b10031acc..3cd13a212a4b8 100644
--- a/core/java/android/inputmethodservice/AbstractInputMethodService.java
+++ b/core/java/android/inputmethodservice/AbstractInputMethodService.java
@@ -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()}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 67e75d205f977..5576857d1f6b9 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -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);
}
}
diff --git a/core/java/android/util/imetracing/ImeTracing.java b/core/java/android/util/imetracing/ImeTracing.java
index 4058eef3e2a37..723f1dd15e238 100644
--- a/core/java/android/util/imetracing/ImeTracing.java
+++ b/core/java/android/util/imetracing/ImeTracing.java
@@ -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.
diff --git a/core/java/android/util/imetracing/ImeTracingClientImpl.java b/core/java/android/util/imetracing/ImeTracingClientImpl.java
index 904b44da97d74..6cc652d942ccb 100644
--- a/core/java/android/util/imetracing/ImeTracingClientImpl.java
+++ b/core/java/android/util/imetracing/ImeTracingClientImpl.java
@@ -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);
diff --git a/core/java/android/util/imetracing/ImeTracingServerImpl.java b/core/java/android/util/imetracing/ImeTracingServerImpl.java
index d758d77fb2f26..e793c280afbc8 100644
--- a/core/java/android/util/imetracing/ImeTracingServerImpl.java
+++ b/core/java/android/util/imetracing/ImeTracingServerImpl.java
@@ -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
}
diff --git a/core/java/android/util/imetracing/InputConnectionHelper.java b/core/java/android/util/imetracing/InputConnectionHelper.java
new file mode 100644
index 0000000000000..39f1e01eb4a9f
--- /dev/null
+++ b/core/java/android/util/imetracing/InputConnectionHelper.java
@@ -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 length.
+ * @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 length.
+ * @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
+ * beforeLength and afterLength .
+ * @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;
+ }
+}
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 1c82619a61ade..c4f32c433598c 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -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 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 internalTypes = InsetsState.toInternalType(types);
for (int i = internalTypes.size() - 1; i >= 0; i--) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 2bea0d6b4b04c..8321f2b28771e 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -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);
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 8d2c2d96637fd..907b5b085b590 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -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());
+ }
}
}
}
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index 4deb40a0d772e..1d5935db63225 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -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) {
diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
index 8c763a6efe549..b70348a953841 100644
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/InputConnectionWrapper.java
@@ -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
diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java
index d30d662806d49..6cdf0df17b65c 100644
--- a/core/java/com/android/internal/widget/EditableInputConnection.java
+++ b/core/java/com/android/internal/widget/EditableInputConnection.java
@@ -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());
}
diff --git a/core/proto/android/inputmethodservice/inputmethodservice.proto b/core/proto/android/inputmethodservice/inputmethodservice.proto
index e5d1713616953..1f68fb4b513da 100644
--- a/core/proto/android/inputmethodservice/inputmethodservice.proto
+++ b/core/proto/android/inputmethodservice/inputmethodservice.proto
@@ -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;
diff --git a/core/proto/android/view/inputmethod/inputconnection.proto b/core/proto/android/view/inputmethod/inputconnection.proto
index ad9a95aa95e6a..d1f257ff2c5c4 100644
--- a/core/proto/android/view/inputmethod/inputconnection.proto
+++ b/core/proto/android/view/inputmethod/inputconnection.proto
@@ -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;
+ }
+ }
}
\ No newline at end of file
diff --git a/core/proto/android/view/inputmethod/inputmethodeditortrace.proto b/core/proto/android/view/inputmethod/inputmethodeditortrace.proto
index c1dce6f2d093b..8e4377ca124cf 100644
--- a/core/proto/android/view/inputmethod/inputmethodeditortrace.proto
+++ b/core/proto/android/view/inputmethod/inputmethodeditortrace.proto
@@ -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;
}
}