diff options
7 files changed, 126 insertions, 1 deletions
diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 8c537336bdde..deb5aca53b78 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -2160,10 +2160,15 @@ package android.provider { field public static final String NAMESPACE_APP_COMPAT_OVERRIDES = "app_compat_overrides"; field public static final String NAMESPACE_CONSTRAIN_DISPLAY_APIS = "constrain_display_apis"; field public static final String NAMESPACE_DEVICE_IDLE = "device_idle"; + field public static final String NAMESPACE_INPUT_METHOD_MANAGER = "input_method_manager"; field public static final String NAMESPACE_JOB_SCHEDULER = "jobscheduler"; field public static final String NAMESPACE_SELECTION_TOOLBAR = "selection_toolbar"; } + public interface InputMethodManagerDeviceConfig { + field public static final String KEY_HIDE_IME_WHEN_NO_EDITOR_FOCUS = "hide_ime_when_no_editor_focus"; + } + public final class Settings { field public static final int RESET_MODE_PACKAGE_DEFAULTS = 1; // 0x1 } diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java index b7adcb84102d..d125cbb80a27 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -775,6 +775,14 @@ public final class DeviceConfig { */ public static final String NAMESPACE_WEAR = "wear"; + /** + * Namespace for the input method manager platform features. + * + * @hide + */ + @TestApi + public static final String NAMESPACE_INPUT_METHOD_MANAGER = "input_method_manager"; + private static final Object sLock = new Object(); @GuardedBy("sLock") private static ArrayMap<OnPropertiesChangedListener, Pair<String, Executor>> sListeners = diff --git a/core/java/android/provider/InputMethodManagerDeviceConfig.java b/core/java/android/provider/InputMethodManagerDeviceConfig.java new file mode 100644 index 000000000000..906b133d30d1 --- /dev/null +++ b/core/java/android/provider/InputMethodManagerDeviceConfig.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2022 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.provider; + +import android.annotation.TestApi; + +/** + * Interface for accessing keys belonging to {@link DeviceConfig#NAMESPACE_INPUT_METHOD_MANAGER}. + * @hide + */ +@TestApi +public interface InputMethodManagerDeviceConfig { + /** + * Whether the IME should be hidden when the window gained focus without an editor focused. + */ + String KEY_HIDE_IME_WHEN_NO_EDITOR_FOCUS = "hide_ime_when_no_editor_focus"; +} diff --git a/core/java/com/android/internal/inputmethod/InputMethodDebug.java b/core/java/com/android/internal/inputmethod/InputMethodDebug.java index 1852c593535b..b7b2e71469ba 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodDebug.java +++ b/core/java/com/android/internal/inputmethod/InputMethodDebug.java @@ -254,6 +254,8 @@ public final class InputMethodDebug { return "HIDE_SOFT_INPUT_EXTRACT_INPUT_CHANGED"; case SoftInputShowHideReason.HIDE_SOFT_INPUT_IMM_DEPRECATION: return "HIDE_SOFT_INPUT_IMM_DEPRECATION"; + case SoftInputShowHideReason.HIDE_WINDOW_GAINED_FOCUS_WITHOUT_EDITOR: + return "HIDE_WINDOW_GAINED_FOCUS_WITHOUT_EDITOR"; default: return "Unknown=" + reason; } diff --git a/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java b/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java index f5b58c01c293..f1635ebe5fb3 100644 --- a/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java +++ b/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java @@ -63,7 +63,8 @@ import java.lang.annotation.Retention; SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_BACK_KEY, SoftInputShowHideReason.HIDE_SOFT_INPUT_IME_TOGGLE_SOFT_INPUT, SoftInputShowHideReason.HIDE_SOFT_INPUT_EXTRACT_INPUT_CHANGED, - SoftInputShowHideReason.HIDE_SOFT_INPUT_IMM_DEPRECATION}) + SoftInputShowHideReason.HIDE_SOFT_INPUT_IMM_DEPRECATION, + SoftInputShowHideReason.HIDE_WINDOW_GAINED_FOCUS_WITHOUT_EDITOR}) public @interface SoftInputShowHideReason { /** Show soft input by {@link android.view.inputmethod.InputMethodManager#showSoftInput}. */ int SHOW_SOFT_INPUT = 0; @@ -247,4 +248,9 @@ public @interface SoftInputShowHideReason { * {@link InputMethodManager#hideSoftInputFromInputMethod(IBinder, int)}. */ int HIDE_SOFT_INPUT_IMM_DEPRECATION = 31; + + /** + * Hide soft input when the window gained focus without an editor from the IME shown window. + */ + int HIDE_WINDOW_GAINED_FOCUS_WITHOUT_EDITOR = 32; } diff --git a/services/core/java/com/android/server/inputmethod/InputMethodDeviceConfigs.java b/services/core/java/com/android/server/inputmethod/InputMethodDeviceConfigs.java new file mode 100644 index 000000000000..9d5393f38dba --- /dev/null +++ b/services/core/java/com/android/server/inputmethod/InputMethodDeviceConfigs.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2022 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 com.android.server.inputmethod; + +import static android.provider.InputMethodManagerDeviceConfig.KEY_HIDE_IME_WHEN_NO_EDITOR_FOCUS; + +import android.app.ActivityThread; +import android.provider.DeviceConfig; + +/** + * Class for the device-level configuration related to the input method manager + * platform features in {@link DeviceConfig}. + */ +public final class InputMethodDeviceConfigs { + private boolean mHideImeWhenNoEditorFocus; + private final DeviceConfig.OnPropertiesChangedListener mDeviceConfigChangedListener; + + public InputMethodDeviceConfigs() { + mDeviceConfigChangedListener = properties -> { + if (!DeviceConfig.NAMESPACE_INPUT_METHOD_MANAGER.equals(properties.getNamespace())) { + return; + } + for (String name : properties.getKeyset()) { + if (KEY_HIDE_IME_WHEN_NO_EDITOR_FOCUS.equals(name)) { + mHideImeWhenNoEditorFocus = properties.getBoolean(name, + true /* defaultValue */); + } + } + }; + mHideImeWhenNoEditorFocus = DeviceConfig.getBoolean( + DeviceConfig.NAMESPACE_INPUT_METHOD_MANAGER, + KEY_HIDE_IME_WHEN_NO_EDITOR_FOCUS, true); + DeviceConfig.addOnPropertiesChangedListener( + DeviceConfig.NAMESPACE_INPUT_METHOD_MANAGER, + ActivityThread.currentApplication().getMainExecutor(), + mDeviceConfigChangedListener); + } + + /** + * Whether the IME should be hidden when the window gained focus without an editor focused. + */ + public boolean shouldHideImeWhenNoEditorFocus() { + return mHideImeWhenNoEditorFocus; + } +} diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 7bd835c73749..729de41dcbcd 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -303,6 +303,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub final PackageManagerInternal mPackageManagerInternal; final InputManagerInternal mInputManagerInternal; final ImePlatformCompatUtils mImePlatformCompatUtils; + final InputMethodDeviceConfigs mInputMethodDeviceConfigs; private final DisplayManagerInternal mDisplayManagerInternal; final boolean mHasFeature; private final ArrayMap<String, List<InputMethodSubtype>> mAdditionalSubtypeMap = @@ -1732,6 +1733,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); mImePlatformCompatUtils = new ImePlatformCompatUtils(); + mInputMethodDeviceConfigs = new InputMethodDeviceConfigs(); mImeDisplayValidator = mWindowManagerInternal::getDisplayImePolicy; mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); mAppOpsManager = mContext.getSystemService(AppOpsManager.class); @@ -3889,6 +3891,18 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub SoftInputShowHideReason.HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR); } } + if (!isTextEditor && mInputShown && startInputByWinGainedFocus + && mInputMethodDeviceConfigs.shouldHideImeWhenNoEditorFocus()) { + // Hide the soft-keyboard when the system do nothing for softInputModeState + // of the window being gained focus without an editor. This behavior benefits + // to resolve some unexpected IME visible cases while that window with following + // configurations being switched from an IME shown window: + // 1) SOFT_INPUT_STATE_UNCHANGED state without an editor + // 2) SOFT_INPUT_STATE_VISIBLE state without an editor + // 3) SOFT_INPUT_STATE_ALWAYS_VISIBLE state without an editor + hideCurrentInputLocked(mCurFocusedWindow, 0, null, + SoftInputShowHideReason.HIDE_WINDOW_GAINED_FOCUS_WITHOUT_EDITOR); + } res = startInputUncheckedLocked(cs, inputContext, remoteAccessibilityInputConnection, editorInfo, startInputFlags, startInputReason, unverifiedTargetSdkVersion, |