diff options
| author | Taran Singh <tarandeep@google.com> | 2021-03-01 19:35:51 +0000 |
|---|---|---|
| committer | Taran Singh <tarandeep@google.com> | 2021-03-10 08:22:42 +0000 |
| commit | 9a2eed9f496f1fbca3434b672dfdeb2f59448078 (patch) | |
| tree | f7512e2d3dff38f92f4e3228212444c6c53fc8c1 /core/java/android/inputmethodservice/InputMethodService.java | |
| parent | ee971e56485627db54ef7a5336f710368c732726 (diff) | |
Avoid IME restart for configChanges
Handle onConfigurationChanged() in order to prevent restarting
InputMethodService everytime. We introduce a new API attribute
"configChanges" in InputMethod(attrs.xml) which when declared
by IME, will be responsible for handling mentioned
configuration changes.
This CL re-introduces [1] with fix: Use new Configuration instance for
IMS#mLastKnownConfig
[1] Iff88b768c6b06cf5cf1fe9e97ee97f8f78e6f0bd
Bug: 167948419
Test: atest InputMethodServiceTest
Manually:
1. Patch Ie91e7a8e06b80864ef9409031e8543858552d70d to use dual
display area.
2. Open applications with editors on both display areas.
3. Attach a debug point for IMS#onConfigurationChanged().
4. Make sure IMS#resetStateForNewConfiguration() is not called
when IME moves between these two identical DisplayAreas
Change-Id: Ib94fddadb0dae648cf73a4c1642e51edebd19f50
Diffstat (limited to 'core/java/android/inputmethodservice/InputMethodService.java')
| -rw-r--r-- | core/java/android/inputmethodservice/InputMethodService.java | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 7e2be01feb01..40a0fc4e8339 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -70,6 +70,7 @@ import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledSince; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; +import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.content.res.Resources; @@ -131,6 +132,7 @@ import android.widget.TextView; import android.window.WindowMetricsHelper; import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.inputmethod.IInputContentUriToken; import com.android.internal.inputmethod.IInputMethodPrivilegedOperations; import com.android.internal.inputmethod.InputMethodPrivilegedOperations; @@ -513,6 +515,8 @@ public class InputMethodService extends AbstractInputMethodService { private boolean mIsAutomotive; private Handler mHandler; private boolean mImeSurfaceScheduledForRemoval; + private Configuration mLastKnownConfig; + private int mHandledConfigChanges; /** * An opaque {@link Binder} token of window requesting {@link InputMethodImpl#showSoftInput} @@ -588,12 +592,13 @@ public class InputMethodService extends AbstractInputMethodService { @MainThread @Override public final void initializeInternal(@NonNull IBinder token, int displayId, - IInputMethodPrivilegedOperations privilegedOperations) { + IInputMethodPrivilegedOperations privilegedOperations, int configChanges) { if (InputMethodPrivilegedOperationsRegistry.isRegistered(token)) { Log.w(TAG, "The token has already registered, ignore this initialization."); return; } Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.initializeInternal"); + mHandledConfigChanges = configChanges; mPrivOps.set(privilegedOperations); InputMethodPrivilegedOperationsRegistry.put(token, mPrivOps); updateInputMethodDisplay(displayId); @@ -821,6 +826,9 @@ public class InputMethodService extends AbstractInputMethodService { setImeWindowStatus(mapToImeWindowStatus(), mBackDisposition); } final boolean isVisible = isInputViewShown(); + if (isVisible && getResources() != null) { + mLastKnownConfig = new Configuration(getResources().getConfiguration()); + } final boolean visibilityChanged = isVisible != wasVisible; if (resultReceiver != null) { resultReceiver.send(visibilityChanged @@ -1428,10 +1436,30 @@ public class InputMethodService extends AbstractInputMethodService { * state: {@link #onStartInput} if input is active, and * {@link #onCreateInputView} and {@link #onStartInputView} and related * appropriate functions if the UI is displayed. + * <p>Starting with {@link Build.VERSION_CODES#S}, IMEs can opt into handling configuration + * changes themselves instead of being restarted with + * {@link android.R.styleable#InputMethod_configChanges}. */ @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - resetStateForNewConfiguration(); + if (shouldImeRestartForConfig(newConfig)) { + resetStateForNewConfiguration(); + } + } + + /** + * @return {@code true} if {@link InputMethodService} needs to restart to handle + * .{@link #onConfigurationChanged(Configuration)} + */ + @VisibleForTesting + boolean shouldImeRestartForConfig(@NonNull Configuration newConfig) { + if (mLastKnownConfig == null) { + return true; + } + // If the new config is the same as the config this Service is already running with, + // then don't bother calling resetStateForNewConfiguration. + int unhandledDiff = (mLastKnownConfig.diffPublicOnly(newConfig) & ~mHandledConfigChanges); + return unhandledDiff != 0; } private void resetStateForNewConfiguration() { @@ -3181,7 +3209,17 @@ public class InputMethodService extends AbstractInputMethodService { requestHideSelf(InputMethodManager.HIDE_NOT_ALWAYS); } } - + + @VisibleForTesting + void setLastKnownConfig(@NonNull Configuration config) { + mLastKnownConfig = config; + } + + @VisibleForTesting + void setHandledConfigChanges(int configChanges) { + mHandledConfigChanges = configChanges; + } + void startExtractingText(boolean inputChanged) { final ExtractEditText eet = mExtractEditText; if (eet != null && getCurrentInputStarted() |
