Loading core/java/android/accessibilityservice/AccessibilityInputMethodSession.java 0 → 100644 +33 −0 Original line number Original line Diff line number Diff line /* * 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.accessibilityservice; import android.view.inputmethod.EditorInfo; import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection; interface AccessibilityInputMethodSession { void finishInput(); void updateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd); void invalidateInput(EditorInfo editorInfo, IRemoteAccessibilityInputConnection connection, int sessionId); void setEnabled(boolean enabled); } core/java/android/accessibilityservice/AccessibilityInputMethodSessionWrapper.java 0 → 100644 +116 −0 Original line number Original line Diff line number Diff line /* * 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.accessibilityservice; import android.annotation.AnyThread; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Handler; import android.os.Looper; import android.view.inputmethod.EditorInfo; import com.android.internal.inputmethod.IAccessibilityInputMethodSession; import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection; import java.util.concurrent.atomic.AtomicReference; final class AccessibilityInputMethodSessionWrapper extends IAccessibilityInputMethodSession.Stub { private final Handler mHandler; @NonNull private final AtomicReference<AccessibilityInputMethodSession> mSessionRef; AccessibilityInputMethodSessionWrapper( @NonNull Looper looper, @NonNull AccessibilityInputMethodSession session) { mSessionRef = new AtomicReference<>(session); mHandler = Handler.createAsync(looper); } @AnyThread @Nullable AccessibilityInputMethodSession getSession() { return mSessionRef.get(); } @Override public void updateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd) { if (mHandler.getLooper().isCurrentThread()) { doUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd); } else { mHandler.post(() -> doUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd)); } } private void doUpdateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd) { final AccessibilityInputMethodSession session = mSessionRef.get(); if (session != null) { session.updateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd); } } @Override public void finishInput() { if (mHandler.getLooper().isCurrentThread()) { doFinishInput(); } else { mHandler.post(this::doFinishInput); } } private void doFinishInput() { final AccessibilityInputMethodSession session = mSessionRef.get(); if (session != null) { session.finishInput(); } } @Override public void finishSession() { if (mHandler.getLooper().isCurrentThread()) { doFinishSession(); } else { mHandler.post(this::doFinishSession); } } private void doFinishSession() { mSessionRef.set(null); } @Override public void invalidateInput(EditorInfo editorInfo, IRemoteAccessibilityInputConnection connection, int sessionId) { if (mHandler.getLooper().isCurrentThread()) { doInvalidateInput(editorInfo, connection, sessionId); } else { mHandler.post(() -> doInvalidateInput(editorInfo, connection, sessionId)); } } private void doInvalidateInput(EditorInfo editorInfo, IRemoteAccessibilityInputConnection connection, int sessionId) { final AccessibilityInputMethodSession session = mSessionRef.get(); if (session != null) { session.invalidateInput(editorInfo, connection, sessionId); } } } core/java/android/accessibilityservice/AccessibilityService.java +38 −95 Original line number Original line Diff line number Diff line Loading @@ -40,8 +40,6 @@ import android.graphics.ParcelableColorSpace; import android.graphics.Region; import android.graphics.Region; import android.hardware.HardwareBuffer; import android.hardware.HardwareBuffer; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager; import android.inputmethodservice.IInputMethodSessionWrapper; import android.inputmethodservice.RemoteInputConnection; import android.os.Build; import android.os.Build; import android.os.Bundle; import android.os.Bundle; import android.os.Handler; import android.os.Handler; Loading @@ -68,22 +66,19 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.view.accessibility.AccessibilityWindowInfo; import android.view.accessibility.AccessibilityWindowInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputBinding; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodSession; import com.android.internal.inputmethod.CancellationGroup; import com.android.internal.inputmethod.CancellationGroup; import com.android.internal.inputmethod.IAccessibilityInputMethodSession; import com.android.internal.inputmethod.IAccessibilityInputMethodSessionCallback; import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection; import com.android.internal.inputmethod.RemoteAccessibilityInputConnection; import com.android.internal.os.HandlerCaller; import com.android.internal.os.HandlerCaller; import com.android.internal.os.SomeArgs; import com.android.internal.os.SomeArgs; import com.android.internal.util.Preconditions; import com.android.internal.util.Preconditions; import com.android.internal.util.function.pooled.PooledLambda; import com.android.internal.util.function.pooled.PooledLambda; import com.android.internal.view.IInputContext; import com.android.internal.view.IInputMethodSession; import com.android.internal.view.IInputSessionWithIdCallback; import java.lang.annotation.Retention; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.util.Collections; import java.util.Collections; import java.util.List; import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.Executor; Loading Loading @@ -639,20 +634,10 @@ public abstract class AccessibilityService extends Service { /** This is called when the system action list is changed. */ /** This is called when the system action list is changed. */ void onSystemActionsChanged(); void onSystemActionsChanged(); /** This is called when an app requests ime sessions or when the service is enabled. */ /** This is called when an app requests ime sessions or when the service is enabled. */ void createImeSession(IInputSessionWithIdCallback callback); void createImeSession(IAccessibilityInputMethodSessionCallback callback); /** * This is called when InputMethodManagerService requests to set the session enabled or * disabled */ void setImeSessionEnabled(InputMethodSession session, boolean enabled); /** This is called when an app binds input or when the service is enabled. */ void bindInput(InputBinding binding); /** This is called when an app unbinds input or when the service is disabled. */ void unbindInput(); /** This is called when an app starts input or when the service is enabled. */ /** This is called when an app starts input or when the service is enabled. */ void startInput(@Nullable InputConnection inputConnection, void startInput(@Nullable RemoteAccessibilityInputConnection inputConnection, @NonNull EditorInfo editorInfo, boolean restarting, @NonNull EditorInfo editorInfo, boolean restarting); @NonNull IBinder startInputToken); } } /** /** Loading Loading @@ -2740,42 +2725,20 @@ public abstract class AccessibilityService extends Service { } } @Override @Override public void createImeSession(IInputSessionWithIdCallback callback) { public void createImeSession(IAccessibilityInputMethodSessionCallback callback) { if (mInputMethod != null) { if (mInputMethod != null) { mInputMethod.createImeSession(callback); mInputMethod.createImeSession(callback); } } } } @Override @Override public void setImeSessionEnabled(InputMethodSession session, boolean enabled) { public void startInput(@Nullable RemoteAccessibilityInputConnection connection, if (mInputMethod != null) { @NonNull EditorInfo editorInfo, boolean restarting) { mInputMethod.setImeSessionEnabled(session, enabled); } } @Override public void bindInput(InputBinding binding) { if (mInputMethod != null) { mInputMethod.bindInput(binding); } } @Override public void unbindInput() { if (mInputMethod != null) { mInputMethod.unbindInput(); } } @Override public void startInput(@Nullable InputConnection inputConnection, @NonNull EditorInfo editorInfo, boolean restarting, @NonNull IBinder startInputToken) { if (mInputMethod != null) { if (mInputMethod != null) { if (restarting) { if (restarting) { mInputMethod.restartInput(inputConnection, editorInfo); mInputMethod.restartInput(connection, editorInfo); } else { } else { mInputMethod.startInput(inputConnection, editorInfo); mInputMethod.startInput(connection, editorInfo); } } } } } } Loading Loading @@ -2806,8 +2769,6 @@ public abstract class AccessibilityService extends Service { private static final int DO_ON_SYSTEM_ACTIONS_CHANGED = 14; private static final int DO_ON_SYSTEM_ACTIONS_CHANGED = 14; private static final int DO_CREATE_IME_SESSION = 15; private static final int DO_CREATE_IME_SESSION = 15; private static final int DO_SET_IME_SESSION_ENABLED = 16; private static final int DO_SET_IME_SESSION_ENABLED = 16; private static final int DO_BIND_INPUT = 17; private static final int DO_UNBIND_INPUT = 18; private static final int DO_START_INPUT = 19; private static final int DO_START_INPUT = 19; private final HandlerCaller mCaller; private final HandlerCaller mCaller; Loading @@ -2818,15 +2779,14 @@ public abstract class AccessibilityService extends Service { private int mConnectionId = AccessibilityInteractionClient.NO_ID; private int mConnectionId = AccessibilityInteractionClient.NO_ID; /** /** * This is not {@null} only between {@link #bindInput(InputBinding)} and * This is not {@code null} only between {@link #bindInput()} and {@link #unbindInput()} so * {@link #unbindInput()} so that {@link RemoteInputConnection} can query if * that {@link RemoteAccessibilityInputConnection} can query if {@link #unbindInput()} has * {@link #unbindInput()} has already been called or not, mainly to avoid unnecessary * already been called or not, mainly to avoid unnecessary blocking operations. * blocking operations. * * * <p>This field must be set and cleared only from the binder thread(s), where the system * <p>This field must be set and cleared only from the binder thread(s), where the system * guarantees that {@link #bindInput(InputBinding)}, * guarantees that {@link #bindInput()}, * {@link #startInput(IBinder, IInputContext, EditorInfo, boolean)}, and * {@link #startInput(IRemoteAccessibilityInputConnection, EditorInfo, boolean)}, * {@link #unbindInput()} are called with the same order as the original calls * and {@link #unbindInput()} are called with the same order as the original calls * in {@link com.android.server.inputmethod.InputMethodManagerService}. * in {@link com.android.server.inputmethod.InputMethodManagerService}. * See {@link IBinder#FLAG_ONEWAY} for detailed semantics.</p> * See {@link IBinder#FLAG_ONEWAY} for detailed semantics.</p> */ */ Loading Loading @@ -2927,7 +2887,7 @@ public abstract class AccessibilityService extends Service { } } /** This is called when an app requests ime sessions or when the service is enabled. */ /** This is called when an app requests ime sessions or when the service is enabled. */ public void createImeSession(IInputSessionWithIdCallback callback) { public void createImeSession(IAccessibilityInputMethodSessionCallback callback) { final Message message = mCaller.obtainMessageO(DO_CREATE_IME_SESSION, callback); final Message message = mCaller.obtainMessageO(DO_CREATE_IME_SESSION, callback); mCaller.sendMessage(message); mCaller.sendMessage(message); } } Loading @@ -2936,10 +2896,11 @@ public abstract class AccessibilityService extends Service { * This is called when InputMethodManagerService requests to set the session enabled or * This is called when InputMethodManagerService requests to set the session enabled or * disabled * disabled */ */ public void setImeSessionEnabled(IInputMethodSession session, boolean enabled) { public void setImeSessionEnabled(IAccessibilityInputMethodSession session, boolean enabled) { try { try { InputMethodSession ls = ((IInputMethodSessionWrapper) AccessibilityInputMethodSession ls = session).getInternalInputMethodSession(); ((AccessibilityInputMethodSessionWrapper) session).getSession(); if (ls == null) { if (ls == null) { Log.w(LOG_TAG, "Session is already finished: " + session); Log.w(LOG_TAG, "Session is already finished: " + session); return; return; Loading @@ -2952,17 +2913,11 @@ public abstract class AccessibilityService extends Service { } } /** This is called when an app binds input or when the service is enabled. */ /** This is called when an app binds input or when the service is enabled. */ public void bindInput(InputBinding binding) { public void bindInput() { if (mCancellationGroup != null) { if (mCancellationGroup != null) { Log.e(LOG_TAG, "bindInput must be paired with unbindInput."); Log.e(LOG_TAG, "bindInput must be paired with unbindInput."); } } mCancellationGroup = new CancellationGroup(); mCancellationGroup = new CancellationGroup(); InputConnection ic = new RemoteInputConnection(new WeakReference<>(() -> mContext), IInputContext.Stub.asInterface(binding.getConnectionToken()), mCancellationGroup); InputBinding nu = new InputBinding(ic, binding); final Message message = mCaller.obtainMessageO(DO_BIND_INPUT, nu); mCaller.sendMessage(message); } } /** This is called when an app unbinds input or when the service is disabled. */ /** This is called when an app unbinds input or when the service is disabled. */ Loading @@ -2974,18 +2929,17 @@ public abstract class AccessibilityService extends Service { } else { } else { Log.e(LOG_TAG, "unbindInput must be paired with bindInput."); Log.e(LOG_TAG, "unbindInput must be paired with bindInput."); } } mCaller.sendMessage(mCaller.obtainMessage(DO_UNBIND_INPUT)); } } /** This is called when an app starts input or when the service is enabled. */ /** This is called when an app starts input or when the service is enabled. */ public void startInput(IBinder startInputToken, IInputContext inputContext, public void startInput(IRemoteAccessibilityInputConnection connection, EditorInfo editorInfo, boolean restarting) { EditorInfo editorInfo, boolean restarting) { if (mCancellationGroup == null) { if (mCancellationGroup == null) { Log.e(LOG_TAG, "startInput must be called after bindInput."); Log.e(LOG_TAG, "startInput must be called after bindInput."); mCancellationGroup = new CancellationGroup(); mCancellationGroup = new CancellationGroup(); } } final Message message = mCaller.obtainMessageOOOOII(DO_START_INPUT, startInputToken, final Message message = mCaller.obtainMessageOOOOII(DO_START_INPUT, null /* unused */, inputContext, editorInfo, mCancellationGroup, restarting ? 1 : 0, connection, editorInfo, mCancellationGroup, restarting ? 1 : 0, 0 /* unused */); 0 /* unused */); mCaller.sendMessage(message); mCaller.sendMessage(message); } } Loading Loading @@ -3157,44 +3111,33 @@ public abstract class AccessibilityService extends Service { } } case DO_CREATE_IME_SESSION: { case DO_CREATE_IME_SESSION: { if (mConnectionId != AccessibilityInteractionClient.NO_ID) { if (mConnectionId != AccessibilityInteractionClient.NO_ID) { IInputSessionWithIdCallback callback = IAccessibilityInputMethodSessionCallback callback = (IInputSessionWithIdCallback) message.obj; (IAccessibilityInputMethodSessionCallback) message.obj; mCallback.createImeSession(callback); mCallback.createImeSession(callback); } } return; return; } } case DO_SET_IME_SESSION_ENABLED: { case DO_SET_IME_SESSION_ENABLED: { if (mConnectionId != AccessibilityInteractionClient.NO_ID) { if (mConnectionId != AccessibilityInteractionClient.NO_ID) { mCallback.setImeSessionEnabled((InputMethodSession) message.obj, AccessibilityInputMethodSession session = message.arg1 != 0); (AccessibilityInputMethodSession) message.obj; } session.setEnabled(message.arg1 != 0); return; } case DO_BIND_INPUT: { if (mConnectionId != AccessibilityInteractionClient.NO_ID) { mCallback.bindInput((InputBinding) message.obj); } return; } case DO_UNBIND_INPUT: { if (mConnectionId != AccessibilityInteractionClient.NO_ID) { mCallback.unbindInput(); } } return; return; } } case DO_START_INPUT: { case DO_START_INPUT: { if (mConnectionId != AccessibilityInteractionClient.NO_ID) { if (mConnectionId != AccessibilityInteractionClient.NO_ID) { final SomeArgs args = (SomeArgs) message.obj; final SomeArgs args = (SomeArgs) message.obj; final IBinder startInputToken = (IBinder) args.arg1; final IRemoteAccessibilityInputConnection connection = final IInputContext inputContext = (IInputContext) args.arg2; (IRemoteAccessibilityInputConnection) args.arg2; final EditorInfo info = (EditorInfo) args.arg3; final EditorInfo info = (EditorInfo) args.arg3; final CancellationGroup cancellationGroup = (CancellationGroup) args.arg4; final CancellationGroup cancellationGroup = (CancellationGroup) args.arg4; final boolean restarting = args.argi5 == 1; final boolean restarting = args.argi5 == 1; final InputConnection ic = inputContext != null final RemoteAccessibilityInputConnection ic = connection == null ? null ? new RemoteInputConnection(new WeakReference<>(() -> mContext), : new RemoteAccessibilityInputConnection( inputContext, cancellationGroup) : null; connection, cancellationGroup); info.makeCompatible(mContext.getApplicationInfo().targetSdkVersion); info.makeCompatible(mContext.getApplicationInfo().targetSdkVersion); mCallback.startInput(ic, info, restarting, startInputToken); mCallback.startInput(ic, info, restarting); args.recycle(); args.recycle(); } } return; return; Loading core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl +8 −9 Original line number Original line Diff line number Diff line Loading @@ -25,10 +25,9 @@ import android.accessibilityservice.MagnificationConfig; import android.view.KeyEvent; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.MotionEvent; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputBinding; import com.android.internal.inputmethod.IAccessibilityInputMethodSession; import com.android.internal.view.IInputContext; import com.android.internal.inputmethod.IAccessibilityInputMethodSessionCallback; import com.android.internal.view.IInputMethodSession; import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection; import com.android.internal.view.IInputSessionWithIdCallback; /** /** * Top-level interface to an accessibility service component. * Top-level interface to an accessibility service component. Loading Loading @@ -69,14 +68,14 @@ import com.android.internal.view.IInputSessionWithIdCallback; void onSystemActionsChanged(); void onSystemActionsChanged(); void createImeSession(IInputSessionWithIdCallback callback); void createImeSession(in IAccessibilityInputMethodSessionCallback callback); void setImeSessionEnabled(IInputMethodSession session, boolean enabled); void setImeSessionEnabled(in IAccessibilityInputMethodSession session, boolean enabled); void bindInput(in InputBinding binding); void bindInput(); void unbindInput(); void unbindInput(); void startInput(in IBinder startInputToken, in IInputContext inputContext, void startInput(in IRemoteAccessibilityInputConnection connection, in EditorInfo editorInfo, in EditorInfo editorInfo, boolean restarting); boolean restarting); } } core/java/android/accessibilityservice/InputMethod.java +35 −140 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/android/accessibilityservice/AccessibilityInputMethodSession.java 0 → 100644 +33 −0 Original line number Original line Diff line number Diff line /* * 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.accessibilityservice; import android.view.inputmethod.EditorInfo; import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection; interface AccessibilityInputMethodSession { void finishInput(); void updateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd); void invalidateInput(EditorInfo editorInfo, IRemoteAccessibilityInputConnection connection, int sessionId); void setEnabled(boolean enabled); }
core/java/android/accessibilityservice/AccessibilityInputMethodSessionWrapper.java 0 → 100644 +116 −0 Original line number Original line Diff line number Diff line /* * 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.accessibilityservice; import android.annotation.AnyThread; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Handler; import android.os.Looper; import android.view.inputmethod.EditorInfo; import com.android.internal.inputmethod.IAccessibilityInputMethodSession; import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection; import java.util.concurrent.atomic.AtomicReference; final class AccessibilityInputMethodSessionWrapper extends IAccessibilityInputMethodSession.Stub { private final Handler mHandler; @NonNull private final AtomicReference<AccessibilityInputMethodSession> mSessionRef; AccessibilityInputMethodSessionWrapper( @NonNull Looper looper, @NonNull AccessibilityInputMethodSession session) { mSessionRef = new AtomicReference<>(session); mHandler = Handler.createAsync(looper); } @AnyThread @Nullable AccessibilityInputMethodSession getSession() { return mSessionRef.get(); } @Override public void updateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd) { if (mHandler.getLooper().isCurrentThread()) { doUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd); } else { mHandler.post(() -> doUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd)); } } private void doUpdateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd) { final AccessibilityInputMethodSession session = mSessionRef.get(); if (session != null) { session.updateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd); } } @Override public void finishInput() { if (mHandler.getLooper().isCurrentThread()) { doFinishInput(); } else { mHandler.post(this::doFinishInput); } } private void doFinishInput() { final AccessibilityInputMethodSession session = mSessionRef.get(); if (session != null) { session.finishInput(); } } @Override public void finishSession() { if (mHandler.getLooper().isCurrentThread()) { doFinishSession(); } else { mHandler.post(this::doFinishSession); } } private void doFinishSession() { mSessionRef.set(null); } @Override public void invalidateInput(EditorInfo editorInfo, IRemoteAccessibilityInputConnection connection, int sessionId) { if (mHandler.getLooper().isCurrentThread()) { doInvalidateInput(editorInfo, connection, sessionId); } else { mHandler.post(() -> doInvalidateInput(editorInfo, connection, sessionId)); } } private void doInvalidateInput(EditorInfo editorInfo, IRemoteAccessibilityInputConnection connection, int sessionId) { final AccessibilityInputMethodSession session = mSessionRef.get(); if (session != null) { session.invalidateInput(editorInfo, connection, sessionId); } } }
core/java/android/accessibilityservice/AccessibilityService.java +38 −95 Original line number Original line Diff line number Diff line Loading @@ -40,8 +40,6 @@ import android.graphics.ParcelableColorSpace; import android.graphics.Region; import android.graphics.Region; import android.hardware.HardwareBuffer; import android.hardware.HardwareBuffer; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager; import android.inputmethodservice.IInputMethodSessionWrapper; import android.inputmethodservice.RemoteInputConnection; import android.os.Build; import android.os.Build; import android.os.Bundle; import android.os.Bundle; import android.os.Handler; import android.os.Handler; Loading @@ -68,22 +66,19 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.view.accessibility.AccessibilityWindowInfo; import android.view.accessibility.AccessibilityWindowInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputBinding; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodSession; import com.android.internal.inputmethod.CancellationGroup; import com.android.internal.inputmethod.CancellationGroup; import com.android.internal.inputmethod.IAccessibilityInputMethodSession; import com.android.internal.inputmethod.IAccessibilityInputMethodSessionCallback; import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection; import com.android.internal.inputmethod.RemoteAccessibilityInputConnection; import com.android.internal.os.HandlerCaller; import com.android.internal.os.HandlerCaller; import com.android.internal.os.SomeArgs; import com.android.internal.os.SomeArgs; import com.android.internal.util.Preconditions; import com.android.internal.util.Preconditions; import com.android.internal.util.function.pooled.PooledLambda; import com.android.internal.util.function.pooled.PooledLambda; import com.android.internal.view.IInputContext; import com.android.internal.view.IInputMethodSession; import com.android.internal.view.IInputSessionWithIdCallback; import java.lang.annotation.Retention; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.util.Collections; import java.util.Collections; import java.util.List; import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.Executor; Loading Loading @@ -639,20 +634,10 @@ public abstract class AccessibilityService extends Service { /** This is called when the system action list is changed. */ /** This is called when the system action list is changed. */ void onSystemActionsChanged(); void onSystemActionsChanged(); /** This is called when an app requests ime sessions or when the service is enabled. */ /** This is called when an app requests ime sessions or when the service is enabled. */ void createImeSession(IInputSessionWithIdCallback callback); void createImeSession(IAccessibilityInputMethodSessionCallback callback); /** * This is called when InputMethodManagerService requests to set the session enabled or * disabled */ void setImeSessionEnabled(InputMethodSession session, boolean enabled); /** This is called when an app binds input or when the service is enabled. */ void bindInput(InputBinding binding); /** This is called when an app unbinds input or when the service is disabled. */ void unbindInput(); /** This is called when an app starts input or when the service is enabled. */ /** This is called when an app starts input or when the service is enabled. */ void startInput(@Nullable InputConnection inputConnection, void startInput(@Nullable RemoteAccessibilityInputConnection inputConnection, @NonNull EditorInfo editorInfo, boolean restarting, @NonNull EditorInfo editorInfo, boolean restarting); @NonNull IBinder startInputToken); } } /** /** Loading Loading @@ -2740,42 +2725,20 @@ public abstract class AccessibilityService extends Service { } } @Override @Override public void createImeSession(IInputSessionWithIdCallback callback) { public void createImeSession(IAccessibilityInputMethodSessionCallback callback) { if (mInputMethod != null) { if (mInputMethod != null) { mInputMethod.createImeSession(callback); mInputMethod.createImeSession(callback); } } } } @Override @Override public void setImeSessionEnabled(InputMethodSession session, boolean enabled) { public void startInput(@Nullable RemoteAccessibilityInputConnection connection, if (mInputMethod != null) { @NonNull EditorInfo editorInfo, boolean restarting) { mInputMethod.setImeSessionEnabled(session, enabled); } } @Override public void bindInput(InputBinding binding) { if (mInputMethod != null) { mInputMethod.bindInput(binding); } } @Override public void unbindInput() { if (mInputMethod != null) { mInputMethod.unbindInput(); } } @Override public void startInput(@Nullable InputConnection inputConnection, @NonNull EditorInfo editorInfo, boolean restarting, @NonNull IBinder startInputToken) { if (mInputMethod != null) { if (mInputMethod != null) { if (restarting) { if (restarting) { mInputMethod.restartInput(inputConnection, editorInfo); mInputMethod.restartInput(connection, editorInfo); } else { } else { mInputMethod.startInput(inputConnection, editorInfo); mInputMethod.startInput(connection, editorInfo); } } } } } } Loading Loading @@ -2806,8 +2769,6 @@ public abstract class AccessibilityService extends Service { private static final int DO_ON_SYSTEM_ACTIONS_CHANGED = 14; private static final int DO_ON_SYSTEM_ACTIONS_CHANGED = 14; private static final int DO_CREATE_IME_SESSION = 15; private static final int DO_CREATE_IME_SESSION = 15; private static final int DO_SET_IME_SESSION_ENABLED = 16; private static final int DO_SET_IME_SESSION_ENABLED = 16; private static final int DO_BIND_INPUT = 17; private static final int DO_UNBIND_INPUT = 18; private static final int DO_START_INPUT = 19; private static final int DO_START_INPUT = 19; private final HandlerCaller mCaller; private final HandlerCaller mCaller; Loading @@ -2818,15 +2779,14 @@ public abstract class AccessibilityService extends Service { private int mConnectionId = AccessibilityInteractionClient.NO_ID; private int mConnectionId = AccessibilityInteractionClient.NO_ID; /** /** * This is not {@null} only between {@link #bindInput(InputBinding)} and * This is not {@code null} only between {@link #bindInput()} and {@link #unbindInput()} so * {@link #unbindInput()} so that {@link RemoteInputConnection} can query if * that {@link RemoteAccessibilityInputConnection} can query if {@link #unbindInput()} has * {@link #unbindInput()} has already been called or not, mainly to avoid unnecessary * already been called or not, mainly to avoid unnecessary blocking operations. * blocking operations. * * * <p>This field must be set and cleared only from the binder thread(s), where the system * <p>This field must be set and cleared only from the binder thread(s), where the system * guarantees that {@link #bindInput(InputBinding)}, * guarantees that {@link #bindInput()}, * {@link #startInput(IBinder, IInputContext, EditorInfo, boolean)}, and * {@link #startInput(IRemoteAccessibilityInputConnection, EditorInfo, boolean)}, * {@link #unbindInput()} are called with the same order as the original calls * and {@link #unbindInput()} are called with the same order as the original calls * in {@link com.android.server.inputmethod.InputMethodManagerService}. * in {@link com.android.server.inputmethod.InputMethodManagerService}. * See {@link IBinder#FLAG_ONEWAY} for detailed semantics.</p> * See {@link IBinder#FLAG_ONEWAY} for detailed semantics.</p> */ */ Loading Loading @@ -2927,7 +2887,7 @@ public abstract class AccessibilityService extends Service { } } /** This is called when an app requests ime sessions or when the service is enabled. */ /** This is called when an app requests ime sessions or when the service is enabled. */ public void createImeSession(IInputSessionWithIdCallback callback) { public void createImeSession(IAccessibilityInputMethodSessionCallback callback) { final Message message = mCaller.obtainMessageO(DO_CREATE_IME_SESSION, callback); final Message message = mCaller.obtainMessageO(DO_CREATE_IME_SESSION, callback); mCaller.sendMessage(message); mCaller.sendMessage(message); } } Loading @@ -2936,10 +2896,11 @@ public abstract class AccessibilityService extends Service { * This is called when InputMethodManagerService requests to set the session enabled or * This is called when InputMethodManagerService requests to set the session enabled or * disabled * disabled */ */ public void setImeSessionEnabled(IInputMethodSession session, boolean enabled) { public void setImeSessionEnabled(IAccessibilityInputMethodSession session, boolean enabled) { try { try { InputMethodSession ls = ((IInputMethodSessionWrapper) AccessibilityInputMethodSession ls = session).getInternalInputMethodSession(); ((AccessibilityInputMethodSessionWrapper) session).getSession(); if (ls == null) { if (ls == null) { Log.w(LOG_TAG, "Session is already finished: " + session); Log.w(LOG_TAG, "Session is already finished: " + session); return; return; Loading @@ -2952,17 +2913,11 @@ public abstract class AccessibilityService extends Service { } } /** This is called when an app binds input or when the service is enabled. */ /** This is called when an app binds input or when the service is enabled. */ public void bindInput(InputBinding binding) { public void bindInput() { if (mCancellationGroup != null) { if (mCancellationGroup != null) { Log.e(LOG_TAG, "bindInput must be paired with unbindInput."); Log.e(LOG_TAG, "bindInput must be paired with unbindInput."); } } mCancellationGroup = new CancellationGroup(); mCancellationGroup = new CancellationGroup(); InputConnection ic = new RemoteInputConnection(new WeakReference<>(() -> mContext), IInputContext.Stub.asInterface(binding.getConnectionToken()), mCancellationGroup); InputBinding nu = new InputBinding(ic, binding); final Message message = mCaller.obtainMessageO(DO_BIND_INPUT, nu); mCaller.sendMessage(message); } } /** This is called when an app unbinds input or when the service is disabled. */ /** This is called when an app unbinds input or when the service is disabled. */ Loading @@ -2974,18 +2929,17 @@ public abstract class AccessibilityService extends Service { } else { } else { Log.e(LOG_TAG, "unbindInput must be paired with bindInput."); Log.e(LOG_TAG, "unbindInput must be paired with bindInput."); } } mCaller.sendMessage(mCaller.obtainMessage(DO_UNBIND_INPUT)); } } /** This is called when an app starts input or when the service is enabled. */ /** This is called when an app starts input or when the service is enabled. */ public void startInput(IBinder startInputToken, IInputContext inputContext, public void startInput(IRemoteAccessibilityInputConnection connection, EditorInfo editorInfo, boolean restarting) { EditorInfo editorInfo, boolean restarting) { if (mCancellationGroup == null) { if (mCancellationGroup == null) { Log.e(LOG_TAG, "startInput must be called after bindInput."); Log.e(LOG_TAG, "startInput must be called after bindInput."); mCancellationGroup = new CancellationGroup(); mCancellationGroup = new CancellationGroup(); } } final Message message = mCaller.obtainMessageOOOOII(DO_START_INPUT, startInputToken, final Message message = mCaller.obtainMessageOOOOII(DO_START_INPUT, null /* unused */, inputContext, editorInfo, mCancellationGroup, restarting ? 1 : 0, connection, editorInfo, mCancellationGroup, restarting ? 1 : 0, 0 /* unused */); 0 /* unused */); mCaller.sendMessage(message); mCaller.sendMessage(message); } } Loading Loading @@ -3157,44 +3111,33 @@ public abstract class AccessibilityService extends Service { } } case DO_CREATE_IME_SESSION: { case DO_CREATE_IME_SESSION: { if (mConnectionId != AccessibilityInteractionClient.NO_ID) { if (mConnectionId != AccessibilityInteractionClient.NO_ID) { IInputSessionWithIdCallback callback = IAccessibilityInputMethodSessionCallback callback = (IInputSessionWithIdCallback) message.obj; (IAccessibilityInputMethodSessionCallback) message.obj; mCallback.createImeSession(callback); mCallback.createImeSession(callback); } } return; return; } } case DO_SET_IME_SESSION_ENABLED: { case DO_SET_IME_SESSION_ENABLED: { if (mConnectionId != AccessibilityInteractionClient.NO_ID) { if (mConnectionId != AccessibilityInteractionClient.NO_ID) { mCallback.setImeSessionEnabled((InputMethodSession) message.obj, AccessibilityInputMethodSession session = message.arg1 != 0); (AccessibilityInputMethodSession) message.obj; } session.setEnabled(message.arg1 != 0); return; } case DO_BIND_INPUT: { if (mConnectionId != AccessibilityInteractionClient.NO_ID) { mCallback.bindInput((InputBinding) message.obj); } return; } case DO_UNBIND_INPUT: { if (mConnectionId != AccessibilityInteractionClient.NO_ID) { mCallback.unbindInput(); } } return; return; } } case DO_START_INPUT: { case DO_START_INPUT: { if (mConnectionId != AccessibilityInteractionClient.NO_ID) { if (mConnectionId != AccessibilityInteractionClient.NO_ID) { final SomeArgs args = (SomeArgs) message.obj; final SomeArgs args = (SomeArgs) message.obj; final IBinder startInputToken = (IBinder) args.arg1; final IRemoteAccessibilityInputConnection connection = final IInputContext inputContext = (IInputContext) args.arg2; (IRemoteAccessibilityInputConnection) args.arg2; final EditorInfo info = (EditorInfo) args.arg3; final EditorInfo info = (EditorInfo) args.arg3; final CancellationGroup cancellationGroup = (CancellationGroup) args.arg4; final CancellationGroup cancellationGroup = (CancellationGroup) args.arg4; final boolean restarting = args.argi5 == 1; final boolean restarting = args.argi5 == 1; final InputConnection ic = inputContext != null final RemoteAccessibilityInputConnection ic = connection == null ? null ? new RemoteInputConnection(new WeakReference<>(() -> mContext), : new RemoteAccessibilityInputConnection( inputContext, cancellationGroup) : null; connection, cancellationGroup); info.makeCompatible(mContext.getApplicationInfo().targetSdkVersion); info.makeCompatible(mContext.getApplicationInfo().targetSdkVersion); mCallback.startInput(ic, info, restarting, startInputToken); mCallback.startInput(ic, info, restarting); args.recycle(); args.recycle(); } } return; return; Loading
core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl +8 −9 Original line number Original line Diff line number Diff line Loading @@ -25,10 +25,9 @@ import android.accessibilityservice.MagnificationConfig; import android.view.KeyEvent; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.MotionEvent; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputBinding; import com.android.internal.inputmethod.IAccessibilityInputMethodSession; import com.android.internal.view.IInputContext; import com.android.internal.inputmethod.IAccessibilityInputMethodSessionCallback; import com.android.internal.view.IInputMethodSession; import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection; import com.android.internal.view.IInputSessionWithIdCallback; /** /** * Top-level interface to an accessibility service component. * Top-level interface to an accessibility service component. Loading Loading @@ -69,14 +68,14 @@ import com.android.internal.view.IInputSessionWithIdCallback; void onSystemActionsChanged(); void onSystemActionsChanged(); void createImeSession(IInputSessionWithIdCallback callback); void createImeSession(in IAccessibilityInputMethodSessionCallback callback); void setImeSessionEnabled(IInputMethodSession session, boolean enabled); void setImeSessionEnabled(in IAccessibilityInputMethodSession session, boolean enabled); void bindInput(in InputBinding binding); void bindInput(); void unbindInput(); void unbindInput(); void startInput(in IBinder startInputToken, in IInputContext inputContext, void startInput(in IRemoteAccessibilityInputConnection connection, in EditorInfo editorInfo, in EditorInfo editorInfo, boolean restarting); boolean restarting); } }
core/java/android/accessibilityservice/InputMethod.java +35 −140 File changed.Preview size limit exceeded, changes collapsed. Show changes