diff options
| author | TreeHugger Robot <treehugger-gerrit@google.com> | 2018-09-07 02:11:07 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2018-09-07 02:11:07 +0000 |
| commit | 826a36c19b5ca86bf976f66c45c703fdc8db92ee (patch) | |
| tree | b932bcc0ac22f56e3508b5b0d55059b327580172 /core/java | |
| parent | 2e2ea1fb13b7d931fdbad3cc0d8983a4135de81b (diff) | |
| parent | c54c1171640519ae0ad8da1f32477295d96db1b8 (diff) | |
Merge "Add a new Binder interface to allow IMS to directly talk to IMMS"
Diffstat (limited to 'core/java')
8 files changed, 193 insertions, 124 deletions
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java index 2c7e51a1db25..00a1f6feecc5 100644 --- a/core/java/android/inputmethodservice/IInputMethodWrapper.java +++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java @@ -35,6 +35,7 @@ import android.view.inputmethod.InputMethod; import android.view.inputmethod.InputMethodSession; import android.view.inputmethod.InputMethodSubtype; +import com.android.internal.inputmethod.IInputMethodPrivilegedOperations; import com.android.internal.os.HandlerCaller; import com.android.internal.os.SomeArgs; import com.android.internal.view.IInputContext; @@ -60,7 +61,7 @@ class IInputMethodWrapper extends IInputMethod.Stub private static final String TAG = "InputMethodWrapper"; 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_UNSET_INPUT_CONTEXT = 30; private static final int DO_START_INPUT = 32; @@ -159,9 +160,15 @@ class IInputMethodWrapper extends IInputMethod.Stub args.recycle(); return; } - - case DO_ATTACH_TOKEN: { - inputMethod.attachToken((IBinder)msg.obj); + + case DO_INITIALIZE_INTERNAL: { + SomeArgs args = (SomeArgs) msg.obj; + try { + inputMethod.initializeInternal((IBinder) args.arg1, + (IInputMethodPrivilegedOperations) args.arg2); + } finally { + args.recycle(); + } return; } case DO_SET_INPUT_CONTEXT: { @@ -246,8 +253,9 @@ class IInputMethodWrapper extends IInputMethod.Stub @BinderThread @Override - public void attachToken(IBinder token) { - mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_ATTACH_TOKEN, token)); + public void initializeInternal(IBinder token, IInputMethodPrivilegedOperations privOps) { + mCaller.executeOrSendMessage( + mCaller.obtainMessageOO(DO_INITIALIZE_INTERNAL, token, privOps)); } @BinderThread diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 64c934b332f2..ea7d42ee79a9 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -42,6 +42,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; +import android.os.RemoteException; import android.os.ResultReceiver; import android.os.SystemClock; import android.provider.Settings; @@ -79,6 +80,9 @@ import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.TextView; +import com.android.internal.inputmethod.IInputContentUriToken; +import com.android.internal.inputmethod.IInputMethodPrivilegedOperations; + import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.annotation.Retention; @@ -342,7 +346,8 @@ public class InputMethodService extends AbstractInputMethodService { private static final int BACK_DISPOSITION_MAX = BACK_DISPOSITION_ADJUST_NOTHING; InputMethodManager mImm; - + private IInputMethodPrivilegedOperations mPrivOps; + @UnsupportedAppUsage int mTheme = 0; @@ -446,6 +451,22 @@ public class InputMethodService extends AbstractInputMethodService { 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} */ @MainThread @Override @@ -470,9 +491,7 @@ public class InputMethodService extends AbstractInputMethodService { mInputConnection = binding.getConnection(); if (DEBUG) Log.v(TAG, "bindInput(): binding=" + binding + " ic=" + mInputConnection); - if (mImm != null && mToken != null) { - mImm.reportFullscreenMode(mToken, mIsFullscreen); - } + reportFullscreenMode(); initialize(); onBindInput(); } @@ -521,7 +540,11 @@ public class InputMethodService extends AbstractInputMethodService { public void dispatchStartInputWithToken(@Nullable InputConnection inputConnection, @NonNull EditorInfo editorInfo, boolean restarting, @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(). // Otherwise IME developers who have overridden those interface methods will lose @@ -563,8 +586,8 @@ public class InputMethodService extends AbstractInputMethodService { } clearInsetOfPreviousIme(); // If user uses hard keyboard, IME button should always be shown. - mImm.setImeWindowStatus(mToken, mapToImeWindowStatus(isInputViewShown()), - mBackDisposition); + setImeWindowStatus(mapToImeWindowStatus(isInputViewShown()), mBackDisposition); + if (resultReceiver != null) { resultReceiver.send(wasVis != isInputViewShown() ? 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 * {@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. boolean showing = onEvaluateInputViewShown(); - mImm.setImeWindowStatus(mToken, IME_ACTIVE | (showing ? IME_VISIBLE : 0), - mBackDisposition); + setImeWindowStatus(IME_ACTIVE | (showing ? IME_VISIBLE : 0), mBackDisposition); } } @@ -1090,7 +1123,7 @@ public class InputMethodService extends AbstractInputMethodService { return; } mBackDisposition = disposition; - mImm.setImeWindowStatus(mToken, mapToImeWindowStatus(isInputViewShown()), mBackDisposition); + setImeWindowStatus(mapToImeWindowStatus(isInputViewShown()), mBackDisposition); } /** @@ -1188,7 +1221,18 @@ public class InputMethodService extends AbstractInputMethodService { public EditorInfo getCurrentInputEditorInfo() { 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 * 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) { changed = true; mIsFullscreen = isFullscreen; - if (mImm != null && mToken != null) { - mImm.reportFullscreenMode(mToken, mIsFullscreen); - } + reportFullscreenMode(); mFullscreenApplied = true; initialize(); LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) @@ -1823,7 +1865,7 @@ public class InputMethodService extends AbstractInputMethodService { final int nextImeWindowStatus = mapToImeWindowStatus(isInputViewShown()); if (previousImeWindowStatus != nextImeWindowStatus) { - mImm.setImeWindowStatus(mToken, nextImeWindowStatus, mBackDisposition); + setImeWindowStatus(nextImeWindowStatus, mBackDisposition); } if ((previousImeWindowStatus & IME_ACTIVE) == 0) { if (DEBUG) Log.v(TAG, "showWindow: showing!"); @@ -1848,7 +1890,7 @@ public class InputMethodService extends AbstractInputMethodService { } private void doHideWindow() { - mImm.setImeWindowStatus(mToken, 0, mBackDisposition); + setImeWindowStatus(0, mBackDisposition); hideWindow(); } @@ -1889,11 +1931,31 @@ public class InputMethodService extends AbstractInputMethodService { + " mShouldClearInsetOfPreviousIme=" + mShouldClearInsetOfPreviousIme); if (!mShouldClearInsetOfPreviousIme) return; - mImm.clearLastInputMethodWindowForTransition(mToken); + clearLastInputMethodWindowForTransition(); 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 * may be followed by a series of {@link #onStartInput(EditorInfo, boolean)} * and {@link #onFinishInput()} calls as the user navigates through its @@ -2806,7 +2868,40 @@ public class InputMethodService extends AbstractInputMethodService { if (getCurrentInputConnection() != inputConnection) { 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) { diff --git a/core/java/android/view/inputmethod/InputContentInfo.java b/core/java/android/view/inputmethod/InputContentInfo.java index 7104a2871f21..0d0fea6edd1f 100644 --- a/core/java/android/view/inputmethod/InputContentInfo.java +++ b/core/java/android/view/inputmethod/InputContentInfo.java @@ -183,7 +183,15 @@ public final class InputContentInfo implements Parcelable { @Nullable 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) { throw new IllegalStateException("URI token is already set"); } diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java index ca14ebef392b..f45507c2b8b3 100644 --- a/core/java/android/view/inputmethod/InputMethod.java +++ b/core/java/android/view/inputmethod/InputMethod.java @@ -25,6 +25,8 @@ import android.inputmethodservice.InputMethodService; import android.os.IBinder; import android.os.ResultReceiver; +import com.android.internal.inputmethod.IInputMethodPrivilegedOperations; + /** * The InputMethod interface represents an input method which can generate key * events and text, such as digital, email addresses, CJK characters, other @@ -79,7 +81,25 @@ public interface InputMethod { public interface SessionCallback { 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 * unique token for the session it has with the system service. It is diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 0ecd09fa8d71..baac4cd0de9a 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -29,7 +29,6 @@ import android.content.Context; import android.content.pm.PackageManager; import android.graphics.Rect; import android.inputmethodservice.InputMethodService; -import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -56,7 +55,6 @@ import android.view.ViewRootImpl; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import android.view.autofill.AutofillManager; -import com.android.internal.inputmethod.IInputContentUriToken; import com.android.internal.os.SomeArgs; import com.android.internal.view.IInputConnectionWrapper; import com.android.internal.view.IInputContext; @@ -810,24 +808,6 @@ public final class InputMethodManager { } /** @hide */ - public void setImeWindowStatus(IBinder imeToken, int vis, int backDisposition) { - try { - mService.setImeWindowStatus(imeToken, vis, backDisposition); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** @hide */ - public void reportStartInput(IBinder imeToken, IBinder startInputToken) { - try { - mService.reportStartInput(imeToken, startInputToken); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** @hide */ @UnsupportedAppUsage public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) { try { @@ -859,17 +839,6 @@ public final class InputMethodManager { } /** - * @hide - */ - public void reportFullscreenMode(IBinder token, boolean fullscreen) { - try { - mService.reportFullscreenMode(token, fullscreen); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** * Return true if the given view is the currently active view for the * input method. */ @@ -2354,28 +2323,6 @@ public final class InputMethodManager { } /** - * 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> - * @hide - * @param token Supplies the identifying token given to an input method when it was started, - * which allows it to perform this operation on itself. - */ - public void clearLastInputMethodWindowForTransition(final IBinder token) { - synchronized (mH) { - try { - mService.clearLastInputMethodWindowForTransition(token); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - } - - /** * Force switch to the last used input method and subtype. If the last input method didn't have * any subtypes, the framework will simply switch to the last input method with no subtype * specified. @@ -2513,40 +2460,6 @@ public final class InputMethodManager { } } - /** - * 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 token Supplies the identifying token given to an input method when it was started, - * which allows it to perform this operation on itself. - * @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}. - * @hide - */ - public void exposeContent(@NonNull IBinder token, @NonNull InputContentInfo inputContentInfo, - @NonNull EditorInfo editorInfo) { - final IInputContentUriToken uriToken; - final Uri contentUri = inputContentInfo.getContentUri(); - try { - uriToken = mService.createInputContentUriToken(token, 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; - } - void doDump(FileDescriptor fd, PrintWriter fout, String[] args) { final Printer p = new PrintWriterPrinter(fout); p.println("Input method client state for " + this + ":"); diff --git a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl new file mode 100644 index 000000000000..449b4a560dc6 --- /dev/null +++ b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2018 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.internal.inputmethod; + +import android.net.Uri; + +import com.android.internal.inputmethod.IInputContentUriToken; + +/** + * Defines priviledged operations that only the current IME is allowed to call. + * Actual operations are implemented and handled by InputMethodManagerService. + */ +interface IInputMethodPrivilegedOperations { + void setImeWindowStatus(int vis, int backDisposition); + void reportStartInput(in IBinder startInputToken); + void clearLastInputMethodWindowForTransition(); + IInputContentUriToken createInputContentUriToken(in Uri contentUri, in String packageName); + void reportFullscreenMode(boolean fullscreen); +} diff --git a/core/java/com/android/internal/view/IInputMethod.aidl b/core/java/com/android/internal/view/IInputMethod.aidl index 5b29f4cb9fb4..b6a654aac563 100644 --- a/core/java/com/android/internal/view/IInputMethod.aidl +++ b/core/java/com/android/internal/view/IInputMethod.aidl @@ -22,6 +22,7 @@ import android.view.InputChannel; 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.IInputContext; import com.android.internal.view.IInputMethodSession; import com.android.internal.view.IInputSessionCallback; @@ -32,7 +33,7 @@ import com.android.internal.view.IInputSessionCallback; * {@hide} */ oneway interface IInputMethod { - void attachToken(IBinder token); + void initializeInternal(IBinder token, IInputMethodPrivilegedOperations privOps); void bindInput(in InputBinding binding); diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 09ccf67a775e..c08c8718230d 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -16,13 +16,12 @@ package com.android.internal.view; -import android.net.Uri; import android.os.ResultReceiver; import android.text.style.SuggestionSpan; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.EditorInfo; -import com.android.internal.inputmethod.IInputContentUriToken; + import com.android.internal.view.InputBindResult; import com.android.internal.view.IInputContext; import com.android.internal.view.IInputMethodClient; @@ -69,8 +68,6 @@ interface IInputMethodManager { void hideMySoftInput(in IBinder token, int flags); void showMySoftInput(in IBinder token, int flags); void updateStatusIcon(in IBinder token, String packageName, int iconId); - void setImeWindowStatus(in IBinder token, int vis, int backDisposition); - void reportStartInput(in IBinder token, in IBinder startInputToken); void registerSuggestionSpansForNotification(in SuggestionSpan[] spans); boolean notifySuggestionPicked(in SuggestionSpan span, String originalString, int index); InputMethodSubtype getCurrentInputMethodSubtype(); @@ -82,12 +79,6 @@ interface IInputMethodManager { // This is kept due to @UnsupportedAppUsage. // TODO(Bug 113914148): Consider removing this. int getInputMethodWindowVisibleHeight(); - void clearLastInputMethodWindowForTransition(in IBinder token); - - IInputContentUriToken createInputContentUriToken(in IBinder token, in Uri contentUri, - in String packageName); - - void reportFullscreenMode(in IBinder token, boolean fullscreen); oneway void notifyUserAction(int sequenceNumber); } |
