Merge "Pre-render input method (IME transitions 1/n)"
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index 1030694..37b25c8 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -179,19 +179,24 @@
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: {
@@ -291,14 +296,17 @@
@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
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 38ddc16..5b3ad77 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -346,6 +346,13 @@
*/
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;
@@ -362,10 +369,19 @@
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;
@@ -552,15 +568,18 @@
*/
@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);
+ }
}
/**
@@ -570,14 +589,27 @@
@Override
public void hideSoftInput(int flags, ResultReceiver resultReceiver) {
if (DEBUG) Log.v(TAG, "hideSoftInput()");
- boolean wasVis = isInputViewShown();
- mShowInputFlags = 0;
- mShowInputRequested = false;
- doHideWindow();
+ 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);
}
}
@@ -589,17 +621,28 @@
@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)) {
- showWindow(true);
+ 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);
}
}
@@ -972,7 +1015,7 @@
void initViews() {
mInitialized = false;
- mWindowCreated = false;
+ mViewsCreated = false;
mShowInputRequested = false;
mShowInputFlags = 0;
@@ -1046,7 +1089,7 @@
}
private void resetStateForNewConfiguration() {
- boolean visible = mWindowVisible;
+ boolean visible = mDecorViewVisible;
int showFlags = mShowInputFlags;
boolean showingInput = mShowInputRequested;
CompletionInfo[] completions = mCurCompletions;
@@ -1129,7 +1172,7 @@
return;
}
mBackDisposition = disposition;
- setImeWindowStatus(mapToImeWindowStatus(isInputViewShown()), mBackDisposition);
+ setImeWindowStatus(mapToImeWindowStatus(), mBackDisposition);
}
/**
@@ -1380,7 +1423,7 @@
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,
@@ -1439,7 +1482,7 @@
*/
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) {
@@ -1458,14 +1501,14 @@
public boolean isShowInputRequested() {
return mShowInputRequested;
}
-
+
/**
* Return whether the soft input view is <em>currently</em> shown to the
* user. This is the state that was last determined and
* applied by {@link #updateInputViewShown()}.
*/
public boolean isInputViewShown() {
- return mIsInputViewShown && mWindowVisible;
+ return mCanPreRender ? mWindowVisible : mIsInputViewShown && mDecorViewVisible;
}
/**
@@ -1499,7 +1542,7 @@
*/
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.
@@ -1804,7 +1847,8 @@
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);
@@ -1814,18 +1858,42 @@
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;
@@ -1836,8 +1904,8 @@
updateFullscreenMode();
updateInputViewShown();
- if (!mWindowCreated) {
- mWindowCreated = true;
+ if (!mViewsCreated) {
+ mViewsCreated = true;
initialize();
if (DEBUG) Log.v(TAG, "CALL: onCreateCandidatesView");
View v = onCreateCandidatesView();
@@ -1846,6 +1914,10 @@
setCandidatesView(v);
}
}
+ return doShowInput;
+ }
+
+ private void startViews(boolean doShowInput) {
if (mShowInputRequested) {
if (!mInputViewStarted) {
if (DEBUG) Log.v(TAG, "CALL: onStartInputView");
@@ -1857,29 +1929,26 @@
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;
@@ -1891,12 +1960,15 @@
}
public void hideWindow() {
- finishViews();
- if (mWindowVisible) {
+ if (DEBUG) Log.v(TAG, "CALL: hideWindow");
+ mIsPreRendered = false;
+ mWindowVisible = false;
+ finishViews(false /* finishingInput */);
+ if (mDecorViewVisible) {
mWindow.hide();
- mWindowVisible = false;
+ mDecorViewVisible = false;
onWindowHidden();
- mWindowWasVisible = false;
+ mDecorViewWasVisible = false;
}
updateFullscreenMode();
}
@@ -1956,15 +2028,8 @@
}
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();
@@ -1984,7 +2049,7 @@
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;
@@ -1995,6 +2060,31 @@
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;
}
}
@@ -2153,7 +2243,7 @@
// 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.
@@ -2180,7 +2270,6 @@
return mExtractEditText;
}
-
/**
* Called back when a {@link KeyEvent} is forwarded from the target application.
*
@@ -2893,8 +2982,11 @@
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);
}
/**
@@ -2904,9 +2996,10 @@
@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);
@@ -2926,6 +3019,8 @@
p.println(" mShowInputRequested=" + mShowInputRequested
+ " mLastShowInputRequested=" + mLastShowInputRequested
+ + " mCanPreRender=" + mCanPreRender
+ + " mIsPreRendered=" + mIsPreRendered
+ " mShowInputFlags=0x" + Integer.toHexString(mShowInputFlags));
p.println(" mCandidatesVisibility=" + mCandidatesVisibility
+ " mFullscreenApplied=" + mFullscreenApplied
diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java
index d09323d..112653a 100644
--- a/core/java/android/view/inputmethod/InputMethod.java
+++ b/core/java/android/view/inputmethod/InputMethod.java
@@ -219,7 +219,7 @@
@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 {
diff --git a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
index 7600dc9..8978496 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
@@ -100,6 +100,7 @@
* @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
*/
diff --git a/core/java/com/android/internal/view/IInputMethod.aidl b/core/java/com/android/internal/view/IInputMethod.aidl
index 97d5a65..2ee902a 100644
--- a/core/java/com/android/internal/view/IInputMethod.aidl
+++ b/core/java/com/android/internal/view/IInputMethod.aidl
@@ -40,7 +40,7 @@
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);
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 3fd3945..3b4e4dd 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -288,6 +288,8 @@
private static final class DebugFlags {
static final DebugFlag FLAG_OPTIMIZE_START_INPUT =
new DebugFlag("debug.optimize_startinput", false);
+ static final DebugFlag FLAG_PRE_RENDER_IME_VIEWS =
+ new DebugFlag("persist.pre_render_ime_views", false);
}
@UserIdInt
@@ -304,6 +306,7 @@
final boolean mHasFeature;
private final ArrayMap<String, List<InputMethodSubtype>> mAdditionalSubtypeMap =
new ArrayMap<>();
+ private final boolean mIsLowRam;
private final HardKeyboardListener mHardKeyboardListener;
private final AppOpsManager mAppOpsManager;
private final UserManager mUserManager;
@@ -403,6 +406,10 @@
final ClientDeathRecipient clientDeathRecipient;
boolean sessionRequested;
+ // Determines if IMEs should be pre-rendered.
+ // DebugFlag can be flipped anytime. This flag is kept per-client to maintain behavior
+ // through the life of the current client.
+ boolean shouldPreRenderIme;
SessionState curSession;
@Override
@@ -615,6 +622,10 @@
* <dd>
* If this bit is ON, some of IME view, e.g. software input, candidate view, is visible.
* </dd>
+ * dt>{@link InputMethodService#IME_INVISIBLE}</dt>
+ * <dd> If this bit is ON, IME is ready with views from last EditorInfo but is
+ * currently invisible.
+ * </dd>
* </dl>
* <em>Do not update this value outside of setImeWindowStatus.</em>
*/
@@ -1361,6 +1372,7 @@
mSlotIme = mContext.getString(com.android.internal.R.string.status_bar_ime);
mHardKeyboardBehavior = mContext.getResources().getInteger(
com.android.internal.R.integer.config_externalHardKeyboardBehavior);
+ mIsLowRam = ActivityManager.isLowRamDeviceStatic();
Bundle extras = new Bundle();
extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true);
@@ -2264,7 +2276,10 @@
if (mSwitchingDialog != null) return false;
if (mWindowManagerInternal.isKeyguardShowingAndNotOccluded()
&& mKeyguardManager != null && mKeyguardManager.isKeyguardSecure()) return false;
- if ((visibility & InputMethodService.IME_ACTIVE) == 0) return false;
+ if ((visibility & InputMethodService.IME_ACTIVE) == 0
+ || (visibility & InputMethodService.IME_INVISIBLE) != 0) {
+ return false;
+ }
if (mWindowManagerInternal.isHardKeyboardAvailable()) {
if (mHardKeyboardBehavior == HardKeyboardBehavior.WIRELESS_AFFORDANCE) {
// When physical keyboard is attached, we show the ime switcher (or notification if
@@ -2372,6 +2387,12 @@
if (mCurToken == null) {
return;
}
+ if (DEBUG) {
+ Slog.d(TAG, "IME window vis: " + vis
+ + " active: " + (vis & InputMethodService.IME_ACTIVE)
+ + " inv: " + (vis & InputMethodService.IME_INVISIBLE));
+ }
+
// TODO: Move this clearing calling identity block to setImeWindowStatus after making sure
// all updateSystemUi happens on system previlege.
final long ident = Binder.clearCallingIdentity();
@@ -2830,6 +2851,14 @@
if (PER_PROFILE_IME_ENABLED && userId != mSettings.getCurrentUserId()) {
switchUserLocked(userId);
}
+ // Master feature flag that overrides other conditions and forces IME preRendering.
+ if (DEBUG) {
+ Slog.v(TAG, "IME PreRendering MASTER flag: "
+ + DebugFlags.FLAG_PRE_RENDER_IME_VIEWS.value()
+ + ", LowRam: " + mIsLowRam);
+ }
+ // pre-rendering not supported on low-ram devices.
+ cs.shouldPreRenderIme = DebugFlags.FLAG_PRE_RENDER_IME_VIEWS.value() && !mIsLowRam;
if (mCurFocusedWindow == windowToken) {
if (DEBUG) {
@@ -3493,7 +3522,7 @@
try {
setEnabledSessionInMainThread(session);
session.method.startInput(startInputToken, inputContext, missingMethods,
- editorInfo, restarting);
+ editorInfo, restarting, session.client.shouldPreRenderIme);
} catch (RemoteException e) {
}
args.recycle();
@@ -4421,6 +4450,7 @@
@ShellCommandResult
private int refreshDebugProperties() {
DebugFlags.FLAG_OPTIMIZE_START_INPUT.refresh();
+ DebugFlags.FLAG_PRE_RENDER_IME_VIEWS.refresh();
return ShellCommandResult.SUCCESS;
}