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) {