summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/WindowManager.java8
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java6
-rw-r--r--core/java/com/android/internal/inputmethod/InputMethodUtils.java21
-rw-r--r--core/java/com/android/internal/view/IInputMethodManager.aidl3
-rw-r--r--core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java29
-rw-r--r--services/core/java/com/android/server/InputMethodManagerService.java48
6 files changed, 98 insertions, 17 deletions
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 500701de7f23..ce3022ed791d 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1672,12 +1672,20 @@ public interface WindowManager extends ViewManager {
* Visibility state for {@link #softInputMode}: please show the soft
* input area when normally appropriate (when the user is navigating
* forward to your window).
+ *
+ * <p>Applications that target {@link android.os.Build.VERSION_CODES#P} and later, this flag
+ * is ignored unless there is a focused view that returns {@code true} from
+ * {@link View#isInEditMode()} when the window is focused.</p>
*/
public static final int SOFT_INPUT_STATE_VISIBLE = 4;
/**
* Visibility state for {@link #softInputMode}: please always make the
* soft input area visible when this window receives input focus.
+ *
+ * <p>Applications that target {@link android.os.Build.VERSION_CODES#P} and later, this flag
+ * is ignored unless there is a focused view that returns {@code true} from
+ * {@link View#isInEditMode()} when the window is focused.</p>
*/
public static final int SOFT_INPUT_STATE_ALWAYS_VISIBLE = 5;
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 3cd8d4a2417d..9f033d72167f 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1333,7 +1333,8 @@ public final class InputMethodManager {
+ Integer.toHexString(controlFlags));
final InputBindResult res = mService.startInputOrWindowGainedFocus(
startInputReason, mClient, windowGainingFocus, controlFlags, softInputMode,
- windowFlags, tba, servedContext, missingMethodFlags);
+ windowFlags, tba, servedContext, missingMethodFlags,
+ view.getContext().getApplicationInfo().targetSdkVersion);
if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res);
if (res != null) {
if (res.id != null) {
@@ -1588,7 +1589,8 @@ public final class InputMethodManager {
mService.startInputOrWindowGainedFocus(
InputMethodClient.START_INPUT_REASON_WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient,
rootView.getWindowToken(), controlFlags, softInputMode, windowFlags, null,
- null, 0 /* missingMethodFlags */);
+ null, 0 /* missingMethodFlags */,
+ rootView.getContext().getApplicationInfo().targetSdkVersion);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 57efae61a9c6..d3b4dbf1bd82 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -16,6 +16,9 @@
package com.android.internal.inputmethod;
+import static android.view.inputmethod.InputMethodManager.CONTROL_WINDOW_IS_TEXT_EDITOR;
+import static android.view.inputmethod.InputMethodManager.CONTROL_WINDOW_VIEW_HAS_FOCUS;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -26,6 +29,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.res.Resources;
+import android.os.Build;
import android.os.LocaleList;
import android.os.RemoteException;
import android.provider.Settings;
@@ -33,6 +37,7 @@ import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.Log;
import android.util.Pair;
import android.util.Printer;
import android.util.Slog;
@@ -1510,4 +1515,20 @@ public class InputMethodUtils {
}
return locales;
}
+
+ public static boolean isSoftInputModeStateVisibleAllowed(
+ int targetSdkVersion, int controlFlags) {
+ if (targetSdkVersion < Build.VERSION_CODES.P) {
+ // for compatibility.
+ return true;
+ }
+ if ((controlFlags & CONTROL_WINDOW_VIEW_HAS_FOCUS) == 0) {
+ return false;
+ }
+ if ((controlFlags & CONTROL_WINDOW_IS_TEXT_EDITOR) == 0) {
+ return false;
+ }
+ return true;
+ }
+
}
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 1fd5564773b1..ac03d74632fa 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -61,7 +61,8 @@ interface IInputMethodManager {
in IInputMethodClient client, in IBinder windowToken, int controlFlags,
/* @android.view.WindowManager.LayoutParams.SoftInputModeFlags */ int softInputMode,
int windowFlags, in EditorInfo attribute, IInputContext inputContext,
- /* @InputConnectionInspector.MissingMethodFlags */ int missingMethodFlags);
+ /* @InputConnectionInspector.MissingMethodFlags */ int missingMethodFlags,
+ int unverifiedTargetSdkVersion);
void showInputMethodPickerFromClient(in IInputMethodClient client,
int auxiliarySubtypeMode);
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
index 33cd328a6d80..e6ac68294564 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
@@ -16,6 +16,9 @@
package com.android.internal.inputmethod;
+import static android.view.inputmethod.InputMethodManager.CONTROL_WINDOW_IS_TEXT_EDITOR;
+import static android.view.inputmethod.InputMethodManager.CONTROL_WINDOW_VIEW_HAS_FOCUS;
+
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.in;
import static org.hamcrest.Matchers.not;
@@ -31,6 +34,7 @@ import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.os.Build;
import android.os.LocaleList;
import android.os.Parcel;
import android.support.test.InstrumentationRegistry;
@@ -1410,4 +1414,29 @@ public class InputMethodUtilsTest {
assertEquals(new Locale("a b c"), InputMethodUtils.constructLocaleFromString("a b c"));
assertEquals(new Locale("en-US"), InputMethodUtils.constructLocaleFromString("en-US"));
}
+
+ @Test
+ public void testIsSoftInputModeStateVisibleAllowed() {
+ // On pre-P devices, SOFT_INPUT_STATE_VISIBLE/SOFT_INPUT_STATE_ALWAYS_VISIBLE are always
+ // allowed, regardless of the focused view state.
+ assertTrue(InputMethodUtils.isSoftInputModeStateVisibleAllowed(
+ Build.VERSION_CODES.O_MR1, 0));
+ assertTrue(InputMethodUtils.isSoftInputModeStateVisibleAllowed(
+ Build.VERSION_CODES.O_MR1, CONTROL_WINDOW_VIEW_HAS_FOCUS));
+ assertTrue(InputMethodUtils.isSoftInputModeStateVisibleAllowed(
+ Build.VERSION_CODES.O_MR1,
+ CONTROL_WINDOW_VIEW_HAS_FOCUS | CONTROL_WINDOW_IS_TEXT_EDITOR));
+
+ // On P+ devices, SOFT_INPUT_STATE_VISIBLE/SOFT_INPUT_STATE_ALWAYS_VISIBLE are allowed only
+ // when there is a focused View and its View#onCheckIsTextEditor() returns true.
+ assertFalse(InputMethodUtils.isSoftInputModeStateVisibleAllowed(
+ Build.VERSION_CODES.P, 0));
+ assertFalse(InputMethodUtils.isSoftInputModeStateVisibleAllowed(
+ Build.VERSION_CODES.P, CONTROL_WINDOW_VIEW_HAS_FOCUS));
+ assertTrue(InputMethodUtils.isSoftInputModeStateVisibleAllowed(
+ Build.VERSION_CODES.P,
+ CONTROL_WINDOW_VIEW_HAS_FOCUS | CONTROL_WINDOW_IS_TEXT_EDITOR));
+
+ }
+
}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 5fed93b1b0b1..25c3fe42f795 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -93,6 +93,7 @@ import android.hardware.input.InputManagerInternal;
import android.inputmethodservice.InputMethodService;
import android.net.Uri;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
import android.os.Environment;
@@ -2723,10 +2724,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
/* @InputMethodClient.StartInputReason */ final int startInputReason,
IInputMethodClient client, IBinder windowToken, int controlFlags, int softInputMode,
int windowFlags, @Nullable EditorInfo attribute, IInputContext inputContext,
- /* @InputConnectionInspector.missingMethods */ final int missingMethods) {
+ /* @InputConnectionInspector.missingMethods */ final int missingMethods,
+ int unverifiedTargetSdkVersion) {
if (windowToken != null) {
return windowGainedFocus(startInputReason, client, windowToken, controlFlags,
- softInputMode, windowFlags, attribute, inputContext, missingMethods);
+ softInputMode, windowFlags, attribute, inputContext, missingMethods,
+ unverifiedTargetSdkVersion);
} else {
return startInput(startInputReason, client, inputContext, missingMethods, attribute,
controlFlags);
@@ -2738,7 +2741,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
IInputMethodClient client, IBinder windowToken, int controlFlags,
/* @android.view.WindowManager.LayoutParams.SoftInputModeFlags */ int softInputMode,
int windowFlags, EditorInfo attribute, IInputContext inputContext,
- /* @InputConnectionInspector.missingMethods */ final int missingMethods) {
+ /* @InputConnectionInspector.missingMethods */ final int missingMethods,
+ int unverifiedTargetSdkVersion) {
// Needs to check the validity before clearing calling identity
final boolean calledFromValidUser = calledFromValidUser();
InputBindResult res = null;
@@ -2754,7 +2758,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
+ " attribute=" + attribute
+ " controlFlags=#" + Integer.toHexString(controlFlags)
+ " softInputMode=" + InputMethodClient.softInputModeToString(softInputMode)
- + " windowFlags=#" + Integer.toHexString(windowFlags));
+ + " windowFlags=#" + Integer.toHexString(windowFlags)
+ + " unverifiedTargetSdkVersion=" + unverifiedTargetSdkVersion);
ClientState cs = mClients.get(client.asBinder());
if (cs == null) {
@@ -2868,22 +2873,37 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
if ((softInputMode &
WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
if (DEBUG) Slog.v(TAG, "Window asks to show input going forward");
- if (attribute != null) {
- res = startInputUncheckedLocked(cs, inputContext,
- missingMethods, attribute, controlFlags, startInputReason);
- didStart = true;
+ if (InputMethodUtils.isSoftInputModeStateVisibleAllowed(
+ unverifiedTargetSdkVersion, controlFlags)) {
+ if (attribute != null) {
+ res = startInputUncheckedLocked(cs, inputContext,
+ missingMethods, attribute, controlFlags,
+ startInputReason);
+ didStart = true;
+ }
+ showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
+ } else {
+ Slog.e(TAG, "SOFT_INPUT_STATE_VISIBLE is ignored because"
+ + " there is no focused view that also returns true from"
+ + " View#onCheckIsTextEditor()");
}
- showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
}
break;
case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
if (DEBUG) Slog.v(TAG, "Window asks to always show input");
- if (attribute != null) {
- res = startInputUncheckedLocked(cs, inputContext, missingMethods,
- attribute, controlFlags, startInputReason);
- didStart = true;
+ if (InputMethodUtils.isSoftInputModeStateVisibleAllowed(
+ unverifiedTargetSdkVersion, controlFlags)) {
+ if (attribute != null) {
+ res = startInputUncheckedLocked(cs, inputContext, missingMethods,
+ attribute, controlFlags, startInputReason);
+ didStart = true;
+ }
+ showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
+ } else {
+ Slog.e(TAG, "SOFT_INPUT_STATE_ALWAYS_VISIBLE is ignored because"
+ + " there is no focused view that also returns true from"
+ + " View#onCheckIsTextEditor()");
}
- showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
break;
}