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

Commit 826a36c1 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add a new Binder interface to allow IMS to directly talk to IMMS"

parents 2e2ea1fb c54c1171
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -381,6 +381,7 @@ java_defaults {
        "core/java/com/android/internal/backup/IBackupTransport.aidl",
        "core/java/com/android/internal/backup/IBackupTransport.aidl",
        "core/java/com/android/internal/backup/IObbBackupService.aidl",
        "core/java/com/android/internal/backup/IObbBackupService.aidl",
        "core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl",
        "core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl",
        "core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl",
        "core/java/com/android/internal/net/INetworkWatchlistManager.aidl",
        "core/java/com/android/internal/net/INetworkWatchlistManager.aidl",
        "core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl",
        "core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl",
        "core/java/com/android/internal/policy/IKeyguardDismissCallback.aidl",
        "core/java/com/android/internal/policy/IKeyguardDismissCallback.aidl",
+14 −6
Original line number Original line Diff line number Diff line
@@ -35,6 +35,7 @@ import android.view.inputmethod.InputMethod;
import android.view.inputmethod.InputMethodSession;
import android.view.inputmethod.InputMethodSession;
import android.view.inputmethod.InputMethodSubtype;
import android.view.inputmethod.InputMethodSubtype;


import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
import com.android.internal.os.HandlerCaller;
import com.android.internal.os.HandlerCaller;
import com.android.internal.os.SomeArgs;
import com.android.internal.os.SomeArgs;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputContext;
@@ -60,7 +61,7 @@ class IInputMethodWrapper extends IInputMethod.Stub
    private static final String TAG = "InputMethodWrapper";
    private static final String TAG = "InputMethodWrapper";


    private static final int DO_DUMP = 1;
    private static final int DO_DUMP = 1;
    private static final int DO_ATTACH_TOKEN = 10;
    private static final int DO_INITIALIZE_INTERNAL = 10;
    private static final int DO_SET_INPUT_CONTEXT = 20;
    private static final int DO_SET_INPUT_CONTEXT = 20;
    private static final int DO_UNSET_INPUT_CONTEXT = 30;
    private static final int DO_UNSET_INPUT_CONTEXT = 30;
    private static final int DO_START_INPUT = 32;
    private static final int DO_START_INPUT = 32;
@@ -160,8 +161,14 @@ class IInputMethodWrapper extends IInputMethod.Stub
                return;
                return;
            }
            }


            case DO_ATTACH_TOKEN: {
            case DO_INITIALIZE_INTERNAL: {
                inputMethod.attachToken((IBinder)msg.obj);
                SomeArgs args = (SomeArgs) msg.obj;
                try {
                    inputMethod.initializeInternal((IBinder) args.arg1,
                            (IInputMethodPrivilegedOperations) args.arg2);
                } finally {
                    args.recycle();
                }
                return;
                return;
            }
            }
            case DO_SET_INPUT_CONTEXT: {
            case DO_SET_INPUT_CONTEXT: {
@@ -246,8 +253,9 @@ class IInputMethodWrapper extends IInputMethod.Stub


    @BinderThread
    @BinderThread
    @Override
    @Override
    public void attachToken(IBinder token) {
    public void initializeInternal(IBinder token, IInputMethodPrivilegedOperations privOps) {
        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_ATTACH_TOKEN, token));
        mCaller.executeOrSendMessage(
                mCaller.obtainMessageOO(DO_INITIALIZE_INTERNAL, token, privOps));
    }
    }


    @BinderThread
    @BinderThread
+113 −18
Original line number Original line Diff line number Diff line
@@ -42,6 +42,7 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ResultReceiver;
import android.os.SystemClock;
import android.os.SystemClock;
import android.provider.Settings;
import android.provider.Settings;
@@ -79,6 +80,9 @@ import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.TextView;


import com.android.internal.inputmethod.IInputContentUriToken;
import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;

import java.io.FileDescriptor;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.Retention;
@@ -342,6 +346,7 @@ public class InputMethodService extends AbstractInputMethodService {
    private static final int BACK_DISPOSITION_MAX = BACK_DISPOSITION_ADJUST_NOTHING;
    private static final int BACK_DISPOSITION_MAX = BACK_DISPOSITION_ADJUST_NOTHING;


    InputMethodManager mImm;
    InputMethodManager mImm;
    private IInputMethodPrivilegedOperations mPrivOps;


    @UnsupportedAppUsage
    @UnsupportedAppUsage
    int mTheme = 0;
    int mTheme = 0;
@@ -444,6 +449,22 @@ public class InputMethodService extends AbstractInputMethodService {
     * all of the standard behavior for an input method.
     * all of the standard behavior for an input method.
     */
     */
    public class InputMethodImpl extends AbstractInputMethodImpl {
    public class InputMethodImpl extends AbstractInputMethodImpl {
        /**
         * {@inheritDoc}
         * @hide
         */
        @MainThread
        @Override
        public final void initializeInternal(IBinder token,
                IInputMethodPrivilegedOperations privilegedOperations) {
            if (mToken != null) {
                throw new IllegalStateException("initializeInternal() must be called at most once."
                        + " privOps=" + privilegedOperations);
            }
            mPrivOps = privilegedOperations;
            attachToken(token);
        }

        /**
        /**
         * {@inheritDoc}
         * {@inheritDoc}
         */
         */
@@ -470,9 +491,7 @@ public class InputMethodService extends AbstractInputMethodService {
            mInputConnection = binding.getConnection();
            mInputConnection = binding.getConnection();
            if (DEBUG) Log.v(TAG, "bindInput(): binding=" + binding
            if (DEBUG) Log.v(TAG, "bindInput(): binding=" + binding
                    + " ic=" + mInputConnection);
                    + " ic=" + mInputConnection);
            if (mImm != null && mToken != null) {
            reportFullscreenMode();
                mImm.reportFullscreenMode(mToken, mIsFullscreen);
            }
            initialize();
            initialize();
            onBindInput();
            onBindInput();
        }
        }
@@ -521,7 +540,11 @@ public class InputMethodService extends AbstractInputMethodService {
        public void dispatchStartInputWithToken(@Nullable InputConnection inputConnection,
        public void dispatchStartInputWithToken(@Nullable InputConnection inputConnection,
                @NonNull EditorInfo editorInfo, boolean restarting,
                @NonNull EditorInfo editorInfo, boolean restarting,
                @NonNull IBinder startInputToken) {
                @NonNull IBinder startInputToken) {
            mImm.reportStartInput(mToken, startInputToken);
            try {
                mPrivOps.reportStartInput(startInputToken);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }


            // This needs to be dispatched to interface methods rather than doStartInput().
            // This needs to be dispatched to interface methods rather than doStartInput().
            // Otherwise IME developers who have overridden those interface methods will lose
            // Otherwise IME developers who have overridden those interface methods will lose
@@ -563,8 +586,8 @@ public class InputMethodService extends AbstractInputMethodService {
            }
            }
            clearInsetOfPreviousIme();
            clearInsetOfPreviousIme();
            // If user uses hard keyboard, IME button should always be shown.
            // If user uses hard keyboard, IME button should always be shown.
            mImm.setImeWindowStatus(mToken, mapToImeWindowStatus(isInputViewShown()),
            setImeWindowStatus(mapToImeWindowStatus(isInputViewShown()), mBackDisposition);
                    mBackDisposition);

            if (resultReceiver != null) {
            if (resultReceiver != null) {
                resultReceiver.send(wasVis != isInputViewShown()
                resultReceiver.send(wasVis != isInputViewShown()
                        ? InputMethodManager.RESULT_SHOWN
                        ? InputMethodManager.RESULT_SHOWN
@@ -583,6 +606,17 @@ public class InputMethodService extends AbstractInputMethodService {
        }
        }
    }
    }


    private void setImeWindowStatus(int visibilityFlags, int backDisposition) {
        if (mPrivOps == null) {
            return;
        }
        try {
            mPrivOps.setImeWindowStatus(visibilityFlags, backDisposition);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
    /**
     * Concrete implementation of
     * Concrete implementation of
     * {@link AbstractInputMethodService.AbstractInputMethodSessionImpl} that provides
     * {@link AbstractInputMethodService.AbstractInputMethodSessionImpl} that provides
@@ -1039,8 +1073,7 @@ public class InputMethodService extends AbstractInputMethodService {
            }
            }
            // If user uses hard keyboard, IME button should always be shown.
            // If user uses hard keyboard, IME button should always be shown.
            boolean showing = onEvaluateInputViewShown();
            boolean showing = onEvaluateInputViewShown();
            mImm.setImeWindowStatus(mToken, IME_ACTIVE | (showing ? IME_VISIBLE : 0),
            setImeWindowStatus(IME_ACTIVE | (showing ? IME_VISIBLE : 0), mBackDisposition);
                    mBackDisposition);
        }
        }
    }
    }


@@ -1090,7 +1123,7 @@ public class InputMethodService extends AbstractInputMethodService {
            return;
            return;
        }
        }
        mBackDisposition = disposition;
        mBackDisposition = disposition;
        mImm.setImeWindowStatus(mToken, mapToImeWindowStatus(isInputViewShown()), mBackDisposition);
        setImeWindowStatus(mapToImeWindowStatus(isInputViewShown()), mBackDisposition);
    }
    }


    /**
    /**
@@ -1189,6 +1222,17 @@ public class InputMethodService extends AbstractInputMethodService {
        return mInputEditorInfo;
        return mInputEditorInfo;
    }
    }


    private void reportFullscreenMode() {
        if (mPrivOps == null) {
            return;
        }
        try {
            mPrivOps.reportFullscreenMode(mIsFullscreen);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
    /**
     * Re-evaluate whether the input method should be running in fullscreen
     * Re-evaluate whether the input method should be running in fullscreen
     * mode, and update its UI if this has changed since the last time it
     * mode, and update its UI if this has changed since the last time it
@@ -1203,9 +1247,7 @@ public class InputMethodService extends AbstractInputMethodService {
        if (mIsFullscreen != isFullscreen || !mFullscreenApplied) {
        if (mIsFullscreen != isFullscreen || !mFullscreenApplied) {
            changed = true;
            changed = true;
            mIsFullscreen = isFullscreen;
            mIsFullscreen = isFullscreen;
            if (mImm != null && mToken != null) {
            reportFullscreenMode();
                mImm.reportFullscreenMode(mToken, mIsFullscreen);
            }
            mFullscreenApplied = true;
            mFullscreenApplied = true;
            initialize();
            initialize();
            LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
            LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
@@ -1823,7 +1865,7 @@ public class InputMethodService extends AbstractInputMethodService {


        final int nextImeWindowStatus = mapToImeWindowStatus(isInputViewShown());
        final int nextImeWindowStatus = mapToImeWindowStatus(isInputViewShown());
        if (previousImeWindowStatus != nextImeWindowStatus) {
        if (previousImeWindowStatus != nextImeWindowStatus) {
            mImm.setImeWindowStatus(mToken, nextImeWindowStatus, mBackDisposition);
            setImeWindowStatus(nextImeWindowStatus, mBackDisposition);
        }
        }
        if ((previousImeWindowStatus & IME_ACTIVE) == 0) {
        if ((previousImeWindowStatus & IME_ACTIVE) == 0) {
            if (DEBUG) Log.v(TAG, "showWindow: showing!");
            if (DEBUG) Log.v(TAG, "showWindow: showing!");
@@ -1848,7 +1890,7 @@ public class InputMethodService extends AbstractInputMethodService {
    }
    }


    private void doHideWindow() {
    private void doHideWindow() {
        mImm.setImeWindowStatus(mToken, 0, mBackDisposition);
        setImeWindowStatus(0, mBackDisposition);
        hideWindow();
        hideWindow();
    }
    }


@@ -1889,10 +1931,30 @@ public class InputMethodService extends AbstractInputMethodService {
                + " mShouldClearInsetOfPreviousIme=" + mShouldClearInsetOfPreviousIme);
                + " mShouldClearInsetOfPreviousIme=" + mShouldClearInsetOfPreviousIme);
        if (!mShouldClearInsetOfPreviousIme) return;
        if (!mShouldClearInsetOfPreviousIme) return;


        mImm.clearLastInputMethodWindowForTransition(mToken);
        clearLastInputMethodWindowForTransition();
        mShouldClearInsetOfPreviousIme = false;
        mShouldClearInsetOfPreviousIme = false;
    }
    }


    /**
     * Tells the system that the IME decided to not show a window and the system no longer needs to
     * use the previous IME's inset.
     *
     * <p>Caveat: {@link android.inputmethodservice.InputMethodService#clearInsetOfPreviousIme()}
     * is the only expected caller of this method.  Do not depend on this anywhere else.</p>
     *
     * <p>TODO: We probably need to reconsider how IME should be handled.</p>
     */
    private void clearLastInputMethodWindowForTransition() {
        if (mPrivOps == null) {
            return;
        }
        try {
            mPrivOps.clearLastInputMethodWindowForTransition();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
    /**
     * Called when a new client has bound to the input method.  This
     * Called when a new client has bound to the input method.  This
     * may be followed by a series of {@link #onStartInput(EditorInfo, boolean)}
     * may be followed by a series of {@link #onStartInput(EditorInfo, boolean)}
@@ -2806,7 +2868,40 @@ public class InputMethodService extends AbstractInputMethodService {
        if (getCurrentInputConnection() != inputConnection) {
        if (getCurrentInputConnection() != inputConnection) {
            return;
            return;
        }
        }
        mImm.exposeContent(mToken, inputContentInfo, getCurrentInputEditorInfo());
        exposeContentInternal(inputContentInfo, getCurrentInputEditorInfo());
    }

    /**
     * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access
     * permission to the content.
     *
     * <p>See {@link android.inputmethodservice.InputMethodService#exposeContent(InputContentInfo,
     * InputConnection)} for details.</p>
     *
     * @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) {
        if (mPrivOps == null) {
            return;
        }
        final IInputContentUriToken uriToken;
        final Uri contentUri = inputContentInfo.getContentUri();
        try {
            uriToken = mPrivOps.createInputContentUriToken(contentUri, editorInfo.packageName);
            if (uriToken == null) {
                return;
            }
        } catch (RemoteException e) {
            Log.e(TAG, "createInputContentAccessToken failed. contentUri=" + contentUri.toString()
                    + " packageName=" + editorInfo.packageName, e);
            return;
        }
        inputContentInfo.setUriToken(uriToken);
        return;
    }
    }


    private static int mapToImeWindowStatus(boolean isInputViewShown) {
    private static int mapToImeWindowStatus(boolean isInputViewShown) {
+9 −1
Original line number Original line Diff line number Diff line
@@ -183,7 +183,15 @@ public final class InputContentInfo implements Parcelable {
    @Nullable
    @Nullable
    public Uri getLinkUri() { return mLinkUri; }
    public Uri getLinkUri() { return mLinkUri; }


    void setUriToken(IInputContentUriToken token) {
    /**
     * Update the internal state of this object to be associated with the given token.
     *
     * <p>TODO(yukawa): Come up with an idea to make {@link InputContentInfo} immutable.</p>
     *
     * @param token special URI token obtained from the system.
     * @hide
     */
    public void setUriToken(IInputContentUriToken token) {
        if (mUriToken != null) {
        if (mUriToken != null) {
            throw new IllegalStateException("URI token is already set");
            throw new IllegalStateException("URI token is already set");
        }
        }
+21 −1
Original line number Original line Diff line number Diff line
@@ -25,6 +25,8 @@ import android.inputmethodservice.InputMethodService;
import android.os.IBinder;
import android.os.IBinder;
import android.os.ResultReceiver;
import android.os.ResultReceiver;


import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;

/**
/**
 * The InputMethod interface represents an input method which can generate key
 * The InputMethod interface represents an input method which can generate key
 * events and text, such as digital, email addresses, CJK characters, other
 * events and text, such as digital, email addresses, CJK characters, other
@@ -80,6 +82,24 @@ public interface InputMethod {
        public void sessionCreated(InputMethodSession session);
        public void sessionCreated(InputMethodSession session);
    }
    }


    /**
     * Called first thing after an input method is created, this supplies a
     * unique token for the session it has with the system service as well as
     * IPC endpoint to do some other privileged operations.
     *
     * @param token special token for the system to identify
     *              {@link InputMethodService}
     * @param privilegedOperations IPC endpoint to do some privileged
     *                             operations that are allowed only to the
     *                             current IME.
     * @hide
     */
    @MainThread
    default void initializeInternal(IBinder token,
            IInputMethodPrivilegedOperations privilegedOperations) {
        attachToken(token);
    }

    /**
    /**
     * Called first thing after an input method is created, this supplies a
     * Called first thing after an input method is created, this supplies a
     * unique token for the session it has with the system service.  It is
     * unique token for the session it has with the system service.  It is
Loading