Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e24ed79e authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

Hide IInputMethodManager.{add,remove}Client() from apps

Since IInputMethodManager.{add,remove}Client() are just callbacks from
WindowManagerService to InputMethodManagerService, we can simply move
those two methods to InputMethodManagerInternal instead of having them
in IInputMethodManager.aidl, which ends up exposing those methods to
any random user process.

This enables us to clean up WindowManagerService because it is no
longer responsible for obtaining IInputMethodManager and passing it to
each Session instance.

This also allows us to get rid of several RemoteException handlers
from Session class, because now the complier knows that those
callbacks will never throw RemoteException.

Fix: 112670859
Test: atest CtsInputMethodTestCases CtsInputMethodServiceHostTestCases
Test: prebuilts/checkstyle/checkstyle.py -f frameworks/base/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
Change-Id: I453200fd5847e9a78876affb6a1caec221525e1d
parent c3de83e7
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -43,9 +43,6 @@ interface IInputMethodManager {
    // TODO: We should change the return type from List to List<Parcelable>
    // Currently there is a bug that aidl doesn't accept List<Parcelable>
    List getShortcutInputMethodsAndSubtypes();
    void addClient(in IInputMethodClient client,
            in IInputContext inputContext, int uid, int pid);
    void removeClient(in IInputMethodClient client);

    void finishInput(in IInputMethodClient client);
    boolean showSoftInput(in IInputMethodClient client, int flags,
+27 −13
Original line number Diff line number Diff line
@@ -204,6 +204,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
    static final int MSG_START_INPUT = 2000;
    static final int MSG_START_VR_INPUT = 2010;

    static final int MSG_ADD_CLIENT = 2980;
    static final int MSG_REMOVE_CLIENT = 2990;
    static final int MSG_UNBIND_CLIENT = 3000;
    static final int MSG_BIND_CLIENT = 3010;
    static final int MSG_SET_ACTIVE = 3020;
@@ -1712,22 +1714,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
        }
    }

    @Override
    public void addClient(IInputMethodClient client, IInputContext inputContext, int uid, int pid) {
        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
            throw new SecurityException("Only system process can call this method.");
        }
    void addClient(ClientState clientState) {
        synchronized (mMethodMap) {
            mClients.put(client.asBinder(), new ClientState(client,
                    inputContext, uid, pid));
            mClients.put(clientState.client.asBinder(), clientState);
        }
    }

    @Override
    public void removeClient(IInputMethodClient client) {
        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
            throw new SecurityException("Only system process can call this method.");
        }
    void removeClient(IInputMethodClient client) {
        synchronized (mMethodMap) {
            ClientState cs = mClients.remove(client.asBinder());
            if (cs != null) {
@@ -3413,6 +3406,15 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
                return true;
            }

            // ---------------------------------------------------------
            case MSG_ADD_CLIENT:
                addClient((ClientState) msg.obj);
                return true;

            case MSG_REMOVE_CLIENT:
                removeClient((IInputMethodClient) msg.obj);
                return true;

            // ---------------------------------------------------------

            case MSG_UNBIND_CLIENT:
@@ -4404,7 +4406,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
        }
    }

    private static final class LocalServiceImpl implements InputMethodManagerInternal {
    private static final class LocalServiceImpl extends InputMethodManagerInternal {
        @NonNull
        private final Handler mHandler;

@@ -4412,6 +4414,18 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
            mHandler = handler;
        }

        @Override
        public void addClient(IInputMethodClient client, IInputContext inputContext, int uid,
                int pid) {
            mHandler.sendMessage(mHandler.obtainMessage(MSG_ADD_CLIENT,
                    new ClientState(client, inputContext, uid, pid)));
        }

        @Override
        public void removeClient(IInputMethodClient client) {
            mHandler.sendMessage(mHandler.obtainMessage(MSG_REMOVE_CLIENT, client));
        }

        @Override
        public void setInteractive(boolean interactive) {
            // Do everything in handler so as not to block the caller.
+57 −4
Original line number Diff line number Diff line
@@ -18,23 +18,76 @@ package com.android.server.inputmethod;

import android.content.ComponentName;

import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;

/**
 * Input method manager local system service interface.
 */
public interface InputMethodManagerInternal {
public abstract class InputMethodManagerInternal {
    /**
     * Called by the window manager service when a client process is being attached to the window
     * manager service.
     * @param client {@link android.os.Binder} proxy that is associated with the singleton instance
     *               of {@link android.view.inputmethod.InputMethodManager} that runs on the client
     *               process
     * @param inputContext communication channel for the dummy
     *                     {@link android.view.inputmethod.InputConnection}
     * @param uid UID of the client process
     * @param pid PID of the client process
     */
    public abstract void addClient(IInputMethodClient client, IInputContext inputContext, int uid,
            int pid);

    /**
     * Called by the window manager service when a client process is being attached to the window
     * manager service.
     * @param client {@link android.os.Binder} proxy that is associated with the singleton instance
     *               of {@link android.view.inputmethod.InputMethodManager} that runs on the client
     *               process
     */
    public abstract void removeClient(IInputMethodClient client);

    /**
     * Called by the power manager to tell the input method manager whether it
     * should start watching for wake events.
     */
    void setInteractive(boolean interactive);
    public abstract void setInteractive(boolean interactive);

    /**
     * Hides the current input method, if visible.
     */
    void hideCurrentInputMethod();
    public abstract void hideCurrentInputMethod();

    /**
     * Switches to VR InputMethod defined in the packageName of {@param componentName}.
     */
    void startVrInputMethodNoCheck(ComponentName componentName);
    public abstract void startVrInputMethodNoCheck(ComponentName componentName);

    /**
     * Fake implementation of {@link InputMethodManagerInternal}.  All the methods do nothing.
     */
    public static final InputMethodManagerInternal NOP =
            new InputMethodManagerInternal() {
                @Override
                public void addClient(IInputMethodClient client, IInputContext inputContext,
                        int uid, int pid) {
                }

                @Override
                public void removeClient(IInputMethodClient client) {
                }

                @Override
                public void setInteractive(boolean interactive) {
                }

                @Override
                public void hideCurrentInputMethod() {
                }

                @Override
                public void startVrInputMethodNoCheck(ComponentName componentName) {
                }
            };
}
+12 −30
Original line number Diff line number Diff line
@@ -58,7 +58,8 @@ import android.view.WindowManager;
import com.android.internal.os.logging.MetricsLoggerWrapper;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
import com.android.internal.view.IInputMethodManager;
import com.android.server.LocalServices;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.wm.WindowManagerService.H;

import java.io.PrintWriter;
@@ -73,6 +74,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
    final WindowManagerService mService;
    final IWindowSessionCallback mCallback;
    final IInputMethodClient mClient;
    final InputMethodManagerInternal mInputMethodManagerInternal;
    final int mUid;
    final int mPid;
    private final String mStringName;
@@ -98,6 +100,12 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
        mService = service;
        mCallback = callback;
        mClient = client;
        // Depending on the timing when Session object gets called and SystemServer#mFactoryTestMode
        // this could be null, right?
        final InputMethodManagerInternal immInternal =
                LocalServices.getService(InputMethodManagerInternal.class);
        mInputMethodManagerInternal =
                immInternal != null ? immInternal : InputMethodManagerInternal.NOP;
        mUid = Binder.getCallingUid();
        mPid = Binder.getCallingPid();
        mLastReportedAnimatorScale = service.getCurrentAnimatorScale();
@@ -126,31 +134,12 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
        sb.append("}");
        mStringName = sb.toString();

        synchronized (mService.mWindowMap) {
            if (mService.mInputMethodManager == null && mService.mHaveInputMethods) {
                IBinder b = ServiceManager.getService(
                        Context.INPUT_METHOD_SERVICE);
                mService.mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
            }
        }
        long ident = Binder.clearCallingIdentity();
        mInputMethodManagerInternal.addClient(client, inputContext, mUid, mPid);
        try {
            // Note: it is safe to call in to the input method manager
            // here because we are not holding our lock.
            if (mService.mInputMethodManager != null) {
                mService.mInputMethodManager.addClient(client, inputContext, mUid, mPid);
            }
            client.asBinder().linkToDeath(this, 0);
        } catch (RemoteException e) {
            // The caller has died, so we can just forget about this.
            try {
                if (mService.mInputMethodManager != null) {
                    mService.mInputMethodManager.removeClient(client);
                }
            } catch (RemoteException ee) {
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
            mInputMethodManagerInternal.removeClient(client);
        }
    }

@@ -170,14 +159,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {

    @Override
    public void binderDied() {
        // Note: it is safe to call in to the input method manager
        // here because we are not holding our lock.
        try {
            if (mService.mInputMethodManager != null) {
                mService.mInputMethodManager.removeClient(mClient);
            }
        } catch (RemoteException e) {
        }
        mInputMethodManagerInternal.removeClient(mClient);
        synchronized(mService.mWindowMap) {
            mClient.asBinder().unlinkToDeath(this, 0);
            mClientDead = true;
+4 −12
Original line number Diff line number Diff line
@@ -234,7 +234,6 @@ import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.LatencyTracker;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
import com.android.internal.view.IInputMethodManager;
import com.android.internal.view.WindowManagerPolicyThread;
import com.android.server.AnimationThread;
import com.android.server.DisplayThread;
@@ -417,8 +416,6 @@ public class WindowManagerService extends IWindowManager.Stub

    final Context mContext;

    final boolean mHaveInputMethods;

    final boolean mHasPermanentDpad;
    final long mDrawLockTimeoutMillis;
    final boolean mAllowAnimationsInLowPowerMode;
@@ -521,8 +518,6 @@ public class WindowManagerService extends IWindowManager.Stub
    /** List of window currently causing non-system overlay windows to be hidden. */
    private ArrayList<WindowState> mHidingNonSystemOverlayWindows = new ArrayList<>();

    IInputMethodManager mInputMethodManager;

    AccessibilityController mAccessibilityController;
    private RecentsAnimationController mRecentsAnimationController;

@@ -905,11 +900,10 @@ public class WindowManagerService extends IWindowManager.Stub
    }

    public static WindowManagerService main(final Context context, final InputManagerService im,
            final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
            WindowManagerPolicy policy) {
            final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy) {
        DisplayThread.getHandler().runWithScissors(() ->
                sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
                        onlyCore, policy), 0);
                sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy),
                0);
        return sInstance;
    }

@@ -930,11 +924,9 @@ public class WindowManagerService extends IWindowManager.Stub
    }

    private WindowManagerService(Context context, InputManagerService inputManager,
            boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
            WindowManagerPolicy policy) {
            boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy) {
        installLock(this, INDEX_WINDOW);
        mContext = context;
        mHaveInputMethods = haveInputMethods;
        mAllowBootMessages = showBootMsgs;
        mOnlyCore = onlyCore;
        mLimitedAlphaCompositing = context.getResources().getBoolean(
Loading