Loading core/java/android/inputmethodservice/IInputMethodWrapper.java +17 −9 Original line number Diff line number Diff line Loading @@ -179,19 +179,24 @@ class IInputMethodWrapper extends IInputMethod.Stub return; case DO_START_INPUT: { final SomeArgs args = (SomeArgs) msg.obj; final int missingMethods = msg.arg1; final boolean restarting = msg.arg2 != 0; final IBinder startInputToken = (IBinder) args.arg1; final IInputContext inputContext = (IInputContext) args.arg2; final EditorInfo info = (EditorInfo) args.arg3; final AtomicBoolean isUnbindIssued = (AtomicBoolean) args.arg4; SomeArgs moreArgs = (SomeArgs) args.arg5; final InputConnection ic = inputContext != null ? new InputConnectionWrapper( mTarget, inputContext, missingMethods, isUnbindIssued) : null; mTarget, inputContext, moreArgs.argi3, isUnbindIssued) : null; info.makeCompatible(mTargetSdkVersion); inputMethod.dispatchStartInputWithToken(ic, info, restarting /* restarting */, startInputToken); inputMethod.dispatchStartInputWithToken( ic, info, moreArgs.argi1 == 1 /* restarting */, startInputToken, moreArgs.argi2 == 1 /* shouldPreRenderIme */); args.recycle(); moreArgs.recycle(); return; } case DO_CREATE_SESSION: { Loading Loading @@ -291,14 +296,17 @@ class IInputMethodWrapper extends IInputMethod.Stub @Override public void startInput(IBinder startInputToken, IInputContext inputContext, @InputConnectionInspector.MissingMethodFlags final int missingMethods, EditorInfo attribute, boolean restarting) { EditorInfo attribute, boolean restarting, boolean shouldPreRenderIme) { if (mIsUnbindIssued == null) { Log.e(TAG, "startInput must be called after bindInput."); mIsUnbindIssued = new AtomicBoolean(); } mCaller.executeOrSendMessage(mCaller.obtainMessageIIOOOO(DO_START_INPUT, missingMethods, restarting ? 1 : 0, startInputToken, inputContext, attribute, mIsUnbindIssued)); SomeArgs args = SomeArgs.obtain(); args.argi1 = restarting ? 1 : 0; args.argi2 = shouldPreRenderIme ? 1 : 0; args.argi3 = missingMethods; mCaller.executeOrSendMessage(mCaller.obtainMessageOOOOO( DO_START_INPUT, startInputToken, inputContext, attribute, mIsUnbindIssued, args)); } @BinderThread Loading core/java/android/inputmethodservice/InputMethodService.java +170 −75 Original line number Diff line number Diff line Loading @@ -346,6 +346,13 @@ public class InputMethodService extends AbstractInputMethodService { */ public static final int IME_VISIBLE = 0x2; /** * @hide * The IME is active and ready with views but set invisible. * This flag cannot be combined with {@link #IME_VISIBLE}. */ public static final int IME_INVISIBLE = 0x4; // Min and max values for back disposition. private static final int BACK_DISPOSITION_MIN = BACK_DISPOSITION_DEFAULT; private static final int BACK_DISPOSITION_MAX = BACK_DISPOSITION_ADJUST_NOTHING; Loading @@ -362,10 +369,19 @@ public class InputMethodService extends AbstractInputMethodService { View mRootView; SoftInputWindow mWindow; boolean mInitialized; boolean mWindowCreated; boolean mWindowVisible; boolean mWindowWasVisible; boolean mViewsCreated; // IME views visibility. boolean mDecorViewVisible; boolean mDecorViewWasVisible; boolean mInShowWindow; // True if pre-rendering of IME views/window is supported. boolean mCanPreRender; // If IME is pre-rendered. boolean mIsPreRendered; // IME window visibility. // Use (mDecorViewVisible && mWindowVisible) to check if IME is visible to the user. boolean mWindowVisible; ViewGroup mFullscreenArea; FrameLayout mExtractFrame; FrameLayout mCandidatesFrame; Loading Loading @@ -552,15 +568,18 @@ public class InputMethodService extends AbstractInputMethodService { */ @MainThread @Override public void dispatchStartInputWithToken(@Nullable InputConnection inputConnection, public final void dispatchStartInputWithToken(@Nullable InputConnection inputConnection, @NonNull EditorInfo editorInfo, boolean restarting, @NonNull IBinder startInputToken) { @NonNull IBinder startInputToken, boolean shouldPreRenderIme) { mPrivOps.reportStartInput(startInputToken); // This needs to be dispatched to interface methods rather than doStartInput(). // Otherwise IME developers who have overridden those interface methods will lose // notifications. super.dispatchStartInputWithToken(inputConnection, editorInfo, restarting, startInputToken); mCanPreRender = shouldPreRenderIme; if (DEBUG) Log.v(TAG, "Will Pre-render IME: " + mCanPreRender); if (restarting) { restartInput(inputConnection, editorInfo); } else { startInput(inputConnection, editorInfo); } } /** Loading @@ -570,14 +589,27 @@ public class InputMethodService extends AbstractInputMethodService { @Override public void hideSoftInput(int flags, ResultReceiver resultReceiver) { if (DEBUG) Log.v(TAG, "hideSoftInput()"); boolean wasVis = isInputViewShown(); final boolean wasVisible = mIsPreRendered ? mDecorViewVisible && mWindowVisible : isInputViewShown(); if (mIsPreRendered) { // TODO: notify visibility to insets consumer. if (DEBUG) { Log.v(TAG, "Making IME window invisible"); } setImeWindowStatus(IME_ACTIVE | IME_INVISIBLE, mBackDisposition); onPreRenderedWindowVisibilityChanged(false /* setVisible */); } else { mShowInputFlags = 0; mShowInputRequested = false; doHideWindow(); } final boolean isVisible = mIsPreRendered ? mDecorViewVisible && mWindowVisible : isInputViewShown(); final boolean visibilityChanged = isVisible != wasVisible; if (resultReceiver != null) { resultReceiver.send(wasVis != isInputViewShown() resultReceiver.send(visibilityChanged ? InputMethodManager.RESULT_HIDDEN : (wasVis ? InputMethodManager.RESULT_UNCHANGED_SHOWN : (wasVisible ? InputMethodManager.RESULT_UNCHANGED_SHOWN : InputMethodManager.RESULT_UNCHANGED_HIDDEN), null); } } Loading @@ -589,17 +621,28 @@ public class InputMethodService extends AbstractInputMethodService { @Override public void showSoftInput(int flags, ResultReceiver resultReceiver) { if (DEBUG) Log.v(TAG, "showSoftInput()"); boolean wasVis = isInputViewShown(); final boolean wasVisible = mIsPreRendered ? mDecorViewVisible && mWindowVisible : isInputViewShown(); if (dispatchOnShowInputRequested(flags, false)) { if (mIsPreRendered) { // TODO: notify visibility to insets consumer. if (DEBUG) { Log.v(TAG, "Making IME window visible"); } onPreRenderedWindowVisibilityChanged(true /* setVisible */); } else { showWindow(true); } } // If user uses hard keyboard, IME button should always be shown. setImeWindowStatus(mapToImeWindowStatus(isInputViewShown()), mBackDisposition); setImeWindowStatus(mapToImeWindowStatus(), mBackDisposition); final boolean isVisible = mIsPreRendered ? mDecorViewVisible && mWindowVisible : isInputViewShown(); final boolean visibilityChanged = isVisible != wasVisible; if (resultReceiver != null) { resultReceiver.send(wasVis != isInputViewShown() resultReceiver.send(visibilityChanged ? InputMethodManager.RESULT_SHOWN : (wasVis ? InputMethodManager.RESULT_UNCHANGED_SHOWN : (wasVisible ? InputMethodManager.RESULT_UNCHANGED_SHOWN : InputMethodManager.RESULT_UNCHANGED_HIDDEN), null); } } Loading Loading @@ -972,7 +1015,7 @@ public class InputMethodService extends AbstractInputMethodService { void initViews() { mInitialized = false; mWindowCreated = false; mViewsCreated = false; mShowInputRequested = false; mShowInputFlags = 0; Loading Loading @@ -1046,7 +1089,7 @@ public class InputMethodService extends AbstractInputMethodService { } private void resetStateForNewConfiguration() { boolean visible = mWindowVisible; boolean visible = mDecorViewVisible; int showFlags = mShowInputFlags; boolean showingInput = mShowInputRequested; CompletionInfo[] completions = mCurCompletions; Loading Loading @@ -1129,7 +1172,7 @@ public class InputMethodService extends AbstractInputMethodService { return; } mBackDisposition = disposition; setImeWindowStatus(mapToImeWindowStatus(isInputViewShown()), mBackDisposition); setImeWindowStatus(mapToImeWindowStatus(), mBackDisposition); } /** Loading Loading @@ -1380,7 +1423,7 @@ public class InputMethodService extends AbstractInputMethodService { mExtractFrame.setVisibility(View.GONE); } updateCandidatesVisibility(mCandidatesVisibility == View.VISIBLE); if (mWindowWasVisible && mFullscreenArea.getVisibility() != vis) { if (mDecorViewWasVisible && mFullscreenArea.getVisibility() != vis) { int animRes = mThemeAttrs.getResourceId(vis == View.VISIBLE ? com.android.internal.R.styleable.InputMethodService_imeExtractEnterAnimation : com.android.internal.R.styleable.InputMethodService_imeExtractExitAnimation, Loading Loading @@ -1439,7 +1482,7 @@ public class InputMethodService extends AbstractInputMethodService { */ public void updateInputViewShown() { boolean isShown = mShowInputRequested && onEvaluateInputViewShown(); if (mIsInputViewShown != isShown && mWindowVisible) { if (mIsInputViewShown != isShown && mDecorViewVisible) { mIsInputViewShown = isShown; mInputFrame.setVisibility(isShown ? View.VISIBLE : View.GONE); if (mInputView == null) { Loading @@ -1465,7 +1508,7 @@ public class InputMethodService extends AbstractInputMethodService { * applied by {@link #updateInputViewShown()}. */ public boolean isInputViewShown() { return mIsInputViewShown && mWindowVisible; return mCanPreRender ? mWindowVisible : mIsInputViewShown && mDecorViewVisible; } /** Loading Loading @@ -1499,7 +1542,7 @@ public class InputMethodService extends AbstractInputMethodService { */ public void setCandidatesViewShown(boolean shown) { updateCandidatesVisibility(shown); if (!mShowInputRequested && mWindowVisible != shown) { if (!mShowInputRequested && mDecorViewVisible != shown) { // If we are being asked to show the candidates view while the app // has not asked for the input view to be shown, then we need // to update whether the window is shown. Loading Loading @@ -1804,7 +1847,8 @@ public class InputMethodService extends AbstractInputMethodService { public void showWindow(boolean showInput) { if (DEBUG) Log.v(TAG, "Showing window: showInput=" + showInput + " mShowInputRequested=" + mShowInputRequested + " mWindowCreated=" + mWindowCreated + " mViewsCreated=" + mViewsCreated + " mDecorViewVisible=" + mDecorViewVisible + " mWindowVisible=" + mWindowVisible + " mInputStarted=" + mInputStarted + " mShowInputFlags=" + mShowInputFlags); Loading @@ -1814,18 +1858,42 @@ public class InputMethodService extends AbstractInputMethodService { return; } mWindowWasVisible = mWindowVisible; mDecorViewWasVisible = mDecorViewVisible; mInShowWindow = true; showWindowInner(showInput); mWindowWasVisible = true; boolean isPreRenderedAndInvisible = mIsPreRendered && !mWindowVisible; final int previousImeWindowStatus = (mDecorViewVisible ? IME_ACTIVE : 0) | (isInputViewShown() ? (isPreRenderedAndInvisible ? IME_INVISIBLE : IME_VISIBLE) : 0); startViews(prepareWindow(showInput)); final int nextImeWindowStatus = mapToImeWindowStatus(); if (previousImeWindowStatus != nextImeWindowStatus) { setImeWindowStatus(nextImeWindowStatus, mBackDisposition); } // compute visibility onWindowShown(); mIsPreRendered = mCanPreRender; if (mIsPreRendered) { onPreRenderedWindowVisibilityChanged(true /* setVisible */); } else { // Pre-rendering not supported. if (DEBUG) Log.d(TAG, "No pre-rendering supported"); mWindowVisible = true; } // request draw for the IME surface. // When IME is not pre-rendered, this will actually show the IME. if ((previousImeWindowStatus & IME_ACTIVE) == 0) { if (DEBUG) Log.v(TAG, "showWindow: draw decorView!"); mWindow.show(); } mDecorViewWasVisible = true; mInShowWindow = false; } void showWindowInner(boolean showInput) { private boolean prepareWindow(boolean showInput) { boolean doShowInput = false; final int previousImeWindowStatus = (mWindowVisible ? IME_ACTIVE : 0) | (isInputViewShown() ? IME_VISIBLE : 0); mWindowVisible = true; mDecorViewVisible = true; if (!mShowInputRequested && mInputStarted && showInput) { doShowInput = true; mShowInputRequested = true; Loading @@ -1836,8 +1904,8 @@ public class InputMethodService extends AbstractInputMethodService { updateFullscreenMode(); updateInputViewShown(); if (!mWindowCreated) { mWindowCreated = true; if (!mViewsCreated) { mViewsCreated = true; initialize(); if (DEBUG) Log.v(TAG, "CALL: onCreateCandidatesView"); View v = onCreateCandidatesView(); Loading @@ -1846,6 +1914,10 @@ public class InputMethodService extends AbstractInputMethodService { setCandidatesView(v); } } return doShowInput; } private void startViews(boolean doShowInput) { if (mShowInputRequested) { if (!mInputViewStarted) { if (DEBUG) Log.v(TAG, "CALL: onStartInputView"); Loading @@ -1857,29 +1929,26 @@ public class InputMethodService extends AbstractInputMethodService { mCandidatesViewStarted = true; onStartCandidatesView(mInputEditorInfo, false); } if (doShowInput) { startExtractingText(false); if (doShowInput) startExtractingText(false); } final int nextImeWindowStatus = mapToImeWindowStatus(isInputViewShown()); if (previousImeWindowStatus != nextImeWindowStatus) { setImeWindowStatus(nextImeWindowStatus, mBackDisposition); } if ((previousImeWindowStatus & IME_ACTIVE) == 0) { if (DEBUG) Log.v(TAG, "showWindow: showing!"); private void onPreRenderedWindowVisibilityChanged(boolean setVisible) { mWindowVisible = setVisible; mShowInputFlags = setVisible ? mShowInputFlags : 0; mShowInputRequested = setVisible; mDecorViewVisible = setVisible; if (setVisible) { onWindowShown(); mWindow.show(); } } private void finishViews() { private void finishViews(boolean finishingInput) { if (mInputViewStarted) { if (DEBUG) Log.v(TAG, "CALL: onFinishInputView"); onFinishInputView(false); onFinishInputView(finishingInput); } else if (mCandidatesViewStarted) { if (DEBUG) Log.v(TAG, "CALL: onFinishCandidatesView"); onFinishCandidatesView(false); onFinishCandidatesView(finishingInput); } mInputViewStarted = false; mCandidatesViewStarted = false; Loading @@ -1891,12 +1960,15 @@ public class InputMethodService extends AbstractInputMethodService { } public void hideWindow() { finishViews(); if (mWindowVisible) { mWindow.hide(); if (DEBUG) Log.v(TAG, "CALL: hideWindow"); mIsPreRendered = false; mWindowVisible = false; finishViews(false /* finishingInput */); if (mDecorViewVisible) { mWindow.hide(); mDecorViewVisible = false; onWindowHidden(); mWindowWasVisible = false; mDecorViewWasVisible = false; } updateFullscreenMode(); } Loading Loading @@ -1956,15 +2028,8 @@ public class InputMethodService extends AbstractInputMethodService { } void doFinishInput() { if (mInputViewStarted) { if (DEBUG) Log.v(TAG, "CALL: onFinishInputView"); onFinishInputView(true); } else if (mCandidatesViewStarted) { if (DEBUG) Log.v(TAG, "CALL: onFinishCandidatesView"); onFinishCandidatesView(true); } mInputViewStarted = false; mCandidatesViewStarted = false; if (DEBUG) Log.v(TAG, "CALL: doFinishInput"); finishViews(true /* finishingInput */); if (mInputStarted) { if (DEBUG) Log.v(TAG, "CALL: onFinishInput"); onFinishInput(); Loading @@ -1984,7 +2049,7 @@ public class InputMethodService extends AbstractInputMethodService { initialize(); if (DEBUG) Log.v(TAG, "CALL: onStartInput"); onStartInput(attribute, restarting); if (mWindowVisible) { if (mDecorViewVisible) { if (mShowInputRequested) { if (DEBUG) Log.v(TAG, "CALL: onStartInputView"); mInputViewStarted = true; Loading @@ -1995,6 +2060,31 @@ public class InputMethodService extends AbstractInputMethodService { mCandidatesViewStarted = true; onStartCandidatesView(mInputEditorInfo, restarting); } } else if (mCanPreRender && mInputEditorInfo != null && mStartedInputConnection != null) { // Pre-render IME views and window when real EditorInfo is available. // pre-render IME window and keep it invisible. if (DEBUG) Log.v(TAG, "Pre-Render IME for " + mInputEditorInfo.fieldName); if (mInShowWindow) { Log.w(TAG, "Re-entrance in to showWindow"); return; } mDecorViewWasVisible = mDecorViewVisible; mInShowWindow = true; startViews(prepareWindow(true /* showInput */)); // compute visibility mIsPreRendered = true; onPreRenderedWindowVisibilityChanged(false /* setVisible */); // request draw for the IME surface. // When IME is not pre-rendered, this will actually show the IME. if (DEBUG) Log.v(TAG, "showWindow: draw decorView!"); mWindow.show(); mDecorViewWasVisible = true; mInShowWindow = false; } else { mIsPreRendered = false; } } Loading Loading @@ -2153,7 +2243,7 @@ public class InputMethodService extends AbstractInputMethodService { // consume the back key. if (doIt) requestHideSelf(0); return true; } else if (mWindowVisible) { } else if (mDecorViewVisible) { if (mCandidatesVisibility == View.VISIBLE) { // If we are showing candidates even if no input area, then // hide them. Loading @@ -2180,7 +2270,6 @@ public class InputMethodService extends AbstractInputMethodService { return mExtractEditText; } /** * Called back when a {@link KeyEvent} is forwarded from the target application. * Loading Loading @@ -2893,8 +2982,11 @@ public class InputMethodService extends AbstractInputMethodService { inputContentInfo.setUriToken(uriToken); } private static int mapToImeWindowStatus(boolean isInputViewShown) { return IME_ACTIVE | (isInputViewShown ? IME_VISIBLE : 0); private int mapToImeWindowStatus() { return IME_ACTIVE | (isInputViewShown() ? (mCanPreRender ? (mWindowVisible ? IME_VISIBLE : IME_INVISIBLE) : IME_VISIBLE) : 0); } /** Loading @@ -2904,9 +2996,10 @@ public class InputMethodService extends AbstractInputMethodService { @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { final Printer p = new PrintWriterPrinter(fout); p.println("Input method service state for " + this + ":"); p.println(" mWindowCreated=" + mWindowCreated); p.println(" mWindowVisible=" + mWindowVisible + " mWindowWasVisible=" + mWindowWasVisible p.println(" mViewsCreated=" + mViewsCreated); p.println(" mDecorViewVisible=" + mDecorViewVisible + " mDecorViewWasVisible=" + mDecorViewWasVisible + " mWindowVisible=" + mWindowVisible + " mInShowWindow=" + mInShowWindow); p.println(" Configuration=" + getResources().getConfiguration()); p.println(" mToken=" + mToken); Loading @@ -2926,6 +3019,8 @@ public class InputMethodService extends AbstractInputMethodService { p.println(" mShowInputRequested=" + mShowInputRequested + " mLastShowInputRequested=" + mLastShowInputRequested + " mCanPreRender=" + mCanPreRender + " mIsPreRendered=" + mIsPreRendered + " mShowInputFlags=0x" + Integer.toHexString(mShowInputFlags)); p.println(" mCandidatesVisibility=" + mCandidatesVisibility + " mFullscreenApplied=" + mFullscreenApplied Loading core/java/android/view/inputmethod/InputMethod.java +1 −1 Original line number Diff line number Diff line Loading @@ -219,7 +219,7 @@ public interface InputMethod { @MainThread default void dispatchStartInputWithToken(@Nullable InputConnection inputConnection, @NonNull EditorInfo editorInfo, boolean restarting, @NonNull IBinder startInputToken) { @NonNull IBinder startInputToken, boolean shouldPreRenderIme) { if (restarting) { restartInput(inputConnection, editorInfo); } else { Loading core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java +1 −0 Original line number Diff line number Diff line Loading @@ -100,6 +100,7 @@ public final class InputMethodPrivilegedOperations { * @param backDisposition disposition flags * @see android.inputmethodservice.InputMethodService#IME_ACTIVE * @see android.inputmethodservice.InputMethodService#IME_VISIBLE * @see android.inputmethodservice.InputMethodService#IME_INVISIBLE * @see android.inputmethodservice.InputMethodService#BACK_DISPOSITION_DEFAULT * @see android.inputmethodservice.InputMethodService#BACK_DISPOSITION_ADJUST_NOTHING */ Loading core/java/com/android/internal/view/IInputMethod.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -40,7 +40,7 @@ oneway interface IInputMethod { void unbindInput(); void startInput(in IBinder startInputToken, in IInputContext inputContext, int missingMethods, in EditorInfo attribute, boolean restarting); in EditorInfo attribute, boolean restarting, boolean preRenderImeViews); void createSession(in InputChannel channel, IInputSessionCallback callback); Loading Loading
core/java/android/inputmethodservice/IInputMethodWrapper.java +17 −9 Original line number Diff line number Diff line Loading @@ -179,19 +179,24 @@ class IInputMethodWrapper extends IInputMethod.Stub return; case DO_START_INPUT: { final SomeArgs args = (SomeArgs) msg.obj; final int missingMethods = msg.arg1; final boolean restarting = msg.arg2 != 0; final IBinder startInputToken = (IBinder) args.arg1; final IInputContext inputContext = (IInputContext) args.arg2; final EditorInfo info = (EditorInfo) args.arg3; final AtomicBoolean isUnbindIssued = (AtomicBoolean) args.arg4; SomeArgs moreArgs = (SomeArgs) args.arg5; final InputConnection ic = inputContext != null ? new InputConnectionWrapper( mTarget, inputContext, missingMethods, isUnbindIssued) : null; mTarget, inputContext, moreArgs.argi3, isUnbindIssued) : null; info.makeCompatible(mTargetSdkVersion); inputMethod.dispatchStartInputWithToken(ic, info, restarting /* restarting */, startInputToken); inputMethod.dispatchStartInputWithToken( ic, info, moreArgs.argi1 == 1 /* restarting */, startInputToken, moreArgs.argi2 == 1 /* shouldPreRenderIme */); args.recycle(); moreArgs.recycle(); return; } case DO_CREATE_SESSION: { Loading Loading @@ -291,14 +296,17 @@ class IInputMethodWrapper extends IInputMethod.Stub @Override public void startInput(IBinder startInputToken, IInputContext inputContext, @InputConnectionInspector.MissingMethodFlags final int missingMethods, EditorInfo attribute, boolean restarting) { EditorInfo attribute, boolean restarting, boolean shouldPreRenderIme) { if (mIsUnbindIssued == null) { Log.e(TAG, "startInput must be called after bindInput."); mIsUnbindIssued = new AtomicBoolean(); } mCaller.executeOrSendMessage(mCaller.obtainMessageIIOOOO(DO_START_INPUT, missingMethods, restarting ? 1 : 0, startInputToken, inputContext, attribute, mIsUnbindIssued)); SomeArgs args = SomeArgs.obtain(); args.argi1 = restarting ? 1 : 0; args.argi2 = shouldPreRenderIme ? 1 : 0; args.argi3 = missingMethods; mCaller.executeOrSendMessage(mCaller.obtainMessageOOOOO( DO_START_INPUT, startInputToken, inputContext, attribute, mIsUnbindIssued, args)); } @BinderThread Loading
core/java/android/inputmethodservice/InputMethodService.java +170 −75 Original line number Diff line number Diff line Loading @@ -346,6 +346,13 @@ public class InputMethodService extends AbstractInputMethodService { */ public static final int IME_VISIBLE = 0x2; /** * @hide * The IME is active and ready with views but set invisible. * This flag cannot be combined with {@link #IME_VISIBLE}. */ public static final int IME_INVISIBLE = 0x4; // Min and max values for back disposition. private static final int BACK_DISPOSITION_MIN = BACK_DISPOSITION_DEFAULT; private static final int BACK_DISPOSITION_MAX = BACK_DISPOSITION_ADJUST_NOTHING; Loading @@ -362,10 +369,19 @@ public class InputMethodService extends AbstractInputMethodService { View mRootView; SoftInputWindow mWindow; boolean mInitialized; boolean mWindowCreated; boolean mWindowVisible; boolean mWindowWasVisible; boolean mViewsCreated; // IME views visibility. boolean mDecorViewVisible; boolean mDecorViewWasVisible; boolean mInShowWindow; // True if pre-rendering of IME views/window is supported. boolean mCanPreRender; // If IME is pre-rendered. boolean mIsPreRendered; // IME window visibility. // Use (mDecorViewVisible && mWindowVisible) to check if IME is visible to the user. boolean mWindowVisible; ViewGroup mFullscreenArea; FrameLayout mExtractFrame; FrameLayout mCandidatesFrame; Loading Loading @@ -552,15 +568,18 @@ public class InputMethodService extends AbstractInputMethodService { */ @MainThread @Override public void dispatchStartInputWithToken(@Nullable InputConnection inputConnection, public final void dispatchStartInputWithToken(@Nullable InputConnection inputConnection, @NonNull EditorInfo editorInfo, boolean restarting, @NonNull IBinder startInputToken) { @NonNull IBinder startInputToken, boolean shouldPreRenderIme) { mPrivOps.reportStartInput(startInputToken); // This needs to be dispatched to interface methods rather than doStartInput(). // Otherwise IME developers who have overridden those interface methods will lose // notifications. super.dispatchStartInputWithToken(inputConnection, editorInfo, restarting, startInputToken); mCanPreRender = shouldPreRenderIme; if (DEBUG) Log.v(TAG, "Will Pre-render IME: " + mCanPreRender); if (restarting) { restartInput(inputConnection, editorInfo); } else { startInput(inputConnection, editorInfo); } } /** Loading @@ -570,14 +589,27 @@ public class InputMethodService extends AbstractInputMethodService { @Override public void hideSoftInput(int flags, ResultReceiver resultReceiver) { if (DEBUG) Log.v(TAG, "hideSoftInput()"); boolean wasVis = isInputViewShown(); final boolean wasVisible = mIsPreRendered ? mDecorViewVisible && mWindowVisible : isInputViewShown(); if (mIsPreRendered) { // TODO: notify visibility to insets consumer. if (DEBUG) { Log.v(TAG, "Making IME window invisible"); } setImeWindowStatus(IME_ACTIVE | IME_INVISIBLE, mBackDisposition); onPreRenderedWindowVisibilityChanged(false /* setVisible */); } else { mShowInputFlags = 0; mShowInputRequested = false; doHideWindow(); } final boolean isVisible = mIsPreRendered ? mDecorViewVisible && mWindowVisible : isInputViewShown(); final boolean visibilityChanged = isVisible != wasVisible; if (resultReceiver != null) { resultReceiver.send(wasVis != isInputViewShown() resultReceiver.send(visibilityChanged ? InputMethodManager.RESULT_HIDDEN : (wasVis ? InputMethodManager.RESULT_UNCHANGED_SHOWN : (wasVisible ? InputMethodManager.RESULT_UNCHANGED_SHOWN : InputMethodManager.RESULT_UNCHANGED_HIDDEN), null); } } Loading @@ -589,17 +621,28 @@ public class InputMethodService extends AbstractInputMethodService { @Override public void showSoftInput(int flags, ResultReceiver resultReceiver) { if (DEBUG) Log.v(TAG, "showSoftInput()"); boolean wasVis = isInputViewShown(); final boolean wasVisible = mIsPreRendered ? mDecorViewVisible && mWindowVisible : isInputViewShown(); if (dispatchOnShowInputRequested(flags, false)) { if (mIsPreRendered) { // TODO: notify visibility to insets consumer. if (DEBUG) { Log.v(TAG, "Making IME window visible"); } onPreRenderedWindowVisibilityChanged(true /* setVisible */); } else { showWindow(true); } } // If user uses hard keyboard, IME button should always be shown. setImeWindowStatus(mapToImeWindowStatus(isInputViewShown()), mBackDisposition); setImeWindowStatus(mapToImeWindowStatus(), mBackDisposition); final boolean isVisible = mIsPreRendered ? mDecorViewVisible && mWindowVisible : isInputViewShown(); final boolean visibilityChanged = isVisible != wasVisible; if (resultReceiver != null) { resultReceiver.send(wasVis != isInputViewShown() resultReceiver.send(visibilityChanged ? InputMethodManager.RESULT_SHOWN : (wasVis ? InputMethodManager.RESULT_UNCHANGED_SHOWN : (wasVisible ? InputMethodManager.RESULT_UNCHANGED_SHOWN : InputMethodManager.RESULT_UNCHANGED_HIDDEN), null); } } Loading Loading @@ -972,7 +1015,7 @@ public class InputMethodService extends AbstractInputMethodService { void initViews() { mInitialized = false; mWindowCreated = false; mViewsCreated = false; mShowInputRequested = false; mShowInputFlags = 0; Loading Loading @@ -1046,7 +1089,7 @@ public class InputMethodService extends AbstractInputMethodService { } private void resetStateForNewConfiguration() { boolean visible = mWindowVisible; boolean visible = mDecorViewVisible; int showFlags = mShowInputFlags; boolean showingInput = mShowInputRequested; CompletionInfo[] completions = mCurCompletions; Loading Loading @@ -1129,7 +1172,7 @@ public class InputMethodService extends AbstractInputMethodService { return; } mBackDisposition = disposition; setImeWindowStatus(mapToImeWindowStatus(isInputViewShown()), mBackDisposition); setImeWindowStatus(mapToImeWindowStatus(), mBackDisposition); } /** Loading Loading @@ -1380,7 +1423,7 @@ public class InputMethodService extends AbstractInputMethodService { mExtractFrame.setVisibility(View.GONE); } updateCandidatesVisibility(mCandidatesVisibility == View.VISIBLE); if (mWindowWasVisible && mFullscreenArea.getVisibility() != vis) { if (mDecorViewWasVisible && mFullscreenArea.getVisibility() != vis) { int animRes = mThemeAttrs.getResourceId(vis == View.VISIBLE ? com.android.internal.R.styleable.InputMethodService_imeExtractEnterAnimation : com.android.internal.R.styleable.InputMethodService_imeExtractExitAnimation, Loading Loading @@ -1439,7 +1482,7 @@ public class InputMethodService extends AbstractInputMethodService { */ public void updateInputViewShown() { boolean isShown = mShowInputRequested && onEvaluateInputViewShown(); if (mIsInputViewShown != isShown && mWindowVisible) { if (mIsInputViewShown != isShown && mDecorViewVisible) { mIsInputViewShown = isShown; mInputFrame.setVisibility(isShown ? View.VISIBLE : View.GONE); if (mInputView == null) { Loading @@ -1465,7 +1508,7 @@ public class InputMethodService extends AbstractInputMethodService { * applied by {@link #updateInputViewShown()}. */ public boolean isInputViewShown() { return mIsInputViewShown && mWindowVisible; return mCanPreRender ? mWindowVisible : mIsInputViewShown && mDecorViewVisible; } /** Loading Loading @@ -1499,7 +1542,7 @@ public class InputMethodService extends AbstractInputMethodService { */ public void setCandidatesViewShown(boolean shown) { updateCandidatesVisibility(shown); if (!mShowInputRequested && mWindowVisible != shown) { if (!mShowInputRequested && mDecorViewVisible != shown) { // If we are being asked to show the candidates view while the app // has not asked for the input view to be shown, then we need // to update whether the window is shown. Loading Loading @@ -1804,7 +1847,8 @@ public class InputMethodService extends AbstractInputMethodService { public void showWindow(boolean showInput) { if (DEBUG) Log.v(TAG, "Showing window: showInput=" + showInput + " mShowInputRequested=" + mShowInputRequested + " mWindowCreated=" + mWindowCreated + " mViewsCreated=" + mViewsCreated + " mDecorViewVisible=" + mDecorViewVisible + " mWindowVisible=" + mWindowVisible + " mInputStarted=" + mInputStarted + " mShowInputFlags=" + mShowInputFlags); Loading @@ -1814,18 +1858,42 @@ public class InputMethodService extends AbstractInputMethodService { return; } mWindowWasVisible = mWindowVisible; mDecorViewWasVisible = mDecorViewVisible; mInShowWindow = true; showWindowInner(showInput); mWindowWasVisible = true; boolean isPreRenderedAndInvisible = mIsPreRendered && !mWindowVisible; final int previousImeWindowStatus = (mDecorViewVisible ? IME_ACTIVE : 0) | (isInputViewShown() ? (isPreRenderedAndInvisible ? IME_INVISIBLE : IME_VISIBLE) : 0); startViews(prepareWindow(showInput)); final int nextImeWindowStatus = mapToImeWindowStatus(); if (previousImeWindowStatus != nextImeWindowStatus) { setImeWindowStatus(nextImeWindowStatus, mBackDisposition); } // compute visibility onWindowShown(); mIsPreRendered = mCanPreRender; if (mIsPreRendered) { onPreRenderedWindowVisibilityChanged(true /* setVisible */); } else { // Pre-rendering not supported. if (DEBUG) Log.d(TAG, "No pre-rendering supported"); mWindowVisible = true; } // request draw for the IME surface. // When IME is not pre-rendered, this will actually show the IME. if ((previousImeWindowStatus & IME_ACTIVE) == 0) { if (DEBUG) Log.v(TAG, "showWindow: draw decorView!"); mWindow.show(); } mDecorViewWasVisible = true; mInShowWindow = false; } void showWindowInner(boolean showInput) { private boolean prepareWindow(boolean showInput) { boolean doShowInput = false; final int previousImeWindowStatus = (mWindowVisible ? IME_ACTIVE : 0) | (isInputViewShown() ? IME_VISIBLE : 0); mWindowVisible = true; mDecorViewVisible = true; if (!mShowInputRequested && mInputStarted && showInput) { doShowInput = true; mShowInputRequested = true; Loading @@ -1836,8 +1904,8 @@ public class InputMethodService extends AbstractInputMethodService { updateFullscreenMode(); updateInputViewShown(); if (!mWindowCreated) { mWindowCreated = true; if (!mViewsCreated) { mViewsCreated = true; initialize(); if (DEBUG) Log.v(TAG, "CALL: onCreateCandidatesView"); View v = onCreateCandidatesView(); Loading @@ -1846,6 +1914,10 @@ public class InputMethodService extends AbstractInputMethodService { setCandidatesView(v); } } return doShowInput; } private void startViews(boolean doShowInput) { if (mShowInputRequested) { if (!mInputViewStarted) { if (DEBUG) Log.v(TAG, "CALL: onStartInputView"); Loading @@ -1857,29 +1929,26 @@ public class InputMethodService extends AbstractInputMethodService { mCandidatesViewStarted = true; onStartCandidatesView(mInputEditorInfo, false); } if (doShowInput) { startExtractingText(false); if (doShowInput) startExtractingText(false); } final int nextImeWindowStatus = mapToImeWindowStatus(isInputViewShown()); if (previousImeWindowStatus != nextImeWindowStatus) { setImeWindowStatus(nextImeWindowStatus, mBackDisposition); } if ((previousImeWindowStatus & IME_ACTIVE) == 0) { if (DEBUG) Log.v(TAG, "showWindow: showing!"); private void onPreRenderedWindowVisibilityChanged(boolean setVisible) { mWindowVisible = setVisible; mShowInputFlags = setVisible ? mShowInputFlags : 0; mShowInputRequested = setVisible; mDecorViewVisible = setVisible; if (setVisible) { onWindowShown(); mWindow.show(); } } private void finishViews() { private void finishViews(boolean finishingInput) { if (mInputViewStarted) { if (DEBUG) Log.v(TAG, "CALL: onFinishInputView"); onFinishInputView(false); onFinishInputView(finishingInput); } else if (mCandidatesViewStarted) { if (DEBUG) Log.v(TAG, "CALL: onFinishCandidatesView"); onFinishCandidatesView(false); onFinishCandidatesView(finishingInput); } mInputViewStarted = false; mCandidatesViewStarted = false; Loading @@ -1891,12 +1960,15 @@ public class InputMethodService extends AbstractInputMethodService { } public void hideWindow() { finishViews(); if (mWindowVisible) { mWindow.hide(); if (DEBUG) Log.v(TAG, "CALL: hideWindow"); mIsPreRendered = false; mWindowVisible = false; finishViews(false /* finishingInput */); if (mDecorViewVisible) { mWindow.hide(); mDecorViewVisible = false; onWindowHidden(); mWindowWasVisible = false; mDecorViewWasVisible = false; } updateFullscreenMode(); } Loading Loading @@ -1956,15 +2028,8 @@ public class InputMethodService extends AbstractInputMethodService { } void doFinishInput() { if (mInputViewStarted) { if (DEBUG) Log.v(TAG, "CALL: onFinishInputView"); onFinishInputView(true); } else if (mCandidatesViewStarted) { if (DEBUG) Log.v(TAG, "CALL: onFinishCandidatesView"); onFinishCandidatesView(true); } mInputViewStarted = false; mCandidatesViewStarted = false; if (DEBUG) Log.v(TAG, "CALL: doFinishInput"); finishViews(true /* finishingInput */); if (mInputStarted) { if (DEBUG) Log.v(TAG, "CALL: onFinishInput"); onFinishInput(); Loading @@ -1984,7 +2049,7 @@ public class InputMethodService extends AbstractInputMethodService { initialize(); if (DEBUG) Log.v(TAG, "CALL: onStartInput"); onStartInput(attribute, restarting); if (mWindowVisible) { if (mDecorViewVisible) { if (mShowInputRequested) { if (DEBUG) Log.v(TAG, "CALL: onStartInputView"); mInputViewStarted = true; Loading @@ -1995,6 +2060,31 @@ public class InputMethodService extends AbstractInputMethodService { mCandidatesViewStarted = true; onStartCandidatesView(mInputEditorInfo, restarting); } } else if (mCanPreRender && mInputEditorInfo != null && mStartedInputConnection != null) { // Pre-render IME views and window when real EditorInfo is available. // pre-render IME window and keep it invisible. if (DEBUG) Log.v(TAG, "Pre-Render IME for " + mInputEditorInfo.fieldName); if (mInShowWindow) { Log.w(TAG, "Re-entrance in to showWindow"); return; } mDecorViewWasVisible = mDecorViewVisible; mInShowWindow = true; startViews(prepareWindow(true /* showInput */)); // compute visibility mIsPreRendered = true; onPreRenderedWindowVisibilityChanged(false /* setVisible */); // request draw for the IME surface. // When IME is not pre-rendered, this will actually show the IME. if (DEBUG) Log.v(TAG, "showWindow: draw decorView!"); mWindow.show(); mDecorViewWasVisible = true; mInShowWindow = false; } else { mIsPreRendered = false; } } Loading Loading @@ -2153,7 +2243,7 @@ public class InputMethodService extends AbstractInputMethodService { // consume the back key. if (doIt) requestHideSelf(0); return true; } else if (mWindowVisible) { } else if (mDecorViewVisible) { if (mCandidatesVisibility == View.VISIBLE) { // If we are showing candidates even if no input area, then // hide them. Loading @@ -2180,7 +2270,6 @@ public class InputMethodService extends AbstractInputMethodService { return mExtractEditText; } /** * Called back when a {@link KeyEvent} is forwarded from the target application. * Loading Loading @@ -2893,8 +2982,11 @@ public class InputMethodService extends AbstractInputMethodService { inputContentInfo.setUriToken(uriToken); } private static int mapToImeWindowStatus(boolean isInputViewShown) { return IME_ACTIVE | (isInputViewShown ? IME_VISIBLE : 0); private int mapToImeWindowStatus() { return IME_ACTIVE | (isInputViewShown() ? (mCanPreRender ? (mWindowVisible ? IME_VISIBLE : IME_INVISIBLE) : IME_VISIBLE) : 0); } /** Loading @@ -2904,9 +2996,10 @@ public class InputMethodService extends AbstractInputMethodService { @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { final Printer p = new PrintWriterPrinter(fout); p.println("Input method service state for " + this + ":"); p.println(" mWindowCreated=" + mWindowCreated); p.println(" mWindowVisible=" + mWindowVisible + " mWindowWasVisible=" + mWindowWasVisible p.println(" mViewsCreated=" + mViewsCreated); p.println(" mDecorViewVisible=" + mDecorViewVisible + " mDecorViewWasVisible=" + mDecorViewWasVisible + " mWindowVisible=" + mWindowVisible + " mInShowWindow=" + mInShowWindow); p.println(" Configuration=" + getResources().getConfiguration()); p.println(" mToken=" + mToken); Loading @@ -2926,6 +3019,8 @@ public class InputMethodService extends AbstractInputMethodService { p.println(" mShowInputRequested=" + mShowInputRequested + " mLastShowInputRequested=" + mLastShowInputRequested + " mCanPreRender=" + mCanPreRender + " mIsPreRendered=" + mIsPreRendered + " mShowInputFlags=0x" + Integer.toHexString(mShowInputFlags)); p.println(" mCandidatesVisibility=" + mCandidatesVisibility + " mFullscreenApplied=" + mFullscreenApplied Loading
core/java/android/view/inputmethod/InputMethod.java +1 −1 Original line number Diff line number Diff line Loading @@ -219,7 +219,7 @@ public interface InputMethod { @MainThread default void dispatchStartInputWithToken(@Nullable InputConnection inputConnection, @NonNull EditorInfo editorInfo, boolean restarting, @NonNull IBinder startInputToken) { @NonNull IBinder startInputToken, boolean shouldPreRenderIme) { if (restarting) { restartInput(inputConnection, editorInfo); } else { Loading
core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java +1 −0 Original line number Diff line number Diff line Loading @@ -100,6 +100,7 @@ public final class InputMethodPrivilegedOperations { * @param backDisposition disposition flags * @see android.inputmethodservice.InputMethodService#IME_ACTIVE * @see android.inputmethodservice.InputMethodService#IME_VISIBLE * @see android.inputmethodservice.InputMethodService#IME_INVISIBLE * @see android.inputmethodservice.InputMethodService#BACK_DISPOSITION_DEFAULT * @see android.inputmethodservice.InputMethodService#BACK_DISPOSITION_ADJUST_NOTHING */ Loading
core/java/com/android/internal/view/IInputMethod.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -40,7 +40,7 @@ oneway interface IInputMethod { void unbindInput(); void startInput(in IBinder startInputToken, in IInputContext inputContext, int missingMethods, in EditorInfo attribute, boolean restarting); in EditorInfo attribute, boolean restarting, boolean preRenderImeViews); void createSession(in InputChannel channel, IInputSessionCallback callback); Loading