InterrogationActivityTest.java revision 79311c4af8b54d3cd47ab37a120c648bfc990511
1/** 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 * express or implied. See the License for the specific language governing permissions and 12 * limitations under the License. 13 */ 14 15package android.accessibilityservice; 16 17import static android.view.accessibility.AccessibilityNodeInfo.ACTION_FOCUS; 18import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_FOCUS; 19import static android.view.accessibility.AccessibilityNodeInfo.ACTION_SELECT; 20import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_SELECTION; 21 22import android.graphics.Rect; 23import android.os.SystemClock; 24import android.test.ActivityInstrumentationTestCase2; 25import android.test.suitebuilder.annotation.LargeTest; 26import android.util.Log; 27import android.view.accessibility.AccessibilityEvent; 28import android.view.accessibility.AccessibilityNodeInfo; 29 30import com.android.frameworks.coretests.R; 31import com.android.internal.util.Predicate; 32 33import java.util.ArrayList; 34import java.util.LinkedList; 35import java.util.List; 36import java.util.Queue; 37 38/** 39 * Activity for testing the accessibility APIs for "interrogation" of 40 * the screen content. These APIs allow exploring the screen and 41 * requesting an action to be performed on a given view from an 42 * AccessiiblityService. 43 */ 44public class InterrogationActivityTest 45 extends ActivityInstrumentationTestCase2<InterrogationActivity> { 46 private static final boolean DEBUG = false; 47 48 private static String LOG_TAG = "InterrogationActivityTest"; 49 50 // Timeout for the accessibility state of an Activity to be fully initialized. 51 private static final int TIMEOUT_PROPAGATE_ACCESSIBILITY_EVENT_MILLIS = 5000; 52 53 // Handle to a connection to the AccessibilityManagerService 54 private UiTestAutomationBridge mUiTestAutomationBridge; 55 56 public InterrogationActivityTest() { 57 super(InterrogationActivity.class); 58 } 59 60 @Override 61 public void setUp() throws Exception { 62 super.setUp(); 63 mUiTestAutomationBridge = new UiTestAutomationBridge(); 64 mUiTestAutomationBridge.connect(); 65 mUiTestAutomationBridge.executeCommandAndWaitForAccessibilityEvent(new Runnable() { 66 // wait for the first accessibility event 67 @Override 68 public void run() { 69 // bring up the activity 70 getActivity(); 71 } 72 }, 73 new Predicate<AccessibilityEvent>() { 74 @Override 75 public boolean apply(AccessibilityEvent event) { 76 return (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 77 && event.getPackageName().equals(getActivity().getPackageName())); 78 } 79 }, 80 TIMEOUT_PROPAGATE_ACCESSIBILITY_EVENT_MILLIS); 81 } 82 83 @Override 84 public void tearDown() throws Exception { 85 mUiTestAutomationBridge.disconnect(); 86 super.tearDown(); 87 } 88 89 @LargeTest 90 public void testFindAccessibilityNodeInfoByViewId() throws Exception { 91 final long startTimeMillis = SystemClock.uptimeMillis(); 92 try { 93 AccessibilityNodeInfo button = mUiTestAutomationBridge 94 .findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5); 95 assertNotNull(button); 96 assertEquals(0, button.getChildCount()); 97 98 // bounds 99 Rect bounds = new Rect(); 100 button.getBoundsInParent(bounds); 101 assertEquals(0, bounds.left); 102 assertEquals(0, bounds.top); 103 assertEquals(160, bounds.right); 104 assertEquals(100, bounds.bottom); 105 106 // char sequence attributes 107 assertEquals("com.android.frameworks.coretests", button.getPackageName()); 108 assertEquals("android.widget.Button", button.getClassName()); 109 assertEquals("Button5", button.getText()); 110 assertNull(button.getContentDescription()); 111 112 // boolean attributes 113 assertTrue(button.isFocusable()); 114 assertTrue(button.isClickable()); 115 assertTrue(button.isEnabled()); 116 assertFalse(button.isFocused()); 117 assertTrue(button.isClickable()); 118 assertFalse(button.isPassword()); 119 assertFalse(button.isSelected()); 120 assertFalse(button.isCheckable()); 121 assertFalse(button.isChecked()); 122 123 // actions 124 assertEquals(ACTION_FOCUS | ACTION_SELECT | ACTION_CLEAR_SELECTION, 125 button.getActions()); 126 } finally { 127 if (DEBUG) { 128 final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis; 129 Log.i(LOG_TAG, "testFindAccessibilityNodeInfoByViewId: " 130 + elapsedTimeMillis + "ms"); 131 } 132 } 133 } 134 135 @LargeTest 136 public void testFindAccessibilityNodeInfoByViewText() throws Exception { 137 final long startTimeMillis = SystemClock.uptimeMillis(); 138 try { 139 // find a view by text 140 List<AccessibilityNodeInfo> buttons = mUiTestAutomationBridge 141 .findAccessibilityNodeInfosByTextInActiveWindow("butto"); 142 assertEquals(9, buttons.size()); 143 } finally { 144 if (DEBUG) { 145 final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis; 146 Log.i(LOG_TAG, "testFindAccessibilityNodeInfoByViewText: " 147 + elapsedTimeMillis + "ms"); 148 } 149 } 150 } 151 152 @LargeTest 153 public void testFindAccessibilityNodeInfoByViewTextContentDescription() throws Exception { 154 final long startTimeMillis = SystemClock.uptimeMillis(); 155 try { 156 // find a view by text 157 List<AccessibilityNodeInfo> buttons = mUiTestAutomationBridge 158 .findAccessibilityNodeInfosByTextInActiveWindow("contentDescription"); 159 assertEquals(1, buttons.size()); 160 } finally { 161 if (DEBUG) { 162 final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis; 163 Log.i(LOG_TAG, "testFindAccessibilityNodeInfoByViewTextContentDescription: " 164 + elapsedTimeMillis + "ms"); 165 } 166 } 167 } 168 169 @LargeTest 170 public void testTraverseAllViews() throws Exception { 171 final long startTimeMillis = SystemClock.uptimeMillis(); 172 try { 173 // make list of expected nodes 174 List<String> classNameAndTextList = new ArrayList<String>(); 175 classNameAndTextList.add("android.widget.LinearLayout"); 176 classNameAndTextList.add("android.widget.LinearLayout"); 177 classNameAndTextList.add("android.widget.LinearLayout"); 178 classNameAndTextList.add("android.widget.LinearLayout"); 179 classNameAndTextList.add("android.widget.ButtonButton1"); 180 classNameAndTextList.add("android.widget.ButtonButton2"); 181 classNameAndTextList.add("android.widget.ButtonButton3"); 182 classNameAndTextList.add("android.widget.ButtonButton4"); 183 classNameAndTextList.add("android.widget.ButtonButton5"); 184 classNameAndTextList.add("android.widget.ButtonButton6"); 185 classNameAndTextList.add("android.widget.ButtonButton7"); 186 classNameAndTextList.add("android.widget.ButtonButton8"); 187 classNameAndTextList.add("android.widget.ButtonButton9"); 188 189 AccessibilityNodeInfo root = mUiTestAutomationBridge 190 .findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.root); 191 assertNotNull("We must find the existing root.", root); 192 193 Queue<AccessibilityNodeInfo> fringe = new LinkedList<AccessibilityNodeInfo>(); 194 fringe.add(root); 195 196 // do a BFS traversal and check nodes 197 while (!fringe.isEmpty()) { 198 AccessibilityNodeInfo current = fringe.poll(); 199 200 CharSequence className = current.getClassName(); 201 CharSequence text = current.getText(); 202 String receivedClassNameAndText = className.toString() 203 + ((text != null) ? text.toString() : ""); 204 String expectedClassNameAndText = classNameAndTextList.remove(0); 205 206 assertEquals("Did not get the expected node info", 207 expectedClassNameAndText, receivedClassNameAndText); 208 209 final int childCount = current.getChildCount(); 210 for (int i = 0; i < childCount; i++) { 211 AccessibilityNodeInfo child = current.getChild(i); 212 fringe.add(child); 213 } 214 } 215 } finally { 216 if (DEBUG) { 217 final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis; 218 Log.i(LOG_TAG, "testTraverseAllViews: " + elapsedTimeMillis + "ms"); 219 } 220 } 221 } 222 223 @LargeTest 224 public void testPerformAccessibilityActionFocus() throws Exception { 225 final long startTimeMillis = SystemClock.uptimeMillis(); 226 try { 227 // find a view and make sure it is not focused 228 AccessibilityNodeInfo button = mUiTestAutomationBridge 229 .findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5); 230 assertFalse(button.isFocused()); 231 232 // focus the view 233 assertTrue(button.performAction(ACTION_FOCUS)); 234 235 // find the view again and make sure it is focused 236 button = mUiTestAutomationBridge 237 .findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5); 238 assertTrue(button.isFocused()); 239 } finally { 240 if (DEBUG) { 241 final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis; 242 Log.i(LOG_TAG, "testPerformAccessibilityActionFocus: " + elapsedTimeMillis + "ms"); 243 } 244 } 245 } 246 247 @LargeTest 248 public void testPerformAccessibilityActionClearFocus() throws Exception { 249 final long startTimeMillis = SystemClock.uptimeMillis(); 250 try { 251 // find a view and make sure it is not focused 252 AccessibilityNodeInfo button = mUiTestAutomationBridge 253 .findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5); 254 assertFalse(button.isFocused()); 255 256 // focus the view 257 assertTrue(button.performAction(ACTION_FOCUS)); 258 259 // find the view again and make sure it is focused 260 button = mUiTestAutomationBridge 261 .findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5); 262 assertTrue(button.isFocused()); 263 264 // unfocus the view 265 assertTrue(button.performAction(ACTION_CLEAR_FOCUS)); 266 267 // find the view again and make sure it is not focused 268 button = mUiTestAutomationBridge 269 .findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5); 270 assertFalse(button.isFocused()); 271 } finally { 272 if (DEBUG) { 273 final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis; 274 Log.i(LOG_TAG, "testPerformAccessibilityActionClearFocus: " 275 + elapsedTimeMillis + "ms"); 276 } 277 } 278 } 279 280 @LargeTest 281 public void testPerformAccessibilityActionSelect() throws Exception { 282 final long startTimeMillis = SystemClock.uptimeMillis(); 283 try { 284 // find a view and make sure it is not selected 285 AccessibilityNodeInfo button = mUiTestAutomationBridge 286 .findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5); 287 assertFalse(button.isSelected()); 288 289 // select the view 290 assertTrue(button.performAction(ACTION_SELECT)); 291 292 // find the view again and make sure it is selected 293 button = mUiTestAutomationBridge 294 .findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5); 295 assertTrue(button.isSelected()); 296 } finally { 297 if (DEBUG) { 298 final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis; 299 Log.i(LOG_TAG, "testPerformAccessibilityActionSelect: " + elapsedTimeMillis + "ms"); 300 } 301 } 302 } 303 304 @LargeTest 305 public void testPerformAccessibilityActionClearSelection() throws Exception { 306 final long startTimeMillis = SystemClock.uptimeMillis(); 307 try { 308 // find a view and make sure it is not selected 309 AccessibilityNodeInfo button = mUiTestAutomationBridge 310 .findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5); 311 assertFalse(button.isSelected()); 312 313 // select the view 314 assertTrue(button.performAction(ACTION_SELECT)); 315 316 // find the view again and make sure it is selected 317 button = mUiTestAutomationBridge 318 .findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5); 319 assertTrue(button.isSelected()); 320 321 // unselect the view 322 assertTrue(button.performAction(ACTION_CLEAR_SELECTION)); 323 324 // find the view again and make sure it is not selected 325 button = mUiTestAutomationBridge 326 .findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5); 327 assertFalse(button.isSelected()); 328 } finally { 329 if (DEBUG) { 330 final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis; 331 Log.i(LOG_TAG, "testPerformAccessibilityActionClearSelection: " 332 + elapsedTimeMillis + "ms"); 333 } 334 } 335 } 336 337 @LargeTest 338 public void testAccessibilityEventGetSource() throws Exception { 339 final long startTimeMillis = SystemClock.uptimeMillis(); 340 try { 341 // find a view and make sure it is not focused 342 final AccessibilityNodeInfo button = mUiTestAutomationBridge 343 .findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5); 344 assertFalse(button.isFocused()); 345 346 AccessibilityEvent event = mUiTestAutomationBridge 347 .executeCommandAndWaitForAccessibilityEvent(new Runnable() { 348 @Override 349 public void run() { 350 // focus the view 351 assertTrue(button.performAction(ACTION_FOCUS)); 352 } 353 }, 354 new Predicate<AccessibilityEvent>() { 355 @Override 356 public boolean apply(AccessibilityEvent event) { 357 return (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED 358 && event.getPackageName().equals(getActivity().getPackageName()) 359 && event.getText().get(0).equals(button.getText())); 360 } 361 }, 362 TIMEOUT_PROPAGATE_ACCESSIBILITY_EVENT_MILLIS); 363 364 // check the last event 365 assertNotNull(event); 366 367 // check that last event source 368 AccessibilityNodeInfo source = event.getSource(); 369 assertNotNull(source); 370 371 // bounds 372 Rect buttonBounds = new Rect(); 373 button.getBoundsInParent(buttonBounds); 374 Rect sourceBounds = new Rect(); 375 source.getBoundsInParent(sourceBounds); 376 377 assertEquals(buttonBounds.left, sourceBounds.left); 378 assertEquals(buttonBounds.right, sourceBounds.right); 379 assertEquals(buttonBounds.top, sourceBounds.top); 380 assertEquals(buttonBounds.bottom, sourceBounds.bottom); 381 382 // char sequence attributes 383 assertEquals(button.getPackageName(), source.getPackageName()); 384 assertEquals(button.getClassName(), source.getClassName()); 385 assertEquals(button.getText(), source.getText()); 386 assertSame(button.getContentDescription(), source.getContentDescription()); 387 388 // boolean attributes 389 assertSame(button.isFocusable(), source.isFocusable()); 390 assertSame(button.isClickable(), source.isClickable()); 391 assertSame(button.isEnabled(), source.isEnabled()); 392 assertNotSame(button.isFocused(), source.isFocused()); 393 assertSame(button.isLongClickable(), source.isLongClickable()); 394 assertSame(button.isPassword(), source.isPassword()); 395 assertSame(button.isSelected(), source.isSelected()); 396 assertSame(button.isCheckable(), source.isCheckable()); 397 assertSame(button.isChecked(), source.isChecked()); 398 } finally { 399 if (DEBUG) { 400 final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis; 401 Log.i(LOG_TAG, "testAccessibilityEventGetSource: " + elapsedTimeMillis + "ms"); 402 } 403 } 404 } 405 406 @LargeTest 407 public void testObjectContract() throws Exception { 408 final long startTimeMillis = SystemClock.uptimeMillis(); 409 try { 410 // find a view and make sure it is not focused 411 AccessibilityNodeInfo button = mUiTestAutomationBridge 412 .findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5); 413 assertNotNull(button); 414 AccessibilityNodeInfo parent = button.getParent(); 415 final int childCount = parent.getChildCount(); 416 for (int i = 0; i < childCount; i++) { 417 AccessibilityNodeInfo child = parent.getChild(i); 418 assertNotNull(child); 419 if (child.equals(button)) { 420 assertEquals("Equal objects must have same hasCode.", button.hashCode(), 421 child.hashCode()); 422 return; 423 } 424 } 425 fail("Parent's children do not have the info whose parent is the parent."); 426 } finally { 427 if (DEBUG) { 428 final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis; 429 Log.i(LOG_TAG, "testObjectContract: " + elapsedTimeMillis + "ms"); 430 } 431 } 432 } 433} 434