Loading services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java 0 → 100644 +224 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 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 com.android.server.inputmethod; import android.annotation.AnyThread; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Binder; import android.os.DeadObjectException; import android.os.IBinder; import android.os.RemoteException; import android.os.ResultReceiver; import android.util.Slog; import android.view.InputChannel; import android.view.MotionEvent; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputBinding; import android.view.inputmethod.InputMethodSubtype; import com.android.internal.inputmethod.IInputMethodPrivilegedOperations; import com.android.internal.view.IInlineSuggestionsRequestCallback; import com.android.internal.view.IInputContext; import com.android.internal.view.IInputMethod; import com.android.internal.view.IInputMethodSession; import com.android.internal.view.IInputSessionCallback; import com.android.internal.view.InlineSuggestionsRequestInfo; import java.util.List; /** * A wrapper class to invoke IPCs defined in {@link IInputMethod}. */ final class IInputMethodInvoker { private static final String TAG = InputMethodManagerService.TAG; private static final boolean DEBUG = InputMethodManagerService.DEBUG; @AnyThread @Nullable static IInputMethodInvoker create(@Nullable IInputMethod inputMethod) { if (inputMethod == null) { return null; } if (!Binder.isProxy(inputMethod)) { // IInputMethodInvoker must be used only within the system_server and InputMethodService // must not be running in the system_server. Therefore, "inputMethod" must be a Proxy. throw new UnsupportedOperationException(inputMethod + " must have been a BinderProxy."); } return new IInputMethodInvoker(inputMethod); } /** * A simplified version of {@link android.os.Debug#getCaller()}. * * @return method name of the caller. */ @AnyThread private static String getCallerMethodName() { final StackTraceElement[] callStack = Thread.currentThread().getStackTrace(); if (callStack.length <= 4) { return "<bottom of call stack>"; } return callStack[4].getMethodName(); } @AnyThread private static void logRemoteException(@NonNull RemoteException e) { if (DEBUG || !(e instanceof DeadObjectException)) { Slog.w(TAG, "IPC failed at IInputMethodInvoker#" + getCallerMethodName(), e); } } @AnyThread static int getBinderIdentityHashCode(@Nullable IInputMethodInvoker obj) { if (obj == null) { return 0; } return System.identityHashCode(obj.mTarget); } @NonNull private final IInputMethod mTarget; private IInputMethodInvoker(@NonNull IInputMethod target) { mTarget = target; } @AnyThread @NonNull IBinder asBinder() { return mTarget.asBinder(); } @AnyThread void initializeInternal(IBinder token, IInputMethodPrivilegedOperations privOps, int configChanges, boolean stylusHwSupported) { try { mTarget.initializeInternal(token, privOps, configChanges, stylusHwSupported); } catch (RemoteException e) { logRemoteException(e); } } @AnyThread void onCreateInlineSuggestionsRequest(InlineSuggestionsRequestInfo requestInfo, IInlineSuggestionsRequestCallback cb) { try { mTarget.onCreateInlineSuggestionsRequest(requestInfo, cb); } catch (RemoteException e) { logRemoteException(e); } } @AnyThread void bindInput(InputBinding binding) { try { mTarget.bindInput(binding); } catch (RemoteException e) { logRemoteException(e); } } @AnyThread void unbindInput() { try { mTarget.unbindInput(); } catch (RemoteException e) { logRemoteException(e); } } @AnyThread void startInput(IBinder startInputToken, IInputContext inputContext, EditorInfo attribute, boolean restarting) { try { mTarget.startInput(startInputToken, inputContext, attribute, restarting); } catch (RemoteException e) { logRemoteException(e); } } @AnyThread void createSession(InputChannel channel, IInputSessionCallback callback) { try { mTarget.createSession(channel, callback); } catch (RemoteException e) { logRemoteException(e); } } @AnyThread void setSessionEnabled(IInputMethodSession session, boolean enabled) { try { mTarget.setSessionEnabled(session, enabled); } catch (RemoteException e) { logRemoteException(e); } } // TODO(b/192412909): Convert this back to void method @AnyThread boolean showSoftInput(IBinder showInputToken, int flags, ResultReceiver resultReceiver) { try { mTarget.showSoftInput(showInputToken, flags, resultReceiver); } catch (RemoteException e) { logRemoteException(e); return false; } return true; } // TODO(b/192412909): Convert this back to void method @AnyThread boolean hideSoftInput(IBinder hideInputToken, int flags, ResultReceiver resultReceiver) { try { mTarget.hideSoftInput(hideInputToken, flags, resultReceiver); } catch (RemoteException e) { logRemoteException(e); return false; } return true; } @AnyThread void changeInputMethodSubtype(InputMethodSubtype subtype) { try { mTarget.changeInputMethodSubtype(subtype); } catch (RemoteException e) { logRemoteException(e); } } @AnyThread void canStartStylusHandwriting(int requestId) { try { mTarget.canStartStylusHandwriting(requestId); } catch (RemoteException e) { logRemoteException(e); } } @AnyThread void startStylusHandwriting(InputChannel channel, List<MotionEvent> events) { try { mTarget.startStylusHandwriting(channel, events); } catch (RemoteException e) { logRemoteException(e); } } } services/core/java/com/android/server/inputmethod/InputMethodBindingController.java +3 −3 Original line number Diff line number Diff line Loading @@ -75,7 +75,7 @@ final class InputMethodBindingController { @GuardedBy("ImfLock.class") @Nullable private String mCurId; @GuardedBy("ImfLock.class") @Nullable private String mSelectedMethodId; @GuardedBy("ImfLock.class") @Nullable private Intent mCurIntent; @GuardedBy("ImfLock.class") @Nullable private IInputMethod mCurMethod; @GuardedBy("ImfLock.class") @Nullable private IInputMethodInvoker mCurMethod; @GuardedBy("ImfLock.class") private int mCurMethodUid = Process.INVALID_UID; @GuardedBy("ImfLock.class") private IBinder mCurToken; @GuardedBy("ImfLock.class") private int mCurSeq; Loading Loading @@ -241,7 +241,7 @@ final class InputMethodBindingController { */ @GuardedBy("ImfLock.class") @Nullable IInputMethod getCurMethod() { IInputMethodInvoker getCurMethod() { return mCurMethod; } Loading Loading @@ -298,7 +298,7 @@ final class InputMethodBindingController { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.onServiceConnected"); synchronized (ImfLock.class) { if (mCurIntent != null && name.equals(mCurIntent.getComponent())) { mCurMethod = IInputMethod.Stub.asInterface(service); mCurMethod = IInputMethodInvoker.create(IInputMethod.Stub.asInterface(service)); updateCurrentMethodUid(); if (mCurToken == null) { Slog.w(TAG, "Service connected without a token!"); Loading services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +46 −90 Original line number Diff line number Diff line Loading @@ -167,7 +167,6 @@ import com.android.internal.util.DumpUtils; import com.android.internal.view.IInlineSuggestionsRequestCallback; import com.android.internal.view.IInlineSuggestionsResponseCallback; import com.android.internal.view.IInputContext; import com.android.internal.view.IInputMethod; import com.android.internal.view.IInputMethodClient; import com.android.internal.view.IInputMethodManager; import com.android.internal.view.IInputMethodSession; Loading Loading @@ -329,7 +328,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub static class SessionState { final ClientState client; final IInputMethod method; final IInputMethodInvoker method; IInputMethodSession session; InputChannel channel; Loading @@ -338,14 +337,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub public String toString() { return "SessionState{uid " + client.uid + " pid " + client.pid + " method " + Integer.toHexString( System.identityHashCode(method)) IInputMethodInvoker.getBinderIdentityHashCode(method)) + " session " + Integer.toHexString( System.identityHashCode(session)) + " channel " + channel + "}"; } SessionState(ClientState _client, IInputMethod _method, SessionState(ClientState _client, IInputMethodInvoker _method, IInputMethodSession _session, InputChannel _channel) { client = _client; method = _method; Loading Loading @@ -613,7 +612,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub */ @GuardedBy("ImfLock.class") @Nullable private IInputMethod getCurMethodLocked() { private IInputMethodInvoker getCurMethodLocked() { return mBindingController.getCurMethod(); } Loading Loading @@ -692,8 +691,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub /** * Internal state snapshot when * {@link IInputMethod#startInput(IBinder, IInputContext, EditorInfo, boolean)} is about to be * called. * {@link com.android.internal.view.IInputMethod#startInput(IBinder, IInputContext, EditorInfo, * boolean)} is about to be called. * * <p>Calling that IPC endpoint basically means that * {@link InputMethodService#doStartInput(InputConnection, EditorInfo, boolean)} will be called Loading Loading @@ -1951,18 +1950,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub InlineSuggestionsRequestInfo requestInfo, IInlineSuggestionsRequestCallback callback) { final InputMethodInfo imi = mMethodMap.get(getSelectedMethodIdLocked()); try { IInputMethod curMethod = getCurMethodLocked(); IInputMethodInvoker curMethod = getCurMethodLocked(); if (userId == mSettings.getCurrentUserId() && imi != null && imi.isInlineSuggestionsEnabled() && curMethod != null) { final IInlineSuggestionsRequestCallback callbackImpl = new InlineSuggestionsRequestCallbackDecorator(callback, imi.getPackageName(), mCurTokenDisplayId, getCurTokenLocked(), this); try { curMethod.onCreateInlineSuggestionsRequest(requestInfo, callbackImpl); } catch (RemoteException e) { Slog.w(TAG, "RemoteException calling onCreateInlineSuggestionsRequest()", e); } } else { callback.onInlineSuggestionsUnsupported(); } Loading Loading @@ -2190,13 +2185,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mCurFocusedWindow, 0, null, SoftInputShowHideReason.HIDE_REMOVE_CLIENT); if (mBoundToMethod) { mBoundToMethod = false; IInputMethod curMethod = getCurMethodLocked(); IInputMethodInvoker curMethod = getCurMethodLocked(); if (curMethod != null) { try { curMethod.unbindInput(); } catch (RemoteException e) { // There is nothing interesting about the method dying. } } } mCurClient = null; Loading Loading @@ -2230,13 +2221,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub + mCurClient.client.asBinder()); if (mBoundToMethod) { mBoundToMethod = false; IInputMethod curMethod = getCurMethodLocked(); IInputMethodInvoker curMethod = getCurMethodLocked(); if (curMethod != null) { try { curMethod.unbindInput(); } catch (RemoteException e) { // There is nothing interesting about the method dying. } } } Loading Loading @@ -2285,11 +2272,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @NonNull InputBindResult attachNewInputLocked(@StartInputReason int startInputReason, boolean initial) { if (!mBoundToMethod) { IInputMethod curMethod = getCurMethodLocked(); try { curMethod.bindInput(mCurClient.binding); } catch (RemoteException e) { } getCurMethodLocked().bindInput(mCurClient.binding); mBoundToMethod = true; } Loading @@ -2316,11 +2299,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } final SessionState session = mCurClient.curSession; try { setEnabledSessionLocked(session); session.method.startInput(startInputToken, mCurInputContext, mCurAttribute, restarting); } catch (RemoteException e) { } if (mShowRequested) { if (DEBUG) Slog.v(TAG, "Attach new input asks to show input"); Loading Loading @@ -2514,18 +2494,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } @GuardedBy("ImfLock.class") void initializeImeLocked(@NonNull IInputMethod inputMethod, @NonNull IBinder token, void initializeImeLocked(@NonNull IInputMethodInvoker inputMethod, @NonNull IBinder token, @android.content.pm.ActivityInfo.Config int configChanges, boolean supportStylusHw) { if (DEBUG) { Slog.v(TAG, "Sending attach of token: " + token + " for display: " + mCurTokenDisplayId); } try { inputMethod.initializeInternal(token, new InputMethodPrivilegedOperationsImpl(this, token), configChanges, supportStylusHw); } catch (RemoteException e) { } inputMethod.initializeInternal(token, new InputMethodPrivilegedOperationsImpl(this, token), configChanges, supportStylusHw); } @AnyThread Loading @@ -2535,7 +2511,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } @BinderThread void onSessionCreated(IInputMethod method, IInputMethodSession session, InputChannel channel) { void onSessionCreated(IInputMethodInvoker method, IInputMethodSession session, InputChannel channel) { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.onSessionCreated"); try { synchronized (ImfLock.class) { Loading @@ -2545,7 +2522,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub channel.dispose(); return; } IInputMethod curMethod = getCurMethodLocked(); IInputMethodInvoker curMethod = getCurMethodLocked(); if (curMethod != null && method != null && curMethod.asBinder() == method.asBinder()) { if (mCurClient != null) { Loading Loading @@ -2609,7 +2586,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub cs.sessionRequested = true; final IInputMethod curMethod = getCurMethodLocked(); final IInputMethodInvoker curMethod = getCurMethodLocked(); final IInputSessionCallback.Stub callback = new IInputSessionCallback.Stub() { @Override public void sessionCreated(IInputMethodSession session) { Loading @@ -2624,7 +2601,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub try { curMethod.createSession(clientChannel, callback); } catch (RemoteException e) { } finally { // Dispose the channel because the remote proxy will get its own copy when // unparceled. Loading Loading @@ -3012,14 +2988,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } if (newSubtype != oldSubtype) { setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true); IInputMethod curMethod = getCurMethodLocked(); IInputMethodInvoker curMethod = getCurMethodLocked(); if (curMethod != null) { try { updateSystemUiLocked(mImeWindowVis, mBackDisposition); curMethod.changeInputMethodSubtype(newSubtype); } catch (RemoteException e) { Slog.w(TAG, "Failed to call changeInputMethodSubtype"); } } } return; Loading Loading @@ -3096,13 +3068,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return; } if (DEBUG) Slog.v(TAG, "Client requesting Stylus Handwriting to be started"); final IInputMethod curMethod = getCurMethodLocked(); final IInputMethodInvoker curMethod = getCurMethodLocked(); if (curMethod != null) { try { curMethod.canStartStylusHandwriting(++mHwRequestId); } catch (RemoteException e) { Slog.w(TAG, "RemoteException calling canStartStylusHandwriting(): ", e); } } } finally { Binder.restoreCallingIdentity(ident); Loading Loading @@ -3153,21 +3121,20 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } mBindingController.setCurrentMethodVisible(); final IInputMethod curMethod = getCurMethodLocked(); final IInputMethodInvoker curMethod = getCurMethodLocked(); if (curMethod != null) { // create a placeholder token for IMS so that IMS cannot inject windows into client app. Binder showInputToken = new Binder(); mShowRequestWindowMap.put(showInputToken, windowToken); final int showFlags = getImeShowFlagsLocked(); try { if (DEBUG) { Slog.v(TAG, "Calling " + curMethod + ".showSoftInput(" + showInputToken + ", " + showFlags + ", " + resultReceiver + ") for reason: " + InputMethodDebug.softInputDisplayReasonToString(reason)); } curMethod.showSoftInput(showInputToken, showFlags, resultReceiver); // TODO(b/192412909): Check if we can always call onShowHideSoftInputRequested() or not. if (curMethod.showSoftInput(showInputToken, showFlags, resultReceiver)) { onShowHideSoftInputRequested(true /* show */, windowToken, reason); } catch (RemoteException e) { } mInputShown = true; return true; Loading Loading @@ -3236,7 +3203,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // since Android Eclair. That's why we need to accept IMM#hideSoftInput() even when only // IMMS#InputShown indicates that the software keyboard is shown. // TODO: Clean up, IMMS#mInputShown, IMMS#mImeWindowVis and mShowRequested. IInputMethod curMethod = getCurMethodLocked(); IInputMethodInvoker curMethod = getCurMethodLocked(); final boolean shouldHideSoftInput = (curMethod != null) && (mInputShown || (mImeWindowVis & InputMethodService.IME_ACTIVE) != 0); boolean res; Loading @@ -3252,10 +3219,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub + ", " + resultReceiver + ") for reason: " + InputMethodDebug.softInputDisplayReasonToString(reason)); } try { curMethod.hideSoftInput(hideInputToken, 0 /* flags */, resultReceiver); // TODO(b/192412909): Check if we can always call onShowHideSoftInputRequested() or not. if (curMethod.hideSoftInput(hideInputToken, 0 /* flags */, resultReceiver)) { onShowHideSoftInputRequested(false /* show */, windowToken, reason); } catch (RemoteException e) { } res = true; } else { Loading Loading @@ -4160,7 +4126,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } /** Called right after {@link IInputMethod#showSoftInput}. */ /** Called right after {@link com.android.internal.view.IInputMethod#showSoftInput}. */ @GuardedBy("ImfLock.class") private void onShowHideSoftInputRequested(boolean show, IBinder requestToken, @SoftInputShowHideReason int reason) { Loading Loading @@ -4215,19 +4181,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub void setEnabledSessionLocked(SessionState session) { if (mEnabledSession != session) { if (mEnabledSession != null && mEnabledSession.session != null) { try { if (DEBUG) Slog.v(TAG, "Disabling: " + mEnabledSession); mEnabledSession.method.setSessionEnabled(mEnabledSession.session, false); } catch (RemoteException e) { } } mEnabledSession = session; if (mEnabledSession != null && mEnabledSession.session != null) { try { if (DEBUG) Slog.v(TAG, "Enabling: " + mEnabledSession); mEnabledSession.method.setSessionEnabled(mEnabledSession.session, true); } catch (RemoteException e) { } } } } Loading Loading @@ -4394,12 +4354,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return; } try { // TODO: replace null with actual Channel, MotionEvents getCurMethodLocked().startStylusHandwriting(null, null); } catch (RemoteException e) { Slog.w(TAG, "RemoteException calling startStylusHandwriting(): ", e); } } } Loading Loading @@ -5132,7 +5088,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @BinderThread private void dumpAsStringNoCheck(FileDescriptor fd, PrintWriter pw, String[] args, boolean isCritical) { IInputMethod method; IInputMethodInvoker method; ClientState client; ClientState focusedWindowClient; Loading Loading
services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java 0 → 100644 +224 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 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 com.android.server.inputmethod; import android.annotation.AnyThread; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Binder; import android.os.DeadObjectException; import android.os.IBinder; import android.os.RemoteException; import android.os.ResultReceiver; import android.util.Slog; import android.view.InputChannel; import android.view.MotionEvent; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputBinding; import android.view.inputmethod.InputMethodSubtype; import com.android.internal.inputmethod.IInputMethodPrivilegedOperations; import com.android.internal.view.IInlineSuggestionsRequestCallback; import com.android.internal.view.IInputContext; import com.android.internal.view.IInputMethod; import com.android.internal.view.IInputMethodSession; import com.android.internal.view.IInputSessionCallback; import com.android.internal.view.InlineSuggestionsRequestInfo; import java.util.List; /** * A wrapper class to invoke IPCs defined in {@link IInputMethod}. */ final class IInputMethodInvoker { private static final String TAG = InputMethodManagerService.TAG; private static final boolean DEBUG = InputMethodManagerService.DEBUG; @AnyThread @Nullable static IInputMethodInvoker create(@Nullable IInputMethod inputMethod) { if (inputMethod == null) { return null; } if (!Binder.isProxy(inputMethod)) { // IInputMethodInvoker must be used only within the system_server and InputMethodService // must not be running in the system_server. Therefore, "inputMethod" must be a Proxy. throw new UnsupportedOperationException(inputMethod + " must have been a BinderProxy."); } return new IInputMethodInvoker(inputMethod); } /** * A simplified version of {@link android.os.Debug#getCaller()}. * * @return method name of the caller. */ @AnyThread private static String getCallerMethodName() { final StackTraceElement[] callStack = Thread.currentThread().getStackTrace(); if (callStack.length <= 4) { return "<bottom of call stack>"; } return callStack[4].getMethodName(); } @AnyThread private static void logRemoteException(@NonNull RemoteException e) { if (DEBUG || !(e instanceof DeadObjectException)) { Slog.w(TAG, "IPC failed at IInputMethodInvoker#" + getCallerMethodName(), e); } } @AnyThread static int getBinderIdentityHashCode(@Nullable IInputMethodInvoker obj) { if (obj == null) { return 0; } return System.identityHashCode(obj.mTarget); } @NonNull private final IInputMethod mTarget; private IInputMethodInvoker(@NonNull IInputMethod target) { mTarget = target; } @AnyThread @NonNull IBinder asBinder() { return mTarget.asBinder(); } @AnyThread void initializeInternal(IBinder token, IInputMethodPrivilegedOperations privOps, int configChanges, boolean stylusHwSupported) { try { mTarget.initializeInternal(token, privOps, configChanges, stylusHwSupported); } catch (RemoteException e) { logRemoteException(e); } } @AnyThread void onCreateInlineSuggestionsRequest(InlineSuggestionsRequestInfo requestInfo, IInlineSuggestionsRequestCallback cb) { try { mTarget.onCreateInlineSuggestionsRequest(requestInfo, cb); } catch (RemoteException e) { logRemoteException(e); } } @AnyThread void bindInput(InputBinding binding) { try { mTarget.bindInput(binding); } catch (RemoteException e) { logRemoteException(e); } } @AnyThread void unbindInput() { try { mTarget.unbindInput(); } catch (RemoteException e) { logRemoteException(e); } } @AnyThread void startInput(IBinder startInputToken, IInputContext inputContext, EditorInfo attribute, boolean restarting) { try { mTarget.startInput(startInputToken, inputContext, attribute, restarting); } catch (RemoteException e) { logRemoteException(e); } } @AnyThread void createSession(InputChannel channel, IInputSessionCallback callback) { try { mTarget.createSession(channel, callback); } catch (RemoteException e) { logRemoteException(e); } } @AnyThread void setSessionEnabled(IInputMethodSession session, boolean enabled) { try { mTarget.setSessionEnabled(session, enabled); } catch (RemoteException e) { logRemoteException(e); } } // TODO(b/192412909): Convert this back to void method @AnyThread boolean showSoftInput(IBinder showInputToken, int flags, ResultReceiver resultReceiver) { try { mTarget.showSoftInput(showInputToken, flags, resultReceiver); } catch (RemoteException e) { logRemoteException(e); return false; } return true; } // TODO(b/192412909): Convert this back to void method @AnyThread boolean hideSoftInput(IBinder hideInputToken, int flags, ResultReceiver resultReceiver) { try { mTarget.hideSoftInput(hideInputToken, flags, resultReceiver); } catch (RemoteException e) { logRemoteException(e); return false; } return true; } @AnyThread void changeInputMethodSubtype(InputMethodSubtype subtype) { try { mTarget.changeInputMethodSubtype(subtype); } catch (RemoteException e) { logRemoteException(e); } } @AnyThread void canStartStylusHandwriting(int requestId) { try { mTarget.canStartStylusHandwriting(requestId); } catch (RemoteException e) { logRemoteException(e); } } @AnyThread void startStylusHandwriting(InputChannel channel, List<MotionEvent> events) { try { mTarget.startStylusHandwriting(channel, events); } catch (RemoteException e) { logRemoteException(e); } } }
services/core/java/com/android/server/inputmethod/InputMethodBindingController.java +3 −3 Original line number Diff line number Diff line Loading @@ -75,7 +75,7 @@ final class InputMethodBindingController { @GuardedBy("ImfLock.class") @Nullable private String mCurId; @GuardedBy("ImfLock.class") @Nullable private String mSelectedMethodId; @GuardedBy("ImfLock.class") @Nullable private Intent mCurIntent; @GuardedBy("ImfLock.class") @Nullable private IInputMethod mCurMethod; @GuardedBy("ImfLock.class") @Nullable private IInputMethodInvoker mCurMethod; @GuardedBy("ImfLock.class") private int mCurMethodUid = Process.INVALID_UID; @GuardedBy("ImfLock.class") private IBinder mCurToken; @GuardedBy("ImfLock.class") private int mCurSeq; Loading Loading @@ -241,7 +241,7 @@ final class InputMethodBindingController { */ @GuardedBy("ImfLock.class") @Nullable IInputMethod getCurMethod() { IInputMethodInvoker getCurMethod() { return mCurMethod; } Loading Loading @@ -298,7 +298,7 @@ final class InputMethodBindingController { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.onServiceConnected"); synchronized (ImfLock.class) { if (mCurIntent != null && name.equals(mCurIntent.getComponent())) { mCurMethod = IInputMethod.Stub.asInterface(service); mCurMethod = IInputMethodInvoker.create(IInputMethod.Stub.asInterface(service)); updateCurrentMethodUid(); if (mCurToken == null) { Slog.w(TAG, "Service connected without a token!"); Loading
services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +46 −90 Original line number Diff line number Diff line Loading @@ -167,7 +167,6 @@ import com.android.internal.util.DumpUtils; import com.android.internal.view.IInlineSuggestionsRequestCallback; import com.android.internal.view.IInlineSuggestionsResponseCallback; import com.android.internal.view.IInputContext; import com.android.internal.view.IInputMethod; import com.android.internal.view.IInputMethodClient; import com.android.internal.view.IInputMethodManager; import com.android.internal.view.IInputMethodSession; Loading Loading @@ -329,7 +328,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub static class SessionState { final ClientState client; final IInputMethod method; final IInputMethodInvoker method; IInputMethodSession session; InputChannel channel; Loading @@ -338,14 +337,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub public String toString() { return "SessionState{uid " + client.uid + " pid " + client.pid + " method " + Integer.toHexString( System.identityHashCode(method)) IInputMethodInvoker.getBinderIdentityHashCode(method)) + " session " + Integer.toHexString( System.identityHashCode(session)) + " channel " + channel + "}"; } SessionState(ClientState _client, IInputMethod _method, SessionState(ClientState _client, IInputMethodInvoker _method, IInputMethodSession _session, InputChannel _channel) { client = _client; method = _method; Loading Loading @@ -613,7 +612,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub */ @GuardedBy("ImfLock.class") @Nullable private IInputMethod getCurMethodLocked() { private IInputMethodInvoker getCurMethodLocked() { return mBindingController.getCurMethod(); } Loading Loading @@ -692,8 +691,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub /** * Internal state snapshot when * {@link IInputMethod#startInput(IBinder, IInputContext, EditorInfo, boolean)} is about to be * called. * {@link com.android.internal.view.IInputMethod#startInput(IBinder, IInputContext, EditorInfo, * boolean)} is about to be called. * * <p>Calling that IPC endpoint basically means that * {@link InputMethodService#doStartInput(InputConnection, EditorInfo, boolean)} will be called Loading Loading @@ -1951,18 +1950,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub InlineSuggestionsRequestInfo requestInfo, IInlineSuggestionsRequestCallback callback) { final InputMethodInfo imi = mMethodMap.get(getSelectedMethodIdLocked()); try { IInputMethod curMethod = getCurMethodLocked(); IInputMethodInvoker curMethod = getCurMethodLocked(); if (userId == mSettings.getCurrentUserId() && imi != null && imi.isInlineSuggestionsEnabled() && curMethod != null) { final IInlineSuggestionsRequestCallback callbackImpl = new InlineSuggestionsRequestCallbackDecorator(callback, imi.getPackageName(), mCurTokenDisplayId, getCurTokenLocked(), this); try { curMethod.onCreateInlineSuggestionsRequest(requestInfo, callbackImpl); } catch (RemoteException e) { Slog.w(TAG, "RemoteException calling onCreateInlineSuggestionsRequest()", e); } } else { callback.onInlineSuggestionsUnsupported(); } Loading Loading @@ -2190,13 +2185,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mCurFocusedWindow, 0, null, SoftInputShowHideReason.HIDE_REMOVE_CLIENT); if (mBoundToMethod) { mBoundToMethod = false; IInputMethod curMethod = getCurMethodLocked(); IInputMethodInvoker curMethod = getCurMethodLocked(); if (curMethod != null) { try { curMethod.unbindInput(); } catch (RemoteException e) { // There is nothing interesting about the method dying. } } } mCurClient = null; Loading Loading @@ -2230,13 +2221,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub + mCurClient.client.asBinder()); if (mBoundToMethod) { mBoundToMethod = false; IInputMethod curMethod = getCurMethodLocked(); IInputMethodInvoker curMethod = getCurMethodLocked(); if (curMethod != null) { try { curMethod.unbindInput(); } catch (RemoteException e) { // There is nothing interesting about the method dying. } } } Loading Loading @@ -2285,11 +2272,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @NonNull InputBindResult attachNewInputLocked(@StartInputReason int startInputReason, boolean initial) { if (!mBoundToMethod) { IInputMethod curMethod = getCurMethodLocked(); try { curMethod.bindInput(mCurClient.binding); } catch (RemoteException e) { } getCurMethodLocked().bindInput(mCurClient.binding); mBoundToMethod = true; } Loading @@ -2316,11 +2299,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } final SessionState session = mCurClient.curSession; try { setEnabledSessionLocked(session); session.method.startInput(startInputToken, mCurInputContext, mCurAttribute, restarting); } catch (RemoteException e) { } if (mShowRequested) { if (DEBUG) Slog.v(TAG, "Attach new input asks to show input"); Loading Loading @@ -2514,18 +2494,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } @GuardedBy("ImfLock.class") void initializeImeLocked(@NonNull IInputMethod inputMethod, @NonNull IBinder token, void initializeImeLocked(@NonNull IInputMethodInvoker inputMethod, @NonNull IBinder token, @android.content.pm.ActivityInfo.Config int configChanges, boolean supportStylusHw) { if (DEBUG) { Slog.v(TAG, "Sending attach of token: " + token + " for display: " + mCurTokenDisplayId); } try { inputMethod.initializeInternal(token, new InputMethodPrivilegedOperationsImpl(this, token), configChanges, supportStylusHw); } catch (RemoteException e) { } inputMethod.initializeInternal(token, new InputMethodPrivilegedOperationsImpl(this, token), configChanges, supportStylusHw); } @AnyThread Loading @@ -2535,7 +2511,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } @BinderThread void onSessionCreated(IInputMethod method, IInputMethodSession session, InputChannel channel) { void onSessionCreated(IInputMethodInvoker method, IInputMethodSession session, InputChannel channel) { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.onSessionCreated"); try { synchronized (ImfLock.class) { Loading @@ -2545,7 +2522,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub channel.dispose(); return; } IInputMethod curMethod = getCurMethodLocked(); IInputMethodInvoker curMethod = getCurMethodLocked(); if (curMethod != null && method != null && curMethod.asBinder() == method.asBinder()) { if (mCurClient != null) { Loading Loading @@ -2609,7 +2586,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub cs.sessionRequested = true; final IInputMethod curMethod = getCurMethodLocked(); final IInputMethodInvoker curMethod = getCurMethodLocked(); final IInputSessionCallback.Stub callback = new IInputSessionCallback.Stub() { @Override public void sessionCreated(IInputMethodSession session) { Loading @@ -2624,7 +2601,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub try { curMethod.createSession(clientChannel, callback); } catch (RemoteException e) { } finally { // Dispose the channel because the remote proxy will get its own copy when // unparceled. Loading Loading @@ -3012,14 +2988,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } if (newSubtype != oldSubtype) { setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true); IInputMethod curMethod = getCurMethodLocked(); IInputMethodInvoker curMethod = getCurMethodLocked(); if (curMethod != null) { try { updateSystemUiLocked(mImeWindowVis, mBackDisposition); curMethod.changeInputMethodSubtype(newSubtype); } catch (RemoteException e) { Slog.w(TAG, "Failed to call changeInputMethodSubtype"); } } } return; Loading Loading @@ -3096,13 +3068,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return; } if (DEBUG) Slog.v(TAG, "Client requesting Stylus Handwriting to be started"); final IInputMethod curMethod = getCurMethodLocked(); final IInputMethodInvoker curMethod = getCurMethodLocked(); if (curMethod != null) { try { curMethod.canStartStylusHandwriting(++mHwRequestId); } catch (RemoteException e) { Slog.w(TAG, "RemoteException calling canStartStylusHandwriting(): ", e); } } } finally { Binder.restoreCallingIdentity(ident); Loading Loading @@ -3153,21 +3121,20 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } mBindingController.setCurrentMethodVisible(); final IInputMethod curMethod = getCurMethodLocked(); final IInputMethodInvoker curMethod = getCurMethodLocked(); if (curMethod != null) { // create a placeholder token for IMS so that IMS cannot inject windows into client app. Binder showInputToken = new Binder(); mShowRequestWindowMap.put(showInputToken, windowToken); final int showFlags = getImeShowFlagsLocked(); try { if (DEBUG) { Slog.v(TAG, "Calling " + curMethod + ".showSoftInput(" + showInputToken + ", " + showFlags + ", " + resultReceiver + ") for reason: " + InputMethodDebug.softInputDisplayReasonToString(reason)); } curMethod.showSoftInput(showInputToken, showFlags, resultReceiver); // TODO(b/192412909): Check if we can always call onShowHideSoftInputRequested() or not. if (curMethod.showSoftInput(showInputToken, showFlags, resultReceiver)) { onShowHideSoftInputRequested(true /* show */, windowToken, reason); } catch (RemoteException e) { } mInputShown = true; return true; Loading Loading @@ -3236,7 +3203,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // since Android Eclair. That's why we need to accept IMM#hideSoftInput() even when only // IMMS#InputShown indicates that the software keyboard is shown. // TODO: Clean up, IMMS#mInputShown, IMMS#mImeWindowVis and mShowRequested. IInputMethod curMethod = getCurMethodLocked(); IInputMethodInvoker curMethod = getCurMethodLocked(); final boolean shouldHideSoftInput = (curMethod != null) && (mInputShown || (mImeWindowVis & InputMethodService.IME_ACTIVE) != 0); boolean res; Loading @@ -3252,10 +3219,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub + ", " + resultReceiver + ") for reason: " + InputMethodDebug.softInputDisplayReasonToString(reason)); } try { curMethod.hideSoftInput(hideInputToken, 0 /* flags */, resultReceiver); // TODO(b/192412909): Check if we can always call onShowHideSoftInputRequested() or not. if (curMethod.hideSoftInput(hideInputToken, 0 /* flags */, resultReceiver)) { onShowHideSoftInputRequested(false /* show */, windowToken, reason); } catch (RemoteException e) { } res = true; } else { Loading Loading @@ -4160,7 +4126,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } /** Called right after {@link IInputMethod#showSoftInput}. */ /** Called right after {@link com.android.internal.view.IInputMethod#showSoftInput}. */ @GuardedBy("ImfLock.class") private void onShowHideSoftInputRequested(boolean show, IBinder requestToken, @SoftInputShowHideReason int reason) { Loading Loading @@ -4215,19 +4181,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub void setEnabledSessionLocked(SessionState session) { if (mEnabledSession != session) { if (mEnabledSession != null && mEnabledSession.session != null) { try { if (DEBUG) Slog.v(TAG, "Disabling: " + mEnabledSession); mEnabledSession.method.setSessionEnabled(mEnabledSession.session, false); } catch (RemoteException e) { } } mEnabledSession = session; if (mEnabledSession != null && mEnabledSession.session != null) { try { if (DEBUG) Slog.v(TAG, "Enabling: " + mEnabledSession); mEnabledSession.method.setSessionEnabled(mEnabledSession.session, true); } catch (RemoteException e) { } } } } Loading Loading @@ -4394,12 +4354,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return; } try { // TODO: replace null with actual Channel, MotionEvents getCurMethodLocked().startStylusHandwriting(null, null); } catch (RemoteException e) { Slog.w(TAG, "RemoteException calling startStylusHandwriting(): ", e); } } } Loading Loading @@ -5132,7 +5088,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @BinderThread private void dumpAsStringNoCheck(FileDescriptor fd, PrintWriter pw, String[] args, boolean isCritical) { IInputMethod method; IInputMethodInvoker method; ClientState client; ClientState focusedWindowClient; Loading