Loading core/java/android/accessibilityservice/AccessibilityService.java +24 −9 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package android.accessibilityservice; import com.android.internal.os.HandlerCaller; import android.app.Service; import android.content.Intent; import android.os.IBinder; Loading @@ -25,8 +23,11 @@ import android.os.Message; import android.os.RemoteException; import android.util.Log; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityInteractionClient; import android.view.accessibility.AccessibilityNodeInfo; import com.android.internal.os.HandlerCaller; /** * An accessibility service runs in the background and receives callbacks by the system * when {@link AccessibilityEvent}s are fired. Such events denote some state transition Loading Loading @@ -219,7 +220,7 @@ public abstract class AccessibilityService extends Service { private AccessibilityServiceInfo mInfo; IAccessibilityServiceConnection mConnection; private int mConnectionId; /** * Callback for {@link android.view.accessibility.AccessibilityEvent}s. Loading Loading @@ -264,9 +265,11 @@ public abstract class AccessibilityService extends Service { * AccessibilityManagerService. */ private void sendServiceInfo() { if (mInfo != null && mConnection != null) { IAccessibilityServiceConnection connection = AccessibilityInteractionClient.getInstance().getConnection(mConnectionId); if (mInfo != null && connection != null) { try { mConnection.setServiceInfo(mInfo); connection.setServiceInfo(mInfo); } catch (RemoteException re) { Log.w(LOG_TAG, "Error while setting AccessibilityServiceInfo", re); } Loading Loading @@ -302,8 +305,9 @@ public abstract class AccessibilityService extends Service { mCaller = new HandlerCaller(context, this); } public void setConnection(IAccessibilityServiceConnection connection) { Message message = mCaller.obtainMessageO(DO_SET_SET_CONNECTION, connection); public void setConnection(IAccessibilityServiceConnection connection, int connectionId) { Message message = mCaller.obtainMessageIO(DO_SET_SET_CONNECTION, connectionId, connection); mCaller.sendMessage(message); } Loading @@ -330,8 +334,19 @@ public abstract class AccessibilityService extends Service { mTarget.onInterrupt(); return; case DO_SET_SET_CONNECTION : mConnection = ((IAccessibilityServiceConnection) message.obj); final int connectionId = message.arg1; IAccessibilityServiceConnection connection = (IAccessibilityServiceConnection) message.obj; if (connection != null) { AccessibilityInteractionClient.getInstance().addConnection(connectionId, connection); mConnectionId = connectionId; mTarget.onServiceConnected(); } else { AccessibilityInteractionClient.getInstance().removeConnection(connectionId); mConnectionId = AccessibilityInteractionClient.NO_ID; // TODO: Do we need a onServiceDisconnected callback? } return; default : Log.w(LOG_TAG, "Unknown message type " + message.what); Loading core/java/android/accessibilityservice/IEventListener.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ import android.view.accessibility.AccessibilityEvent; */ oneway interface IEventListener { void setConnection(in IAccessibilityServiceConnection connection); void setConnection(in IAccessibilityServiceConnection connection, int connectionId); void onAccessibilityEvent(in AccessibilityEvent event); Loading core/java/android/util/SparseArray.java +1 −0 Original line number Diff line number Diff line Loading @@ -134,6 +134,7 @@ public class SparseArray<E> implements Cloneable { if (i != o) { keys[o] = keys[i]; values[o] = val; values[i] = null; } o++; Loading core/java/android/view/accessibility/AccessibilityEvent.java +4 −32 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package android.view.accessibility; import android.accessibilityservice.IAccessibilityServiceConnection; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; Loading Loading @@ -589,24 +588,6 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par mPackageName = event.mPackageName; } /** * Sets the connection for interacting with the AccessibilityManagerService. * * @param connection The connection. * * @hide */ @Override public void setConnection(IAccessibilityServiceConnection connection) { super.setConnection(connection); List<AccessibilityRecord> records = mRecords; final int recordCount = records.size(); for (int i = 0; i < recordCount; i++) { AccessibilityRecord record = records.get(i); record.setConnection(connection); } } /** * Sets if this instance is sealed. * Loading Loading @@ -821,23 +802,19 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par * @param parcel A parcel containing the state of a {@link AccessibilityEvent}. */ public void initFromParcel(Parcel parcel) { if (parcel.readInt() == 1) { mConnection = IAccessibilityServiceConnection.Stub.asInterface( parcel.readStrongBinder()); } setSealed(parcel.readInt() == 1); mSealed = (parcel.readInt() == 1); mEventType = parcel.readInt(); mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); mEventTime = parcel.readLong(); mConnectionId = parcel.readInt(); readAccessibilityRecordFromParcel(this, parcel); // Read the records. final int recordCount = parcel.readInt(); for (int i = 0; i < recordCount; i++) { AccessibilityRecord record = AccessibilityRecord.obtain(); // Do this to write the connection only once. record.setConnection(mConnection); readAccessibilityRecordFromParcel(record, parcel); record.mConnectionId = mConnectionId; mRecords.add(record); } } Loading Loading @@ -875,16 +852,11 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par * {@inheritDoc} */ public void writeToParcel(Parcel parcel, int flags) { if (mConnection == null) { parcel.writeInt(0); } else { parcel.writeInt(1); parcel.writeStrongBinder(mConnection.asBinder()); } parcel.writeInt(isSealed() ? 1 : 0); parcel.writeInt(mEventType); TextUtils.writeToParcel(mPackageName, parcel, 0); parcel.writeLong(mEventTime); parcel.writeInt(mConnectionId); writeAccessibilityRecordToParcel(this, parcel, flags); // Write the records. Loading core/java/android/view/accessibility/AccessibilityInteractionClient.java +167 −72 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ import android.graphics.Rect; import android.os.Message; import android.os.RemoteException; import android.os.SystemClock; import android.util.Log; import android.util.SparseArray; import java.util.Collections; import java.util.List; Loading Loading @@ -61,6 +63,12 @@ import java.util.concurrent.atomic.AtomicInteger; public final class AccessibilityInteractionClient extends IAccessibilityInteractionConnectionCallback.Stub { public static final int NO_ID = -1; private static final String LOG_TAG = "AccessibilityInteractionClient"; private static final boolean DEBUG = false; private static final long TIMEOUT_INTERACTION_MILLIS = 5000; private static final Object sStaticLock = new Object(); Loading @@ -83,6 +91,9 @@ public final class AccessibilityInteractionClient private final Rect mTempBounds = new Rect(); private final SparseArray<IAccessibilityServiceConnection> mConnectionCache = new SparseArray<IAccessibilityServiceConnection>(); /** * @return The singleton of this class. */ Loading Loading @@ -111,15 +122,16 @@ public final class AccessibilityInteractionClient /** * Finds an {@link AccessibilityNodeInfo} by accessibility id. * * @param connection A connection for interacting with the system. * @param connectionId The id of a connection for interacting with the system. * @param accessibilityWindowId A unique window id. * @param accessibilityViewId A unique View accessibility id. * @return An {@link AccessibilityNodeInfo} if found, null otherwise. */ public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId( IAccessibilityServiceConnection connection, int accessibilityWindowId, int accessibilityViewId) { public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(int connectionId, int accessibilityWindowId, int accessibilityViewId) { try { IAccessibilityServiceConnection connection = getConnection(connectionId); if (connection != null) { final int interactionId = mInteractionIdCounter.getAndIncrement(); final float windowScale = connection.findAccessibilityNodeInfoByAccessibilityId( accessibilityWindowId, accessibilityViewId, interactionId, this, Loading @@ -128,11 +140,19 @@ public final class AccessibilityInteractionClient if (windowScale > 0) { AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear( interactionId); finalizeAccessibilityNodeInfo(info, connection, windowScale); finalizeAccessibilityNodeInfo(info, connectionId, windowScale); return info; } } else { if (DEBUG) { Log.w(LOG_TAG, "No connection for connection id: " + connectionId); } } } catch (RemoteException re) { /* ignore */ if (DEBUG) { Log.w(LOG_TAG, "Error while calling remote" + " findAccessibilityNodeInfoByAccessibilityId", re); } } return null; } Loading @@ -141,25 +161,36 @@ public final class AccessibilityInteractionClient * Finds an {@link AccessibilityNodeInfo} by View id. The search is performed * in the currently active window and starts from the root View in the window. * * @param connection A connection for interacting with the system. * @param connectionId The id of a connection for interacting with the system. * @param viewId The id of the view. * @return An {@link AccessibilityNodeInfo} if found, null otherwise. */ public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow( IAccessibilityServiceConnection connection, int viewId) { public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(int connectionId, int viewId) { try { IAccessibilityServiceConnection connection = getConnection(connectionId); if (connection != null) { final int interactionId = mInteractionIdCounter.getAndIncrement(); final float windowScale = connection.findAccessibilityNodeInfoByViewIdInActiveWindow( viewId, interactionId, this, Thread.currentThread().getId()); final float windowScale = connection.findAccessibilityNodeInfoByViewIdInActiveWindow(viewId, interactionId, this, Thread.currentThread().getId()); // If the scale is zero the call has failed. if (windowScale > 0) { AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear( interactionId); finalizeAccessibilityNodeInfo(info, connection, windowScale); finalizeAccessibilityNodeInfo(info, connectionId, windowScale); return info; } } else { if (DEBUG) { Log.w(LOG_TAG, "No connection for connection id: " + connectionId); } } } catch (RemoteException re) { /* ignore */ if (DEBUG) { Log.w(LOG_TAG, "Error while calling remote" + " findAccessibilityNodeInfoByViewIdInActiveWindow", re); } } return null; } Loading @@ -169,25 +200,36 @@ public final class AccessibilityInteractionClient * insensitive containment. The search is performed in the currently * active window and starts from the root View in the window. * * @param connection A connection for interacting with the system. * @param connectionId The id of a connection for interacting with the system. * @param text The searched text. * @return A list of found {@link AccessibilityNodeInfo}s. */ public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewTextInActiveWindow( IAccessibilityServiceConnection connection, String text) { int connectionId, String text) { try { IAccessibilityServiceConnection connection = getConnection(connectionId); if (connection != null) { final int interactionId = mInteractionIdCounter.getAndIncrement(); final float windowScale = connection.findAccessibilityNodeInfosByViewTextInActiveWindow( text, interactionId, this, Thread.currentThread().getId()); final float windowScale = connection.findAccessibilityNodeInfosByViewTextInActiveWindow(text, interactionId, this, Thread.currentThread().getId()); // If the scale is zero the call has failed. if (windowScale > 0) { List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear( interactionId); finalizeAccessibilityNodeInfos(infos, connection, windowScale); finalizeAccessibilityNodeInfos(infos, connectionId, windowScale); return infos; } } else { if (DEBUG) { Log.w(LOG_TAG, "No connection for connection id: " + connectionId); } } } catch (RemoteException re) { /* ignore */ if (DEBUG) { Log.w(LOG_TAG, "Error while calling remote" + " findAccessibilityNodeInfosByViewTextInActiveWindow", re); } } return null; } Loading @@ -198,17 +240,18 @@ public final class AccessibilityInteractionClient * id is specified and starts from the View whose accessibility id is * specified. * * @param connection A connection for interacting with the system. * @param connectionId The id of a connection for interacting with the system. * @param text The searched text. * @param accessibilityWindowId A unique window id. * @param accessibilityViewId A unique View accessibility id from where to start the search. * Use {@link android.view.View#NO_ID} to start from the root. * @return A list of found {@link AccessibilityNodeInfo}s. */ public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText( IAccessibilityServiceConnection connection, String text, int accessibilityWindowId, int accessibilityViewId) { public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText(int connectionId, String text, int accessibilityWindowId, int accessibilityViewId) { try { IAccessibilityServiceConnection connection = getConnection(connectionId); if (connection != null) { final int interactionId = mInteractionIdCounter.getAndIncrement(); final float windowScale = connection.findAccessibilityNodeInfosByViewText(text, accessibilityWindowId, accessibilityViewId, interactionId, this, Loading @@ -217,11 +260,19 @@ public final class AccessibilityInteractionClient if (windowScale > 0) { List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear( interactionId); finalizeAccessibilityNodeInfos(infos, connection, windowScale); finalizeAccessibilityNodeInfos(infos, connectionId, windowScale); return infos; } } else { if (DEBUG) { Log.w(LOG_TAG, "No connection for connection id: " + connectionId); } } } catch (RemoteException re) { /* ignore */ if (DEBUG) { Log.w(LOG_TAG, "Error while calling remote" + " findAccessibilityNodeInfosByViewText", re); } } return Collections.emptyList(); } Loading @@ -229,15 +280,17 @@ public final class AccessibilityInteractionClient /** * Performs an accessibility action on an {@link AccessibilityNodeInfo}. * * @param connection A connection for interacting with the system. * @param connectionId The id of a connection for interacting with the system. * @param accessibilityWindowId The id of the window. * @param accessibilityViewId A unique View accessibility id. * @param action The action to perform. * @return Whether the action was performed. */ public boolean performAccessibilityAction(IAccessibilityServiceConnection connection, int accessibilityWindowId, int accessibilityViewId, int action) { public boolean performAccessibilityAction(int connectionId, int accessibilityWindowId, int accessibilityViewId, int action) { try { IAccessibilityServiceConnection connection = getConnection(connectionId); if (connection != null) { final int interactionId = mInteractionIdCounter.getAndIncrement(); final boolean success = connection.performAccessibilityAction( accessibilityWindowId, accessibilityViewId, action, interactionId, this, Loading @@ -245,8 +298,15 @@ public final class AccessibilityInteractionClient if (success) { return getPerformAccessibilityActionResult(interactionId); } } else { if (DEBUG) { Log.w(LOG_TAG, "No connection for connection id: " + connectionId); } } } catch (RemoteException re) { /* ignore */ if (DEBUG) { Log.w(LOG_TAG, "Error while calling remote performAccessibilityAction", re); } } return false; } Loading Loading @@ -406,14 +466,14 @@ public final class AccessibilityInteractionClient * Finalize an {@link AccessibilityNodeInfo} before passing it to the client. * * @param info The info. * @param connection The current connection to the system. * @param connectionId The id of the connection to the system. * @param windowScale The source window compatibility scale. */ private void finalizeAccessibilityNodeInfo(AccessibilityNodeInfo info, IAccessibilityServiceConnection connection, float windowScale) { private void finalizeAccessibilityNodeInfo(AccessibilityNodeInfo info, int connectionId, float windowScale) { if (info != null) { applyCompatibilityScaleIfNeeded(info, windowScale); info.setConnection(connection); info.setConnectionId(connectionId); info.setSealed(true); } } Loading @@ -422,16 +482,16 @@ public final class AccessibilityInteractionClient * Finalize {@link AccessibilityNodeInfo}s before passing them to the client. * * @param infos The {@link AccessibilityNodeInfo}s. * @param connection The current connection to the system. * @param connectionId The id of the connection to the system. * @param windowScale The source window compatibility scale. */ private void finalizeAccessibilityNodeInfos(List<AccessibilityNodeInfo> infos, IAccessibilityServiceConnection connection, float windowScale) { int connectionId, float windowScale) { if (infos != null) { final int infosCount = infos.size(); for (int i = 0; i < infosCount; i++) { AccessibilityNodeInfo info = infos.get(i); finalizeAccessibilityNodeInfo(info, connection, windowScale); finalizeAccessibilityNodeInfo(info, connectionId, windowScale); } } } Loading @@ -449,4 +509,39 @@ public final class AccessibilityInteractionClient return result; } } /** * Gets a cached accessibility service connection. * * @param connectionId The connection id. * @return The cached connection if such. */ public IAccessibilityServiceConnection getConnection(int connectionId) { synchronized (mConnectionCache) { return mConnectionCache.get(connectionId); } } /** * Adds a cached accessibility service connection. * * @param connectionId The connection id. * @param connection The connection. */ public void addConnection(int connectionId, IAccessibilityServiceConnection connection) { synchronized (mConnectionCache) { mConnectionCache.put(connectionId, connection); } } /** * Removes a cached accessibility service connection. * * @param connectionId The connection id. */ public void removeConnection(int connectionId) { synchronized (mConnectionCache) { mConnectionCache.remove(connectionId); } } } Loading
core/java/android/accessibilityservice/AccessibilityService.java +24 −9 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package android.accessibilityservice; import com.android.internal.os.HandlerCaller; import android.app.Service; import android.content.Intent; import android.os.IBinder; Loading @@ -25,8 +23,11 @@ import android.os.Message; import android.os.RemoteException; import android.util.Log; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityInteractionClient; import android.view.accessibility.AccessibilityNodeInfo; import com.android.internal.os.HandlerCaller; /** * An accessibility service runs in the background and receives callbacks by the system * when {@link AccessibilityEvent}s are fired. Such events denote some state transition Loading Loading @@ -219,7 +220,7 @@ public abstract class AccessibilityService extends Service { private AccessibilityServiceInfo mInfo; IAccessibilityServiceConnection mConnection; private int mConnectionId; /** * Callback for {@link android.view.accessibility.AccessibilityEvent}s. Loading Loading @@ -264,9 +265,11 @@ public abstract class AccessibilityService extends Service { * AccessibilityManagerService. */ private void sendServiceInfo() { if (mInfo != null && mConnection != null) { IAccessibilityServiceConnection connection = AccessibilityInteractionClient.getInstance().getConnection(mConnectionId); if (mInfo != null && connection != null) { try { mConnection.setServiceInfo(mInfo); connection.setServiceInfo(mInfo); } catch (RemoteException re) { Log.w(LOG_TAG, "Error while setting AccessibilityServiceInfo", re); } Loading Loading @@ -302,8 +305,9 @@ public abstract class AccessibilityService extends Service { mCaller = new HandlerCaller(context, this); } public void setConnection(IAccessibilityServiceConnection connection) { Message message = mCaller.obtainMessageO(DO_SET_SET_CONNECTION, connection); public void setConnection(IAccessibilityServiceConnection connection, int connectionId) { Message message = mCaller.obtainMessageIO(DO_SET_SET_CONNECTION, connectionId, connection); mCaller.sendMessage(message); } Loading @@ -330,8 +334,19 @@ public abstract class AccessibilityService extends Service { mTarget.onInterrupt(); return; case DO_SET_SET_CONNECTION : mConnection = ((IAccessibilityServiceConnection) message.obj); final int connectionId = message.arg1; IAccessibilityServiceConnection connection = (IAccessibilityServiceConnection) message.obj; if (connection != null) { AccessibilityInteractionClient.getInstance().addConnection(connectionId, connection); mConnectionId = connectionId; mTarget.onServiceConnected(); } else { AccessibilityInteractionClient.getInstance().removeConnection(connectionId); mConnectionId = AccessibilityInteractionClient.NO_ID; // TODO: Do we need a onServiceDisconnected callback? } return; default : Log.w(LOG_TAG, "Unknown message type " + message.what); Loading
core/java/android/accessibilityservice/IEventListener.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ import android.view.accessibility.AccessibilityEvent; */ oneway interface IEventListener { void setConnection(in IAccessibilityServiceConnection connection); void setConnection(in IAccessibilityServiceConnection connection, int connectionId); void onAccessibilityEvent(in AccessibilityEvent event); Loading
core/java/android/util/SparseArray.java +1 −0 Original line number Diff line number Diff line Loading @@ -134,6 +134,7 @@ public class SparseArray<E> implements Cloneable { if (i != o) { keys[o] = keys[i]; values[o] = val; values[i] = null; } o++; Loading
core/java/android/view/accessibility/AccessibilityEvent.java +4 −32 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package android.view.accessibility; import android.accessibilityservice.IAccessibilityServiceConnection; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; Loading Loading @@ -589,24 +588,6 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par mPackageName = event.mPackageName; } /** * Sets the connection for interacting with the AccessibilityManagerService. * * @param connection The connection. * * @hide */ @Override public void setConnection(IAccessibilityServiceConnection connection) { super.setConnection(connection); List<AccessibilityRecord> records = mRecords; final int recordCount = records.size(); for (int i = 0; i < recordCount; i++) { AccessibilityRecord record = records.get(i); record.setConnection(connection); } } /** * Sets if this instance is sealed. * Loading Loading @@ -821,23 +802,19 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par * @param parcel A parcel containing the state of a {@link AccessibilityEvent}. */ public void initFromParcel(Parcel parcel) { if (parcel.readInt() == 1) { mConnection = IAccessibilityServiceConnection.Stub.asInterface( parcel.readStrongBinder()); } setSealed(parcel.readInt() == 1); mSealed = (parcel.readInt() == 1); mEventType = parcel.readInt(); mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); mEventTime = parcel.readLong(); mConnectionId = parcel.readInt(); readAccessibilityRecordFromParcel(this, parcel); // Read the records. final int recordCount = parcel.readInt(); for (int i = 0; i < recordCount; i++) { AccessibilityRecord record = AccessibilityRecord.obtain(); // Do this to write the connection only once. record.setConnection(mConnection); readAccessibilityRecordFromParcel(record, parcel); record.mConnectionId = mConnectionId; mRecords.add(record); } } Loading Loading @@ -875,16 +852,11 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par * {@inheritDoc} */ public void writeToParcel(Parcel parcel, int flags) { if (mConnection == null) { parcel.writeInt(0); } else { parcel.writeInt(1); parcel.writeStrongBinder(mConnection.asBinder()); } parcel.writeInt(isSealed() ? 1 : 0); parcel.writeInt(mEventType); TextUtils.writeToParcel(mPackageName, parcel, 0); parcel.writeLong(mEventTime); parcel.writeInt(mConnectionId); writeAccessibilityRecordToParcel(this, parcel, flags); // Write the records. Loading
core/java/android/view/accessibility/AccessibilityInteractionClient.java +167 −72 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ import android.graphics.Rect; import android.os.Message; import android.os.RemoteException; import android.os.SystemClock; import android.util.Log; import android.util.SparseArray; import java.util.Collections; import java.util.List; Loading Loading @@ -61,6 +63,12 @@ import java.util.concurrent.atomic.AtomicInteger; public final class AccessibilityInteractionClient extends IAccessibilityInteractionConnectionCallback.Stub { public static final int NO_ID = -1; private static final String LOG_TAG = "AccessibilityInteractionClient"; private static final boolean DEBUG = false; private static final long TIMEOUT_INTERACTION_MILLIS = 5000; private static final Object sStaticLock = new Object(); Loading @@ -83,6 +91,9 @@ public final class AccessibilityInteractionClient private final Rect mTempBounds = new Rect(); private final SparseArray<IAccessibilityServiceConnection> mConnectionCache = new SparseArray<IAccessibilityServiceConnection>(); /** * @return The singleton of this class. */ Loading Loading @@ -111,15 +122,16 @@ public final class AccessibilityInteractionClient /** * Finds an {@link AccessibilityNodeInfo} by accessibility id. * * @param connection A connection for interacting with the system. * @param connectionId The id of a connection for interacting with the system. * @param accessibilityWindowId A unique window id. * @param accessibilityViewId A unique View accessibility id. * @return An {@link AccessibilityNodeInfo} if found, null otherwise. */ public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId( IAccessibilityServiceConnection connection, int accessibilityWindowId, int accessibilityViewId) { public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId(int connectionId, int accessibilityWindowId, int accessibilityViewId) { try { IAccessibilityServiceConnection connection = getConnection(connectionId); if (connection != null) { final int interactionId = mInteractionIdCounter.getAndIncrement(); final float windowScale = connection.findAccessibilityNodeInfoByAccessibilityId( accessibilityWindowId, accessibilityViewId, interactionId, this, Loading @@ -128,11 +140,19 @@ public final class AccessibilityInteractionClient if (windowScale > 0) { AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear( interactionId); finalizeAccessibilityNodeInfo(info, connection, windowScale); finalizeAccessibilityNodeInfo(info, connectionId, windowScale); return info; } } else { if (DEBUG) { Log.w(LOG_TAG, "No connection for connection id: " + connectionId); } } } catch (RemoteException re) { /* ignore */ if (DEBUG) { Log.w(LOG_TAG, "Error while calling remote" + " findAccessibilityNodeInfoByAccessibilityId", re); } } return null; } Loading @@ -141,25 +161,36 @@ public final class AccessibilityInteractionClient * Finds an {@link AccessibilityNodeInfo} by View id. The search is performed * in the currently active window and starts from the root View in the window. * * @param connection A connection for interacting with the system. * @param connectionId The id of a connection for interacting with the system. * @param viewId The id of the view. * @return An {@link AccessibilityNodeInfo} if found, null otherwise. */ public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow( IAccessibilityServiceConnection connection, int viewId) { public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(int connectionId, int viewId) { try { IAccessibilityServiceConnection connection = getConnection(connectionId); if (connection != null) { final int interactionId = mInteractionIdCounter.getAndIncrement(); final float windowScale = connection.findAccessibilityNodeInfoByViewIdInActiveWindow( viewId, interactionId, this, Thread.currentThread().getId()); final float windowScale = connection.findAccessibilityNodeInfoByViewIdInActiveWindow(viewId, interactionId, this, Thread.currentThread().getId()); // If the scale is zero the call has failed. if (windowScale > 0) { AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear( interactionId); finalizeAccessibilityNodeInfo(info, connection, windowScale); finalizeAccessibilityNodeInfo(info, connectionId, windowScale); return info; } } else { if (DEBUG) { Log.w(LOG_TAG, "No connection for connection id: " + connectionId); } } } catch (RemoteException re) { /* ignore */ if (DEBUG) { Log.w(LOG_TAG, "Error while calling remote" + " findAccessibilityNodeInfoByViewIdInActiveWindow", re); } } return null; } Loading @@ -169,25 +200,36 @@ public final class AccessibilityInteractionClient * insensitive containment. The search is performed in the currently * active window and starts from the root View in the window. * * @param connection A connection for interacting with the system. * @param connectionId The id of a connection for interacting with the system. * @param text The searched text. * @return A list of found {@link AccessibilityNodeInfo}s. */ public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewTextInActiveWindow( IAccessibilityServiceConnection connection, String text) { int connectionId, String text) { try { IAccessibilityServiceConnection connection = getConnection(connectionId); if (connection != null) { final int interactionId = mInteractionIdCounter.getAndIncrement(); final float windowScale = connection.findAccessibilityNodeInfosByViewTextInActiveWindow( text, interactionId, this, Thread.currentThread().getId()); final float windowScale = connection.findAccessibilityNodeInfosByViewTextInActiveWindow(text, interactionId, this, Thread.currentThread().getId()); // If the scale is zero the call has failed. if (windowScale > 0) { List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear( interactionId); finalizeAccessibilityNodeInfos(infos, connection, windowScale); finalizeAccessibilityNodeInfos(infos, connectionId, windowScale); return infos; } } else { if (DEBUG) { Log.w(LOG_TAG, "No connection for connection id: " + connectionId); } } } catch (RemoteException re) { /* ignore */ if (DEBUG) { Log.w(LOG_TAG, "Error while calling remote" + " findAccessibilityNodeInfosByViewTextInActiveWindow", re); } } return null; } Loading @@ -198,17 +240,18 @@ public final class AccessibilityInteractionClient * id is specified and starts from the View whose accessibility id is * specified. * * @param connection A connection for interacting with the system. * @param connectionId The id of a connection for interacting with the system. * @param text The searched text. * @param accessibilityWindowId A unique window id. * @param accessibilityViewId A unique View accessibility id from where to start the search. * Use {@link android.view.View#NO_ID} to start from the root. * @return A list of found {@link AccessibilityNodeInfo}s. */ public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText( IAccessibilityServiceConnection connection, String text, int accessibilityWindowId, int accessibilityViewId) { public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText(int connectionId, String text, int accessibilityWindowId, int accessibilityViewId) { try { IAccessibilityServiceConnection connection = getConnection(connectionId); if (connection != null) { final int interactionId = mInteractionIdCounter.getAndIncrement(); final float windowScale = connection.findAccessibilityNodeInfosByViewText(text, accessibilityWindowId, accessibilityViewId, interactionId, this, Loading @@ -217,11 +260,19 @@ public final class AccessibilityInteractionClient if (windowScale > 0) { List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear( interactionId); finalizeAccessibilityNodeInfos(infos, connection, windowScale); finalizeAccessibilityNodeInfos(infos, connectionId, windowScale); return infos; } } else { if (DEBUG) { Log.w(LOG_TAG, "No connection for connection id: " + connectionId); } } } catch (RemoteException re) { /* ignore */ if (DEBUG) { Log.w(LOG_TAG, "Error while calling remote" + " findAccessibilityNodeInfosByViewText", re); } } return Collections.emptyList(); } Loading @@ -229,15 +280,17 @@ public final class AccessibilityInteractionClient /** * Performs an accessibility action on an {@link AccessibilityNodeInfo}. * * @param connection A connection for interacting with the system. * @param connectionId The id of a connection for interacting with the system. * @param accessibilityWindowId The id of the window. * @param accessibilityViewId A unique View accessibility id. * @param action The action to perform. * @return Whether the action was performed. */ public boolean performAccessibilityAction(IAccessibilityServiceConnection connection, int accessibilityWindowId, int accessibilityViewId, int action) { public boolean performAccessibilityAction(int connectionId, int accessibilityWindowId, int accessibilityViewId, int action) { try { IAccessibilityServiceConnection connection = getConnection(connectionId); if (connection != null) { final int interactionId = mInteractionIdCounter.getAndIncrement(); final boolean success = connection.performAccessibilityAction( accessibilityWindowId, accessibilityViewId, action, interactionId, this, Loading @@ -245,8 +298,15 @@ public final class AccessibilityInteractionClient if (success) { return getPerformAccessibilityActionResult(interactionId); } } else { if (DEBUG) { Log.w(LOG_TAG, "No connection for connection id: " + connectionId); } } } catch (RemoteException re) { /* ignore */ if (DEBUG) { Log.w(LOG_TAG, "Error while calling remote performAccessibilityAction", re); } } return false; } Loading Loading @@ -406,14 +466,14 @@ public final class AccessibilityInteractionClient * Finalize an {@link AccessibilityNodeInfo} before passing it to the client. * * @param info The info. * @param connection The current connection to the system. * @param connectionId The id of the connection to the system. * @param windowScale The source window compatibility scale. */ private void finalizeAccessibilityNodeInfo(AccessibilityNodeInfo info, IAccessibilityServiceConnection connection, float windowScale) { private void finalizeAccessibilityNodeInfo(AccessibilityNodeInfo info, int connectionId, float windowScale) { if (info != null) { applyCompatibilityScaleIfNeeded(info, windowScale); info.setConnection(connection); info.setConnectionId(connectionId); info.setSealed(true); } } Loading @@ -422,16 +482,16 @@ public final class AccessibilityInteractionClient * Finalize {@link AccessibilityNodeInfo}s before passing them to the client. * * @param infos The {@link AccessibilityNodeInfo}s. * @param connection The current connection to the system. * @param connectionId The id of the connection to the system. * @param windowScale The source window compatibility scale. */ private void finalizeAccessibilityNodeInfos(List<AccessibilityNodeInfo> infos, IAccessibilityServiceConnection connection, float windowScale) { int connectionId, float windowScale) { if (infos != null) { final int infosCount = infos.size(); for (int i = 0; i < infosCount; i++) { AccessibilityNodeInfo info = infos.get(i); finalizeAccessibilityNodeInfo(info, connection, windowScale); finalizeAccessibilityNodeInfo(info, connectionId, windowScale); } } } Loading @@ -449,4 +509,39 @@ public final class AccessibilityInteractionClient return result; } } /** * Gets a cached accessibility service connection. * * @param connectionId The connection id. * @return The cached connection if such. */ public IAccessibilityServiceConnection getConnection(int connectionId) { synchronized (mConnectionCache) { return mConnectionCache.get(connectionId); } } /** * Adds a cached accessibility service connection. * * @param connectionId The connection id. * @param connection The connection. */ public void addConnection(int connectionId, IAccessibilityServiceConnection connection) { synchronized (mConnectionCache) { mConnectionCache.put(connectionId, connection); } } /** * Removes a cached accessibility service connection. * * @param connectionId The connection id. */ public void removeConnection(int connectionId) { synchronized (mConnectionCache) { mConnectionCache.remove(connectionId); } } }