Loading core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -51921,6 +51921,7 @@ package android.view.inputmethod { method public int describeContents(); method public void dump(android.util.Printer, String); method public android.content.ComponentName getComponent(); method public int getConfigChanges(); method public String getId(); method public int getIsDefaultResourceId(); method public String getPackageName(); core/api/test-current.txt +4 −0 Original line number Diff line number Diff line Loading @@ -2899,6 +2899,10 @@ package android.view.inputmethod { method @NonNull public static android.view.inputmethod.InlineSuggestionsResponse newInlineSuggestionsResponse(@NonNull java.util.List<android.view.inputmethod.InlineSuggestion>); } public final class InputMethodInfo implements android.os.Parcelable { ctor public InputMethodInfo(@NonNull String, @NonNull String, @NonNull CharSequence, @NonNull String, int); } public final class InputMethodManager { method public int getDisplayId(); method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public java.util.List<android.view.inputmethod.InputMethodInfo> getInputMethodListAsUser(int); Loading core/java/android/inputmethodservice/IInputMethodWrapper.java +4 −3 Original line number Diff line number Diff line Loading @@ -171,7 +171,7 @@ class IInputMethodWrapper extends IInputMethod.Stub SomeArgs args = (SomeArgs) msg.obj; try { inputMethod.initializeInternal((IBinder) args.arg1, msg.arg1, (IInputMethodPrivilegedOperations) args.arg2); (IInputMethodPrivilegedOperations) args.arg2, (int) args.arg3); } finally { args.recycle(); } Loading Loading @@ -280,9 +280,10 @@ class IInputMethodWrapper extends IInputMethod.Stub @BinderThread @Override public void initializeInternal(IBinder token, int displayId, IInputMethodPrivilegedOperations privOps) { IInputMethodPrivilegedOperations privOps, int configChanges) { mCaller.executeOrSendMessage( mCaller.obtainMessageIOO(DO_INITIALIZE_INTERNAL, displayId, token, privOps)); mCaller.obtainMessageIOOO(DO_INITIALIZE_INTERNAL, displayId, token, privOps, configChanges)); } @BinderThread Loading core/java/android/inputmethodservice/ImsConfigurationTracker.java 0 → 100644 +102 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.inputmethodservice; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.res.Configuration; import android.content.res.Resources; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; /** * Helper class that takes care of Configuration change behavior of {@link InputMethodService}. * Note: this class is public for testing only. Never call any of it's methods for development * of IMEs. * @hide */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public final class ImsConfigurationTracker { /** * A constant value that represents {@link Configuration} has changed from the last time * {@link InputMethodService#onConfigurationChanged(Configuration)} was called. */ private static final int CONFIG_CHANGED = -1; @Nullable private Configuration mLastKnownConfig = null; private int mHandledConfigChanges = 0; private boolean mInitialized = false; /** * Called from {@link InputMethodService.InputMethodImpl * #initializeInternal(IBinder, int, IInputMethodPrivilegedOperations, int)} ()} * @param handledConfigChanges Configuration changes declared handled by IME * {@link android.R.styleable#InputMethod_configChanges}. */ @MainThread public void onInitialize(int handledConfigChanges) { Preconditions.checkState(!mInitialized, "onInitialize can be called only once."); mInitialized = true; mHandledConfigChanges = handledConfigChanges; } /** * Called from {@link InputMethodService.InputMethodImpl#onBindInput()} */ @MainThread public void onBindInput(@Nullable Resources resources) { Preconditions.checkState(mInitialized, "onBindInput can be called only after onInitialize()."); if (mLastKnownConfig == null && resources != null) { mLastKnownConfig = new Configuration(resources.getConfiguration()); } } /** * Dynamically set handled configChanges. * Note: this method is public for testing only. */ public void setHandledConfigChanges(int configChanges) { mHandledConfigChanges = configChanges; } /** * Called from {@link InputMethodService.InputMethodImpl#onConfigurationChanged(Configuration)}} */ @MainThread public void onConfigurationChanged(@NonNull Configuration newConfig, @NonNull Runnable resetStateForNewConfigurationRunner) { if (!mInitialized) { return; } final int diff = mLastKnownConfig != null ? mLastKnownConfig.diffPublicOnly(newConfig) : CONFIG_CHANGED; // If the new config is the same as the config this Service is already running with, // then don't bother calling resetStateForNewConfiguration. final int unhandledDiff = (diff & ~mHandledConfigChanges); if (unhandledDiff != 0) { resetStateForNewConfigurationRunner.run(); } if (diff != 0) { mLastKnownConfig = new Configuration(newConfig); } } } core/java/android/inputmethodservice/InputMethodService.java +9 −3 Original line number Diff line number Diff line Loading @@ -513,6 +513,7 @@ public class InputMethodService extends AbstractInputMethodService { private boolean mIsAutomotive; private Handler mHandler; private boolean mImeSurfaceScheduledForRemoval; private ImsConfigurationTracker mConfigTracker = new ImsConfigurationTracker(); /** * An opaque {@link Binder} token of window requesting {@link InputMethodImpl#showSoftInput} Loading Loading @@ -588,12 +589,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"); mConfigTracker.onInitialize(configChanges); mPrivOps.set(privilegedOperations); InputMethodPrivilegedOperationsRegistry.put(token, mPrivOps); updateInputMethodDisplay(displayId); Loading Loading @@ -663,6 +665,7 @@ public class InputMethodService extends AbstractInputMethodService { reportFullscreenMode(); initialize(); onBindInput(); mConfigTracker.onBindInput(getResources()); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } Loading Loading @@ -1428,10 +1431,13 @@ 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(); mConfigTracker.onConfigurationChanged(newConfig, this::resetStateForNewConfiguration); } private void resetStateForNewConfiguration() { Loading Loading
core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -51921,6 +51921,7 @@ package android.view.inputmethod { method public int describeContents(); method public void dump(android.util.Printer, String); method public android.content.ComponentName getComponent(); method public int getConfigChanges(); method public String getId(); method public int getIsDefaultResourceId(); method public String getPackageName();
core/api/test-current.txt +4 −0 Original line number Diff line number Diff line Loading @@ -2899,6 +2899,10 @@ package android.view.inputmethod { method @NonNull public static android.view.inputmethod.InlineSuggestionsResponse newInlineSuggestionsResponse(@NonNull java.util.List<android.view.inputmethod.InlineSuggestion>); } public final class InputMethodInfo implements android.os.Parcelable { ctor public InputMethodInfo(@NonNull String, @NonNull String, @NonNull CharSequence, @NonNull String, int); } public final class InputMethodManager { method public int getDisplayId(); method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public java.util.List<android.view.inputmethod.InputMethodInfo> getInputMethodListAsUser(int); Loading
core/java/android/inputmethodservice/IInputMethodWrapper.java +4 −3 Original line number Diff line number Diff line Loading @@ -171,7 +171,7 @@ class IInputMethodWrapper extends IInputMethod.Stub SomeArgs args = (SomeArgs) msg.obj; try { inputMethod.initializeInternal((IBinder) args.arg1, msg.arg1, (IInputMethodPrivilegedOperations) args.arg2); (IInputMethodPrivilegedOperations) args.arg2, (int) args.arg3); } finally { args.recycle(); } Loading Loading @@ -280,9 +280,10 @@ class IInputMethodWrapper extends IInputMethod.Stub @BinderThread @Override public void initializeInternal(IBinder token, int displayId, IInputMethodPrivilegedOperations privOps) { IInputMethodPrivilegedOperations privOps, int configChanges) { mCaller.executeOrSendMessage( mCaller.obtainMessageIOO(DO_INITIALIZE_INTERNAL, displayId, token, privOps)); mCaller.obtainMessageIOOO(DO_INITIALIZE_INTERNAL, displayId, token, privOps, configChanges)); } @BinderThread Loading
core/java/android/inputmethodservice/ImsConfigurationTracker.java 0 → 100644 +102 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.inputmethodservice; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.res.Configuration; import android.content.res.Resources; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; /** * Helper class that takes care of Configuration change behavior of {@link InputMethodService}. * Note: this class is public for testing only. Never call any of it's methods for development * of IMEs. * @hide */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public final class ImsConfigurationTracker { /** * A constant value that represents {@link Configuration} has changed from the last time * {@link InputMethodService#onConfigurationChanged(Configuration)} was called. */ private static final int CONFIG_CHANGED = -1; @Nullable private Configuration mLastKnownConfig = null; private int mHandledConfigChanges = 0; private boolean mInitialized = false; /** * Called from {@link InputMethodService.InputMethodImpl * #initializeInternal(IBinder, int, IInputMethodPrivilegedOperations, int)} ()} * @param handledConfigChanges Configuration changes declared handled by IME * {@link android.R.styleable#InputMethod_configChanges}. */ @MainThread public void onInitialize(int handledConfigChanges) { Preconditions.checkState(!mInitialized, "onInitialize can be called only once."); mInitialized = true; mHandledConfigChanges = handledConfigChanges; } /** * Called from {@link InputMethodService.InputMethodImpl#onBindInput()} */ @MainThread public void onBindInput(@Nullable Resources resources) { Preconditions.checkState(mInitialized, "onBindInput can be called only after onInitialize()."); if (mLastKnownConfig == null && resources != null) { mLastKnownConfig = new Configuration(resources.getConfiguration()); } } /** * Dynamically set handled configChanges. * Note: this method is public for testing only. */ public void setHandledConfigChanges(int configChanges) { mHandledConfigChanges = configChanges; } /** * Called from {@link InputMethodService.InputMethodImpl#onConfigurationChanged(Configuration)}} */ @MainThread public void onConfigurationChanged(@NonNull Configuration newConfig, @NonNull Runnable resetStateForNewConfigurationRunner) { if (!mInitialized) { return; } final int diff = mLastKnownConfig != null ? mLastKnownConfig.diffPublicOnly(newConfig) : CONFIG_CHANGED; // If the new config is the same as the config this Service is already running with, // then don't bother calling resetStateForNewConfiguration. final int unhandledDiff = (diff & ~mHandledConfigChanges); if (unhandledDiff != 0) { resetStateForNewConfigurationRunner.run(); } if (diff != 0) { mLastKnownConfig = new Configuration(newConfig); } } }
core/java/android/inputmethodservice/InputMethodService.java +9 −3 Original line number Diff line number Diff line Loading @@ -513,6 +513,7 @@ public class InputMethodService extends AbstractInputMethodService { private boolean mIsAutomotive; private Handler mHandler; private boolean mImeSurfaceScheduledForRemoval; private ImsConfigurationTracker mConfigTracker = new ImsConfigurationTracker(); /** * An opaque {@link Binder} token of window requesting {@link InputMethodImpl#showSoftInput} Loading Loading @@ -588,12 +589,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"); mConfigTracker.onInitialize(configChanges); mPrivOps.set(privilegedOperations); InputMethodPrivilegedOperationsRegistry.put(token, mPrivOps); updateInputMethodDisplay(displayId); Loading Loading @@ -663,6 +665,7 @@ public class InputMethodService extends AbstractInputMethodService { reportFullscreenMode(); initialize(); onBindInput(); mConfigTracker.onBindInput(getResources()); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } Loading Loading @@ -1428,10 +1431,13 @@ 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(); mConfigTracker.onConfigurationChanged(newConfig, this::resetStateForNewConfiguration); } private void resetStateForNewConfiguration() { Loading