diff --git a/core/api/current.txt b/core/api/current.txt
index b30ca65aae1e8..c506e50fa74eb 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -3259,6 +3259,7 @@ package android.accessibilityservice {
field public static final int FEEDBACK_VISUAL = 8; // 0x8
field public static final int FLAG_ENABLE_ACCESSIBILITY_VOLUME = 128; // 0x80
field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
+ field public static final int FLAG_INPUT_METHOD_EDITOR = 32768; // 0x8000
field public static final int FLAG_REPORT_VIEW_IDS = 16; // 0x10
field public static final int FLAG_REQUEST_2_FINGER_PASSTHROUGH = 8192; // 0x2000
field public static final int FLAG_REQUEST_ACCESSIBILITY_BUTTON = 256; // 0x100
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 621d9282784d0..cf3ca20315d8d 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -825,10 +825,16 @@ public abstract class AccessibilityService extends Service {
for (int i = 0; i < mMagnificationControllers.size(); i++) {
mMagnificationControllers.valueAt(i).onServiceConnectedLocked();
}
- // TODO(b/187453053): If service requested ime capabilities
- if (!mInputMethodInitialized) {
- mInputMethod = onCreateInputMethod();
- mInputMethodInitialized = true;
+ AccessibilityServiceInfo info = getServiceInfo();
+ if (info != null) {
+ boolean requestIme = (info.flags
+ & AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR) != 0;
+ if (requestIme && !mInputMethodInitialized) {
+ mInputMethod = onCreateInputMethod();
+ mInputMethodInitialized = true;
+ }
+ } else {
+ Log.e(LOG_TAG, "AccessibilityServiceInfo is null in dispatchServiceConnected");
}
}
if (mSoftKeyboardController != null) {
@@ -1885,7 +1891,7 @@ public abstract class AccessibilityService extends Service {
/**
* The default implementation returns our default {@link InputMethod}. Subclasses can override
* it to provide their own customized version. Accessibility services need to set the
- * {@link AccessibilityServiceInfo#FLAG_REQUEST_IME_APIS} flag to use input method APIs.
+ * {@link AccessibilityServiceInfo#FLAG_INPUT_METHOD_EDITOR} flag to use input method APIs.
*
* @return the InputMethod.
*/
@@ -1898,7 +1904,7 @@ public abstract class AccessibilityService extends Service {
* Returns the InputMethod instance after the system calls {@link #onCreateInputMethod()},
* which may be used to input text or get editable text selection change notifications. It will
* return null if the accessibility service doesn't set the
- * {@link AccessibilityServiceInfo#FLAG_REQUEST_IME_APIS} flag or the system doesn't call
+ * {@link AccessibilityServiceInfo#FLAG_INPUT_METHOD_EDITOR} flag or the system doesn't call
* {@link #onCreateInputMethod()}.
*
* @return the InputMethod instance
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 1167d0b1034f8..f945367fb2dba 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -390,6 +390,15 @@ public class AccessibilityServiceInfo implements Parcelable {
*/
public static final int FLAG_SEND_MOTION_EVENTS = 0x0004000;
+ /**
+ * This flag makes the AccessibilityService an input method editor with a subset of input
+ * method editor capabilities: get the {@link android.view.inputmethod.InputConnection} and get
+ * text selection change notifications.
+ *
+ * @see AccessibilityService#getInputMethod()
+ */
+ public static final int FLAG_INPUT_METHOD_EDITOR = 0x0008000;
+
/** {@hide} */
public static final int FLAG_FORCE_DIRECT_BOOT_AWARE = 0x00010000;
@@ -497,6 +506,7 @@ public class AccessibilityServiceInfo implements Parcelable {
* @see #FLAG_ENABLE_ACCESSIBILITY_VOLUME
* @see #FLAG_REQUEST_ACCESSIBILITY_BUTTON
* @see #FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK
+ * @see #FLAG_INPUT_METHOD_EDITOR
*/
public int flags;
@@ -1332,6 +1342,8 @@ public class AccessibilityServiceInfo implements Parcelable {
return "FLAG_REQUEST_FINGERPRINT_GESTURES";
case FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK:
return "FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK";
+ case FLAG_INPUT_METHOD_EDITOR:
+ return "FLAG_INPUT_METHOD_EDITOR";
default:
return null;
}
diff --git a/core/java/android/accessibilityservice/InputMethod.java b/core/java/android/accessibilityservice/InputMethod.java
index 1684bea274a90..001d804b22d6a 100644
--- a/core/java/android/accessibilityservice/InputMethod.java
+++ b/core/java/android/accessibilityservice/InputMethod.java
@@ -55,7 +55,7 @@ import java.util.concurrent.Executor;
* developers should override them as needed. Developers should also override
* {@link AccessibilityService#onCreateInputMethod()} to return
* their custom InputMethod implementation. Accessibility services also need to set the
- * {@link AccessibilityServiceInfo#FLAG_REQUEST_IME_APIS} flag to use input method APIs.
+ * {@link AccessibilityServiceInfo#FLAG_INPUT_METHOD_EDITOR} flag to use input method APIs.
*/
public class InputMethod {
private static final String LOG_TAG = "A11yInputMethod";
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d774fd4e397a7..7d12d5947f7e4 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3910,6 +3910,8 @@
+
+
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 0f65ebca9b3ac..7f103144b7fb7 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -188,6 +188,8 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
boolean mLastAccessibilityButtonCallbackState;
+ boolean mRequestImeApis;
+
int mFetchFlags;
long mNotificationTimeout;
@@ -385,6 +387,9 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
& AccessibilityServiceInfo.FLAG_REQUEST_FINGERPRINT_GESTURES) != 0;
mRequestAccessibilityButton = (info.flags
& AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0;
+ // TODO(b/218193835): request ime when ime flag is set and clean up when ime flag is unset
+ mRequestImeApis = (info.flags
+ & AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR) != 0;
}
protected boolean supportsFlagForNotImportantViews(AccessibilityServiceInfo info) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 2f049f7edc1fb..48d6229a1dfbb 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -4372,10 +4372,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
userState = getCurrentUserStateLocked();
for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) {
final AccessibilityServiceConnection service = userState.mBoundServices.get(i);
- // TODO(b/187453053): mRequestedIme implementation
- //if (service.mRequestedIme) {
- service.bindInputLocked(binding);
- //}
+ if (service.requestImeApis()) {
+ service.bindInputLocked(binding);
+ }
}
}
}
@@ -4390,10 +4389,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
userState = getCurrentUserStateLocked();
for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) {
final AccessibilityServiceConnection service = userState.mBoundServices.get(i);
- // TODO(187453053): mRequestedIme implementation
- //if (service.mRequestedIme) {
- service.unbindInputLocked();
- //}
+ if (service.requestImeApis()) {
+ service.unbindInputLocked();
+ }
}
}
}
@@ -4403,7 +4401,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
*/
public void startInput(IBinder startInputToken, IInputContext inputContext,
EditorInfo editorInfo, boolean restarting) {
- //TODO(b/187453053): including the java doc
AccessibilityUserState userState;
synchronized (mLock) {
// Keep records of these in case new Accessibility Services are enabled.
@@ -4414,10 +4411,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
userState = getCurrentUserStateLocked();
for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) {
final AccessibilityServiceConnection service = userState.mBoundServices.get(i);
- // TODO(b/187453053): mRequestedIme implementation
- //if (service.mRequestedIme) {
- service.startInputLocked(startInputToken, inputContext, editorInfo, restarting);
- //}
+ if (service.requestImeApis()) {
+ service.startInputLocked(startInputToken, inputContext, editorInfo, restarting);
+ }
}
}
}
@@ -4432,10 +4428,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
userState = getCurrentUserStateLocked();
for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) {
final AccessibilityServiceConnection service = userState.mBoundServices.get(i);
- // TODO(b/187453053): mRequestedIme implementation
- //if (service.mRequestedIme) {
- service.createImeSessionLocked();
- //}
+ if (service.requestImeApis()) {
+ service.createImeSessionLocked();
+ }
}
}
}
@@ -4452,11 +4447,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
userState = getCurrentUserStateLocked();
for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) {
final AccessibilityServiceConnection service = userState.mBoundServices.get(i);
- // TODO(b/187453053): mRequestedIme implementation
- if (sessions.contains(service.mId)) {
- //if (service.mRequestedIme) {
+ if (sessions.contains(service.mId) && service.requestImeApis()) {
service.setImeSessionEnabledLocked(sessions.get(service.mId), enabled);
- //}
}
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
index e06ee77974ec7..06310284b56c2 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
@@ -127,8 +127,9 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect
}
public void unbindLocked() {
- // If requested ime
- mSystemSupport.unbindImeLocked(this);
+ if (requestImeApis()) {
+ mSystemSupport.unbindImeLocked(this);
+ }
mContext.unbindService(this);
AccessibilityUserState userState = mUserStateWeakReference.get();
if (userState == null) return;
@@ -190,8 +191,9 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect
// the new configuration (for example, initializing the input filter).
mMainHandler.sendMessage(obtainMessage(
AccessibilityServiceConnection::initializeService, this));
- //if (service.mRequestedIme) {
- mSystemSupport.requestImeLocked(this);
+ if (requestImeApis()) {
+ mSystemSupport.requestImeLocked(this);
+ }
}
}
@@ -375,7 +377,9 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect
if (!isConnectedLocked()) {
return;
}
- mSystemSupport.unbindImeLocked(this);
+ if (requestImeApis()) {
+ mSystemSupport.unbindImeLocked(this);
+ }
mAccessibilityServiceInfo.crashed = true;
AccessibilityUserState userState = mUserStateWeakReference.get();
if (userState != null) {
@@ -517,6 +521,10 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect
mMainHandler.sendMessage(msg);
}
+ public boolean requestImeApis() {
+ return mRequestImeApis;
+ }
+
private void notifyMotionEventInternal(MotionEvent event) {
final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
if (listener != null) {