diff --git a/core/java/android/inputmethodservice/AbstractInputMethodService.java b/core/java/android/inputmethodservice/AbstractInputMethodService.java
index b359465c4738d..9db41c41c31cb 100644
--- a/core/java/android/inputmethodservice/AbstractInputMethodService.java
+++ b/core/java/android/inputmethodservice/AbstractInputMethodService.java
@@ -25,13 +25,10 @@ import android.content.res.Configuration;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
-import android.util.proto.ProtoOutputStream;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
-import android.view.inputmethod.InputConnection;
-import android.view.inputmethod.InputContentInfo;
import android.view.inputmethod.InputMethod;
import android.view.inputmethod.InputMethodSession;
import android.window.WindowProviderService;
@@ -215,16 +212,6 @@ public abstract class AbstractInputMethodService extends WindowProviderService
*/
public abstract AbstractInputMethodSessionImpl onCreateInputMethodSessionInterface();
- /**
- * 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, @Nullable byte[] icProto);
-
/**
* Implement this to handle {@link android.os.Binder#dump Binder.dump()}
* calls on your input method.
@@ -238,9 +225,36 @@ public abstract class AbstractInputMethodService extends WindowProviderService
if (mInputMethod == null) {
mInputMethod = onCreateInputMethodInterface();
}
- return new IInputMethodWrapper(this, mInputMethod);
+ return new IInputMethodWrapper(createInputMethodServiceInternal(), mInputMethod);
}
-
+
+ /**
+ * Used to inject custom {@link InputMethodServiceInternal}.
+ *
+ * @return the {@link InputMethodServiceInternal} to be used.
+ */
+ @NonNull
+ InputMethodServiceInternal createInputMethodServiceInternal() {
+ return new InputMethodServiceInternal() {
+ /**
+ * {@inheritDoc}
+ */
+ @NonNull
+ @Override
+ public Context getContext() {
+ return AbstractInputMethodService.this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
+ AbstractInputMethodService.this.dump(fd, fout, args);
+ }
+ };
+ }
+
/**
* Implement this to handle trackball events on your input method.
*
@@ -263,35 +277,6 @@ public abstract class AbstractInputMethodService extends WindowProviderService
return false;
}
- /**
- * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access
- * permission to the content.
- *
- *
Default implementation does nothing.
- *
- * @param inputContentInfo Content to be temporarily exposed from the input method to the
- * application.
- * This cannot be {@code null}.
- * @param inputConnection {@link InputConnection} with which
- * {@link InputConnection#commitContent(InputContentInfo, int, android.os.Bundle)} will be
- * called.
- * @return {@code false} if we cannot allow a temporary access permission.
- * @hide
- */
- public void exposeContent(@NonNull InputContentInfo inputContentInfo,
- @NonNull InputConnection inputConnection) {
- return;
- }
-
- /**
- * Called when the user took some actions that should be taken into consideration to update the
- * MRU list for input method rotation.
- *
- * @hide
- */
- public void notifyUserActionIfNecessary() {
- }
-
// TODO(b/149463653): remove it in T. We missed the API deadline in S.
/** @hide */
@Override
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index 99e439ae0fb1b..90990b45e5525 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -76,7 +76,7 @@ class IInputMethodWrapper extends IInputMethod.Stub
private static final int DO_CHANGE_INPUTMETHOD_SUBTYPE = 80;
private static final int DO_CREATE_INLINE_SUGGESTIONS_REQUEST = 90;
- final WeakReference mTarget;
+ final WeakReference mTarget;
final Context mContext;
@UnsupportedAppUsage
final HandlerCaller mCaller;
@@ -129,12 +129,12 @@ class IInputMethodWrapper extends IInputMethod.Stub
}
}
- public IInputMethodWrapper(AbstractInputMethodService context, InputMethod inputMethod) {
- mTarget = new WeakReference<>(context);
- mContext = context.getApplicationContext();
+ IInputMethodWrapper(InputMethodServiceInternal imsInternal, InputMethod inputMethod) {
+ mTarget = new WeakReference<>(imsInternal);
+ mContext = imsInternal.getContext().getApplicationContext();
mCaller = new HandlerCaller(mContext, null, this, true /*asyncHandler*/);
mInputMethod = new WeakReference<>(inputMethod);
- mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
+ mTargetSdkVersion = imsInternal.getContext().getApplicationInfo().targetSdkVersion;
}
@MainThread
@@ -149,7 +149,7 @@ class IInputMethodWrapper extends IInputMethod.Stub
switch (msg.what) {
case DO_DUMP: {
- AbstractInputMethodService target = mTarget.get();
+ InputMethodServiceInternal target = mTarget.get();
if (target == null) {
return;
}
@@ -251,11 +251,11 @@ class IInputMethodWrapper extends IInputMethod.Stub
@BinderThread
@Override
protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
- AbstractInputMethodService target = mTarget.get();
+ InputMethodServiceInternal target = mTarget.get();
if (target == null) {
return;
}
- if (target.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ if (target.getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
fout.println("Permission Denial: can't dump InputMethodManager from from pid="
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index e0b001f5ed192..dadea6792ac16 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -55,7 +55,6 @@ import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACK
import static java.lang.annotation.RetentionPolicy.SOURCE;
-import android.annotation.AnyThread;
import android.annotation.CallSuper;
import android.annotation.DrawableRes;
import android.annotation.IntDef;
@@ -740,7 +739,7 @@ public class InputMethodService extends AbstractInputMethodService {
return;
}
ImeTracing.getInstance().triggerServiceDump(
- "InputMethodService.InputMethodImpl#hideSoftInput", InputMethodService.this,
+ "InputMethodService.InputMethodImpl#hideSoftInput", mDumper,
null /* icProto */);
final boolean wasVisible = isInputViewShown();
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.hideSoftInput");
@@ -797,7 +796,7 @@ public class InputMethodService extends AbstractInputMethodService {
}
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.showSoftInput");
ImeTracing.getInstance().triggerServiceDump(
- "InputMethodService.InputMethodImpl#showSoftInput", InputMethodService.this,
+ "InputMethodService.InputMethodImpl#showSoftInput", mDumper,
null /* icProto */);
final boolean wasVisible = isInputViewShown();
if (dispatchOnShowInputRequested(flags, false)) {
@@ -2222,7 +2221,7 @@ public class InputMethodService extends AbstractInputMethodService {
return;
}
- ImeTracing.getInstance().triggerServiceDump("InputMethodService#showWindow", this,
+ ImeTracing.getInstance().triggerServiceDump("InputMethodService#showWindow", mDumper,
null /* icProto */);
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.showWindow");
mDecorViewWasVisible = mDecorViewVisible;
@@ -2301,7 +2300,7 @@ public class InputMethodService extends AbstractInputMethodService {
*/
private void applyVisibilityInInsetsConsumerIfNecessary(boolean setVisible) {
ImeTracing.getInstance().triggerServiceDump(
- "InputMethodService#applyVisibilityInInsetsConsumerIfNecessary", this,
+ "InputMethodService#applyVisibilityInInsetsConsumerIfNecessary", mDumper,
null /* icProto */);
if (setVisible) {
cancelImeSurfaceRemoval();
@@ -2330,7 +2329,7 @@ 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", mDumper,
null /* icProto */);
mWindowVisible = false;
finishViews(false /* finishingInput */);
@@ -2403,7 +2402,7 @@ 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", mDumper,
null /* icProto */);
finishViews(true /* finishingInput */);
if (mInputStarted) {
@@ -2420,7 +2419,7 @@ public class InputMethodService extends AbstractInputMethodService {
if (!restarting && mInputStarted) {
doFinishInput();
}
- ImeTracing.getInstance().triggerServiceDump("InputMethodService#doStartInput", this,
+ ImeTracing.getInstance().triggerServiceDump("InputMethodService#doStartInput", mDumper,
null /* icProto */);
mInputStarted = true;
mStartedInputConnection = ic;
@@ -2580,7 +2579,7 @@ 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", mDumper,
null /* icProto */);
mPrivOps.hideMySoftInput(flags);
}
@@ -2594,7 +2593,7 @@ 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", mDumper,
null /* icProto */);
mPrivOps.showMySoftInput(flags);
}
@@ -3281,67 +3280,91 @@ public class InputMethodService extends AbstractInputMethodService {
}
/**
- * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access
- * permission to the content.
+ * Used to inject custom {@link InputMethodServiceInternal}.
*
- * @param inputContentInfo Content to be temporarily exposed from the input method to the
- * application.
- * This cannot be {@code null}.
- * @param inputConnection {@link InputConnection} with which
- * {@link InputConnection#commitContent(InputContentInfo, int, Bundle)} will be called.
- * @hide
+ * @return the {@link InputMethodServiceInternal} to be used.
*/
+ @NonNull
@Override
- public final void exposeContent(@NonNull InputContentInfo inputContentInfo,
- @NonNull InputConnection inputConnection) {
- if (inputConnection == null) {
- return;
- }
- if (getCurrentInputConnection() != inputConnection) {
- return;
- }
- exposeContentInternal(inputContentInfo, getCurrentInputEditorInfo());
- }
-
- /**
- * {@inheritDoc}
- * @hide
- */
- @AnyThread
- @Override
- public final void notifyUserActionIfNecessary() {
- synchronized (mLock) {
- if (mNotifyUserActionSent) {
- return;
+ final InputMethodServiceInternal createInputMethodServiceInternal() {
+ return new InputMethodServiceInternal() {
+ /**
+ * {@inheritDoc}
+ */
+ @NonNull
+ @Override
+ public Context getContext() {
+ return InputMethodService.this;
}
- mPrivOps.notifyUserActionAsync();
- mNotifyUserActionSent = true;
- }
- }
- /**
- * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access
- * permission to the content.
- *
- * See {@link android.inputmethodservice.InputMethodService#exposeContent(InputContentInfo,
- * InputConnection)} for details.
- *
- * @param inputContentInfo Content to be temporarily exposed from the input method to the
- * application.
- * This cannot be {@code null}.
- * @param editorInfo The editor that receives {@link InputContentInfo}.
- */
- private void exposeContentInternal(@NonNull InputContentInfo inputContentInfo,
- @NonNull EditorInfo editorInfo) {
- final Uri contentUri = inputContentInfo.getContentUri();
- final IInputContentUriToken uriToken =
- mPrivOps.createInputContentUriToken(contentUri, editorInfo.packageName);
- if (uriToken == null) {
- Log.e(TAG, "createInputContentAccessToken failed. contentUri=" + contentUri.toString()
- + " packageName=" + editorInfo.packageName);
- return;
- }
- inputContentInfo.setUriToken(uriToken);
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void exposeContent(@NonNull InputContentInfo inputContentInfo,
+ @NonNull InputConnection inputConnection) {
+ if (inputConnection == null) {
+ return;
+ }
+ if (getCurrentInputConnection() != inputConnection) {
+ return;
+ }
+ exposeContentInternal(inputContentInfo, getCurrentInputEditorInfo());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void notifyUserActionIfNecessary() {
+ synchronized (mLock) {
+ if (mNotifyUserActionSent) {
+ return;
+ }
+ mPrivOps.notifyUserActionAsync();
+ mNotifyUserActionSent = true;
+ }
+ }
+
+ /**
+ * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access
+ * permission to the content.
+ *
+ * See {@link #exposeContent(InputContentInfo, InputConnection)} for details.
+ *
+ * @param inputContentInfo Content to be temporarily exposed from the input method to
+ * the application. This cannot be {@code null}.
+ * @param editorInfo The editor that receives {@link InputContentInfo}.
+ */
+ private void exposeContentInternal(@NonNull InputContentInfo inputContentInfo,
+ @NonNull EditorInfo editorInfo) {
+ final Uri contentUri = inputContentInfo.getContentUri();
+ final IInputContentUriToken uriToken =
+ mPrivOps.createInputContentUriToken(contentUri, editorInfo.packageName);
+ if (uriToken == null) {
+ Log.e(TAG, "createInputContentAccessToken failed. contentUri="
+ + contentUri.toString() + " packageName=" + editorInfo.packageName);
+ return;
+ }
+ inputContentInfo.setUriToken(uriToken);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter fout, String[]args) {
+ InputMethodService.this.dump(fd, fout, args);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void triggerServiceDump(String where, @Nullable byte[] icProto) {
+ ImeTracing.getInstance().triggerServiceDump(where, mDumper, icProto);
+ }
+ };
}
private int mapToImeWindowStatus() {
@@ -3411,42 +3434,44 @@ public class InputMethodService extends AbstractInputMethodService {
p.println(" mSettingsObserver=" + mSettingsObserver);
}
- /**
- * @hide
- */
- @Override
- public final void dumpProtoInternal(ProtoOutputStream proto, byte[] icProto) {
- final long token = proto.start(InputMethodServiceTraceProto.INPUT_METHOD_SERVICE);
- mWindow.dumpDebug(proto, SOFT_INPUT_WINDOW);
- proto.write(VIEWS_CREATED, mViewsCreated);
- proto.write(DECOR_VIEW_VISIBLE, mDecorViewVisible);
- proto.write(DECOR_VIEW_WAS_VISIBLE, mDecorViewWasVisible);
- proto.write(WINDOW_VISIBLE, mWindowVisible);
- proto.write(IN_SHOW_WINDOW, mInShowWindow);
- proto.write(CONFIGURATION, getResources().getConfiguration().toString());
- proto.write(TOKEN, Objects.toString(mToken));
- proto.write(INPUT_BINDING, Objects.toString(mInputBinding));
- proto.write(INPUT_STARTED, mInputStarted);
- proto.write(INPUT_VIEW_STARTED, mInputViewStarted);
- proto.write(CANDIDATES_VIEW_STARTED, mCandidatesViewStarted);
- if (mInputEditorInfo != null) {
- mInputEditorInfo.dumpDebug(proto, INPUT_EDITOR_INFO);
+ private final ImeTracing.ServiceDumper mDumper = new ImeTracing.ServiceDumper() {
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void dumpToProto(ProtoOutputStream proto, @Nullable byte[] icProto) {
+ final long token = proto.start(InputMethodServiceTraceProto.INPUT_METHOD_SERVICE);
+ mWindow.dumpDebug(proto, SOFT_INPUT_WINDOW);
+ proto.write(VIEWS_CREATED, mViewsCreated);
+ proto.write(DECOR_VIEW_VISIBLE, mDecorViewVisible);
+ proto.write(DECOR_VIEW_WAS_VISIBLE, mDecorViewWasVisible);
+ proto.write(WINDOW_VISIBLE, mWindowVisible);
+ proto.write(IN_SHOW_WINDOW, mInShowWindow);
+ proto.write(CONFIGURATION, getResources().getConfiguration().toString());
+ proto.write(TOKEN, Objects.toString(mToken));
+ proto.write(INPUT_BINDING, Objects.toString(mInputBinding));
+ proto.write(INPUT_STARTED, mInputStarted);
+ proto.write(INPUT_VIEW_STARTED, mInputViewStarted);
+ proto.write(CANDIDATES_VIEW_STARTED, mCandidatesViewStarted);
+ if (mInputEditorInfo != null) {
+ mInputEditorInfo.dumpDebug(proto, INPUT_EDITOR_INFO);
+ }
+ proto.write(SHOW_INPUT_REQUESTED, mShowInputRequested);
+ proto.write(LAST_SHOW_INPUT_REQUESTED, mLastShowInputRequested);
+ proto.write(SHOW_INPUT_FLAGS, mShowInputFlags);
+ proto.write(CANDIDATES_VISIBILITY, mCandidatesVisibility);
+ proto.write(FULLSCREEN_APPLIED, mFullscreenApplied);
+ proto.write(IS_FULLSCREEN, mIsFullscreen);
+ proto.write(EXTRACT_VIEW_HIDDEN, mExtractViewHidden);
+ proto.write(EXTRACTED_TOKEN, mExtractedToken);
+ proto.write(IS_INPUT_VIEW_SHOWN, mIsInputViewShown);
+ 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);
+ }
+ proto.end(token);
}
- proto.write(SHOW_INPUT_REQUESTED, mShowInputRequested);
- proto.write(LAST_SHOW_INPUT_REQUESTED, mLastShowInputRequested);
- proto.write(SHOW_INPUT_FLAGS, mShowInputFlags);
- proto.write(CANDIDATES_VISIBILITY, mCandidatesVisibility);
- proto.write(FULLSCREEN_APPLIED, mFullscreenApplied);
- proto.write(IS_FULLSCREEN, mIsFullscreen);
- proto.write(EXTRACT_VIEW_HIDDEN, mExtractViewHidden);
- proto.write(EXTRACTED_TOKEN, mExtractedToken);
- proto.write(IS_INPUT_VIEW_SHOWN, mIsInputViewShown);
- 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);
- }
- proto.end(token);
- }
+ };
}
diff --git a/core/java/android/inputmethodservice/InputMethodServiceInternal.java b/core/java/android/inputmethodservice/InputMethodServiceInternal.java
new file mode 100644
index 0000000000000..7cd4ff61b2c80
--- /dev/null
+++ b/core/java/android/inputmethodservice/InputMethodServiceInternal.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2021 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.inputmethodservice;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputContentInfo;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * A set of internal methods exposed by {@link InputMethodService} to be called only from other
+ * framework classes for internal use.
+ *
+ * CAVEATS: {@link AbstractInputMethodService} does not support all the methods here.
+ */
+interface InputMethodServiceInternal {
+ /**
+ * @return {@link Context} associated with the service.
+ */
+ @NonNull
+ Context getContext();
+
+ /**
+ * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access
+ * permission to the content.
+ *
+ * @param inputContentInfo Content to be temporarily exposed from the input method to the
+ * application. This cannot be {@code null}.
+ * @param inputConnection {@link InputConnection} with which
+ * {@link InputConnection#commitContent(InputContentInfo, int, Bundle)}
+ * will be called.
+ */
+ default void exposeContent(@NonNull InputContentInfo inputContentInfo,
+ @NonNull InputConnection inputConnection) {
+ }
+
+ /**
+ * Called when the user took some actions that should be taken into consideration to update the
+ * MRU list for input method rotation.
+ */
+ default void notifyUserActionIfNecessary() {
+ }
+
+ /**
+ * Called when the system is asking the IME to dump its information for debugging.
+ *
+ * The caller is responsible for checking {@link android.Manifest.permission.DUMP}.
+ *
+ * @param fd The raw file descriptor that the dump is being sent to.
+ * @param fout The file to which you should dump your state. This will be
+ * closed for you after you return.
+ * @param args additional arguments to the dump request.
+ */
+ default void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
+ }
+
+ /**
+ * Called with {@link com.android.internal.inputmethod.ImeTracing#triggerServiceDump(String,
+ * com.android.internal.inputmethod.ImeTracing.ServiceDumper, byte[])} needs to be triggered
+ * with the given parameters.
+ *
+ * @param where {@code where} parameter to be passed.
+ * @param icProto {@code icProto} parameter to be passed.
+ */
+ default void triggerServiceDump(String where, @Nullable byte[] icProto) {
+ }
+}
diff --git a/core/java/android/inputmethodservice/RemoteInputConnection.java b/core/java/android/inputmethodservice/RemoteInputConnection.java
index 98a49ccb27d80..4fa98be75b46c 100644
--- a/core/java/android/inputmethodservice/RemoteInputConnection.java
+++ b/core/java/android/inputmethodservice/RemoteInputConnection.java
@@ -52,7 +52,7 @@ final class RemoteInputConnection implements InputConnection {
private final IInputContextInvoker mInvoker;
@NonNull
- private final WeakReference mInputMethodService;
+ private final WeakReference mInputMethodService;
@MissingMethodFlags
private final int mMissingMethods;
@@ -67,7 +67,7 @@ final class RemoteInputConnection implements InputConnection {
private final CancellationGroup mCancellationGroup;
RemoteInputConnection(
- @NonNull WeakReference inputMethodService,
+ @NonNull WeakReference inputMethodService,
IInputContext inputContext, @MissingMethodFlags int missingMethods,
@NonNull CancellationGroup cancellationGroup) {
mInputMethodService = inputMethodService;
@@ -90,12 +90,11 @@ final class RemoteInputConnection implements InputConnection {
final CharSequence result = Completable.getResultOrNull(
value, TAG, "getTextAfterCursor()", mCancellationGroup, MAX_WAIT_TIME_MILLIS);
- final AbstractInputMethodService inputMethodService = mInputMethodService.get();
+ final InputMethodServiceInternal inputMethodService = mInputMethodService.get();
if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) {
final byte[] icProto = InputConnectionProtoDumper.buildGetTextAfterCursorProto(length,
flags, result);
- ImeTracing.getInstance().triggerServiceDump(TAG + "#getTextAfterCursor",
- inputMethodService, icProto);
+ inputMethodService.triggerServiceDump(TAG + "#getTextAfterCursor", icProto);
}
return result;
@@ -115,12 +114,11 @@ final class RemoteInputConnection implements InputConnection {
final CharSequence result = Completable.getResultOrNull(
value, TAG, "getTextBeforeCursor()", mCancellationGroup, MAX_WAIT_TIME_MILLIS);
- final AbstractInputMethodService inputMethodService = mInputMethodService.get();
+ final InputMethodServiceInternal inputMethodService = mInputMethodService.get();
if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) {
final byte[] icProto = InputConnectionProtoDumper.buildGetTextBeforeCursorProto(length,
flags, result);
- ImeTracing.getInstance().triggerServiceDump(TAG + "#getTextBeforeCursor",
- inputMethodService, icProto);
+ inputMethodService.triggerServiceDump(TAG + "#getTextBeforeCursor", icProto);
}
return result;
@@ -140,12 +138,11 @@ final class RemoteInputConnection implements InputConnection {
final CharSequence result = Completable.getResultOrNull(
value, TAG, "getSelectedText()", mCancellationGroup, MAX_WAIT_TIME_MILLIS);
- final AbstractInputMethodService inputMethodService = mInputMethodService.get();
+ final InputMethodServiceInternal inputMethodService = mInputMethodService.get();
if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) {
final byte[] icProto = InputConnectionProtoDumper.buildGetSelectedTextProto(flags,
result);
- ImeTracing.getInstance().triggerServiceDump(TAG + "#getSelectedText",
- inputMethodService, icProto);
+ inputMethodService.triggerServiceDump(TAG + "#getSelectedText", icProto);
}
return result;
@@ -179,12 +176,11 @@ final class RemoteInputConnection implements InputConnection {
final SurroundingText result = Completable.getResultOrNull(
value, TAG, "getSurroundingText()", mCancellationGroup, MAX_WAIT_TIME_MILLIS);
- final AbstractInputMethodService inputMethodService = mInputMethodService.get();
+ final InputMethodServiceInternal inputMethodService = mInputMethodService.get();
if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) {
final byte[] icProto = InputConnectionProtoDumper.buildGetSurroundingTextProto(
beforeLength, afterLength, flags, result);
- ImeTracing.getInstance().triggerServiceDump(TAG + "#getSurroundingText",
- inputMethodService, icProto);
+ inputMethodService.triggerServiceDump(TAG + "#getSurroundingText", icProto);
}
return result;
@@ -200,12 +196,11 @@ final class RemoteInputConnection implements InputConnection {
final int result = Completable.getResultOrZero(
value, TAG, "getCursorCapsMode()", mCancellationGroup, MAX_WAIT_TIME_MILLIS);
- final AbstractInputMethodService inputMethodService = mInputMethodService.get();
+ final InputMethodServiceInternal inputMethodService = mInputMethodService.get();
if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) {
final byte[] icProto = InputConnectionProtoDumper.buildGetCursorCapsModeProto(
reqModes, result);
- ImeTracing.getInstance().triggerServiceDump(TAG + "#getCursorCapsMode",
- inputMethodService, icProto);
+ inputMethodService.triggerServiceDump(TAG + "#getCursorCapsMode", icProto);
}
return result;
@@ -221,12 +216,11 @@ final class RemoteInputConnection implements InputConnection {
final ExtractedText result = Completable.getResultOrNull(
value, TAG, "getExtractedText()", mCancellationGroup, MAX_WAIT_TIME_MILLIS);
- final AbstractInputMethodService inputMethodService = mInputMethodService.get();
+ final InputMethodServiceInternal inputMethodService = mInputMethodService.get();
if (inputMethodService != null && ImeTracing.getInstance().isEnabled()) {
final byte[] icProto = InputConnectionProtoDumper.buildGetExtractedTextProto(
request, flags, result);
- ImeTracing.getInstance().triggerServiceDump(TAG + "#getExtractedText",
- inputMethodService, icProto);
+ inputMethodService.triggerServiceDump(TAG + "#getExtractedText", icProto);
}
return result;
@@ -243,7 +237,7 @@ final class RemoteInputConnection implements InputConnection {
@AnyThread
private void notifyUserActionIfNecessary() {
- final AbstractInputMethodService inputMethodService = mInputMethodService.get();
+ final InputMethodServiceInternal inputMethodService = mInputMethodService.get();
if (inputMethodService == null) {
// This basically should not happen, because it's the the caller of this method.
return;
@@ -395,7 +389,7 @@ final class RemoteInputConnection implements InputConnection {
}
if ((flags & InputConnection.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
- final AbstractInputMethodService inputMethodService = mInputMethodService.get();
+ final InputMethodServiceInternal inputMethodService = mInputMethodService.get();
if (inputMethodService == null) {
// This basically should not happen, because it's the caller of this method.
return false;
diff --git a/core/java/com/android/internal/inputmethod/ImeTracing.java b/core/java/com/android/internal/inputmethod/ImeTracing.java
index a95f7560c7c87..71a1957970486 100644
--- a/core/java/com/android/internal/inputmethod/ImeTracing.java
+++ b/core/java/com/android/internal/inputmethod/ImeTracing.java
@@ -19,7 +19,6 @@ package com.android.internal.inputmethod;
import android.annotation.Nullable;
import android.app.ActivityThread;
import android.content.Context;
-import android.inputmethodservice.AbstractInputMethodService;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
@@ -106,14 +105,30 @@ public abstract class ImeTracing {
public abstract void triggerClientDump(String where, InputMethodManager immInstance,
@Nullable byte[] icProto);
+ /**
+ * A delegate for {@link #triggerServiceDump(String, ServiceDumper, byte[])}.
+ */
+ @FunctionalInterface
+ public interface ServiceDumper {
+ /**
+ * Dumps internal data into {@link ProtoOutputStream}.
+ *
+ * @param proto {@link ProtoOutputStream} to be dumped into.
+ * @param icProto {@link android.view.inputmethod.InputConnection} call data in proto
+ * format.
+ */
+ void dumpToProto(ProtoOutputStream proto, @Nullable byte[] 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 dumper {@link ServiceDumper} to be used to dump
+ * {@link android.inputmethodservice.InputMethodService}.
* @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, ServiceDumper dumper,
@Nullable byte[] icProto);
/**
diff --git a/core/java/com/android/internal/inputmethod/ImeTracingClientImpl.java b/core/java/com/android/internal/inputmethod/ImeTracingClientImpl.java
index 91ce5e762ec1a..31d278b5ca543 100644
--- a/core/java/com/android/internal/inputmethod/ImeTracingClientImpl.java
+++ b/core/java/com/android/internal/inputmethod/ImeTracingClientImpl.java
@@ -18,7 +18,6 @@ package com.android.internal.inputmethod;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.inputmethodservice.AbstractInputMethodService;
import android.os.RemoteException;
import android.os.ServiceManager.ServiceNotFoundException;
import android.util.Log;
@@ -65,7 +64,7 @@ class ImeTracingClientImpl extends ImeTracing {
}
@Override
- public void triggerServiceDump(String where, @NonNull AbstractInputMethodService service,
+ public void triggerServiceDump(String where, @NonNull ServiceDumper dumper,
@Nullable byte[] icProto) {
if (!isEnabled() || !isAvailable()) {
return;
@@ -80,7 +79,7 @@ class ImeTracingClientImpl extends ImeTracing {
try {
ProtoOutputStream proto = new ProtoOutputStream();
- service.dumpProtoInternal(proto, icProto);
+ dumper.dumpToProto(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/com/android/internal/inputmethod/ImeTracingServerImpl.java b/core/java/com/android/internal/inputmethod/ImeTracingServerImpl.java
index b5aa91adaea94..d452e60eb1dd8 100644
--- a/core/java/com/android/internal/inputmethod/ImeTracingServerImpl.java
+++ b/core/java/com/android/internal/inputmethod/ImeTracingServerImpl.java
@@ -19,7 +19,6 @@ package com.android.internal.inputmethod;
import static android.os.Build.IS_USER;
import android.annotation.Nullable;
-import android.inputmethodservice.AbstractInputMethodService;
import android.os.RemoteException;
import android.os.ServiceManager.ServiceNotFoundException;
import android.util.Log;
@@ -112,8 +111,7 @@ class ImeTracingServerImpl extends ImeTracing {
}
@Override
- public void triggerServiceDump(String where, AbstractInputMethodService service,
- @Nullable byte[] icProto) {
+ public void triggerServiceDump(String where, ServiceDumper dumper, @Nullable byte[] icProto) {
// Intentionally left empty, this is implemented in ImeTracingClientImpl
}