Loading Android.bp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -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", Loading core/java/android/inputmethodservice/IInputMethodWrapper.java +14 −6 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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: { Loading Loading @@ -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 Loading core/java/android/inputmethodservice/InputMethodService.java +113 −18 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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} */ */ Loading @@ -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(); } } Loading Loading @@ -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 Loading Loading @@ -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 Loading @@ -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 Loading Loading @@ -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); } } } } Loading Loading @@ -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); } } /** /** Loading Loading @@ -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 Loading @@ -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) Loading Loading @@ -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!"); Loading @@ -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(); } } Loading Loading @@ -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)} Loading Loading @@ -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) { Loading core/java/android/view/inputmethod/InputContentInfo.java +9 −1 Original line number Original line Diff line number Diff line Loading @@ -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"); } } Loading core/java/android/view/inputmethod/InputMethod.java +21 −1 Original line number Original line Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading
Android.bp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -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", Loading
core/java/android/inputmethodservice/IInputMethodWrapper.java +14 −6 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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: { Loading Loading @@ -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 Loading
core/java/android/inputmethodservice/InputMethodService.java +113 −18 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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} */ */ Loading @@ -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(); } } Loading Loading @@ -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 Loading Loading @@ -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 Loading @@ -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 Loading Loading @@ -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); } } } } Loading Loading @@ -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); } } /** /** Loading Loading @@ -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 Loading @@ -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) Loading Loading @@ -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!"); Loading @@ -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(); } } Loading Loading @@ -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)} Loading Loading @@ -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) { Loading
core/java/android/view/inputmethod/InputContentInfo.java +9 −1 Original line number Original line Diff line number Diff line Loading @@ -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"); } } Loading
core/java/android/view/inputmethod/InputMethod.java +21 −1 Original line number Original line Diff line number Diff line Loading @@ -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 Loading Loading @@ -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