AccessibilityInteractionClient.java revision 6bc5e530016928027c7b390a8368ecdd5bff072f
18bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov/* 28bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov ** Copyright 2011, The Android Open Source Project 38bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov ** 48bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov ** Licensed under the Apache License, Version 2.0 (the "License"); 58bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov ** you may not use this file except in compliance with the License. 68bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov ** You may obtain a copy of the License at 78bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov ** 88bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov ** http://www.apache.org/licenses/LICENSE-2.0 98bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov ** 108bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov ** Unless required by applicable law or agreed to in writing, software 118bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov ** distributed under the License is distributed on an "AS IS" BASIS, 128bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov ** See the License for the specific language governing permissions and 148bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov ** limitations under the License. 158bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 168bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 178bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganovpackage android.view.accessibility; 188bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 198bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganovimport android.accessibilityservice.IAccessibilityServiceConnection; 208bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganovimport android.graphics.Rect; 218bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganovimport android.os.Message; 228bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganovimport android.os.RemoteException; 238bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganovimport android.os.SystemClock; 248bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 258bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganovimport java.util.Collections; 268bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganovimport java.util.List; 278bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganovimport java.util.concurrent.atomic.AtomicInteger; 288bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 298bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov/** 308bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * This class is a singleton that performs accessibility interaction 318bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * which is it queries remote view hierarchies about snapshots of their 328bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * views as well requests from these hierarchies to perform certain 338bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * actions on their views. 348bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * 358bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * Rationale: The content retrieval APIs are synchronous from a client's 368bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * perspective but internally they are asynchronous. The client thread 378bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * calls into the system requesting an action and providing a callback 388bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * to receive the result after which it waits up to a timeout for that 398bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * result. The system enforces security and the delegates the request 408bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * to a given view hierarchy where a message is posted (from a binder 418bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * thread) describing what to be performed by the main UI thread the 428bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * result of which it delivered via the mentioned callback. However, 438bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * the blocked client thread and the main UI thread of the target view 448bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * hierarchy can be the same thread, for example an accessibility service 458bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * and an activity run in the same process, thus they are executed on the 468bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * same main thread. In such a case the retrieval will fail since the UI 478bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * thread that has to process the message describing the work to be done 488bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * is blocked waiting for a result is has to compute! To avoid this scenario 498bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * when making a call the client also passes its process and thread ids so 508bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * the accessed view hierarchy can detect if the client making the request 518bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * is running in its main UI thread. In such a case the view hierarchy, 528bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * specifically the binder thread performing the IPC to it, does not post a 538bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * message to be run on the UI thread but passes it to the singleton 548bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * interaction client through which all interactions occur and the latter is 558bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * responsible to execute the message before starting to wait for the 568bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * asynchronous result delivered via the callback. In this case the expected 578bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * result is already received so no waiting is performed. 588bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * 598bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @hide 608bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 618bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganovpublic final class AccessibilityInteractionClient 628bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov extends IAccessibilityInteractionConnectionCallback.Stub { 638bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 648bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov private static final long TIMEOUT_INTERACTION_MILLIS = 5000; 658bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 668bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov private static final Object sStaticLock = new Object(); 678bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 688bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov private static AccessibilityInteractionClient sInstance; 698bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 708bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov private final AtomicInteger mInteractionIdCounter = new AtomicInteger(); 718bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 728bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov private final Object mInstanceLock = new Object(); 738bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 748bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov private int mInteractionId = -1; 758bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 768bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov private AccessibilityNodeInfo mFindAccessibilityNodeInfoResult; 778bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 788bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov private List<AccessibilityNodeInfo> mFindAccessibilityNodeInfosResult; 798bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 808bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov private boolean mPerformAccessibilityActionResult; 818bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 828bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov private Message mSameThreadMessage; 838bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 848bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov private final Rect mTempBounds = new Rect(); 858bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 868bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /** 878bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @return The singleton of this class. 888bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 898bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov public static AccessibilityInteractionClient getInstance() { 908bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov synchronized (sStaticLock) { 918bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov if (sInstance == null) { 928bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov sInstance = new AccessibilityInteractionClient(); 938bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 948bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov return sInstance; 958bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 968bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 978bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 988bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /** 998bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * Sets the message to be processed if the interacted view hierarchy 1008bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * and the interacting client are running in the same thread. 1018bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * 1028bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param message The message. 1038bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 1048bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov public void setSameThreadMessage(Message message) { 1058bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov synchronized (mInstanceLock) { 1068bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov mSameThreadMessage = message; 1076bc5e530016928027c7b390a8368ecdd5bff072fSvetoslav Ganov mInstanceLock.notifyAll(); 1088bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 1098bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 1108bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 1118bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /** 1128bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * Finds an {@link AccessibilityNodeInfo} by accessibility id. 1138bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * 1148bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param connection A connection for interacting with the system. 1158bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param accessibilityWindowId A unique window id. 1168bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param accessibilityViewId A unique View accessibility id. 1178bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @return An {@link AccessibilityNodeInfo} if found, null otherwise. 1188bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 1198bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId( 1208bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov IAccessibilityServiceConnection connection, int accessibilityWindowId, 1218bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov int accessibilityViewId) { 1228bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov try { 1238bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov final int interactionId = mInteractionIdCounter.getAndIncrement(); 1248bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov final float windowScale = connection.findAccessibilityNodeInfoByAccessibilityId( 1258bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov accessibilityWindowId, accessibilityViewId, interactionId, this, 1268bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov Thread.currentThread().getId()); 1278bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov // If the scale is zero the call has failed. 1288bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov if (windowScale > 0) { 1298bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear( 1308bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov interactionId); 1318bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov finalizeAccessibilityNodeInfo(info, connection, windowScale); 1328bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov return info; 1338bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 1348bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } catch (RemoteException re) { 1358bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /* ignore */ 1368bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 1378bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov return null; 1388bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 1398bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 1408bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /** 1418bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * Finds an {@link AccessibilityNodeInfo} by View id. The search is performed 1428bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * in the currently active window and starts from the root View in the window. 1438bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * 1448bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param connection A connection for interacting with the system. 1456bc5e530016928027c7b390a8368ecdd5bff072fSvetoslav Ganov * @param viewId The id of the view. 1468bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @return An {@link AccessibilityNodeInfo} if found, null otherwise. 1478bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 1488bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow( 1498bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov IAccessibilityServiceConnection connection, int viewId) { 1508bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov try { 1518bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov final int interactionId = mInteractionIdCounter.getAndIncrement(); 1528bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov final float windowScale = connection.findAccessibilityNodeInfoByViewIdInActiveWindow( 1538bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov viewId, interactionId, this, Thread.currentThread().getId()); 1548bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov // If the scale is zero the call has failed. 1558bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov if (windowScale > 0) { 1568bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear( 1578bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov interactionId); 1588bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov finalizeAccessibilityNodeInfo(info, connection, windowScale); 1598bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov return info; 1608bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 1618bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } catch (RemoteException re) { 1628bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /* ignore */ 1638bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 1648bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov return null; 1658bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 1668bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 1678bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /** 1688bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * Finds {@link AccessibilityNodeInfo}s by View text. The match is case 1698bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * insensitive containment. The search is performed in the currently 1708bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * active window and starts from the root View in the window. 1718bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * 1728bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param connection A connection for interacting with the system. 1738bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param text The searched text. 1748bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @return A list of found {@link AccessibilityNodeInfo}s. 1758bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 1768bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewTextInActiveWindow( 1778bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov IAccessibilityServiceConnection connection, String text) { 1788bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov try { 1798bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov final int interactionId = mInteractionIdCounter.getAndIncrement(); 1808bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov final float windowScale = connection.findAccessibilityNodeInfosByViewTextInActiveWindow( 1818bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov text, interactionId, this, Thread.currentThread().getId()); 1828bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov // If the scale is zero the call has failed. 1838bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov if (windowScale > 0) { 1848bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear( 1858bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov interactionId); 1868bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov finalizeAccessibilityNodeInfos(infos, connection, windowScale); 1878bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov return infos; 1888bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 1898bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } catch (RemoteException re) { 1908bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /* ignore */ 1918bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 1928bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov return null; 1938bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 1948bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 1958bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /** 1968bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * Finds {@link AccessibilityNodeInfo}s by View text. The match is case 1978bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * insensitive containment. The search is performed in the window whose 1988bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * id is specified and starts from the View whose accessibility id is 1998bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * specified. 2008bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * 2018bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param connection A connection for interacting with the system. 2028bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param text The searched text. 2038bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param accessibilityWindowId A unique window id. 2048bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param accessibilityViewId A unique View accessibility id from where to start the search. 2058bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * Use {@link android.view.View#NO_ID} to start from the root. 2068bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @return A list of found {@link AccessibilityNodeInfo}s. 2078bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 2088bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText( 2098bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov IAccessibilityServiceConnection connection, String text, int accessibilityWindowId, 2108bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov int accessibilityViewId) { 2118bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov try { 2128bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov final int interactionId = mInteractionIdCounter.getAndIncrement(); 2138bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov final float windowScale = connection.findAccessibilityNodeInfosByViewText(text, 2148bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov accessibilityWindowId, accessibilityViewId, interactionId, this, 2158bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov Thread.currentThread().getId()); 2168bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov // If the scale is zero the call has failed. 2178bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov if (windowScale > 0) { 2188bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear( 2198bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov interactionId); 2208bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov finalizeAccessibilityNodeInfos(infos, connection, windowScale); 2218bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov return infos; 2228bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 2238bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } catch (RemoteException re) { 2248bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /* ignore */ 2258bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 2268bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov return Collections.emptyList(); 2278bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 2288bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 2298bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /** 2308bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * Performs an accessibility action on an {@link AccessibilityNodeInfo}. 2318bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * 2328bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param connection A connection for interacting with the system. 2338bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param accessibilityWindowId The id of the window. 2348bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param accessibilityViewId A unique View accessibility id. 2358bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param action The action to perform. 2368bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @return Whether the action was performed. 2378bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 2388bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov public boolean performAccessibilityAction(IAccessibilityServiceConnection connection, 2398bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov int accessibilityWindowId, int accessibilityViewId, int action) { 2408bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov try { 2418bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov final int interactionId = mInteractionIdCounter.getAndIncrement(); 2428bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov final boolean success = connection.performAccessibilityAction( 2438bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov accessibilityWindowId, accessibilityViewId, action, interactionId, this, 2448bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov Thread.currentThread().getId()); 2458bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov if (success) { 2468bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov return getPerformAccessibilityActionResult(interactionId); 2478bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 2488bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } catch (RemoteException re) { 2498bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /* ignore */ 2508bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 2518bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov return false; 2528bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 2538bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 2548bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /** 2558bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * Gets the the result of an async request that returns an {@link AccessibilityNodeInfo}. 2568bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * 2578bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param interactionId The interaction id to match the result with the request. 2588bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @return The result {@link AccessibilityNodeInfo}. 2598bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 2608bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov private AccessibilityNodeInfo getFindAccessibilityNodeInfoResultAndClear(int interactionId) { 2618bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov synchronized (mInstanceLock) { 2628bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov final boolean success = waitForResultTimedLocked(interactionId); 2638bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov AccessibilityNodeInfo result = success ? mFindAccessibilityNodeInfoResult : null; 2648bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov clearResultLocked(); 2658bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov return result; 2668bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 2678bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 2688bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 2698bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /** 2708bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * {@inheritDoc} 2718bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 2728bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov public void setFindAccessibilityNodeInfoResult(AccessibilityNodeInfo info, 2738bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov int interactionId) { 2748bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov synchronized (mInstanceLock) { 2758bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov if (interactionId > mInteractionId) { 2768bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov mFindAccessibilityNodeInfoResult = info; 2778bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov mInteractionId = interactionId; 2788bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 2798bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov mInstanceLock.notifyAll(); 2808bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 2818bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 2828bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 2838bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /** 2848bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * Gets the the result of an async request that returns {@link AccessibilityNodeInfo}s. 2858bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * 2868bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param interactionId The interaction id to match the result with the request. 2878bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @return The result {@link AccessibilityNodeInfo}s. 2888bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 2898bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov private List<AccessibilityNodeInfo> getFindAccessibilityNodeInfosResultAndClear( 2908bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov int interactionId) { 2918bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov synchronized (mInstanceLock) { 2928bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov final boolean success = waitForResultTimedLocked(interactionId); 2938bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov List<AccessibilityNodeInfo> result = success ? mFindAccessibilityNodeInfosResult : null; 2948bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov clearResultLocked(); 2958bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov return result; 2968bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 2978bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 2988bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 2998bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /** 3008bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * {@inheritDoc} 3018bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 3028bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov public void setFindAccessibilityNodeInfosResult(List<AccessibilityNodeInfo> infos, 3038bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov int interactionId) { 3048bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov synchronized (mInstanceLock) { 3058bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov if (interactionId > mInteractionId) { 3068bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov mFindAccessibilityNodeInfosResult = infos; 3078bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov mInteractionId = interactionId; 3088bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 3098bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov mInstanceLock.notifyAll(); 3108bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 3118bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 3128bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 3138bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /** 3148bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * Gets the result of a request to perform an accessibility action. 3158bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * 3168bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param interactionId The interaction id to match the result with the request. 3178bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @return Whether the action was performed. 3188bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 3198bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov private boolean getPerformAccessibilityActionResult(int interactionId) { 3208bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov synchronized (mInstanceLock) { 3218bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov final boolean success = waitForResultTimedLocked(interactionId); 3228bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov final boolean result = success ? mPerformAccessibilityActionResult : false; 3238bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov clearResultLocked(); 3248bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov return result; 3258bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 3268bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 3278bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 3288bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /** 3298bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * {@inheritDoc} 3308bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 3318bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov public void setPerformAccessibilityActionResult(boolean succeeded, int interactionId) { 3328bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov synchronized (mInstanceLock) { 3338bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov if (interactionId > mInteractionId) { 3348bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov mPerformAccessibilityActionResult = succeeded; 3358bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov mInteractionId = interactionId; 3368bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 3378bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov mInstanceLock.notifyAll(); 3388bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 3398bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 3408bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 3418bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /** 3428bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * Clears the result state. 3438bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 3448bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov private void clearResultLocked() { 3458bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov mInteractionId = -1; 3468bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov mFindAccessibilityNodeInfoResult = null; 3478bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov mFindAccessibilityNodeInfosResult = null; 3488bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov mPerformAccessibilityActionResult = false; 3498bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 3508bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 3518bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /** 3528bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * Waits up to a given bound for a result of a request and returns it. 3538bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * 3548bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param interactionId The interaction id to match the result with the request. 3558bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @return Whether the result was received. 3568bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 3578bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov private boolean waitForResultTimedLocked(int interactionId) { 3588bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov long waitTimeMillis = TIMEOUT_INTERACTION_MILLIS; 3598bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov final long startTimeMillis = SystemClock.uptimeMillis(); 3608bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov while (true) { 3618bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov try { 3626bc5e530016928027c7b390a8368ecdd5bff072fSvetoslav Ganov Message sameProcessMessage = getSameProcessMessageAndClear(); 3636bc5e530016928027c7b390a8368ecdd5bff072fSvetoslav Ganov if (sameProcessMessage != null) { 3646bc5e530016928027c7b390a8368ecdd5bff072fSvetoslav Ganov sameProcessMessage.getTarget().handleMessage(sameProcessMessage); 3656bc5e530016928027c7b390a8368ecdd5bff072fSvetoslav Ganov } 3666bc5e530016928027c7b390a8368ecdd5bff072fSvetoslav Ganov 3678bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov if (mInteractionId == interactionId) { 3688bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov return true; 3698bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 3708bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov if (mInteractionId > interactionId) { 3718bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov return false; 3728bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 3738bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis; 3748bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov waitTimeMillis = TIMEOUT_INTERACTION_MILLIS - elapsedTimeMillis; 3758bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov if (waitTimeMillis <= 0) { 3768bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov return false; 3778bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 3788bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov mInstanceLock.wait(waitTimeMillis); 3798bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } catch (InterruptedException ie) { 3808bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /* ignore */ 3818bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 3828bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 3838bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 3848bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 3858bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /** 3868bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * Applies compatibility scale to the info bounds if it is not equal to one. 3878bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * 3888bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param info The info whose bounds to scale. 3898bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param scale The scale to apply. 3908bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 3918bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov private void applyCompatibilityScaleIfNeeded(AccessibilityNodeInfo info, float scale) { 3928bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov if (scale == 1.0f) { 3938bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov return; 3948bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 3958bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov Rect bounds = mTempBounds; 3968bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov info.getBoundsInParent(bounds); 3978bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov bounds.scale(scale); 3988bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov info.setBoundsInParent(bounds); 3998bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 4008bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov info.getBoundsInScreen(bounds); 4018bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov bounds.scale(scale); 4028bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov info.setBoundsInScreen(bounds); 4038bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 4048bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 4058bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /** 4068bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * Finalize an {@link AccessibilityNodeInfo} before passing it to the client. 4078bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * 4088bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param info The info. 4098bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param connection The current connection to the system. 4108bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param windowScale The source window compatibility scale. 4118bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 4128bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov private void finalizeAccessibilityNodeInfo(AccessibilityNodeInfo info, 4138bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov IAccessibilityServiceConnection connection, float windowScale) { 4148bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov if (info != null) { 4158bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov applyCompatibilityScaleIfNeeded(info, windowScale); 4168bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov info.setConnection(connection); 4178bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov info.setSealed(true); 4188bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 4198bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 4208bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 4218bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /** 4228bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * Finalize {@link AccessibilityNodeInfo}s before passing them to the client. 4238bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * 4248bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param infos The {@link AccessibilityNodeInfo}s. 4258bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param connection The current connection to the system. 4268bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @param windowScale The source window compatibility scale. 4278bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 4288bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov private void finalizeAccessibilityNodeInfos(List<AccessibilityNodeInfo> infos, 4298bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov IAccessibilityServiceConnection connection, float windowScale) { 4308bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov if (infos != null) { 4318bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov final int infosCount = infos.size(); 4328bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov for (int i = 0; i < infosCount; i++) { 4338bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov AccessibilityNodeInfo info = infos.get(i); 4348bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov finalizeAccessibilityNodeInfo(info, connection, windowScale); 4358bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 4368bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 4378bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 4388bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov 4398bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov /** 4408bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * Gets the message stored if the interacted and interacting 4418bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * threads are the same. 4428bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * 4438bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov * @return The message. 4448bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov */ 4458bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov private Message getSameProcessMessageAndClear() { 4468bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov synchronized (mInstanceLock) { 4478bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov Message result = mSameThreadMessage; 4488bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov mSameThreadMessage = null; 4498bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov return result; 4508bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 4518bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov } 4528bd69610aafc6995126965d1d23b771fe02a9084Svetoslav Ganov} 453