1 /**
2  * Copyright (C) 2012 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 
15 package android.accessibilityservice.cts;
16 
17 import android.app.UiAutomation;
18 import android.content.pm.PackageManager;
19 import android.os.Bundle;
20 import android.test.suitebuilder.annotation.MediumTest;
21 import android.text.Selection;
22 import android.text.TextUtils;
23 import android.view.View;
24 import android.view.accessibility.AccessibilityEvent;
25 import android.view.accessibility.AccessibilityNodeInfo;
26 import android.widget.EditText;
27 import android.widget.TextView;
28 
29 import com.android.cts.accessibilityservice.R;
30 
31 /**
32  * Test cases for testing the accessibility APIs for traversing the text content of
33  * a View at several granularities.
34  */
35 public class AccessibilityTextTraversalTest
36         extends AccessibilityActivityTestCase<AccessibilityTextTraversalActivity>{
37 
AccessibilityTextTraversalTest()38     public AccessibilityTextTraversalTest() {
39         super(AccessibilityTextTraversalActivity.class);
40     }
41 
42     @MediumTest
testActionNextAndPreviousAtGranularityCharacterOverContentDescription()43     public void testActionNextAndPreviousAtGranularityCharacterOverContentDescription()
44             throws Exception {
45         final View view = getActivity().findViewById(R.id.view);
46 
47         getInstrumentation().runOnMainSync(new Runnable() {
48             @Override
49             public void run() {
50                 view.setVisibility(View.VISIBLE);
51                 view.setContentDescription(getString(R.string.a_b));
52             }
53         });
54 
55         final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
56                 .getRootInActiveWindow().findAccessibilityNodeInfosByText(
57                         getString(R.string.a_b)).get(0);
58 
59         final int granularities = text.getMovementGranularities();
60         assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
61                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
62                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
63 
64         final Bundle arguments = new Bundle();
65         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
66                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
67 
68         // Move to the next character and wait for an event.
69         AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
70                 .executeAndWaitForEvent(new Runnable() {
71             @Override
72             public void run() {
73                 text.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
74                         arguments);
75             }
76         }, new UiAutomation.AccessibilityEventFilter() {
77             @Override
78             public boolean accept(AccessibilityEvent event) {
79                 return
80                 (event.getEventType() ==
81                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
82                         && event.getAction() ==
83                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
84                         && event.getPackageName().equals(getActivity().getPackageName())
85                         && event.getClassName().equals(View.class.getName())
86                         && event.getContentDescription().toString().equals(
87                                 getString(R.string.a_b))
88                         && event.getFromIndex() == 0
89                         && event.getToIndex() == 1
90                         && event.getMovementGranularity() ==
91                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
92             }
93         }, TIMEOUT_ASYNC_PROCESSING);
94 
95         // Make sure we got the expected event.
96         assertNotNull(firstExpected);
97 
98         // Move to the next character and wait for an event.
99         AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
100                 .executeAndWaitForEvent(new Runnable() {
101             @Override
102             public void run() {
103                 text.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
104                         arguments);
105             }
106         }, new UiAutomation.AccessibilityEventFilter() {
107             @Override
108             public boolean accept(AccessibilityEvent event) {
109                 return
110                 (event.getEventType() ==
111                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
112                         && event.getAction() ==
113                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
114                         && event.getPackageName().equals(getActivity().getPackageName())
115                         && event.getClassName().equals(View.class.getName())
116                         && event.getContentDescription().toString().equals(
117                                 getString(R.string.a_b))
118                         && event.getFromIndex() == 1
119                         && event.getToIndex() == 2
120                         && event.getMovementGranularity() ==
121                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
122             }
123         }, TIMEOUT_ASYNC_PROCESSING);
124 
125         // Make sure we got the expected event.
126         assertNotNull(secondExpected);
127 
128         // Move to the next character and wait for an event.
129         AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
130                 .executeAndWaitForEvent(new Runnable() {
131             @Override
132             public void run() {
133                 text.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
134                         arguments);
135             }
136         }, new UiAutomation.AccessibilityEventFilter() {
137             @Override
138             public boolean accept(AccessibilityEvent event) {
139                 return
140                 (event.getEventType() ==
141                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
142                         && event.getAction() ==
143                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
144                         && event.getPackageName().equals(getActivity().getPackageName())
145                         && event.getClassName().equals(View.class.getName())
146                         && event.getContentDescription().toString().equals(
147                                 getString(R.string.a_b))
148                         && event.getFromIndex() == 2
149                         && event.getToIndex() == 3
150                         && event.getMovementGranularity() ==
151                                  AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
152             }
153         }, TIMEOUT_ASYNC_PROCESSING);
154 
155         // Make sure we got the expected event.
156         assertNotNull(thirdExpected);
157 
158         // Make sure there is no next.
159         assertFalse(text.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
160                 arguments));
161 
162         // Move to the previous character and wait for an event.
163         AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
164                 .executeAndWaitForEvent(new Runnable() {
165             @Override
166             public void run() {
167                 text.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
168                         arguments);
169             }
170         }, new UiAutomation.AccessibilityEventFilter() {
171             @Override
172             public boolean accept(AccessibilityEvent event) {
173                 return
174                 (event.getEventType() ==
175                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
176                         && event.getAction() ==
177                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
178                         && event.getPackageName().equals(getActivity().getPackageName())
179                         && event.getClassName().equals(View.class.getName())
180                         && event.getContentDescription().toString().equals(
181                                 getString(R.string.a_b))
182                         && event.getFromIndex() == 2
183                         && event.getToIndex() == 3
184                         && event.getMovementGranularity() ==
185                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
186             }
187         }, TIMEOUT_ASYNC_PROCESSING);
188 
189         // Make sure we got the expected event.
190         assertNotNull(fourthExpected);
191 
192         // Move to the previous character and wait for an event.
193         AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
194                 .executeAndWaitForEvent(new Runnable() {
195             @Override
196             public void run() {
197                 text.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
198                         arguments);
199             }
200         }, new UiAutomation.AccessibilityEventFilter() {
201             @Override
202             public boolean accept(AccessibilityEvent event) {
203                 return
204                 (event.getEventType() ==
205                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
206                         && event.getAction() ==
207                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
208                         && event.getPackageName().equals(getActivity().getPackageName())
209                         && event.getClassName().equals(View.class.getName())
210                         && event.getContentDescription().toString().equals(
211                                 getString(R.string.a_b))
212                         && event.getFromIndex() == 1
213                         && event.getToIndex() == 2
214                         && event.getMovementGranularity() ==
215                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
216             }
217         }, TIMEOUT_ASYNC_PROCESSING);
218 
219         // Make sure we got the expected event.
220         assertNotNull(fifthExpected);
221 
222         // Move to the next character and wait for an event.
223         AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
224                 .executeAndWaitForEvent(new Runnable() {
225             @Override
226             public void run() {
227                 text.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
228                         arguments);
229             }
230         }, new UiAutomation.AccessibilityEventFilter() {
231             @Override
232             public boolean accept(AccessibilityEvent event) {
233                 return
234                 (event.getEventType() ==
235                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
236                         && event.getAction() ==
237                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
238                         && event.getPackageName().equals(getActivity().getPackageName())
239                         && event.getClassName().equals(View.class.getName())
240                         && event.getContentDescription().toString().equals(
241                                 getString(R.string.a_b))
242                         && event.getFromIndex() == 0
243                         && event.getToIndex() == 1
244                         && event.getMovementGranularity() ==
245                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
246             }
247         }, TIMEOUT_ASYNC_PROCESSING);
248 
249         // Make sure we got the expected event.
250         assertNotNull(sixthExpected);
251 
252         // Make sure there is no previous.
253         assertFalse(text.performAction(
254                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
255     }
256 
257     @MediumTest
testActionNextAndPreviousAtGranularityWordOverContentDescription()258     public void testActionNextAndPreviousAtGranularityWordOverContentDescription()
259             throws Exception {
260         final View view = getActivity().findViewById(R.id.view);
261 
262         getInstrumentation().runOnMainSync(new Runnable() {
263             @Override
264             public void run() {
265                 view.setVisibility(View.VISIBLE);
266                 view.setContentDescription(getString(R.string.foo_bar_baz));
267             }
268         });
269 
270         final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
271                 .getRootInActiveWindow().findAccessibilityNodeInfosByText(
272                         getString(R.string.foo_bar_baz)).get(0);
273 
274         final int granularities = text.getMovementGranularities();
275         assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
276                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
277                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
278 
279         final Bundle arguments = new Bundle();
280         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
281                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
282 
283         // Move to the next character and wait for an event.
284         AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
285                 .executeAndWaitForEvent(new Runnable() {
286             @Override
287             public void run() {
288                 text.performAction(
289                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
290             }
291         }, new UiAutomation.AccessibilityEventFilter() {
292             @Override
293             public boolean accept(AccessibilityEvent event) {
294                 return
295                 (event.getEventType() ==
296                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
297                         && event.getAction() ==
298                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
299                         && event.getPackageName().equals(getActivity().getPackageName())
300                         && event.getClassName().equals(View.class.getName())
301                         && event.getContentDescription().toString().equals(
302                                 getString(R.string.foo_bar_baz))
303                         && event.getFromIndex() == 0
304                         && event.getToIndex() == 3
305                         && event.getMovementGranularity() ==
306                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
307             }
308         }, TIMEOUT_ASYNC_PROCESSING);
309 
310         // Make sure we got the expected event.
311         assertNotNull(firstExpected);
312 
313         // Move to the next character and wait for an event.
314         AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
315                 .executeAndWaitForEvent(new Runnable() {
316             @Override
317             public void run() {
318                 text.performAction(
319                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
320             }
321         }, new UiAutomation.AccessibilityEventFilter() {
322             @Override
323             public boolean accept(AccessibilityEvent event) {
324                 return
325                 (event.getEventType() ==
326                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
327                         && event.getAction() ==
328                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
329                         && event.getPackageName().equals(getActivity().getPackageName())
330                         && event.getClassName().equals(View.class.getName())
331                         && event.getContentDescription().toString().equals(
332                                 getString(R.string.foo_bar_baz))
333                         && event.getFromIndex() == 4
334                         && event.getToIndex() == 7
335                         && event.getMovementGranularity() ==
336                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
337             }
338         }, TIMEOUT_ASYNC_PROCESSING);
339 
340         // Make sure we got the expected event.
341         assertNotNull(secondExpected);
342 
343         // Move to the next character and wait for an event.
344         AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
345                 .executeAndWaitForEvent(new Runnable() {
346             @Override
347             public void run() {
348                 text.performAction(
349                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
350             }
351         }, new UiAutomation.AccessibilityEventFilter() {
352             @Override
353             public boolean accept(AccessibilityEvent event) {
354                 return
355                 (event.getEventType() ==
356                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
357                         && event.getAction() ==
358                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
359                         && event.getPackageName().equals(getActivity().getPackageName())
360                         && event.getClassName().equals(View.class.getName())
361                         && event.getContentDescription().toString().equals(
362                                 getString(R.string.foo_bar_baz))
363                         && event.getFromIndex() == 8
364                         && event.getToIndex() == 11
365                         && event.getMovementGranularity() ==
366                                AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
367             }
368         }, TIMEOUT_ASYNC_PROCESSING);
369 
370         // Make sure we got the expected event.
371         assertNotNull(thirdExpected);
372 
373         // Make sure there is no next.
374         assertFalse(text.performAction(
375                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
376 
377         // Move to the next character and wait for an event.
378         AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
379                 .executeAndWaitForEvent(new Runnable() {
380             @Override
381             public void run() {
382                 text.performAction(
383                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
384             }
385         }, new UiAutomation.AccessibilityEventFilter() {
386             @Override
387             public boolean accept(AccessibilityEvent event) {
388                 return
389                 (event.getEventType() ==
390                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
391                         && event.getAction() ==
392                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
393                         && event.getPackageName().equals(getActivity().getPackageName())
394                         && event.getClassName().equals(View.class.getName())
395                         && event.getContentDescription().toString().equals(
396                                 getString(R.string.foo_bar_baz))
397                         && event.getFromIndex() == 8
398                         && event.getToIndex() == 11
399                         && event.getMovementGranularity() ==
400                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
401             }
402         }, TIMEOUT_ASYNC_PROCESSING);
403 
404         // Make sure we got the expected event.
405         assertNotNull(fourthExpected);
406 
407         // Move to the next character and wait for an event.
408         AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
409                 .executeAndWaitForEvent(new Runnable() {
410             @Override
411             public void run() {
412                 text.performAction(
413                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
414             }
415         }, new UiAutomation.AccessibilityEventFilter() {
416             @Override
417             public boolean accept(AccessibilityEvent event) {
418                 return
419                 (event.getEventType() ==
420                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
421                         && event.getAction() ==
422                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
423                         && event.getPackageName().equals(getActivity().getPackageName())
424                         && event.getClassName().equals(View.class.getName())
425                         && event.getContentDescription().toString().equals(
426                                 getString(R.string.foo_bar_baz))
427                         && event.getFromIndex() == 4
428                         && event.getToIndex() == 7
429                         && event.getMovementGranularity() ==
430                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
431             }
432         }, TIMEOUT_ASYNC_PROCESSING);
433 
434         // Make sure we got the expected event.
435         assertNotNull(fifthExpected);
436 
437         // Move to the next character and wait for an event.
438         AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
439                 .executeAndWaitForEvent(new Runnable() {
440             @Override
441             public void run() {
442                 text.performAction(
443                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
444             }
445         }, new UiAutomation.AccessibilityEventFilter() {
446             @Override
447             public boolean accept(AccessibilityEvent event) {
448                 return
449                 (event.getEventType() ==
450                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
451                         && event.getAction() ==
452                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
453                         && event.getPackageName().equals(getActivity().getPackageName())
454                         && event.getClassName().equals(View.class.getName())
455                         && event.getContentDescription().toString().equals(
456                                 getString(R.string.foo_bar_baz))
457                         && event.getFromIndex() == 0
458                         && event.getToIndex() == 3
459                         && event.getMovementGranularity() ==
460                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
461             }
462         }, TIMEOUT_ASYNC_PROCESSING);
463 
464         // Make sure we got the expected event.
465         assertNotNull(sixthExpected);
466 
467         // Make sure there is no previous.
468         assertFalse(text.performAction(
469                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
470     }
471 
472     @MediumTest
testActionNextAndPreviousAtGranularityCharacterOverText()473     public void testActionNextAndPreviousAtGranularityCharacterOverText()
474             throws Exception {
475         final TextView textView = (TextView) getActivity().findViewById(R.id.text);
476 
477         getInstrumentation().runOnMainSync(new Runnable() {
478             @Override
479             public void run() {
480                 textView.setVisibility(View.VISIBLE);
481                 textView.setText(getString(R.string.a_b));
482             }
483         });
484 
485         final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
486                .getRootInActiveWindow().findAccessibilityNodeInfosByText(
487                        getString(R.string.a_b)).get(0);
488 
489         final int granularities = text.getMovementGranularities();
490         assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
491                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
492                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
493                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
494                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
495 
496         final Bundle arguments = new Bundle();
497         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
498                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
499 
500         // Move to the next character and wait for an event.
501         AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
502                 .executeAndWaitForEvent(new Runnable() {
503             @Override
504             public void run() {
505                 text.performAction(
506                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
507             }
508         }, new UiAutomation.AccessibilityEventFilter() {
509             @Override
510             public boolean accept(AccessibilityEvent event) {
511                 return
512                 (event.getEventType() ==
513                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
514                         && event.getAction() ==
515                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
516                         && event.getPackageName().equals(getActivity().getPackageName())
517                         && event.getClassName().equals(TextView.class.getName())
518                         && event.getText().size() > 0
519                         && event.getText().get(0).toString().equals(getString(R.string.a_b))
520                         && event.getFromIndex() == 0
521                         && event.getToIndex() == 1
522                         && event.getMovementGranularity() ==
523                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
524             }
525         }, TIMEOUT_ASYNC_PROCESSING);
526 
527         // Make sure we got the expected event.
528         assertNotNull(firstExpected);
529 
530         // Verify the selection position.
531         assertEquals(1, Selection.getSelectionStart(textView.getText()));
532         assertEquals(1, Selection.getSelectionEnd(textView.getText()));
533 
534         // Move to the next character and wait for an event.
535         AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
536                 .executeAndWaitForEvent(new Runnable() {
537             @Override
538             public void run() {
539                 text.performAction(
540                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
541             }
542         }, new UiAutomation.AccessibilityEventFilter() {
543             @Override
544             public boolean accept(AccessibilityEvent event) {
545                 return
546                 (event.getEventType() ==
547                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
548                         && event.getAction() ==
549                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
550                         && event.getPackageName().equals(getActivity().getPackageName())
551                         && event.getClassName().equals(TextView.class.getName())
552                         && event.getText().size() > 0
553                         && event.getText().get(0).toString().equals(getString(R.string.a_b))
554                         && event.getFromIndex() == 1
555                         && event.getToIndex() == 2
556                         && event.getMovementGranularity() ==
557                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
558             }
559         }, TIMEOUT_ASYNC_PROCESSING);
560 
561         // Make sure we got the expected event.
562         assertNotNull(secondExpected);
563 
564         // Verify the selection position.
565         assertEquals(2, Selection.getSelectionStart(textView.getText()));
566         assertEquals(2, Selection.getSelectionEnd(textView.getText()));
567 
568         // Move to the next character and wait for an event.
569         AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
570                 .executeAndWaitForEvent(new Runnable() {
571             @Override
572             public void run() {
573                 text.performAction(
574                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
575             }
576         }, new UiAutomation.AccessibilityEventFilter() {
577             @Override
578             public boolean accept(AccessibilityEvent event) {
579                 return
580                 (event.getEventType() ==
581                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
582                         && event.getAction() ==
583                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
584                         && event.getPackageName().equals(getActivity().getPackageName())
585                         && event.getClassName().equals(TextView.class.getName())
586                         && event.getText().size() > 0
587                         && event.getText().get(0).toString().equals(getString(R.string.a_b))
588                         && event.getFromIndex() == 2
589                         && event.getToIndex() == 3
590                         && event.getMovementGranularity() ==
591                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
592             }
593         }, TIMEOUT_ASYNC_PROCESSING);
594 
595         // Make sure we got the expected event.
596         assertNotNull(thirdExpected);
597 
598         // Verify the selection position.
599         assertEquals(3, Selection.getSelectionStart(textView.getText()));
600         assertEquals(3, Selection.getSelectionEnd(textView.getText()));
601 
602         // Make sure there is no next.
603         assertFalse(text.performAction(
604                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
605 
606         // Verify the selection position.
607         assertEquals(3, Selection.getSelectionStart(textView.getText()));
608         assertEquals(3, Selection.getSelectionEnd(textView.getText()));
609 
610         // Move to the previous character and wait for an event.
611         AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
612                 .executeAndWaitForEvent(new Runnable() {
613             @Override
614             public void run() {
615                 text.performAction(
616                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
617             }
618         }, new UiAutomation.AccessibilityEventFilter() {
619             @Override
620             public boolean accept(AccessibilityEvent event) {
621                 return
622                 (event.getEventType() ==
623                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
624                         && event.getAction() ==
625                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
626                         && event.getPackageName().equals(getActivity().getPackageName())
627                         && event.getClassName().equals(TextView.class.getName())
628                         && event.getText().size() > 0
629                         && event.getText().get(0).toString().equals(getString(R.string.a_b))
630                         && event.getFromIndex() == 2
631                         && event.getToIndex() == 3
632                         && event.getMovementGranularity() ==
633                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
634             }
635         }, TIMEOUT_ASYNC_PROCESSING);
636 
637         // Make sure we got the expected event.
638         assertNotNull(fifthExpected);
639 
640         // Verify the selection position.
641         assertEquals(2, Selection.getSelectionStart(textView.getText()));
642         assertEquals(2, Selection.getSelectionEnd(textView.getText()));
643 
644         // Move to the previous character and wait for an event.
645         AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
646                 .executeAndWaitForEvent(new Runnable() {
647             @Override
648             public void run() {
649                 text.performAction(
650                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
651             }
652         }, new UiAutomation.AccessibilityEventFilter() {
653             @Override
654             public boolean accept(AccessibilityEvent event) {
655                 return
656                 (event.getEventType() ==
657                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
658                         && event.getAction() ==
659                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
660                         && event.getPackageName().equals(getActivity().getPackageName())
661                         && event.getClassName().equals(TextView.class.getName())
662                         && event.getText().size() > 0
663                         && event.getText().get(0).toString().equals(getString(R.string.a_b))
664                         && event.getFromIndex() == 1
665                         && event.getToIndex() == 2
666                         && event.getMovementGranularity() ==
667                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
668             }
669         }, TIMEOUT_ASYNC_PROCESSING);
670 
671         // Make sure we got the expected event.
672         assertNotNull(sixthExpected);
673 
674         // Verify the selection position.
675         assertEquals(1, Selection.getSelectionStart(textView.getText()));
676         assertEquals(1, Selection.getSelectionEnd(textView.getText()));
677 
678         // Move to the previous character and wait for an event.
679         AccessibilityEvent seventhExpected = getInstrumentation().getUiAutomation()
680                 .executeAndWaitForEvent(new Runnable() {
681             @Override
682             public void run() {
683                 text.performAction(
684                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
685             }
686         }, new UiAutomation.AccessibilityEventFilter() {
687             @Override
688             public boolean accept(AccessibilityEvent event) {
689                 return
690                 (event.getEventType() ==
691                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
692                         && event.getAction() ==
693                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
694                         && event.getPackageName().equals(getActivity().getPackageName())
695                         && event.getClassName().equals(TextView.class.getName())
696                         && event.getText().size() > 0
697                         && event.getText().get(0).toString().equals(getString(R.string.a_b))
698                         && event.getFromIndex() == 0
699                         && event.getToIndex() == 1
700                         && event.getMovementGranularity() ==
701                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
702             }
703         }, TIMEOUT_ASYNC_PROCESSING);
704 
705         // Make sure we got the expected event.
706         assertNotNull(seventhExpected);
707 
708         // Verify the selection position.
709         assertEquals(0, Selection.getSelectionStart(textView.getText()));
710         assertEquals(0, Selection.getSelectionEnd(textView.getText()));
711 
712         // Make sure there is no previous.
713         assertFalse(text.performAction(
714                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
715 
716         // Verify the selection position.
717         assertEquals(0, Selection.getSelectionStart(textView.getText()));
718         assertEquals(0, Selection.getSelectionEnd(textView.getText()));
719     }
720 
721     @MediumTest
testActionNextAndPreviousAtGranularityCharacterOverTextExtend()722     public void testActionNextAndPreviousAtGranularityCharacterOverTextExtend()
723             throws Exception {
724         final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
725 
726         getInstrumentation().runOnMainSync(new Runnable() {
727             @Override
728             public void run() {
729                 editText.setVisibility(View.VISIBLE);
730                 editText.setText(getString(R.string.a_b));
731                 Selection.removeSelection(editText.getText());
732             }
733         });
734 
735         final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
736                .getRootInActiveWindow().findAccessibilityNodeInfosByText(
737                        getString(R.string.a_b)).get(0);
738 
739         final int granularities = text.getMovementGranularities();
740         assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
741                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
742                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
743                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
744                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
745 
746         final Bundle arguments = new Bundle();
747         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
748                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
749         arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, true);
750 
751         // Move to the next character and wait for an event.
752         AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
753                 .executeAndWaitForEvent(new Runnable() {
754             @Override
755             public void run() {
756                 text.performAction(
757                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
758             }
759         }, new UiAutomation.AccessibilityEventFilter() {
760             @Override
761             public boolean accept(AccessibilityEvent event) {
762                 return
763                 (event.getEventType() ==
764                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
765                         && event.getAction() ==
766                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
767                         && event.getPackageName().equals(getActivity().getPackageName())
768                         && event.getClassName().equals(EditText.class.getName())
769                         && event.getText().size() > 0
770                         && event.getText().get(0).toString().equals(getString(R.string.a_b))
771                         && event.getFromIndex() == 0
772                         && event.getToIndex() == 1
773                         && event.getMovementGranularity() ==
774                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
775             }
776         }, TIMEOUT_ASYNC_PROCESSING);
777 
778         // Make sure we got the expected event.
779         assertNotNull(firstExpected);
780 
781         // Verify the selection position.
782         assertEquals(0, Selection.getSelectionStart(editText.getText()));
783         assertEquals(1, Selection.getSelectionEnd(editText.getText()));
784 
785         // Move to the next character and wait for an event.
786         AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
787                 .executeAndWaitForEvent(new Runnable() {
788             @Override
789             public void run() {
790                 text.performAction(
791                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
792             }
793         }, new UiAutomation.AccessibilityEventFilter() {
794             @Override
795             public boolean accept(AccessibilityEvent event) {
796                 return
797                 (event.getEventType() ==
798                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
799                         && event.getAction() ==
800                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
801                         && event.getPackageName().equals(getActivity().getPackageName())
802                         && event.getClassName().equals(EditText.class.getName())
803                         && event.getText().size() > 0
804                         && event.getText().get(0).toString().equals(getString(R.string.a_b))
805                         && event.getFromIndex() == 1
806                         && event.getToIndex() == 2
807                         && event.getMovementGranularity() ==
808                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
809             }
810         }, TIMEOUT_ASYNC_PROCESSING);
811 
812         // Make sure we got the expected event.
813         assertNotNull(secondExpected);
814 
815         // Verify the selection position.
816         assertEquals(0, Selection.getSelectionStart(editText.getText()));
817         assertEquals(2, Selection.getSelectionEnd(editText.getText()));
818 
819         // Move to the next character and wait for an event.
820         AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
821                 .executeAndWaitForEvent(new Runnable() {
822             @Override
823             public void run() {
824                 text.performAction(
825                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
826             }
827         }, new UiAutomation.AccessibilityEventFilter() {
828             @Override
829             public boolean accept(AccessibilityEvent event) {
830                 return
831                 (event.getEventType() ==
832                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
833                         && event.getAction() ==
834                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
835                         && event.getPackageName().equals(getActivity().getPackageName())
836                         && event.getClassName().equals(EditText.class.getName())
837                         && event.getText().size() > 0
838                         && event.getText().get(0).toString().equals(getString(R.string.a_b))
839                         && event.getFromIndex() == 2
840                         && event.getToIndex() == 3
841                         && event.getMovementGranularity() ==
842                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
843             }
844         }, TIMEOUT_ASYNC_PROCESSING);
845 
846         // Make sure we got the expected event.
847         assertNotNull(thirdExpected);
848 
849         // Verify the selection position.
850         assertEquals(0, Selection.getSelectionStart(editText.getText()));
851         assertEquals(3, Selection.getSelectionEnd(editText.getText()));
852 
853         // Make sure there is no next.
854         assertFalse(text.performAction(
855                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
856 
857         // Verify the selection position.
858         assertEquals(0, Selection.getSelectionStart(editText.getText()));
859         assertEquals(3, Selection.getSelectionEnd(editText.getText()));
860 
861         // Move to the previous character and wait for an event.
862         AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
863                 .executeAndWaitForEvent(new Runnable() {
864             @Override
865             public void run() {
866                 text.performAction(
867                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
868             }
869         }, new UiAutomation.AccessibilityEventFilter() {
870             @Override
871             public boolean accept(AccessibilityEvent event) {
872                 return
873                 (event.getEventType() ==
874                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
875                         && event.getAction() ==
876                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
877                         && event.getPackageName().equals(getActivity().getPackageName())
878                         && event.getClassName().equals(EditText.class.getName())
879                         && event.getText().size() > 0
880                         && event.getText().get(0).toString().equals(getString(R.string.a_b))
881                         && event.getFromIndex() == 2
882                         && event.getToIndex() == 3
883                         && event.getMovementGranularity() ==
884                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
885             }
886         }, TIMEOUT_ASYNC_PROCESSING);
887 
888         // Make sure we got the expected event.
889         assertNotNull(fourthExpected);
890 
891         // Verify the selection position.
892         assertEquals(0, Selection.getSelectionStart(editText.getText()));
893         assertEquals(2, Selection.getSelectionEnd(editText.getText()));
894 
895         // Move to the previous character and wait for an event.
896         AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
897                 .executeAndWaitForEvent(new Runnable() {
898             @Override
899             public void run() {
900                 text.performAction(
901                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
902             }
903         }, new UiAutomation.AccessibilityEventFilter() {
904             @Override
905             public boolean accept(AccessibilityEvent event) {
906                 return
907                 (event.getEventType() ==
908                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
909                         && event.getAction() ==
910                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
911                         && event.getPackageName().equals(getActivity().getPackageName())
912                         && event.getClassName().equals(EditText.class.getName())
913                         && event.getText().size() > 0
914                         && event.getText().get(0).toString().equals(getString(R.string.a_b))
915                         && event.getFromIndex() == 1
916                         && event.getToIndex() == 2
917                         && event.getMovementGranularity() ==
918                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
919             }
920         }, TIMEOUT_ASYNC_PROCESSING);
921 
922         // Make sure we got the expected event.
923         assertNotNull(fifthExpected);
924 
925         // Verify the selection position.
926         assertEquals(0, Selection.getSelectionStart(editText.getText()));
927         assertEquals(1, Selection.getSelectionEnd(editText.getText()));
928 
929         // Move to the previous character and wait for an event.
930         AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
931                 .executeAndWaitForEvent(new Runnable() {
932             @Override
933             public void run() {
934                 text.performAction(
935                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
936             }
937         }, new UiAutomation.AccessibilityEventFilter() {
938             @Override
939             public boolean accept(AccessibilityEvent event) {
940                 return
941                 (event.getEventType() ==
942                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
943                         && event.getAction() ==
944                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
945                         && event.getPackageName().equals(getActivity().getPackageName())
946                         && event.getClassName().equals(EditText.class.getName())
947                         && event.getText().size() > 0
948                         && event.getText().get(0).toString().equals(getString(R.string.a_b))
949                         && event.getFromIndex() == 0
950                         && event.getToIndex() == 1
951                         && event.getMovementGranularity() ==
952                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
953             }
954         }, TIMEOUT_ASYNC_PROCESSING);
955 
956         // Make sure we got the expected event.
957         assertNotNull(sixthExpected);
958 
959         // Verify the selection position.
960         assertEquals(0, Selection.getSelectionStart(editText.getText()));
961         assertEquals(0, Selection.getSelectionEnd(editText.getText()));
962 
963         // Make sure there is no previous.
964         assertFalse(text.performAction(
965                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
966 
967         // Verify the selection position.
968         assertEquals(0, Selection.getSelectionStart(editText.getText()));
969         assertEquals(0, Selection.getSelectionEnd(editText.getText()));
970 
971         // Focus the view so we can change selection.
972         getInstrumentation().runOnMainSync(new Runnable() {
973             @Override
974             public void run() {
975                 editText.setFocusable(true);
976                 editText.requestFocus();
977             }
978         });
979 
980         // Put selection at the end of the text.
981         Bundle setSelectionArgs = new Bundle();
982         setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 3);
983         setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 3);
984         assertTrue(text.performAction(
985                 AccessibilityNodeInfo.ACTION_SET_SELECTION, setSelectionArgs));
986 
987         // Verify the selection position.
988         assertEquals(3, Selection.getSelectionStart(editText.getText()));
989         assertEquals(3, Selection.getSelectionEnd(editText.getText()));
990 
991         // Unfocus the view so we can get rid of the soft-keyboard.
992         getInstrumentation().runOnMainSync(new Runnable() {
993             @Override
994             public void run() {
995                 editText.clearFocus();
996                 editText.setFocusable(false);
997             }
998         });
999 
1000         // Move to the previous character and wait for an event.
1001         AccessibilityEvent seventhExpected = getInstrumentation().getUiAutomation()
1002                 .executeAndWaitForEvent(new Runnable() {
1003             @Override
1004             public void run() {
1005                 text.performAction(
1006                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
1007             }
1008         }, new UiAutomation.AccessibilityEventFilter() {
1009             @Override
1010             public boolean accept(AccessibilityEvent event) {
1011                 return
1012                 (event.getEventType() ==
1013                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1014                         && event.getAction() ==
1015                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
1016                         && event.getPackageName().equals(getActivity().getPackageName())
1017                         && event.getClassName().equals(EditText.class.getName())
1018                         && event.getText().size() > 0
1019                         && event.getText().get(0).toString().equals(getString(R.string.a_b))
1020                         && event.getFromIndex() == 2
1021                         && event.getToIndex() == 3
1022                         && event.getMovementGranularity() ==
1023                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
1024             }
1025         }, TIMEOUT_ASYNC_PROCESSING);
1026 
1027         // Make sure we got the expected event.
1028         assertNotNull(seventhExpected);
1029 
1030         // Verify the selection position.
1031         assertEquals(3, Selection.getSelectionStart(editText.getText()));
1032         assertEquals(2, Selection.getSelectionEnd(editText.getText()));
1033 
1034         // Move to the previous character and wait for an event.
1035         AccessibilityEvent eightExpected = getInstrumentation().getUiAutomation()
1036                 .executeAndWaitForEvent(new Runnable() {
1037             @Override
1038             public void run() {
1039                 text.performAction(
1040                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
1041             }
1042         }, new UiAutomation.AccessibilityEventFilter() {
1043             @Override
1044             public boolean accept(AccessibilityEvent event) {
1045                 return
1046                 (event.getEventType() ==
1047                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1048                         && event.getAction() ==
1049                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
1050                         && event.getPackageName().equals(getActivity().getPackageName())
1051                         && event.getClassName().equals(EditText.class.getName())
1052                         && event.getText().size() > 0
1053                         && event.getText().get(0).toString().equals(getString(R.string.a_b))
1054                         && event.getFromIndex() == 1
1055                         && event.getToIndex() == 2
1056                         && event.getMovementGranularity() ==
1057                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
1058             }
1059         }, TIMEOUT_ASYNC_PROCESSING);
1060 
1061         // Make sure we got the expected event.
1062         assertNotNull(eightExpected);
1063 
1064         // Verify the selection position.
1065         assertEquals(3, Selection.getSelectionStart(editText.getText()));
1066         assertEquals(1, Selection.getSelectionEnd(editText.getText()));
1067 
1068         // Move to the previous character and wait for an event.
1069         AccessibilityEvent ninethExpected = getInstrumentation().getUiAutomation()
1070                 .executeAndWaitForEvent(new Runnable() {
1071             @Override
1072             public void run() {
1073                 text.performAction(
1074                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
1075             }
1076         }, new UiAutomation.AccessibilityEventFilter() {
1077             @Override
1078             public boolean accept(AccessibilityEvent event) {
1079                 return
1080                 (event.getEventType() ==
1081                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1082                         && event.getAction() ==
1083                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
1084                         && event.getPackageName().equals(getActivity().getPackageName())
1085                         && event.getClassName().equals(EditText.class.getName())
1086                         && event.getText().size() > 0
1087                         && event.getText().get(0).toString().equals(getString(R.string.a_b))
1088                         && event.getFromIndex() == 0
1089                         && event.getToIndex() == 1
1090                         && event.getMovementGranularity() ==
1091                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
1092             }
1093         }, TIMEOUT_ASYNC_PROCESSING);
1094 
1095         // Make sure we got the expected event.
1096         assertNotNull(ninethExpected);
1097 
1098         // Verify the selection position.
1099         assertEquals(3, Selection.getSelectionStart(editText.getText()));
1100         assertEquals(0, Selection.getSelectionEnd(editText.getText()));
1101 
1102         // Make sure there is no previous.
1103         assertFalse(text.performAction(
1104                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
1105 
1106         // Verify the selection position.
1107         assertEquals(3, Selection.getSelectionStart(editText.getText()));
1108         assertEquals(0, Selection.getSelectionEnd(editText.getText()));
1109 
1110         // Move to the next character and wait for an event.
1111         AccessibilityEvent tenthExpected = getInstrumentation().getUiAutomation()
1112                 .executeAndWaitForEvent(new Runnable() {
1113             @Override
1114             public void run() {
1115                 text.performAction(
1116                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
1117             }
1118         }, new UiAutomation.AccessibilityEventFilter() {
1119             @Override
1120             public boolean accept(AccessibilityEvent event) {
1121                 return
1122                 (event.getEventType() ==
1123                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1124                         && event.getAction() ==
1125                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
1126                         && event.getPackageName().equals(getActivity().getPackageName())
1127                         && event.getClassName().equals(EditText.class.getName())
1128                         && event.getText().size() > 0
1129                         && event.getText().get(0).toString().equals(getString(R.string.a_b))
1130                         && event.getFromIndex() == 0
1131                         && event.getToIndex() == 1
1132                         && event.getMovementGranularity() ==
1133                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
1134             }
1135         }, TIMEOUT_ASYNC_PROCESSING);
1136 
1137         // Make sure we got the expected event.
1138         assertNotNull(tenthExpected);
1139 
1140         // Verify the selection position.
1141         assertEquals(3, Selection.getSelectionStart(editText.getText()));
1142         assertEquals(1, Selection.getSelectionEnd(editText.getText()));
1143 
1144         // Move to the next character and wait for an event.
1145         AccessibilityEvent eleventhExpected = getInstrumentation().getUiAutomation()
1146                 .executeAndWaitForEvent(new Runnable() {
1147             @Override
1148             public void run() {
1149                 text.performAction(
1150                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
1151             }
1152         }, new UiAutomation.AccessibilityEventFilter() {
1153             @Override
1154             public boolean accept(AccessibilityEvent event) {
1155                 return
1156                 (event.getEventType() ==
1157                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1158                         && event.getAction() ==
1159                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
1160                         && event.getPackageName().equals(getActivity().getPackageName())
1161                         && event.getClassName().equals(EditText.class.getName())
1162                         && event.getText().size() > 0
1163                         && event.getText().get(0).toString().equals(getString(R.string.a_b))
1164                         && event.getFromIndex() == 1
1165                         && event.getToIndex() == 2
1166                         && event.getMovementGranularity() ==
1167                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
1168             }
1169         }, TIMEOUT_ASYNC_PROCESSING);
1170 
1171         // Make sure we got the expected event.
1172         assertNotNull(eleventhExpected);
1173 
1174         // Verify the selection position.
1175         assertEquals(3, Selection.getSelectionStart(editText.getText()));
1176         assertEquals(2, Selection.getSelectionEnd(editText.getText()));
1177 
1178         // Move to the next character and wait for an event.
1179         AccessibilityEvent twelvethExpected = getInstrumentation().getUiAutomation()
1180                 .executeAndWaitForEvent(new Runnable() {
1181             @Override
1182             public void run() {
1183                 text.performAction(
1184                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
1185             }
1186         }, new UiAutomation.AccessibilityEventFilter() {
1187             @Override
1188             public boolean accept(AccessibilityEvent event) {
1189                 return
1190                 (event.getEventType() ==
1191                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1192                         && event.getAction() ==
1193                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
1194                         && event.getPackageName().equals(getActivity().getPackageName())
1195                         && event.getClassName().equals(EditText.class.getName())
1196                         && event.getText().size() > 0
1197                         && event.getText().get(0).toString().equals(getString(R.string.a_b))
1198                         && event.getFromIndex() == 2
1199                         && event.getToIndex() == 3
1200                         && event.getMovementGranularity() ==
1201                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
1202             }
1203         }, TIMEOUT_ASYNC_PROCESSING);
1204 
1205         // Make sure we got the expected event.
1206         assertNotNull(twelvethExpected);
1207 
1208         // Verify the selection position.
1209         assertEquals(3, Selection.getSelectionStart(editText.getText()));
1210         assertEquals(3, Selection.getSelectionEnd(editText.getText()));
1211 
1212         // Make sure there is no next.
1213         assertFalse(text.performAction(
1214                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
1215 
1216         // Verify the selection position.
1217         assertEquals(3, Selection.getSelectionStart(editText.getText()));
1218         assertEquals(3, Selection.getSelectionEnd(editText.getText()));
1219     }
1220 
1221     @MediumTest
testActionNextAndPreviousAtGranularityWordOverText()1222     public void testActionNextAndPreviousAtGranularityWordOverText() throws Exception {
1223         final TextView textView = (TextView) getActivity().findViewById(R.id.text);
1224 
1225         getInstrumentation().runOnMainSync(new Runnable() {
1226             @Override
1227             public void run() {
1228                 textView.setVisibility(View.VISIBLE);
1229                 textView.setText(getString(R.string.foo_bar_baz));
1230             }
1231         });
1232 
1233         final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
1234                .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
1235                        R.string.foo_bar_baz)).get(0);
1236 
1237         final int granularities = text.getMovementGranularities();
1238         assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
1239                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
1240                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
1241                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
1242                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
1243 
1244         final Bundle arguments = new Bundle();
1245         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
1246                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1247 
1248         // Move to the next word and wait for an event.
1249         AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
1250                 .executeAndWaitForEvent(new Runnable() {
1251             @Override
1252             public void run() {
1253                 text.performAction(
1254                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
1255             }
1256         }, new UiAutomation.AccessibilityEventFilter() {
1257             @Override
1258             public boolean accept(AccessibilityEvent event) {
1259                 return
1260                 (event.getEventType() ==
1261                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1262                         && event.getAction() ==
1263                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
1264                         && event.getPackageName().equals(getActivity().getPackageName())
1265                         && event.getClassName().equals(TextView.class.getName())
1266                         && event.getText().size() > 0
1267                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
1268                         && event.getFromIndex() == 0
1269                         && event.getToIndex() == 3
1270                         && event.getMovementGranularity() ==
1271                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1272             }
1273         }, TIMEOUT_ASYNC_PROCESSING);
1274 
1275         // Make sure we got the expected event.
1276         assertNotNull(firstExpected);
1277 
1278         // Verify the selection position.
1279         assertEquals(3, Selection.getSelectionStart(textView.getText()));
1280         assertEquals(3, Selection.getSelectionEnd(textView.getText()));
1281 
1282         // Move to the next word and wait for an event.
1283         AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
1284                 .executeAndWaitForEvent(new Runnable() {
1285             @Override
1286             public void run() {
1287                 text.performAction(
1288                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
1289             }
1290         }, new UiAutomation.AccessibilityEventFilter() {
1291             @Override
1292             public boolean accept(AccessibilityEvent event) {
1293                 return
1294                 (event.getEventType() ==
1295                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1296                         && event.getAction() ==
1297                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
1298                         && event.getPackageName().equals(getActivity().getPackageName())
1299                         && event.getClassName().equals(TextView.class.getName())
1300                         && event.getText().size() > 0
1301                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
1302                         && event.getFromIndex() == 4
1303                         && event.getToIndex() == 7
1304                         && event.getMovementGranularity() ==
1305                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1306             }
1307         }, TIMEOUT_ASYNC_PROCESSING);
1308 
1309         // Make sure we got the expected event.
1310         assertNotNull(secondExpected);
1311 
1312         // Verify the selection position.
1313         assertEquals(7, Selection.getSelectionStart(textView.getText()));
1314         assertEquals(7, Selection.getSelectionEnd(textView.getText()));
1315 
1316         // Move to the next word and wait for an event.
1317         AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
1318                 .executeAndWaitForEvent(new Runnable() {
1319             @Override
1320             public void run() {
1321                 text.performAction(
1322                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
1323             }
1324         }, new UiAutomation.AccessibilityEventFilter() {
1325             @Override
1326             public boolean accept(AccessibilityEvent event) {
1327                 return
1328                 (event.getEventType() ==
1329                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1330                         && event.getAction() ==
1331                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
1332                         && event.getPackageName().equals(getActivity().getPackageName())
1333                         && event.getClassName().equals(TextView.class.getName())
1334                         && event.getText().size() > 0
1335                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
1336                         && event.getFromIndex() == 8
1337                         && event.getToIndex() == 11
1338                         && event.getMovementGranularity() ==
1339                                  AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1340             }
1341         }, TIMEOUT_ASYNC_PROCESSING);
1342 
1343         // Make sure we got the expected event.
1344         assertNotNull(thirdExpected);
1345 
1346         // Verify the selection position.
1347         assertEquals(11, Selection.getSelectionStart(textView.getText()));
1348         assertEquals(11, Selection.getSelectionEnd(textView.getText()));
1349 
1350         // Make sure there is no next.
1351         assertFalse(text.performAction(
1352                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
1353 
1354         // Verify the selection position.
1355         assertEquals(11, Selection.getSelectionStart(textView.getText()));
1356         assertEquals(11, Selection.getSelectionEnd(textView.getText()));
1357 
1358         // Move to the next word and wait for an event.
1359         AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
1360                 .executeAndWaitForEvent(new Runnable() {
1361             @Override
1362             public void run() {
1363                 text.performAction(
1364                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
1365             }
1366         }, new UiAutomation.AccessibilityEventFilter() {
1367             @Override
1368             public boolean accept(AccessibilityEvent event) {
1369                 return
1370                 (event.getEventType() ==
1371                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1372                         && event.getAction() ==
1373                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
1374                         && event.getPackageName().equals(getActivity().getPackageName())
1375                         && event.getClassName().equals(TextView.class.getName())
1376                         && event.getText().size() > 0
1377                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
1378                         && event.getFromIndex() == 8
1379                         && event.getToIndex() == 11
1380                         && event.getMovementGranularity() ==
1381                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1382             }
1383         }, TIMEOUT_ASYNC_PROCESSING);
1384 
1385         // Make sure we got the expected event.
1386         assertNotNull(fourthExpected);
1387 
1388         // Verify the selection position.
1389         assertEquals(8, Selection.getSelectionStart(textView.getText()));
1390         assertEquals(8, Selection.getSelectionEnd(textView.getText()));
1391 
1392         // Move to the next word and wait for an event.
1393         AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
1394                 .executeAndWaitForEvent(new Runnable() {
1395             @Override
1396             public void run() {
1397                 text.performAction(
1398                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
1399             }
1400         }, new UiAutomation.AccessibilityEventFilter() {
1401             @Override
1402             public boolean accept(AccessibilityEvent event) {
1403                 return
1404                 (event.getEventType() ==
1405                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1406                         && event.getAction() ==
1407                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
1408                         && event.getPackageName().equals(getActivity().getPackageName())
1409                         && event.getClassName().equals(TextView.class.getName())
1410                         && event.getText().size() > 0
1411                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
1412                         && event.getFromIndex() == 4
1413                         && event.getToIndex() == 7
1414                         && event.getMovementGranularity() ==
1415                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1416             }
1417         }, TIMEOUT_ASYNC_PROCESSING);
1418 
1419         // Make sure we got the expected event.
1420         assertNotNull(fifthExpected);
1421 
1422         // Verify the selection position.
1423         assertEquals(4, Selection.getSelectionStart(textView.getText()));
1424         assertEquals(4, Selection.getSelectionEnd(textView.getText()));
1425 
1426         // Move to the next character and wait for an event.
1427         AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
1428                 .executeAndWaitForEvent(new Runnable() {
1429             @Override
1430             public void run() {
1431                 text.performAction(
1432                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
1433             }
1434         }, new UiAutomation.AccessibilityEventFilter() {
1435             @Override
1436             public boolean accept(AccessibilityEvent event) {
1437                 return
1438                 (event.getEventType() ==
1439                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1440                         && event.getAction() ==
1441                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
1442                         && event.getPackageName().equals(getActivity().getPackageName())
1443                         && event.getClassName().equals(TextView.class.getName())
1444                         && event.getText().size() > 0
1445                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
1446                         && event.getFromIndex() == 0
1447                         && event.getToIndex() == 3
1448                         && event.getMovementGranularity() ==
1449                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1450             }
1451         }, TIMEOUT_ASYNC_PROCESSING);
1452 
1453         // Make sure we got the expected event.
1454         assertNotNull(sixthExpected);
1455 
1456         // Verify the selection position.
1457         assertEquals(0, Selection.getSelectionStart(textView.getText()));
1458         assertEquals(0, Selection.getSelectionEnd(textView.getText()));
1459 
1460         // Make sure there is no previous.
1461         assertFalse(text.performAction(
1462                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
1463 
1464         // Verify the selection position.
1465         assertEquals(0, Selection.getSelectionStart(textView.getText()));
1466         assertEquals(0, Selection.getSelectionEnd(textView.getText()));
1467     }
1468 
1469     @MediumTest
testActionNextAndPreviousAtGranularityWordOverEditTextWithContentDescription()1470     public void testActionNextAndPreviousAtGranularityWordOverEditTextWithContentDescription()
1471             throws Exception {
1472         final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
1473 
1474         getInstrumentation().runOnMainSync(new Runnable() {
1475             @Override
1476             public void run() {
1477                 editText.setVisibility(View.VISIBLE);
1478                 editText.setText(getString(R.string.foo_bar_baz));
1479                 editText.setContentDescription(getString(R.string.android_wiki));
1480             }
1481         });
1482 
1483         final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
1484                .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
1485                        R.string.foo_bar_baz)).get(0);
1486 
1487         final int granularities = text.getMovementGranularities();
1488         assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
1489                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
1490                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
1491                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
1492                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
1493 
1494         final Bundle arguments = new Bundle();
1495         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
1496                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1497 
1498         // Move to the next word and wait for an event.
1499         AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
1500                 .executeAndWaitForEvent(new Runnable() {
1501             @Override
1502             public void run() {
1503                 text.performAction(
1504                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
1505             }
1506         }, new UiAutomation.AccessibilityEventFilter() {
1507             @Override
1508             public boolean accept(AccessibilityEvent event) {
1509                 return
1510                 (event.getEventType() ==
1511                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1512                         && event.getAction() ==
1513                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
1514                         && event.getPackageName().equals(getActivity().getPackageName())
1515                         && event.getClassName().equals(EditText.class.getName())
1516                         && event.getText().size() > 0
1517                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
1518                         && event.getContentDescription().equals(getString(R.string.android_wiki))
1519                         && event.getFromIndex() == 0
1520                         && event.getToIndex() == 3
1521                         && event.getMovementGranularity() ==
1522                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1523             }
1524         }, TIMEOUT_ASYNC_PROCESSING);
1525 
1526         // Make sure we got the expected event.
1527         assertNotNull(firstExpected);
1528 
1529         // Verify the selection position.
1530         assertEquals(3, editText.getSelectionStart());
1531         assertEquals(3, editText.getSelectionEnd());
1532 
1533         // Move to the next word and wait for an event.
1534         AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
1535                 .executeAndWaitForEvent(new Runnable() {
1536             @Override
1537             public void run() {
1538                 text.performAction(
1539                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
1540             }
1541         }, new UiAutomation.AccessibilityEventFilter() {
1542             @Override
1543             public boolean accept(AccessibilityEvent event) {
1544                 return
1545                 (event.getEventType() ==
1546                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1547                         && event.getAction() ==
1548                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
1549                         && event.getPackageName().equals(getActivity().getPackageName())
1550                         && event.getClassName().equals(EditText.class.getName())
1551                         && event.getText().size() > 0
1552                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
1553                         && event.getContentDescription().equals(getString(R.string.android_wiki))
1554                         && event.getFromIndex() == 4
1555                         && event.getToIndex() == 7
1556                         && event.getMovementGranularity() ==
1557                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1558             }
1559         }, TIMEOUT_ASYNC_PROCESSING);
1560 
1561         // Make sure we got the expected event.
1562         assertNotNull(secondExpected);
1563 
1564         // Verify the selection position.
1565         assertEquals(7, editText.getSelectionStart());
1566         assertEquals(7, editText.getSelectionEnd());
1567 
1568         // Move to the next word and wait for an event.
1569         AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
1570                 .executeAndWaitForEvent(new Runnable() {
1571             @Override
1572             public void run() {
1573                 text.performAction(
1574                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
1575             }
1576         }, new UiAutomation.AccessibilityEventFilter() {
1577             @Override
1578             public boolean accept(AccessibilityEvent event) {
1579                 return
1580                 (event.getEventType() ==
1581                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1582                         && event.getAction() ==
1583                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
1584                         && event.getPackageName().equals(getActivity().getPackageName())
1585                         && event.getClassName().equals(EditText.class.getName())
1586                         && event.getText().size() > 0
1587                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
1588                         && event.getContentDescription().equals(getString(R.string.android_wiki))
1589                         && event.getFromIndex() == 8
1590                         && event.getToIndex() == 11
1591                         && event.getMovementGranularity() ==
1592                                  AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1593             }
1594         }, TIMEOUT_ASYNC_PROCESSING);
1595 
1596         // Make sure we got the expected event.
1597         assertNotNull(thirdExpected);
1598 
1599         // Verify the selection position.
1600         assertEquals(11, editText.getSelectionStart());
1601         assertEquals(11, editText.getSelectionEnd());
1602 
1603         // Make sure there is no next.
1604         assertFalse(text.performAction(
1605                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
1606 
1607         // Verify the selection position.
1608         assertEquals(11, editText.getSelectionStart());
1609         assertEquals(11, editText.getSelectionEnd());
1610 
1611         // Move to the next word and wait for an event.
1612         AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
1613                 .executeAndWaitForEvent(new Runnable() {
1614             @Override
1615             public void run() {
1616                 text.performAction(
1617                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
1618             }
1619         }, new UiAutomation.AccessibilityEventFilter() {
1620             @Override
1621             public boolean accept(AccessibilityEvent event) {
1622                 return
1623                 (event.getEventType() ==
1624                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1625                         && event.getAction() ==
1626                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
1627                         && event.getPackageName().equals(getActivity().getPackageName())
1628                         && event.getClassName().equals(EditText.class.getName())
1629                         && event.getText().size() > 0
1630                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
1631                         && event.getContentDescription().equals(getString(R.string.android_wiki))
1632                         && event.getFromIndex() == 8
1633                         && event.getToIndex() == 11
1634                         && event.getMovementGranularity() ==
1635                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1636             }
1637         }, TIMEOUT_ASYNC_PROCESSING);
1638 
1639         // Make sure we got the expected event.
1640         assertNotNull(fourthExpected);
1641 
1642         // Verify the selection position.
1643         assertEquals(8, editText.getSelectionStart());
1644         assertEquals(8, editText.getSelectionEnd());
1645 
1646         // Move to the next word and wait for an event.
1647         AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
1648                 .executeAndWaitForEvent(new Runnable() {
1649             @Override
1650             public void run() {
1651                 text.performAction(
1652                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
1653             }
1654         }, new UiAutomation.AccessibilityEventFilter() {
1655             @Override
1656             public boolean accept(AccessibilityEvent event) {
1657                 return
1658                 (event.getEventType() ==
1659                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1660                         && event.getAction() ==
1661                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
1662                         && event.getPackageName().equals(getActivity().getPackageName())
1663                         && event.getClassName().equals(EditText.class.getName())
1664                         && event.getText().size() > 0
1665                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
1666                         && event.getContentDescription().equals(getString(R.string.android_wiki))
1667                         && event.getFromIndex() == 4
1668                         && event.getToIndex() == 7
1669                         && event.getMovementGranularity() ==
1670                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1671             }
1672         }, TIMEOUT_ASYNC_PROCESSING);
1673 
1674         // Make sure we got the expected event.
1675         assertNotNull(fifthExpected);
1676 
1677         // Verify the selection position.
1678         assertEquals(4, editText.getSelectionStart());
1679         assertEquals(4, editText.getSelectionEnd());
1680 
1681         // Move to the next character and wait for an event.
1682         AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
1683                 .executeAndWaitForEvent(new Runnable() {
1684             @Override
1685             public void run() {
1686                 text.performAction(
1687                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
1688             }
1689         }, new UiAutomation.AccessibilityEventFilter() {
1690             @Override
1691             public boolean accept(AccessibilityEvent event) {
1692                 return
1693                 (event.getEventType() ==
1694                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1695                         && event.getAction() ==
1696                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
1697                         && event.getPackageName().equals(getActivity().getPackageName())
1698                         && event.getClassName().equals(EditText.class.getName())
1699                         && event.getText().size() > 0
1700                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
1701                         && event.getContentDescription().equals(getString(R.string.android_wiki))
1702                         && event.getFromIndex() == 0
1703                         && event.getToIndex() == 3
1704                         && event.getMovementGranularity() ==
1705                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1706             }
1707         }, TIMEOUT_ASYNC_PROCESSING);
1708 
1709         // Make sure we got the expected event.
1710         assertNotNull(sixthExpected);
1711 
1712         // Verify the selection position.
1713         assertEquals(0, editText.getSelectionStart());
1714         assertEquals(0, editText.getSelectionEnd());
1715 
1716         // Make sure there is no previous.
1717         assertFalse(text.performAction(
1718                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
1719 
1720         // Verify the selection position.
1721         assertEquals(0, editText.getSelectionStart());
1722         assertEquals(0, editText.getSelectionEnd());
1723     }
1724 
1725     @MediumTest
testActionNextAndPreviousAtGranularityWordOverTextExtend()1726     public void testActionNextAndPreviousAtGranularityWordOverTextExtend() throws Exception {
1727         final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
1728 
1729         getInstrumentation().runOnMainSync(new Runnable() {
1730             @Override
1731             public void run() {
1732                 editText.setVisibility(View.VISIBLE);
1733                 editText.setText(getString(R.string.foo_bar_baz));
1734                 Selection.removeSelection(editText.getText());
1735             }
1736         });
1737 
1738         final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
1739                .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
1740                        R.string.foo_bar_baz)).get(0);
1741 
1742         final int granularities = text.getMovementGranularities();
1743         assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
1744                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
1745                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
1746                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
1747                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
1748 
1749         final Bundle arguments = new Bundle();
1750         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
1751                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1752         arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, true);
1753 
1754         // Move to the next word and wait for an event.
1755         AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
1756                 .executeAndWaitForEvent(new Runnable() {
1757             @Override
1758             public void run() {
1759                 text.performAction(
1760                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
1761             }
1762         }, new UiAutomation.AccessibilityEventFilter() {
1763             @Override
1764             public boolean accept(AccessibilityEvent event) {
1765                 return
1766                 (event.getEventType() ==
1767                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1768                         && event.getAction() ==
1769                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
1770                         && event.getPackageName().equals(getActivity().getPackageName())
1771                         && event.getClassName().equals(EditText.class.getName())
1772                         && event.getText().size() > 0
1773                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
1774                         && event.getFromIndex() == 0
1775                         && event.getToIndex() == 3
1776                         && event.getMovementGranularity() ==
1777                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1778             }
1779         }, TIMEOUT_ASYNC_PROCESSING);
1780 
1781         // Make sure we got the expected event.
1782         assertNotNull(firstExpected);
1783 
1784         // Verify the selection position.
1785         assertEquals(0, Selection.getSelectionStart(editText.getText()));
1786         assertEquals(3, Selection.getSelectionEnd(editText.getText()));
1787 
1788         // Move to the next word and wait for an event.
1789         AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
1790                 .executeAndWaitForEvent(new Runnable() {
1791             @Override
1792             public void run() {
1793                 text.performAction(
1794                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
1795             }
1796         }, new UiAutomation.AccessibilityEventFilter() {
1797             @Override
1798             public boolean accept(AccessibilityEvent event) {
1799                 return
1800                 (event.getEventType() ==
1801                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1802                         && event.getAction() ==
1803                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
1804                         && event.getPackageName().equals(getActivity().getPackageName())
1805                         && event.getClassName().equals(EditText.class.getName())
1806                         && event.getText().size() > 0
1807                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
1808                         && event.getFromIndex() == 4
1809                         && event.getToIndex() == 7
1810                         && event.getMovementGranularity() ==
1811                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1812             }
1813         }, TIMEOUT_ASYNC_PROCESSING);
1814 
1815         // Make sure we got the expected event.
1816         assertNotNull(secondExpected);
1817 
1818         // Verify the selection position.
1819         assertEquals(0, Selection.getSelectionStart(editText.getText()));
1820         assertEquals(7, Selection.getSelectionEnd(editText.getText()));
1821 
1822         // Move to the next word and wait for an event.
1823         AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
1824                 .executeAndWaitForEvent(new Runnable() {
1825             @Override
1826             public void run() {
1827                 text.performAction(
1828                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
1829             }
1830         }, new UiAutomation.AccessibilityEventFilter() {
1831             @Override
1832             public boolean accept(AccessibilityEvent event) {
1833                 return
1834                 (event.getEventType() ==
1835                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1836                         && event.getAction() ==
1837                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
1838                         && event.getPackageName().equals(getActivity().getPackageName())
1839                         && event.getClassName().equals(EditText.class.getName())
1840                         && event.getText().size() > 0
1841                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
1842                         && event.getFromIndex() == 8
1843                         && event.getToIndex() == 11
1844                         && event.getMovementGranularity() ==
1845                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1846             }
1847         }, TIMEOUT_ASYNC_PROCESSING);
1848 
1849         // Make sure we got the expected event.
1850         assertNotNull(thirdExpected);
1851 
1852         // Verify the selection position.
1853         assertEquals(0, Selection.getSelectionStart(editText.getText()));
1854         assertEquals(11, Selection.getSelectionEnd(editText.getText()));
1855 
1856         // Make sure there is no next.
1857         assertFalse(text.performAction(
1858                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
1859 
1860         // Move to the previous word and wait for an event.
1861         AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
1862                 .executeAndWaitForEvent(new Runnable() {
1863             @Override
1864             public void run() {
1865                 text.performAction(
1866                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
1867             }
1868         }, new UiAutomation.AccessibilityEventFilter() {
1869             @Override
1870             public boolean accept(AccessibilityEvent event) {
1871                 return
1872                 (event.getEventType() ==
1873                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1874                         && event.getAction() ==
1875                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
1876                         && event.getPackageName().equals(getActivity().getPackageName())
1877                         && event.getClassName().equals(EditText.class.getName())
1878                         && event.getText().size() > 0
1879                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
1880                         && event.getFromIndex() == 8
1881                         && event.getToIndex() == 11
1882                         && event.getMovementGranularity() ==
1883                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1884             }
1885         }, TIMEOUT_ASYNC_PROCESSING);
1886 
1887         // Make sure we got the expected event.
1888         assertNotNull(fourthExpected);
1889 
1890         // Verify the selection position.
1891         assertEquals(0, Selection.getSelectionStart(editText.getText()));
1892         assertEquals(8, Selection.getSelectionEnd(editText.getText()));
1893 
1894         // Move to the previous word and wait for an event.
1895         AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
1896                 .executeAndWaitForEvent(new Runnable() {
1897             @Override
1898             public void run() {
1899                 text.performAction(
1900                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
1901             }
1902         }, new UiAutomation.AccessibilityEventFilter() {
1903             @Override
1904             public boolean accept(AccessibilityEvent event) {
1905                 return
1906                 (event.getEventType() ==
1907                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1908                         && event.getAction() ==
1909                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
1910                         && event.getPackageName().equals(getActivity().getPackageName())
1911                         && event.getClassName().equals(EditText.class.getName())
1912                         && event.getText().size() > 0
1913                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
1914                         && event.getFromIndex() == 4
1915                         && event.getToIndex() == 7
1916                         && event.getMovementGranularity() ==
1917                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1918             }
1919         }, TIMEOUT_ASYNC_PROCESSING);
1920 
1921         // Make sure we got the expected event.
1922         assertNotNull(fifthExpected);
1923 
1924         // Verify the selection position.
1925         assertEquals(0, Selection.getSelectionStart(editText.getText()));
1926         assertEquals(4, Selection.getSelectionEnd(editText.getText()));
1927 
1928         // Move to the previous character and wait for an event.
1929         AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
1930                 .executeAndWaitForEvent(new Runnable() {
1931             @Override
1932             public void run() {
1933                 text.performAction(
1934                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
1935             }
1936         }, new UiAutomation.AccessibilityEventFilter() {
1937             @Override
1938             public boolean accept(AccessibilityEvent event) {
1939                 return
1940                 (event.getEventType() ==
1941                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
1942                         && event.getAction() ==
1943                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
1944                         && event.getPackageName().equals(getActivity().getPackageName())
1945                         && event.getClassName().equals(EditText.class.getName())
1946                         && event.getText().size() > 0
1947                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
1948                         && event.getFromIndex() == 0
1949                         && event.getToIndex() == 3
1950                         && event.getMovementGranularity() ==
1951                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
1952             }
1953         }, TIMEOUT_ASYNC_PROCESSING);
1954 
1955         // Make sure we got the expected event.
1956         assertNotNull(sixthExpected);
1957 
1958         // Verify the selection position.
1959         assertEquals(0, Selection.getSelectionStart(editText.getText()));
1960         assertEquals(0, Selection.getSelectionEnd(editText.getText()));
1961 
1962         // Make sure there is no previous.
1963         assertFalse(text.performAction(
1964                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
1965 
1966         // Verify the selection position.
1967         assertEquals(0, Selection.getSelectionStart(editText.getText()));
1968         assertEquals(0, Selection.getSelectionEnd(editText.getText()));
1969 
1970         // Focus the view so we can change selection.
1971         getInstrumentation().runOnMainSync(new Runnable() {
1972             @Override
1973             public void run() {
1974                 editText.setFocusable(true);
1975                 editText.requestFocus();
1976             }
1977         });
1978 
1979         // Put selection at the end of the text.
1980         Bundle setSelectionArgs = new Bundle();
1981         setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 11);
1982         setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 11);
1983         assertTrue(text.performAction(
1984                 AccessibilityNodeInfo.ACTION_SET_SELECTION, setSelectionArgs));
1985 
1986         // Verify the selection position.
1987         assertEquals(11, Selection.getSelectionStart(editText.getText()));
1988         assertEquals(11, Selection.getSelectionEnd(editText.getText()));
1989 
1990         // Unfocus the view so we can get rid of the soft-keyboard.
1991         getInstrumentation().runOnMainSync(new Runnable() {
1992             @Override
1993             public void run() {
1994                 editText.clearFocus();
1995                 editText.setFocusable(false);
1996             }
1997         });
1998 
1999         // Move to the previous word and wait for an event.
2000         AccessibilityEvent seventhExpected = getInstrumentation().getUiAutomation()
2001                 .executeAndWaitForEvent(new Runnable() {
2002             @Override
2003             public void run() {
2004                 text.performAction(
2005                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
2006             }
2007         }, new UiAutomation.AccessibilityEventFilter() {
2008             @Override
2009             public boolean accept(AccessibilityEvent event) {
2010                 return
2011                 (event.getEventType() ==
2012                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2013                         && event.getAction() ==
2014                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
2015                         && event.getPackageName().equals(getActivity().getPackageName())
2016                         && event.getClassName().equals(EditText.class.getName())
2017                         && event.getText().size() > 0
2018                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
2019                         && event.getFromIndex() == 8
2020                         && event.getToIndex() == 11
2021                         && event.getMovementGranularity() ==
2022                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
2023             }
2024         }, TIMEOUT_ASYNC_PROCESSING);
2025 
2026         // Make sure we got the expected event.
2027         assertNotNull(seventhExpected);
2028 
2029         // Verify the selection position.
2030         assertEquals(11, Selection.getSelectionStart(editText.getText()));
2031         assertEquals(8, Selection.getSelectionEnd(editText.getText()));
2032 
2033         // Move to the previous word and wait for an event.
2034         AccessibilityEvent eightExpected = getInstrumentation().getUiAutomation()
2035                 .executeAndWaitForEvent(new Runnable() {
2036             @Override
2037             public void run() {
2038                 text.performAction(
2039                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
2040             }
2041         }, new UiAutomation.AccessibilityEventFilter() {
2042             @Override
2043             public boolean accept(AccessibilityEvent event) {
2044                 return
2045                 (event.getEventType() ==
2046                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2047                         && event.getAction() ==
2048                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
2049                         && event.getPackageName().equals(getActivity().getPackageName())
2050                         && event.getClassName().equals(EditText.class.getName())
2051                         && event.getText().size() > 0
2052                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
2053                         && event.getFromIndex() == 4
2054                         && event.getToIndex() == 7
2055                         && event.getMovementGranularity() ==
2056                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
2057             }
2058         }, TIMEOUT_ASYNC_PROCESSING);
2059 
2060         // Make sure we got the expected event.
2061         assertNotNull(eightExpected);
2062 
2063         // Verify the selection position.
2064         assertEquals(11, Selection.getSelectionStart(editText.getText()));
2065         assertEquals(4, Selection.getSelectionEnd(editText.getText()));
2066 
2067         // Move to the previous character and wait for an event.
2068         AccessibilityEvent ninethExpected = getInstrumentation().getUiAutomation()
2069                 .executeAndWaitForEvent(new Runnable() {
2070             @Override
2071             public void run() {
2072                 text.performAction(
2073                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
2074             }
2075         }, new UiAutomation.AccessibilityEventFilter() {
2076             @Override
2077             public boolean accept(AccessibilityEvent event) {
2078                 return
2079                 (event.getEventType() ==
2080                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2081                         && event.getAction() ==
2082                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
2083                         && event.getPackageName().equals(getActivity().getPackageName())
2084                         && event.getClassName().equals(EditText.class.getName())
2085                         && event.getText().size() > 0
2086                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
2087                         && event.getFromIndex() == 0
2088                         && event.getToIndex() == 3
2089                         && event.getMovementGranularity() ==
2090                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
2091             }
2092         }, TIMEOUT_ASYNC_PROCESSING);
2093 
2094         // Make sure we got the expected event.
2095         assertNotNull(ninethExpected);
2096 
2097         // Verify the selection position.
2098         assertEquals(11, Selection.getSelectionStart(editText.getText()));
2099         assertEquals(0, Selection.getSelectionEnd(editText.getText()));
2100 
2101         // Make sure there is no previous.
2102         assertFalse(text.performAction(
2103                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
2104 
2105         // Verify the selection position.
2106         assertEquals(11, Selection.getSelectionStart(editText.getText()));
2107         assertEquals(0, Selection.getSelectionEnd(editText.getText()));
2108 
2109         // Move to the next word and wait for an event.
2110         AccessibilityEvent tenthExpected = getInstrumentation().getUiAutomation()
2111                 .executeAndWaitForEvent(new Runnable() {
2112             @Override
2113             public void run() {
2114                 text.performAction(
2115                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
2116             }
2117         }, new UiAutomation.AccessibilityEventFilter() {
2118             @Override
2119             public boolean accept(AccessibilityEvent event) {
2120                 return
2121                 (event.getEventType() ==
2122                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2123                         && event.getAction() ==
2124                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
2125                         && event.getPackageName().equals(getActivity().getPackageName())
2126                         && event.getClassName().equals(EditText.class.getName())
2127                         && event.getText().size() > 0
2128                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
2129                         && event.getFromIndex() == 0
2130                         && event.getToIndex() == 3
2131                         && event.getMovementGranularity() ==
2132                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
2133             }
2134         }, TIMEOUT_ASYNC_PROCESSING);
2135 
2136         // Make sure we got the expected event.
2137         assertNotNull(tenthExpected);
2138 
2139         // Verify the selection position.
2140         assertEquals(11, Selection.getSelectionStart(editText.getText()));
2141         assertEquals(3, Selection.getSelectionEnd(editText.getText()));
2142 
2143         // Move to the next word and wait for an event.
2144         AccessibilityEvent eleventhExpected = getInstrumentation().getUiAutomation()
2145                 .executeAndWaitForEvent(new Runnable() {
2146             @Override
2147             public void run() {
2148                 text.performAction(
2149                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
2150             }
2151         }, new UiAutomation.AccessibilityEventFilter() {
2152             @Override
2153             public boolean accept(AccessibilityEvent event) {
2154                 return
2155                 (event.getEventType() ==
2156                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2157                         && event.getAction() ==
2158                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
2159                         && event.getPackageName().equals(getActivity().getPackageName())
2160                         && event.getClassName().equals(EditText.class.getName())
2161                         && event.getText().size() > 0
2162                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
2163                         && event.getFromIndex() == 4
2164                         && event.getToIndex() == 7
2165                         && event.getMovementGranularity() ==
2166                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
2167             }
2168         }, TIMEOUT_ASYNC_PROCESSING);
2169 
2170         // Make sure we got the expected event.
2171         assertNotNull(eleventhExpected);
2172 
2173         // Verify the selection position.
2174         assertEquals(11, Selection.getSelectionStart(editText.getText()));
2175         assertEquals(7, Selection.getSelectionEnd(editText.getText()));
2176 
2177         // Move to the next word and wait for an event.
2178         AccessibilityEvent twelvthExpected = getInstrumentation().getUiAutomation()
2179                 .executeAndWaitForEvent(new Runnable() {
2180             @Override
2181             public void run() {
2182                 text.performAction(
2183                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
2184             }
2185         }, new UiAutomation.AccessibilityEventFilter() {
2186             @Override
2187             public boolean accept(AccessibilityEvent event) {
2188                 return
2189                 (event.getEventType() ==
2190                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2191                         && event.getAction() ==
2192                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
2193                         && event.getPackageName().equals(getActivity().getPackageName())
2194                         && event.getClassName().equals(EditText.class.getName())
2195                         && event.getText().size() > 0
2196                         && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
2197                         && event.getFromIndex() == 8
2198                         && event.getToIndex() == 11
2199                         && event.getMovementGranularity() ==
2200                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
2201             }
2202         }, TIMEOUT_ASYNC_PROCESSING);
2203 
2204         // Make sure we got the expected event.
2205         assertNotNull(twelvthExpected);
2206 
2207         // Verify the selection position.
2208         assertEquals(11, Selection.getSelectionStart(editText.getText()));
2209         assertEquals(11, Selection.getSelectionEnd(editText.getText()));
2210 
2211         // Make sure there is no next.
2212         assertFalse(text.performAction(
2213                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
2214 
2215         // Verify the selection position.
2216         assertEquals(11, Selection.getSelectionStart(editText.getText()));
2217         assertEquals(11, Selection.getSelectionEnd(editText.getText()));
2218     }
2219 
2220     @MediumTest
testActionNextAndPreviousAtGranularityLineOverText()2221     public void testActionNextAndPreviousAtGranularityLineOverText() throws Exception {
2222         final TextView textView = (TextView) getActivity().findViewById(R.id.text);
2223 
2224         getInstrumentation().runOnMainSync(new Runnable() {
2225             @Override
2226             public void run() {
2227                 textView.setVisibility(View.VISIBLE);
2228                 textView.setText(getString(R.string.android_wiki_short));
2229             }
2230         });
2231 
2232         final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
2233                .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
2234                        R.string.android_wiki_short)).get(0);
2235 
2236         final int granularities = text.getMovementGranularities();
2237         assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
2238                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
2239                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
2240                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
2241                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
2242 
2243         final Bundle arguments = new Bundle();
2244         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
2245                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
2246 
2247         // Move to the next line and wait for an event.
2248         AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
2249                 .executeAndWaitForEvent(new Runnable() {
2250             @Override
2251             public void run() {
2252                 text.performAction(
2253                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
2254             }
2255         }, new UiAutomation.AccessibilityEventFilter() {
2256             @Override
2257             public boolean accept(AccessibilityEvent event) {
2258                 return
2259                 (event.getEventType() ==
2260                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2261                         && event.getAction() ==
2262                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
2263                         && event.getPackageName().equals(getActivity().getPackageName())
2264                         && event.getClassName().equals(TextView.class.getName())
2265                         && event.getText().size() > 0
2266                         && event.getText().get(0).toString().equals(getString(
2267                                 R.string.android_wiki_short))
2268                         && event.getFromIndex() == 0
2269                         && event.getToIndex() == 13
2270                         && event.getMovementGranularity() ==
2271                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
2272             }
2273         }, TIMEOUT_ASYNC_PROCESSING);
2274 
2275         // Make sure we got the expected event.
2276         assertNotNull(firstExpected);
2277 
2278         // Verify the selection position.
2279         assertEquals(13, Selection.getSelectionStart(textView.getText()));
2280         assertEquals(13, Selection.getSelectionEnd(textView.getText()));
2281 
2282         // Move to the next line and wait for an event.
2283         AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
2284                 .executeAndWaitForEvent(new Runnable() {
2285             @Override
2286             public void run() {
2287                 text.performAction(
2288                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
2289             }
2290         }, new UiAutomation.AccessibilityEventFilter() {
2291             @Override
2292             public boolean accept(AccessibilityEvent event) {
2293                 return
2294                 (event.getEventType() ==
2295                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2296                         && event.getAction() ==
2297                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
2298                         && event.getPackageName().equals(getActivity().getPackageName())
2299                         && event.getClassName().equals(TextView.class.getName())
2300                         && event.getText().size() > 0
2301                         && event.getText().get(0).toString().equals(getString(
2302                                 R.string.android_wiki_short))
2303                         && event.getFromIndex() == 13
2304                         && event.getToIndex() == 25
2305                         && event.getMovementGranularity() ==
2306                                  AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
2307             }
2308         }, TIMEOUT_ASYNC_PROCESSING);
2309 
2310         // Make sure we got the expected event.
2311         assertNotNull(secondExpected);
2312 
2313         // Verify the selection position.
2314         assertEquals(25, Selection.getSelectionStart(textView.getText()));
2315         assertEquals(25, Selection.getSelectionEnd(textView.getText()));
2316 
2317         // Move to the next line and wait for an event.
2318         AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
2319                 .executeAndWaitForEvent(new Runnable() {
2320             @Override
2321             public void run() {
2322                 text.performAction(
2323                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
2324             }
2325         }, new UiAutomation.AccessibilityEventFilter() {
2326             @Override
2327             public boolean accept(AccessibilityEvent event) {
2328                 return
2329                 (event.getEventType() ==
2330                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2331                         && event.getAction() ==
2332                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
2333                         && event.getPackageName().equals(getActivity().getPackageName())
2334                         && event.getClassName().equals(TextView.class.getName())
2335                         && event.getText().size() > 0
2336                         && event.getText().get(0).toString().equals(getString(
2337                                 R.string.android_wiki_short))
2338                         && event.getFromIndex() == 25
2339                         && event.getToIndex() == 34
2340                         && event.getMovementGranularity() ==
2341                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
2342             }
2343         }, TIMEOUT_ASYNC_PROCESSING);
2344 
2345         // Make sure we got the expected event.
2346         assertNotNull(thirdExpected);
2347 
2348         // Verify the selection position.
2349         assertEquals(34, Selection.getSelectionStart(textView.getText()));
2350         assertEquals(34, Selection.getSelectionEnd(textView.getText()));
2351 
2352         // Make sure there is no next.
2353         assertFalse(text.performAction(
2354                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
2355 
2356         // Verify the selection position.
2357         assertEquals(34, Selection.getSelectionStart(textView.getText()));
2358         assertEquals(34, Selection.getSelectionEnd(textView.getText()));
2359 
2360         // Move to the previous line and wait for an event.
2361         AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
2362                 .executeAndWaitForEvent(new Runnable() {
2363             @Override
2364             public void run() {
2365                 text.performAction(
2366                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
2367             }
2368         }, new UiAutomation.AccessibilityEventFilter() {
2369             @Override
2370             public boolean accept(AccessibilityEvent event) {
2371                 return
2372                 (event.getEventType() ==
2373                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2374                         && event.getAction() ==
2375                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
2376                         && event.getPackageName().equals(getActivity().getPackageName())
2377                         && event.getClassName().equals(TextView.class.getName())
2378                         && event.getText().size() > 0
2379                         && event.getText().get(0).toString().equals(getString(
2380                                 R.string.android_wiki_short))
2381                         && event.getFromIndex() == 25
2382                         && event.getToIndex() == 34
2383                         && event.getMovementGranularity() ==
2384                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
2385             }
2386         }, TIMEOUT_ASYNC_PROCESSING);
2387 
2388         // Make sure we got the expected event.
2389         assertNotNull(fourthExpected);
2390 
2391         // Verify the selection position.
2392         assertEquals(25, Selection.getSelectionStart(textView.getText()));
2393         assertEquals(25, Selection.getSelectionEnd(textView.getText()));
2394 
2395         // Move to the previous line and wait for an event.
2396         AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
2397                 .executeAndWaitForEvent(new Runnable() {
2398             @Override
2399             public void run() {
2400                 text.performAction(
2401                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
2402             }
2403         }, new UiAutomation.AccessibilityEventFilter() {
2404             @Override
2405             public boolean accept(AccessibilityEvent event) {
2406                 return
2407                 (event.getEventType() ==
2408                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2409                         && event.getAction() ==
2410                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
2411                         && event.getPackageName().equals(getActivity().getPackageName())
2412                         && event.getClassName().equals(TextView.class.getName())
2413                         && event.getText().size() > 0
2414                         && event.getText().get(0).toString().equals(getString(
2415                                 R.string.android_wiki_short))
2416                         && event.getFromIndex() == 13
2417                         && event.getToIndex() == 25
2418                         && event.getMovementGranularity() ==
2419                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
2420             }
2421         }, TIMEOUT_ASYNC_PROCESSING);
2422 
2423         // Make sure we got the expected event.
2424         assertNotNull(fifthExpected);
2425 
2426         // Verify the selection position.
2427         assertEquals(13, Selection.getSelectionStart(textView.getText()));
2428         assertEquals(13, Selection.getSelectionEnd(textView.getText()));
2429 
2430         // Move to the previous line and wait for an event.
2431         AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
2432                 .executeAndWaitForEvent(new Runnable() {
2433             @Override
2434             public void run() {
2435                 text.performAction(
2436                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
2437             }
2438         }, new UiAutomation.AccessibilityEventFilter() {
2439             @Override
2440             public boolean accept(AccessibilityEvent event) {
2441                 return
2442                 (event.getEventType() ==
2443                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2444                         && event.getAction() ==
2445                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
2446                         && event.getPackageName().equals(getActivity().getPackageName())
2447                         && event.getClassName().equals(TextView.class.getName())
2448                         && event.getText().size() > 0
2449                         && event.getText().get(0).toString().equals(getString(
2450                                 R.string.android_wiki_short))
2451                         && event.getFromIndex() == 0
2452                         && event.getToIndex() == 13
2453                         && event.getMovementGranularity() ==
2454                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
2455             }
2456         }, TIMEOUT_ASYNC_PROCESSING);
2457 
2458         // Make sure we got the expected event.
2459         assertNotNull(sixthExpected);
2460 
2461         // Verify the selection position.
2462         assertEquals(0, Selection.getSelectionStart(textView.getText()));
2463         assertEquals(0, Selection.getSelectionEnd(textView.getText()));
2464 
2465         // Make sure there is no previous.
2466         assertFalse(text.performAction(
2467                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
2468 
2469         // Verify the selection position.
2470         assertEquals(0, Selection.getSelectionStart(textView.getText()));
2471         assertEquals(0, Selection.getSelectionEnd(textView.getText()));
2472     }
2473 
2474     @MediumTest
testActionNextAndPreviousAtGranularityLineOverTextExtend()2475     public void testActionNextAndPreviousAtGranularityLineOverTextExtend() throws Exception {
2476         final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
2477 
2478         getInstrumentation().runOnMainSync(new Runnable() {
2479             @Override
2480             public void run() {
2481                 editText.setVisibility(View.VISIBLE);
2482                 editText.setText(getString(R.string.android_wiki_short));
2483                 Selection.removeSelection(editText.getText());
2484             }
2485         });
2486 
2487         final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
2488                .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
2489                        R.string.android_wiki_short)).get(0);
2490 
2491         final int granularities = text.getMovementGranularities();
2492         assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
2493                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
2494                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
2495                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
2496                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
2497 
2498         final Bundle arguments = new Bundle();
2499         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
2500                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
2501         arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, true);
2502 
2503         // Move to the next line and wait for an event.
2504         AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
2505                 .executeAndWaitForEvent(new Runnable() {
2506             @Override
2507             public void run() {
2508                 text.performAction(
2509                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
2510             }
2511         }, new UiAutomation.AccessibilityEventFilter() {
2512             @Override
2513             public boolean accept(AccessibilityEvent event) {
2514                 return
2515                 (event.getEventType() ==
2516                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2517                         && event.getAction() ==
2518                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
2519                         && event.getPackageName().equals(getActivity().getPackageName())
2520                         && event.getClassName().equals(EditText.class.getName())
2521                         && event.getText().size() > 0
2522                         && event.getText().get(0).toString().equals(getString(
2523                                 R.string.android_wiki_short))
2524                         && event.getFromIndex() == 0
2525                         && event.getToIndex() == 13
2526                         && event.getMovementGranularity() ==
2527                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
2528             }
2529         }, TIMEOUT_ASYNC_PROCESSING);
2530 
2531         // Make sure we got the expected event.
2532         assertNotNull(firstExpected);
2533 
2534         // Verify the selection position.
2535         assertEquals(0, Selection.getSelectionStart(editText.getText()));
2536         assertEquals(13, Selection.getSelectionEnd(editText.getText()));
2537 
2538         // Move to the next line and wait for an event.
2539         AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
2540                 .executeAndWaitForEvent(new Runnable() {
2541             @Override
2542             public void run() {
2543                 text.performAction(
2544                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
2545             }
2546         }, new UiAutomation.AccessibilityEventFilter() {
2547             @Override
2548             public boolean accept(AccessibilityEvent event) {
2549                 return
2550                 (event.getEventType() ==
2551                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2552                         && event.getAction() ==
2553                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
2554                         && event.getPackageName().equals(getActivity().getPackageName())
2555                         && event.getClassName().equals(EditText.class.getName())
2556                         && event.getText().size() > 0
2557                         && event.getText().get(0).toString().equals(getString(
2558                                 R.string.android_wiki_short))
2559                         && event.getFromIndex() == 13
2560                         && event.getToIndex() == 25
2561                         && event.getMovementGranularity() ==
2562                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
2563             }
2564         }, TIMEOUT_ASYNC_PROCESSING);
2565 
2566         // Make sure we got the expected event.
2567         assertNotNull(secondExpected);
2568 
2569         // Verify the selection position.
2570         assertEquals(0, Selection.getSelectionStart(editText.getText()));
2571         assertEquals(25, Selection.getSelectionEnd(editText.getText()));
2572 
2573         // Move to the next line and wait for an event.
2574         AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
2575                 .executeAndWaitForEvent(new Runnable() {
2576             @Override
2577             public void run() {
2578                 text.performAction(
2579                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
2580             }
2581         }, new UiAutomation.AccessibilityEventFilter() {
2582             @Override
2583             public boolean accept(AccessibilityEvent event) {
2584                 return
2585                 (event.getEventType() ==
2586                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2587                         && event.getAction() ==
2588                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
2589                         && event.getPackageName().equals(getActivity().getPackageName())
2590                         && event.getClassName().equals(EditText.class.getName())
2591                         && event.getText().size() > 0
2592                         && event.getText().get(0).toString().equals(getString(
2593                                 R.string.android_wiki_short))
2594                         && event.getFromIndex() == 25
2595                         && event.getToIndex() == 34
2596                         && event.getMovementGranularity() ==
2597                                  AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
2598             }
2599         }, TIMEOUT_ASYNC_PROCESSING);
2600 
2601         // Make sure we got the expected event.
2602         assertNotNull(thirdExpected);
2603 
2604         // Verify the selection position.
2605         assertEquals(0, Selection.getSelectionStart(editText.getText()));
2606         assertEquals(34, Selection.getSelectionEnd(editText.getText()));
2607 
2608         // Move to the previous line and wait for an event.
2609         AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
2610                 .executeAndWaitForEvent(new Runnable() {
2611             @Override
2612             public void run() {
2613                 text.performAction(
2614                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
2615             }
2616         }, new UiAutomation.AccessibilityEventFilter() {
2617             @Override
2618             public boolean accept(AccessibilityEvent event) {
2619                 return
2620                 (event.getEventType() ==
2621                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2622                         && event.getAction() ==
2623                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
2624                         && event.getPackageName().equals(getActivity().getPackageName())
2625                         && event.getClassName().equals(EditText.class.getName())
2626                         && event.getText().size() > 0
2627                         && event.getText().get(0).toString().equals(getString(
2628                                 R.string.android_wiki_short))
2629                         && event.getFromIndex() == 25
2630                         && event.getToIndex() == 34
2631                         && event.getMovementGranularity() ==
2632                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
2633             }
2634         }, TIMEOUT_ASYNC_PROCESSING);
2635 
2636         // Make sure we got the expected event.
2637         assertNotNull(fourthExpected);
2638 
2639         // Verify the selection position.
2640         assertEquals(0, Selection.getSelectionStart(editText.getText()));
2641         assertEquals(25, Selection.getSelectionEnd(editText.getText()));
2642 
2643         // Move to the previous line and wait for an event.
2644         AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
2645                 .executeAndWaitForEvent(new Runnable() {
2646             @Override
2647             public void run() {
2648                 text.performAction(
2649                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
2650             }
2651         }, new UiAutomation.AccessibilityEventFilter() {
2652             @Override
2653             public boolean accept(AccessibilityEvent event) {
2654                 return
2655                 (event.getEventType() ==
2656                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2657                         && event.getAction() ==
2658                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
2659                         && event.getPackageName().equals(getActivity().getPackageName())
2660                         && event.getClassName().equals(EditText.class.getName())
2661                         && event.getText().size() > 0
2662                         && event.getText().get(0).toString().equals(getString(
2663                                 R.string.android_wiki_short))
2664                         && event.getFromIndex() == 13
2665                         && event.getToIndex() == 25
2666                         && event.getMovementGranularity() ==
2667                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
2668             }
2669         }, TIMEOUT_ASYNC_PROCESSING);
2670 
2671         // Make sure we got the expected event.
2672         assertNotNull(fifthExpected);
2673 
2674         // Verify the selection position.
2675         assertEquals(0, Selection.getSelectionStart(editText.getText()));
2676         assertEquals(13, Selection.getSelectionEnd(editText.getText()));
2677 
2678         // Move to the previous line and wait for an event.
2679         AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
2680                 .executeAndWaitForEvent(new Runnable() {
2681             @Override
2682             public void run() {
2683                 text.performAction(
2684                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
2685             }
2686         }, new UiAutomation.AccessibilityEventFilter() {
2687             @Override
2688             public boolean accept(AccessibilityEvent event) {
2689                 return
2690                 (event.getEventType() ==
2691                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2692                         && event.getAction() ==
2693                                AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
2694                         && event.getPackageName().equals(getActivity().getPackageName())
2695                         && event.getClassName().equals(EditText.class.getName())
2696                         && event.getText().size() > 0
2697                         && event.getText().get(0).toString().equals(getString(
2698                                 R.string.android_wiki_short))
2699                         && event.getFromIndex() == 0
2700                         && event.getToIndex() == 13
2701                         && event.getMovementGranularity() ==
2702                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
2703             }
2704         }, TIMEOUT_ASYNC_PROCESSING);
2705 
2706         // Make sure we got the expected event.
2707         assertNotNull(sixthExpected);
2708 
2709         // Verify the selection position.
2710         assertEquals(0, Selection.getSelectionStart(editText.getText()));
2711         assertEquals(0, Selection.getSelectionEnd(editText.getText()));
2712 
2713         // Make sure there is no previous.
2714         assertFalse(text.performAction(
2715                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
2716 
2717         // Verify the selection position.
2718         assertEquals(0, Selection.getSelectionStart(editText.getText()));
2719         assertEquals(0, Selection.getSelectionEnd(editText.getText()));
2720 
2721         // Focus the view so we can change selection.
2722         getInstrumentation().runOnMainSync(new Runnable() {
2723             @Override
2724             public void run() {
2725                 editText.setFocusable(true);
2726                 editText.requestFocus();
2727             }
2728         });
2729 
2730         // Put selection at the end of the text.
2731         Bundle setSelectionArgs = new Bundle();
2732         setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 34);
2733         setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 34);
2734         assertTrue(text.performAction(
2735                 AccessibilityNodeInfo.ACTION_SET_SELECTION, setSelectionArgs));
2736 
2737         // Verify the selection position.
2738         assertEquals(34, Selection.getSelectionStart(editText.getText()));
2739         assertEquals(34, Selection.getSelectionEnd(editText.getText()));
2740 
2741         // Unocus the view so we can hide the keyboard.
2742         getInstrumentation().runOnMainSync(new Runnable() {
2743             @Override
2744             public void run() {
2745                 editText.clearFocus();
2746                 editText.setFocusable(false);
2747             }
2748         });
2749 
2750         // Move to the previous line and wait for an event.
2751         AccessibilityEvent seventhExpected = getInstrumentation().getUiAutomation()
2752                 .executeAndWaitForEvent(new Runnable() {
2753             @Override
2754             public void run() {
2755                 text.performAction(
2756                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
2757             }
2758         }, new UiAutomation.AccessibilityEventFilter() {
2759             @Override
2760             public boolean accept(AccessibilityEvent event) {
2761                 return
2762                 (event.getEventType() ==
2763                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2764                         && event.getAction() ==
2765                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
2766                         && event.getPackageName().equals(getActivity().getPackageName())
2767                         && event.getClassName().equals(EditText.class.getName())
2768                         && event.getText().size() > 0
2769                         && event.getText().get(0).toString().equals(getString(
2770                                 R.string.android_wiki_short))
2771                         && event.getFromIndex() == 25
2772                         && event.getToIndex() == 34
2773                         && event.getMovementGranularity() ==
2774                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
2775             }
2776         }, TIMEOUT_ASYNC_PROCESSING);
2777 
2778         // Make sure we got the expected event.
2779         assertNotNull(seventhExpected);
2780 
2781         // Verify the selection position.
2782         assertEquals(34, Selection.getSelectionStart(editText.getText()));
2783         assertEquals(25, Selection.getSelectionEnd(editText.getText()));
2784 
2785         // Move to the previous line and wait for an event.
2786         AccessibilityEvent eightExpected = getInstrumentation().getUiAutomation()
2787                 .executeAndWaitForEvent(new Runnable() {
2788             @Override
2789             public void run() {
2790                 text.performAction(
2791                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
2792             }
2793         }, new UiAutomation.AccessibilityEventFilter() {
2794             @Override
2795             public boolean accept(AccessibilityEvent event) {
2796                 return
2797                 (event.getEventType() ==
2798                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2799                         && event.getAction() ==
2800                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
2801                         && event.getPackageName().equals(getActivity().getPackageName())
2802                         && event.getClassName().equals(EditText.class.getName())
2803                         && event.getText().size() > 0
2804                         && event.getText().get(0).toString().equals(getString(
2805                                 R.string.android_wiki_short))
2806                         && event.getFromIndex() == 13
2807                         && event.getToIndex() == 25
2808                         && event.getMovementGranularity() ==
2809                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
2810             }
2811         }, TIMEOUT_ASYNC_PROCESSING);
2812 
2813         // Make sure we got the expected event.
2814         assertNotNull(eightExpected);
2815 
2816         // Verify the selection position.
2817         assertEquals(34, Selection.getSelectionStart(editText.getText()));
2818         assertEquals(13, Selection.getSelectionEnd(editText.getText()));
2819 
2820         // Move to the previous line and wait for an event.
2821         AccessibilityEvent ninethExpected = getInstrumentation().getUiAutomation()
2822                 .executeAndWaitForEvent(new Runnable() {
2823             @Override
2824             public void run() {
2825                 text.performAction(
2826                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
2827             }
2828         }, new UiAutomation.AccessibilityEventFilter() {
2829             @Override
2830             public boolean accept(AccessibilityEvent event) {
2831                 return
2832                 (event.getEventType() ==
2833                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2834                         && event.getAction() ==
2835                                AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
2836                         && event.getPackageName().equals(getActivity().getPackageName())
2837                         && event.getClassName().equals(EditText.class.getName())
2838                         && event.getText().size() > 0
2839                         && event.getText().get(0).toString().equals(getString(
2840                                 R.string.android_wiki_short))
2841                         && event.getFromIndex() == 0
2842                         && event.getToIndex() == 13
2843                         && event.getMovementGranularity() ==
2844                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
2845             }
2846         }, TIMEOUT_ASYNC_PROCESSING);
2847 
2848         // Make sure we got the expected event.
2849         assertNotNull(ninethExpected);
2850 
2851         // Verify the selection position.
2852         assertEquals(34, Selection.getSelectionStart(editText.getText()));
2853         assertEquals(0, Selection.getSelectionEnd(editText.getText()));
2854 
2855         // Make sure there is no previous.
2856         assertFalse(text.performAction(
2857                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
2858 
2859         // Verify the selection position.
2860         assertEquals(34, Selection.getSelectionStart(editText.getText()));
2861         assertEquals(0, Selection.getSelectionEnd(editText.getText()));
2862 
2863         // Move to the next line and wait for an event.
2864         AccessibilityEvent tenthExpected = getInstrumentation().getUiAutomation()
2865                 .executeAndWaitForEvent(new Runnable() {
2866             @Override
2867             public void run() {
2868                 text.performAction(
2869                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
2870             }
2871         }, new UiAutomation.AccessibilityEventFilter() {
2872             @Override
2873             public boolean accept(AccessibilityEvent event) {
2874                 return
2875                 (event.getEventType() ==
2876                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2877                         && event.getAction() ==
2878                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
2879                         && event.getPackageName().equals(getActivity().getPackageName())
2880                         && event.getClassName().equals(EditText.class.getName())
2881                         && event.getText().size() > 0
2882                         && event.getText().get(0).toString().equals(getString(
2883                                 R.string.android_wiki_short))
2884                         && event.getFromIndex() == 0
2885                         && event.getToIndex() == 13
2886                         && event.getMovementGranularity() ==
2887                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
2888             }
2889         }, TIMEOUT_ASYNC_PROCESSING);
2890 
2891         // Make sure we got the expected event.
2892         assertNotNull(tenthExpected);
2893 
2894         // Verify the selection position.
2895         assertEquals(34, Selection.getSelectionStart(editText.getText()));
2896         assertEquals(13, Selection.getSelectionEnd(editText.getText()));
2897 
2898         // Move to the next line and wait for an event.
2899         AccessibilityEvent eleventhExpected = getInstrumentation().getUiAutomation()
2900                 .executeAndWaitForEvent(new Runnable() {
2901             @Override
2902             public void run() {
2903                 text.performAction(
2904                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
2905             }
2906         }, new UiAutomation.AccessibilityEventFilter() {
2907             @Override
2908             public boolean accept(AccessibilityEvent event) {
2909                 return
2910                 (event.getEventType() ==
2911                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2912                         && event.getAction() ==
2913                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
2914                         && event.getPackageName().equals(getActivity().getPackageName())
2915                         && event.getClassName().equals(EditText.class.getName())
2916                         && event.getText().size() > 0
2917                         && event.getText().get(0).toString().equals(getString(
2918                                 R.string.android_wiki_short))
2919                         && event.getFromIndex() == 13
2920                         && event.getToIndex() == 25
2921                         && event.getMovementGranularity() ==
2922                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
2923             }
2924         }, TIMEOUT_ASYNC_PROCESSING);
2925 
2926         // Make sure we got the expected event.
2927         assertNotNull(eleventhExpected);
2928 
2929         // Verify the selection position.
2930         assertEquals(34, Selection.getSelectionStart(editText.getText()));
2931         assertEquals(25, Selection.getSelectionEnd(editText.getText()));
2932 
2933         // Move to the next line and wait for an event.
2934         AccessibilityEvent twelvethExpected = getInstrumentation().getUiAutomation()
2935                 .executeAndWaitForEvent(new Runnable() {
2936             @Override
2937             public void run() {
2938                 text.performAction(
2939                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
2940             }
2941         }, new UiAutomation.AccessibilityEventFilter() {
2942             @Override
2943             public boolean accept(AccessibilityEvent event) {
2944                 return
2945                 (event.getEventType() ==
2946                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
2947                         && event.getAction() ==
2948                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
2949                         && event.getPackageName().equals(getActivity().getPackageName())
2950                         && event.getClassName().equals(EditText.class.getName())
2951                         && event.getText().size() > 0
2952                         && event.getText().get(0).toString().equals(getString(
2953                                 R.string.android_wiki_short))
2954                         && event.getFromIndex() == 25
2955                         && event.getToIndex() == 34
2956                         && event.getMovementGranularity() ==
2957                                  AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
2958             }
2959         }, TIMEOUT_ASYNC_PROCESSING);
2960 
2961         // Make sure we got the expected event.
2962         assertNotNull(twelvethExpected);
2963 
2964         // Verify the selection position.
2965         assertEquals(34, Selection.getSelectionStart(editText.getText()));
2966         assertEquals(34, Selection.getSelectionEnd(editText.getText()));
2967     }
2968 
2969     @MediumTest
testActionNextAndPreviousAtGranularityPageOverText()2970     public void testActionNextAndPreviousAtGranularityPageOverText() throws Exception {
2971         final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
2972 
2973         getInstrumentation().runOnMainSync(new Runnable() {
2974             @Override
2975             public void run() {
2976                 editText.setVisibility(View.VISIBLE);
2977                 editText.setText(getString(R.string.android_wiki));
2978                 Selection.removeSelection(editText.getText());
2979             }
2980         });
2981 
2982         final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
2983                .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
2984                        R.string.android_wiki)).get(0);
2985 
2986         final int granularities = text.getMovementGranularities();
2987         assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
2988                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
2989                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
2990                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
2991                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
2992 
2993         final Bundle arguments = new Bundle();
2994         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
2995                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
2996 
2997         // Move to the next page and wait for an event.
2998         AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
2999                 .executeAndWaitForEvent(new Runnable() {
3000             @Override
3001             public void run() {
3002                 text.performAction(
3003                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
3004             }
3005         }, new UiAutomation.AccessibilityEventFilter() {
3006             @Override
3007             public boolean accept(AccessibilityEvent event) {
3008                 return
3009                 (event.getEventType() ==
3010                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3011                         && event.getAction() ==
3012                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
3013                         && event.getPackageName().equals(getActivity().getPackageName())
3014                         && event.getClassName().equals(EditText.class.getName())
3015                         && event.getText().size() > 0
3016                         && event.getText().get(0).toString().equals(getString(
3017                                 R.string.android_wiki))
3018                         && event.getFromIndex() == 0
3019                         && event.getToIndex() == 53
3020                         && event.getMovementGranularity() ==
3021                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3022             }
3023         }, TIMEOUT_ASYNC_PROCESSING);
3024 
3025         // Make sure we got the expected event.
3026         assertNotNull(firstExpected);
3027 
3028         // Verify the selection position.
3029         assertEquals(53, Selection.getSelectionStart(editText.getText()));
3030         assertEquals(53, Selection.getSelectionEnd(editText.getText()));
3031 
3032         // Move to the next page and wait for an event.
3033         AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
3034                 .executeAndWaitForEvent(new Runnable() {
3035             @Override
3036             public void run() {
3037                 text.performAction(
3038                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
3039             }
3040         }, new UiAutomation.AccessibilityEventFilter() {
3041             @Override
3042             public boolean accept(AccessibilityEvent event) {
3043                 return
3044                 (event.getEventType() ==
3045                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3046                         && event.getAction() ==
3047                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
3048                         && event.getPackageName().equals(getActivity().getPackageName())
3049                         && event.getClassName().equals(EditText.class.getName())
3050                         && event.getText().size() > 0
3051                         && event.getText().get(0).toString().equals(getString(
3052                                 R.string.android_wiki))
3053                         && event.getFromIndex() == 53
3054                         && event.getToIndex() == 103
3055                         && event.getMovementGranularity() ==
3056                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3057             }
3058         }, TIMEOUT_ASYNC_PROCESSING);
3059 
3060         // Make sure we got the expected event.
3061         assertNotNull(secondExpected);
3062 
3063         // Verify the selection position.
3064         assertEquals(103, Selection.getSelectionStart(editText.getText()));
3065         assertEquals(103, Selection.getSelectionEnd(editText.getText()));
3066 
3067         // Move to the next page and wait for an event.
3068         AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
3069                 .executeAndWaitForEvent(new Runnable() {
3070             @Override
3071             public void run() {
3072                 text.performAction(
3073                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
3074             }
3075         }, new UiAutomation.AccessibilityEventFilter() {
3076             @Override
3077             public boolean accept(AccessibilityEvent event) {
3078                 return
3079                 (event.getEventType() ==
3080                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3081                         && event.getAction() ==
3082                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
3083                         && event.getPackageName().equals(getActivity().getPackageName())
3084                         && event.getClassName().equals(EditText.class.getName())
3085                         && event.getText().size() > 0
3086                         && event.getText().get(0).toString().equals(getString(
3087                                 R.string.android_wiki))
3088                         && event.getFromIndex() == 103
3089                         && event.getToIndex() == 153
3090                         && event.getMovementGranularity() ==
3091                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3092             }
3093         }, TIMEOUT_ASYNC_PROCESSING);
3094 
3095         // Make sure we got the expected event.
3096         assertNotNull(thirdExpected);
3097 
3098         // Verify the selection position.
3099         assertEquals(153, Selection.getSelectionStart(editText.getText()));
3100         assertEquals(153, Selection.getSelectionEnd(editText.getText()));
3101 
3102         // Make sure there is no next.
3103         assertFalse(text.performAction(
3104                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
3105 
3106         // Verify the selection position.
3107         assertEquals(153, Selection.getSelectionStart(editText.getText()));
3108         assertEquals(153, Selection.getSelectionEnd(editText.getText()));
3109 
3110         // Move to the previous page and wait for an event.
3111         AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
3112                 .executeAndWaitForEvent(new Runnable() {
3113             @Override
3114             public void run() {
3115                 text.performAction(
3116                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
3117             }
3118         }, new UiAutomation.AccessibilityEventFilter() {
3119             @Override
3120             public boolean accept(AccessibilityEvent event) {
3121                 return
3122                 (event.getEventType() ==
3123                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3124                         && event.getAction() ==
3125                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
3126                         && event.getPackageName().equals(getActivity().getPackageName())
3127                         && event.getClassName().equals(EditText.class.getName())
3128                         && event.getText().size() > 0
3129                         && event.getText().get(0).toString().equals(getString(
3130                                 R.string.android_wiki))
3131                         && event.getFromIndex() == 103
3132                         && event.getToIndex() == 153
3133                         && event.getMovementGranularity() ==
3134                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3135             }
3136         }, TIMEOUT_ASYNC_PROCESSING);
3137 
3138         // Make sure we got the expected event.
3139         assertNotNull(fourthExpected);
3140 
3141         // Verify the selection position.
3142         assertEquals(103, Selection.getSelectionStart(editText.getText()));
3143         assertEquals(103, Selection.getSelectionEnd(editText.getText()));
3144 
3145         // Move to the previous page and wait for an event.
3146         AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
3147                 .executeAndWaitForEvent(new Runnable() {
3148             @Override
3149             public void run() {
3150                 text.performAction(
3151                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
3152             }
3153         }, new UiAutomation.AccessibilityEventFilter() {
3154             @Override
3155             public boolean accept(AccessibilityEvent event) {
3156                 return
3157                 (event.getEventType() ==
3158                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3159                         && event.getAction() ==
3160                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
3161                         && event.getPackageName().equals(getActivity().getPackageName())
3162                         && event.getClassName().equals(EditText.class.getName())
3163                         && event.getText().size() > 0
3164                         && event.getText().get(0).toString().equals(getString(
3165                                 R.string.android_wiki))
3166                         && event.getFromIndex() == 53
3167                         && event.getToIndex() == 103
3168                         && event.getMovementGranularity() ==
3169                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3170             }
3171         }, TIMEOUT_ASYNC_PROCESSING);
3172 
3173         // Make sure we got the expected event.
3174         assertNotNull(fifthExpected);
3175 
3176         // Verify the selection position.
3177         assertEquals(53, Selection.getSelectionStart(editText.getText()));
3178         assertEquals(53, Selection.getSelectionEnd(editText.getText()));
3179 
3180         // Move to the previous page and wait for an event.
3181         AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
3182                 .executeAndWaitForEvent(new Runnable() {
3183             @Override
3184             public void run() {
3185                 text.performAction(
3186                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
3187             }
3188         }, new UiAutomation.AccessibilityEventFilter() {
3189             @Override
3190             public boolean accept(AccessibilityEvent event) {
3191                 return
3192                 (event.getEventType() ==
3193                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3194                         && event.getAction() ==
3195                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
3196                         && event.getPackageName().equals(getActivity().getPackageName())
3197                         && event.getClassName().equals(EditText.class.getName())
3198                         && event.getText().size() > 0
3199                         && event.getText().get(0).toString().equals(getString(
3200                                 R.string.android_wiki))
3201                         && event.getFromIndex() == 0
3202                         && event.getToIndex() == 53
3203                         && event.getMovementGranularity() ==
3204                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3205             }
3206         }, TIMEOUT_ASYNC_PROCESSING);
3207 
3208         // Make sure we got the expected event.
3209         assertNotNull(sixthExpected);
3210 
3211         // Verify the selection position.
3212         assertEquals(0, Selection.getSelectionStart(editText.getText()));
3213         assertEquals(0, Selection.getSelectionEnd(editText.getText()));
3214 
3215         // Make sure there is no previous.
3216         assertFalse(text.performAction(
3217                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
3218 
3219         // Verify the selection position.
3220         assertEquals(0, Selection.getSelectionStart(editText.getText()));
3221         assertEquals(0, Selection.getSelectionEnd(editText.getText()));
3222     }
3223 
3224     @MediumTest
testActionNextAndPreviousAtGranularityPageOverTextExtend()3225     public void testActionNextAndPreviousAtGranularityPageOverTextExtend() throws Exception {
3226         final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
3227 
3228         getInstrumentation().runOnMainSync(new Runnable() {
3229             @Override
3230             public void run() {
3231                 editText.setVisibility(View.VISIBLE);
3232                 editText.setText(getString(R.string.android_wiki));
3233                 Selection.removeSelection(editText.getText());
3234             }
3235         });
3236 
3237         final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
3238                .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
3239                        R.string.android_wiki)).get(0);
3240 
3241         final int granularities = text.getMovementGranularities();
3242         assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
3243                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
3244                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
3245                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
3246                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3247 
3248         final Bundle arguments = new Bundle();
3249         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
3250                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3251         arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, true);
3252 
3253         // Move to the next page and wait for an event.
3254         AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
3255                 .executeAndWaitForEvent(new Runnable() {
3256             @Override
3257             public void run() {
3258                 text.performAction(
3259                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
3260             }
3261         }, new UiAutomation.AccessibilityEventFilter() {
3262             @Override
3263             public boolean accept(AccessibilityEvent event) {
3264                 return
3265                 (event.getEventType() ==
3266                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3267                         && event.getAction() ==
3268                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
3269                         && event.getPackageName().equals(getActivity().getPackageName())
3270                         && event.getClassName().equals(EditText.class.getName())
3271                         && event.getText().size() > 0
3272                         && event.getText().get(0).toString().equals(getString(
3273                                 R.string.android_wiki))
3274                         && event.getFromIndex() == 0
3275                         && event.getToIndex() == 53
3276                         && event.getMovementGranularity() ==
3277                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3278             }
3279         }, TIMEOUT_ASYNC_PROCESSING);
3280 
3281         // Make sure we got the expected event.
3282         assertNotNull(firstExpected);
3283 
3284         // Verify the selection position.
3285         assertEquals(0, Selection.getSelectionStart(editText.getText()));
3286         assertEquals(53, Selection.getSelectionEnd(editText.getText()));
3287 
3288         // Move to the next page and wait for an event.
3289         AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
3290                 .executeAndWaitForEvent(new Runnable() {
3291             @Override
3292             public void run() {
3293                 text.performAction(
3294                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
3295             }
3296         }, new UiAutomation.AccessibilityEventFilter() {
3297             @Override
3298             public boolean accept(AccessibilityEvent event) {
3299                 return
3300                 (event.getEventType() ==
3301                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3302                         && event.getAction() ==
3303                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
3304                         && event.getPackageName().equals(getActivity().getPackageName())
3305                         && event.getClassName().equals(EditText.class.getName())
3306                         && event.getText().size() > 0
3307                         && event.getText().get(0).toString().equals(getString(
3308                                 R.string.android_wiki))
3309                         && event.getFromIndex() == 53
3310                         && event.getToIndex() == 103
3311                         && event.getMovementGranularity() ==
3312                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3313             }
3314         }, TIMEOUT_ASYNC_PROCESSING);
3315 
3316         // Make sure we got the expected event.
3317         assertNotNull(secondExpected);
3318 
3319         // Verify the selection position.
3320         assertEquals(0, Selection.getSelectionStart(editText.getText()));
3321         assertEquals(103, Selection.getSelectionEnd(editText.getText()));
3322 
3323         // Move to the next page and wait for an event.
3324         AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
3325                 .executeAndWaitForEvent(new Runnable() {
3326             @Override
3327             public void run() {
3328                 text.performAction(
3329                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
3330             }
3331         }, new UiAutomation.AccessibilityEventFilter() {
3332             @Override
3333             public boolean accept(AccessibilityEvent event) {
3334                 return
3335                 (event.getEventType() ==
3336                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3337                         && event.getAction() ==
3338                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
3339                         && event.getPackageName().equals(getActivity().getPackageName())
3340                         && event.getClassName().equals(EditText.class.getName())
3341                         && event.getText().size() > 0
3342                         && event.getText().get(0).toString().equals(getString(
3343                                 R.string.android_wiki))
3344                         && event.getFromIndex() == 103
3345                         && event.getToIndex() == 153
3346                         && event.getMovementGranularity() ==
3347                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3348             }
3349         }, TIMEOUT_ASYNC_PROCESSING);
3350 
3351         // Make sure we got the expected event.
3352         assertNotNull(thirdExpected);
3353 
3354         // Verify the selection position.
3355         assertEquals(0, Selection.getSelectionStart(editText.getText()));
3356         assertEquals(153, Selection.getSelectionEnd(editText.getText()));
3357 
3358         // Make sure there is no next.
3359         assertFalse(text.performAction(
3360                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
3361 
3362         // Move to the previous page and wait for an event.
3363         AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
3364                 .executeAndWaitForEvent(new Runnable() {
3365             @Override
3366             public void run() {
3367                 text.performAction(
3368                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
3369             }
3370         }, new UiAutomation.AccessibilityEventFilter() {
3371             @Override
3372             public boolean accept(AccessibilityEvent event) {
3373                 return
3374                 (event.getEventType() ==
3375                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3376                         && event.getAction() ==
3377                                  AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
3378                         && event.getPackageName().equals(getActivity().getPackageName())
3379                         && event.getClassName().equals(EditText.class.getName())
3380                         && event.getText().size() > 0
3381                         && event.getText().get(0).toString().equals(getString(
3382                                 R.string.android_wiki))
3383                         && event.getFromIndex() == 103
3384                         && event.getToIndex() == 153
3385                         && event.getMovementGranularity() ==
3386                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3387             }
3388         }, TIMEOUT_ASYNC_PROCESSING);
3389 
3390         // Make sure we got the expected event.
3391         assertNotNull(fourthExpected);
3392 
3393         // Verify the selection position.
3394         assertEquals(0, Selection.getSelectionStart(editText.getText()));
3395         assertEquals(103, Selection.getSelectionEnd(editText.getText()));
3396 
3397         // Move to the previous page and wait for an event.
3398         AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
3399                 .executeAndWaitForEvent(new Runnable() {
3400             @Override
3401             public void run() {
3402                 text.performAction(
3403                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
3404             }
3405         }, new UiAutomation.AccessibilityEventFilter() {
3406             @Override
3407             public boolean accept(AccessibilityEvent event) {
3408                 return
3409                 (event.getEventType() ==
3410                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3411                         && event.getAction() ==
3412                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
3413                         && event.getPackageName().equals(getActivity().getPackageName())
3414                         && event.getClassName().equals(EditText.class.getName())
3415                         && event.getText().size() > 0
3416                         && event.getText().get(0).toString().equals(getString(
3417                                 R.string.android_wiki))
3418                         && event.getFromIndex() == 53
3419                         && event.getToIndex() == 103
3420                         && event.getMovementGranularity() ==
3421                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3422             }
3423         }, TIMEOUT_ASYNC_PROCESSING);
3424 
3425         // Make sure we got the expected event.
3426         assertNotNull(fifthExpected);
3427 
3428         // Verify the selection position.
3429         assertEquals(0, Selection.getSelectionStart(editText.getText()));
3430         assertEquals(53, Selection.getSelectionEnd(editText.getText()));
3431 
3432         // Move to the previous page and wait for an event.
3433         AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
3434                 .executeAndWaitForEvent(new Runnable() {
3435             @Override
3436             public void run() {
3437                 text.performAction(
3438                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
3439             }
3440         }, new UiAutomation.AccessibilityEventFilter() {
3441             @Override
3442             public boolean accept(AccessibilityEvent event) {
3443                 return
3444                 (event.getEventType() ==
3445                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3446                         && event.getAction() ==
3447                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
3448                         && event.getPackageName().equals(getActivity().getPackageName())
3449                         && event.getClassName().equals(EditText.class.getName())
3450                         && event.getText().size() > 0
3451                         && event.getText().get(0).toString().equals(getString(
3452                                 R.string.android_wiki))
3453                         && event.getFromIndex() == 0
3454                         && event.getToIndex() == 53
3455                         && event.getMovementGranularity() ==
3456                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3457             }
3458         }, TIMEOUT_ASYNC_PROCESSING);
3459 
3460         // Make sure we got the expected event.
3461         assertNotNull(sixthExpected);
3462 
3463         // Verify the selection position.
3464         assertEquals(0, Selection.getSelectionStart(editText.getText()));
3465         assertEquals(0, Selection.getSelectionEnd(editText.getText()));
3466 
3467         // Make sure there is no previous.
3468         assertFalse(text.performAction(
3469                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
3470 
3471         // Verify the selection position.
3472         assertEquals(0, Selection.getSelectionStart(editText.getText()));
3473         assertEquals(0, Selection.getSelectionEnd(editText.getText()));
3474 
3475         // Focus the view so we can change selection.
3476         getInstrumentation().runOnMainSync(new Runnable() {
3477             @Override
3478             public void run() {
3479                 editText.setFocusable(true);
3480                 editText.requestFocus();
3481             }
3482         });
3483 
3484         // Put selection at the end of the text.
3485         Bundle setSelectionArgs = new Bundle();
3486         setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 153);
3487         setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 153);
3488         assertTrue(text.performAction(
3489                 AccessibilityNodeInfo.ACTION_SET_SELECTION, setSelectionArgs));
3490 
3491         // Verify the selection position.
3492         assertEquals(153, Selection.getSelectionStart(editText.getText()));
3493         assertEquals(153, Selection.getSelectionEnd(editText.getText()));
3494 
3495         // Unfocus the view so we can hide the soft-keyboard.
3496         getInstrumentation().runOnMainSync(new Runnable() {
3497             @Override
3498             public void run() {
3499                 editText.clearFocus();
3500                 editText.setFocusable(false);
3501             }
3502         });
3503 
3504         // Move to the previous page and wait for an event.
3505         AccessibilityEvent seventhExpected = getInstrumentation().getUiAutomation()
3506                 .executeAndWaitForEvent(new Runnable() {
3507             @Override
3508             public void run() {
3509                 text.performAction(
3510                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
3511             }
3512         }, new UiAutomation.AccessibilityEventFilter() {
3513             @Override
3514             public boolean accept(AccessibilityEvent event) {
3515                 return
3516                 (event.getEventType() ==
3517                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3518                         && event.getAction() ==
3519                                  AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
3520                         && event.getPackageName().equals(getActivity().getPackageName())
3521                         && event.getClassName().equals(EditText.class.getName())
3522                         && event.getText().size() > 0
3523                         && event.getText().get(0).toString().equals(getString(
3524                                 R.string.android_wiki))
3525                         && event.getFromIndex() == 103
3526                         && event.getToIndex() == 153
3527                         && event.getMovementGranularity() ==
3528                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3529             }
3530         }, TIMEOUT_ASYNC_PROCESSING);
3531 
3532         // Make sure we got the expected event.
3533         assertNotNull(seventhExpected);
3534 
3535         // Verify the selection position.
3536         assertEquals(153, Selection.getSelectionStart(editText.getText()));
3537         assertEquals(103, Selection.getSelectionEnd(editText.getText()));
3538 
3539         // Move to the previous page and wait for an event.
3540         AccessibilityEvent eightExpected = getInstrumentation().getUiAutomation()
3541                 .executeAndWaitForEvent(new Runnable() {
3542             @Override
3543             public void run() {
3544                 text.performAction(
3545                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
3546             }
3547         }, new UiAutomation.AccessibilityEventFilter() {
3548             @Override
3549             public boolean accept(AccessibilityEvent event) {
3550                 return
3551                 (event.getEventType() ==
3552                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3553                         && event.getAction() ==
3554                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
3555                         && event.getPackageName().equals(getActivity().getPackageName())
3556                         && event.getClassName().equals(EditText.class.getName())
3557                         && event.getText().size() > 0
3558                         && event.getText().get(0).toString().equals(getString(
3559                                 R.string.android_wiki))
3560                         && event.getFromIndex() == 53
3561                         && event.getToIndex() == 103
3562                         && event.getMovementGranularity() ==
3563                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3564             }
3565         }, TIMEOUT_ASYNC_PROCESSING);
3566 
3567         // Make sure we got the expected event.
3568         assertNotNull(eightExpected);
3569 
3570         // Verify the selection position.
3571         assertEquals(153, Selection.getSelectionStart(editText.getText()));
3572         assertEquals(53, Selection.getSelectionEnd(editText.getText()));
3573 
3574         // Move to the previous page and wait for an event.
3575         AccessibilityEvent ninethExpected = getInstrumentation().getUiAutomation()
3576                 .executeAndWaitForEvent(new Runnable() {
3577             @Override
3578             public void run() {
3579                 text.performAction(
3580                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
3581             }
3582         }, new UiAutomation.AccessibilityEventFilter() {
3583             @Override
3584             public boolean accept(AccessibilityEvent event) {
3585                 return
3586                 (event.getEventType() ==
3587                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3588                         && event.getAction() ==
3589                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
3590                         && event.getPackageName().equals(getActivity().getPackageName())
3591                         && event.getClassName().equals(EditText.class.getName())
3592                         && event.getText().size() > 0
3593                         && event.getText().get(0).toString().equals(getString(
3594                                 R.string.android_wiki))
3595                         && event.getFromIndex() == 0
3596                         && event.getToIndex() == 53
3597                         && event.getMovementGranularity() ==
3598                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3599             }
3600         }, TIMEOUT_ASYNC_PROCESSING);
3601 
3602         // Make sure we got the expected event.
3603         assertNotNull(ninethExpected);
3604 
3605         // Verify the selection position.
3606         assertEquals(153, Selection.getSelectionStart(editText.getText()));
3607         assertEquals(0, Selection.getSelectionEnd(editText.getText()));
3608 
3609         // Make sure there is no previous.
3610         assertFalse(text.performAction(
3611                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
3612 
3613         // Verify the selection position.
3614         assertEquals(153, Selection.getSelectionStart(editText.getText()));
3615         assertEquals(0, Selection.getSelectionEnd(editText.getText()));
3616 
3617         // Move to the next page and wait for an event.
3618         AccessibilityEvent tenthExpected = getInstrumentation().getUiAutomation()
3619                 .executeAndWaitForEvent(new Runnable() {
3620             @Override
3621             public void run() {
3622                 text.performAction(
3623                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
3624             }
3625         }, new UiAutomation.AccessibilityEventFilter() {
3626             @Override
3627             public boolean accept(AccessibilityEvent event) {
3628                 return
3629                 (event.getEventType() ==
3630                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3631                         && event.getAction() ==
3632                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
3633                         && event.getPackageName().equals(getActivity().getPackageName())
3634                         && event.getClassName().equals(EditText.class.getName())
3635                         && event.getText().size() > 0
3636                         && event.getText().get(0).toString().equals(getString(
3637                                 R.string.android_wiki))
3638                         && event.getFromIndex() == 0
3639                         && event.getToIndex() == 53
3640                         && event.getMovementGranularity() ==
3641                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3642             }
3643         }, TIMEOUT_ASYNC_PROCESSING);
3644 
3645         // Make sure we got the expected event.
3646         assertNotNull(tenthExpected);
3647 
3648         // Verify the selection position.
3649         assertEquals(153, Selection.getSelectionStart(editText.getText()));
3650         assertEquals(53, Selection.getSelectionEnd(editText.getText()));
3651 
3652         // Move to the next page and wait for an event.
3653         AccessibilityEvent eleventhExpected = getInstrumentation().getUiAutomation()
3654                 .executeAndWaitForEvent(new Runnable() {
3655             @Override
3656             public void run() {
3657                 text.performAction(
3658                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
3659             }
3660         }, new UiAutomation.AccessibilityEventFilter() {
3661             @Override
3662             public boolean accept(AccessibilityEvent event) {
3663                 return
3664                 (event.getEventType() ==
3665                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3666                         && event.getAction() ==
3667                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
3668                         && event.getPackageName().equals(getActivity().getPackageName())
3669                         && event.getClassName().equals(EditText.class.getName())
3670                         && event.getText().size() > 0
3671                         && event.getText().get(0).toString().equals(getString(
3672                                 R.string.android_wiki))
3673                         && event.getFromIndex() == 53
3674                         && event.getToIndex() == 103
3675                         && event.getMovementGranularity() ==
3676                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3677             }
3678         }, TIMEOUT_ASYNC_PROCESSING);
3679 
3680         // Make sure we got the expected event.
3681         assertNotNull(eleventhExpected);
3682 
3683         // Verify the selection position.
3684         assertEquals(153, Selection.getSelectionStart(editText.getText()));
3685         assertEquals(103, Selection.getSelectionEnd(editText.getText()));
3686 
3687         // Move to the next page and wait for an event.
3688         AccessibilityEvent twelvethExpected = getInstrumentation().getUiAutomation()
3689                 .executeAndWaitForEvent(new Runnable() {
3690             @Override
3691             public void run() {
3692                 text.performAction(
3693                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
3694             }
3695         }, new UiAutomation.AccessibilityEventFilter() {
3696             @Override
3697             public boolean accept(AccessibilityEvent event) {
3698                 return
3699                 (event.getEventType() ==
3700                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3701                         && event.getAction() ==
3702                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
3703                         && event.getPackageName().equals(getActivity().getPackageName())
3704                         && event.getClassName().equals(EditText.class.getName())
3705                         && event.getText().size() > 0
3706                         && event.getText().get(0).toString().equals(getString(
3707                                 R.string.android_wiki))
3708                         && event.getFromIndex() == 103
3709                         && event.getToIndex() == 153
3710                         && event.getMovementGranularity() ==
3711                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3712             }
3713         }, TIMEOUT_ASYNC_PROCESSING);
3714 
3715         // Make sure we got the expected event.
3716         assertNotNull(twelvethExpected);
3717 
3718         // Verify the selection position.
3719         assertEquals(153, Selection.getSelectionStart(editText.getText()));
3720         assertEquals(153, Selection.getSelectionEnd(editText.getText()));
3721     }
3722 
3723     @MediumTest
testActionNextAndPreviousAtGranularityParagraphOverText()3724     public void testActionNextAndPreviousAtGranularityParagraphOverText() throws Exception {
3725         final TextView textView = (TextView) getActivity().findViewById(R.id.edit);
3726 
3727         getInstrumentation().runOnMainSync(new Runnable() {
3728             @Override
3729             public void run() {
3730                 textView.setVisibility(View.VISIBLE);
3731                 textView.setText(getString(R.string.android_wiki_paragraphs));
3732             }
3733         });
3734 
3735         final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
3736                .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
3737                        R.string.android_wiki_paragraphs)).get(0);
3738 
3739         final int granularities = text.getMovementGranularities();
3740         assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
3741                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
3742                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
3743                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
3744                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
3745 
3746         final Bundle arguments = new Bundle();
3747         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
3748                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
3749 
3750         // Move to the next paragraph and wait for an event.
3751         AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
3752                 .executeAndWaitForEvent(new Runnable() {
3753             @Override
3754             public void run() {
3755                 text.performAction(
3756                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
3757             }
3758         }, new UiAutomation.AccessibilityEventFilter() {
3759             @Override
3760             public boolean accept(AccessibilityEvent event) {
3761                 return
3762                 (event.getEventType() ==
3763                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3764                         && event.getAction() ==
3765                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
3766                         && event.getPackageName().equals(getActivity().getPackageName())
3767                         && event.getClassName().equals(EditText.class.getName())
3768                         && event.getText().size() > 0
3769                         && event.getText().get(0).toString().equals(getString(
3770                                 R.string.android_wiki_paragraphs))
3771                         && event.getFromIndex() == 2
3772                         && event.getToIndex() == 14
3773                         && event.getMovementGranularity() ==
3774                                  AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
3775             }
3776         }, TIMEOUT_ASYNC_PROCESSING);
3777 
3778         // Make sure we got the expected event.
3779         assertNotNull(firstExpected);
3780 
3781         // Verify the selection position.
3782         assertEquals(14, Selection.getSelectionStart(textView.getText()));
3783         assertEquals(14, Selection.getSelectionEnd(textView.getText()));
3784 
3785         // Move to the next paragraph and wait for an event.
3786         AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
3787                 .executeAndWaitForEvent(new Runnable() {
3788             @Override
3789             public void run() {
3790                 text.performAction(
3791                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
3792             }
3793         }, new UiAutomation.AccessibilityEventFilter() {
3794             @Override
3795             public boolean accept(AccessibilityEvent event) {
3796                 return
3797                 (event.getEventType() ==
3798                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3799                         && event.getAction() ==
3800                                  AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
3801                         && event.getPackageName().equals(getActivity().getPackageName())
3802                         && event.getClassName().equals(EditText.class.getName())
3803                         && event.getText().size() > 0
3804                         && event.getText().get(0).toString().equals(getString(
3805                                 R.string.android_wiki_paragraphs))
3806                         && event.getFromIndex() == 16
3807                         && event.getToIndex() == 32
3808                         && event.getMovementGranularity() ==
3809                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
3810             }
3811         }, TIMEOUT_ASYNC_PROCESSING);
3812 
3813         // Make sure we got the expected event.
3814         assertNotNull(secondExpected);
3815 
3816         // Verify the selection position.
3817         assertEquals(32, Selection.getSelectionStart(textView.getText()));
3818         assertEquals(32, Selection.getSelectionEnd(textView.getText()));
3819 
3820         // Move to the next paragraph and wait for an event.
3821         AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
3822                 .executeAndWaitForEvent(new Runnable() {
3823             @Override
3824             public void run() {
3825                 text.performAction(
3826                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
3827             }
3828         }, new UiAutomation.AccessibilityEventFilter() {
3829             @Override
3830             public boolean accept(AccessibilityEvent event) {
3831                 return
3832                 (event.getEventType() ==
3833                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3834                         && event.getAction() ==
3835                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
3836                         && event.getPackageName().equals(getActivity().getPackageName())
3837                         && event.getClassName().equals(EditText.class.getName())
3838                         && event.getText().size() > 0
3839                         && event.getText().get(0).toString().equals(getString(
3840                                 R.string.android_wiki_paragraphs))
3841                         && event.getFromIndex() == 33
3842                         && event.getToIndex() == 47
3843                         && event.getMovementGranularity() ==
3844                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
3845             }
3846         }, TIMEOUT_ASYNC_PROCESSING);
3847 
3848         // Make sure we got the expected event.
3849         assertNotNull(thirdExpected);
3850 
3851         // Verify the selection position.
3852         assertEquals(47, Selection.getSelectionStart(textView.getText()));
3853         assertEquals(47, Selection.getSelectionEnd(textView.getText()));
3854 
3855         // Make sure there is no next.
3856         assertFalse(text.performAction(
3857                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
3858 
3859         // Verify the selection position.
3860         assertEquals(47, Selection.getSelectionStart(textView.getText()));
3861         assertEquals(47, Selection.getSelectionEnd(textView.getText()));
3862 
3863         // Move to the previous paragraph and wait for an event.
3864         AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
3865                 .executeAndWaitForEvent(new Runnable() {
3866             @Override
3867             public void run() {
3868                 text.performAction(
3869                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
3870             }
3871         }, new UiAutomation.AccessibilityEventFilter() {
3872             @Override
3873             public boolean accept(AccessibilityEvent event) {
3874                 return
3875                 (event.getEventType() ==
3876                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3877                         && event.getAction() ==
3878                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
3879                         && event.getPackageName().equals(getActivity().getPackageName())
3880                         && event.getClassName().equals(EditText.class.getName())
3881                         && event.getText().size() > 0
3882                         && event.getText().get(0).toString().equals(getString(
3883                                 R.string.android_wiki_paragraphs))
3884                         && event.getFromIndex() == 33
3885                         && event.getToIndex() == 47
3886                         && event.getMovementGranularity() ==
3887                                  AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
3888             }
3889         }, TIMEOUT_ASYNC_PROCESSING);
3890 
3891         // Make sure we got the expected event.
3892         assertNotNull(fourthExpected);
3893 
3894         // Verify the selection position.
3895         assertEquals(33, Selection.getSelectionStart(textView.getText()));
3896         assertEquals(33, Selection.getSelectionEnd(textView.getText()));
3897 
3898         // Move to the previous paragraph and wait for an event.
3899         AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
3900                 .executeAndWaitForEvent(new Runnable() {
3901             @Override
3902             public void run() {
3903                 text.performAction(
3904                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
3905             }
3906         }, new UiAutomation.AccessibilityEventFilter() {
3907             @Override
3908             public boolean accept(AccessibilityEvent event) {
3909                 return
3910                 (event.getEventType() ==
3911                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3912                         && event.getAction() ==
3913                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
3914                         && event.getPackageName().equals(getActivity().getPackageName())
3915                         && event.getClassName().equals(EditText.class.getName())
3916                         && event.getText().size() > 0
3917                         && event.getText().get(0).toString().equals(getString(
3918                                 R.string.android_wiki_paragraphs))
3919                         && event.getFromIndex() == 16
3920                         && event.getToIndex() == 32
3921                         && event.getMovementGranularity() ==
3922                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
3923             }
3924         }, TIMEOUT_ASYNC_PROCESSING);
3925 
3926         // Make sure we got the expected event.
3927         assertNotNull(fifthExpected);
3928 
3929         // Verify the selection position.
3930         assertEquals(16, Selection.getSelectionStart(textView.getText()));
3931         assertEquals(16, Selection.getSelectionEnd(textView.getText()));
3932 
3933         // Move to the previous paragraph and wait for an event.
3934         AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
3935                 .executeAndWaitForEvent(new Runnable() {
3936             @Override
3937             public void run() {
3938                 text.performAction(
3939                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
3940             }
3941         }, new UiAutomation.AccessibilityEventFilter() {
3942             @Override
3943             public boolean accept(AccessibilityEvent event) {
3944                 return
3945                 (event.getEventType() ==
3946                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
3947                         && event.getAction() ==
3948                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
3949                         && event.getPackageName().equals(getActivity().getPackageName())
3950                         && event.getClassName().equals(EditText.class.getName())
3951                         && event.getText().size() > 0
3952                         && event.getText().get(0).toString().equals(getString(
3953                                 R.string.android_wiki_paragraphs))
3954                         && event.getFromIndex() == 2
3955                         && event.getToIndex() == 14
3956                         && event.getMovementGranularity() ==
3957                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
3958             }
3959         }, TIMEOUT_ASYNC_PROCESSING);
3960 
3961         // Make sure we got the expected event.
3962         assertNotNull(sixthExpected);
3963 
3964         // Verify the selection position.
3965         assertEquals(2, Selection.getSelectionStart(textView.getText()));
3966         assertEquals(2, Selection.getSelectionEnd(textView.getText()));
3967 
3968         // Make sure there is no previous.
3969         assertFalse(text.performAction(
3970                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
3971 
3972         // Verify the selection position.
3973         assertEquals(2, Selection.getSelectionStart(textView.getText()));
3974         assertEquals(2, Selection.getSelectionEnd(textView.getText()));
3975     }
3976 
3977     @MediumTest
testActionNextAndPreviousAtGranularityParagraphOverTextExtend()3978     public void testActionNextAndPreviousAtGranularityParagraphOverTextExtend() throws Exception {
3979         final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
3980 
3981         getInstrumentation().runOnMainSync(new Runnable() {
3982             @Override
3983             public void run() {
3984                 editText.setVisibility(View.VISIBLE);
3985                 editText.setText(getString(R.string.android_wiki_paragraphs));
3986                 Selection.removeSelection(editText.getText());
3987             }
3988         });
3989 
3990         final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
3991                .getRootInActiveWindow().findAccessibilityNodeInfosByText(getString(
3992                        R.string.android_wiki_paragraphs)).get(0);
3993 
3994         final int granularities = text.getMovementGranularities();
3995         assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
3996                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
3997                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
3998                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
3999                 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
4000 
4001         final Bundle arguments = new Bundle();
4002         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
4003                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
4004         arguments.putBoolean(AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN, true);
4005 
4006         // Move to the next paragraph and wait for an event.
4007         AccessibilityEvent firstExpected = getInstrumentation().getUiAutomation()
4008                 .executeAndWaitForEvent(new Runnable() {
4009             @Override
4010             public void run() {
4011                 text.performAction(
4012                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
4013             }
4014         }, new UiAutomation.AccessibilityEventFilter() {
4015             @Override
4016             public boolean accept(AccessibilityEvent event) {
4017                 return
4018                 (event.getEventType() ==
4019                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
4020                         && event.getAction() ==
4021                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
4022                         && event.getPackageName().equals(getActivity().getPackageName())
4023                         && event.getClassName().equals(EditText.class.getName())
4024                         && event.getText().size() > 0
4025                         && event.getText().get(0).toString().equals(getString(
4026                                 R.string.android_wiki_paragraphs))
4027                         && event.getFromIndex() == 2
4028                         && event.getToIndex() == 14
4029                         && event.getMovementGranularity() ==
4030                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
4031             }
4032         }, TIMEOUT_ASYNC_PROCESSING);
4033 
4034         // Make sure we got the expected event.
4035         assertNotNull(firstExpected);
4036 
4037         // Verify the selection position.
4038         assertEquals(2, Selection.getSelectionStart(editText.getText()));
4039         assertEquals(14, Selection.getSelectionEnd(editText.getText()));
4040 
4041         // Move to the next paragraph and wait for an event.
4042         AccessibilityEvent secondExpected = getInstrumentation().getUiAutomation()
4043                 .executeAndWaitForEvent(new Runnable() {
4044             @Override
4045             public void run() {
4046                 text.performAction(
4047                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
4048             }
4049         }, new UiAutomation.AccessibilityEventFilter() {
4050             @Override
4051             public boolean accept(AccessibilityEvent event) {
4052                 return
4053                 (event.getEventType() ==
4054                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
4055                         && event.getAction() ==
4056                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
4057                         && event.getPackageName().equals(getActivity().getPackageName())
4058                         && event.getClassName().equals(EditText.class.getName())
4059                         && event.getText().size() > 0
4060                         && event.getText().get(0).toString().equals(getString(
4061                                 R.string.android_wiki_paragraphs))
4062                         && event.getFromIndex() == 16
4063                         && event.getToIndex() == 32
4064                         && event.getMovementGranularity() ==
4065                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
4066             }
4067         }, TIMEOUT_ASYNC_PROCESSING);
4068 
4069         // Make sure we got the expected event.
4070         assertNotNull(secondExpected);
4071 
4072         // Verify the selection position.
4073         assertEquals(2, Selection.getSelectionStart(editText.getText()));
4074         assertEquals(32, Selection.getSelectionEnd(editText.getText()));
4075 
4076         // Move to the next paragraph and wait for an event.
4077         AccessibilityEvent thirdExpected = getInstrumentation().getUiAutomation()
4078                 .executeAndWaitForEvent(new Runnable() {
4079             @Override
4080             public void run() {
4081                 text.performAction(
4082                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
4083             }
4084         }, new UiAutomation.AccessibilityEventFilter() {
4085             @Override
4086             public boolean accept(AccessibilityEvent event) {
4087                 return
4088                 (event.getEventType() ==
4089                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
4090                         && event.getAction() ==
4091                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
4092                         && event.getPackageName().equals(getActivity().getPackageName())
4093                         && event.getClassName().equals(EditText.class.getName())
4094                         && event.getText().size() > 0
4095                         && event.getText().get(0).toString().equals(getString(
4096                                 R.string.android_wiki_paragraphs))
4097                         && event.getFromIndex() == 33
4098                         && event.getToIndex() == 47
4099                         && event.getMovementGranularity() ==
4100                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
4101             }
4102         }, TIMEOUT_ASYNC_PROCESSING);
4103 
4104         // Make sure we got the expected event.
4105         assertNotNull(thirdExpected);
4106 
4107         // Verify the selection position.
4108         assertEquals(2, Selection.getSelectionStart(editText.getText()));
4109         assertEquals(47, Selection.getSelectionEnd(editText.getText()));
4110 
4111         // Make sure there is no next.
4112         assertFalse(text.performAction(
4113                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
4114 
4115         // Verify the selection position.
4116         assertEquals(2, Selection.getSelectionStart(editText.getText()));
4117         assertEquals(47, Selection.getSelectionEnd(editText.getText()));
4118 
4119         // Move to the previous paragraph and wait for an event.
4120         AccessibilityEvent fourthExpected = getInstrumentation().getUiAutomation()
4121                 .executeAndWaitForEvent(new Runnable() {
4122             @Override
4123             public void run() {
4124                 text.performAction(
4125                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
4126             }
4127         }, new UiAutomation.AccessibilityEventFilter() {
4128             @Override
4129             public boolean accept(AccessibilityEvent event) {
4130                 return
4131                 (event.getEventType() ==
4132                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
4133                         && event.getAction() ==
4134                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
4135                         && event.getPackageName().equals(getActivity().getPackageName())
4136                         && event.getClassName().equals(EditText.class.getName())
4137                         && event.getText().size() > 0
4138                         && event.getText().get(0).toString().equals(getString(
4139                                 R.string.android_wiki_paragraphs))
4140                         && event.getFromIndex() == 33
4141                         && event.getToIndex() == 47
4142                         && event.getMovementGranularity() ==
4143                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
4144             }
4145         }, TIMEOUT_ASYNC_PROCESSING);
4146 
4147         // Make sure we got the expected event.
4148         assertNotNull(fourthExpected);
4149 
4150         // Verify the selection position.
4151         assertEquals(2, Selection.getSelectionStart(editText.getText()));
4152         assertEquals(33, Selection.getSelectionEnd(editText.getText()));
4153 
4154         // Move to the previous paragraph and wait for an event.
4155         AccessibilityEvent fifthExpected = getInstrumentation().getUiAutomation()
4156                 .executeAndWaitForEvent(new Runnable() {
4157             @Override
4158             public void run() {
4159                 text.performAction(
4160                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
4161             }
4162         }, new UiAutomation.AccessibilityEventFilter() {
4163             @Override
4164             public boolean accept(AccessibilityEvent event) {
4165                 return
4166                 (event.getEventType() ==
4167                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
4168                         && event.getAction() ==
4169                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
4170                         && event.getPackageName().equals(getActivity().getPackageName())
4171                         && event.getClassName().equals(EditText.class.getName())
4172                         && event.getText().size() > 0
4173                         && event.getText().get(0).toString().equals(getString(
4174                                 R.string.android_wiki_paragraphs))
4175                         && event.getFromIndex() == 16
4176                         && event.getToIndex() == 32
4177                         && event.getMovementGranularity() ==
4178                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
4179             }
4180         }, TIMEOUT_ASYNC_PROCESSING);
4181 
4182         // Make sure we got the expected event.
4183         assertNotNull(fifthExpected);
4184 
4185         // Verify the selection position.
4186         assertEquals(2, Selection.getSelectionStart(editText.getText()));
4187         assertEquals(16, Selection.getSelectionEnd(editText.getText()));
4188 
4189         // Move to the previous paragraph and wait for an event.
4190         AccessibilityEvent sixthExpected = getInstrumentation().getUiAutomation()
4191                 .executeAndWaitForEvent(new Runnable() {
4192             @Override
4193             public void run() {
4194                 text.performAction(
4195                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
4196             }
4197         }, new UiAutomation.AccessibilityEventFilter() {
4198             @Override
4199             public boolean accept(AccessibilityEvent event) {
4200                 return
4201                 (event.getEventType() ==
4202                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
4203                         && event.getAction() ==
4204                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
4205                         && event.getPackageName().equals(getActivity().getPackageName())
4206                         && event.getClassName().equals(EditText.class.getName())
4207                         && event.getText().size() > 0
4208                         && event.getText().get(0).toString().equals(getString(
4209                                 R.string.android_wiki_paragraphs))
4210                         && event.getFromIndex() == 2
4211                         && event.getToIndex() == 14
4212                         && event.getMovementGranularity() ==
4213                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
4214             }
4215         }, TIMEOUT_ASYNC_PROCESSING);
4216 
4217         // Make sure we got the expected event.
4218         assertNotNull(sixthExpected);
4219 
4220         // Verify the selection position.
4221         assertEquals(2, Selection.getSelectionStart(editText.getText()));
4222         assertEquals(2, Selection.getSelectionEnd(editText.getText()));
4223 
4224         // Make sure there is no previous.
4225         assertFalse(text.performAction(
4226                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
4227 
4228         // Verify the selection position.
4229         assertEquals(2, Selection.getSelectionStart(editText.getText()));
4230         assertEquals(2, Selection.getSelectionEnd(editText.getText()));
4231 
4232         // Focus the view so we can change selection.
4233         getInstrumentation().runOnMainSync(new Runnable() {
4234             @Override
4235             public void run() {
4236                 editText.setFocusable(true);
4237                 editText.requestFocus();
4238             }
4239         });
4240 
4241         // Put selection at the end of the text.
4242         Bundle setSelectionArgs = new Bundle();
4243         setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 47);
4244         setSelectionArgs.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 47);
4245         assertTrue(text.performAction(
4246                 AccessibilityNodeInfo.ACTION_SET_SELECTION, setSelectionArgs));
4247 
4248         // Verify the selection position.
4249         assertEquals(47, Selection.getSelectionStart(editText.getText()));
4250         assertEquals(47, Selection.getSelectionEnd(editText.getText()));
4251 
4252         // Unfocus the view so we can get rid of the soft-keyboard.
4253         getInstrumentation().runOnMainSync(new Runnable() {
4254             @Override
4255             public void run() {
4256                 editText.clearFocus();
4257                 editText.setFocusable(false);
4258             }
4259         });
4260 
4261         // Move to the previous paragraph and wait for an event.
4262         AccessibilityEvent seventhExpected = getInstrumentation().getUiAutomation()
4263                 .executeAndWaitForEvent(new Runnable() {
4264             @Override
4265             public void run() {
4266                 text.performAction(
4267                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
4268             }
4269         }, new UiAutomation.AccessibilityEventFilter() {
4270             @Override
4271             public boolean accept(AccessibilityEvent event) {
4272                 return
4273                 (event.getEventType() ==
4274                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
4275                         && event.getAction() ==
4276                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
4277                         && event.getPackageName().equals(getActivity().getPackageName())
4278                         && event.getClassName().equals(EditText.class.getName())
4279                         && event.getText().size() > 0
4280                         && event.getText().get(0).toString().equals(getString(
4281                                 R.string.android_wiki_paragraphs))
4282                         && event.getFromIndex() == 33
4283                         && event.getToIndex() == 47
4284                         && event.getMovementGranularity() ==
4285                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
4286             }
4287         }, TIMEOUT_ASYNC_PROCESSING);
4288 
4289         // Make sure we got the expected event.
4290         assertNotNull(seventhExpected);
4291 
4292         // Verify the selection position.
4293         assertEquals(47, Selection.getSelectionStart(editText.getText()));
4294         assertEquals(33, Selection.getSelectionEnd(editText.getText()));
4295 
4296         // Move to the previous paragraph and wait for an event.
4297         AccessibilityEvent eightExpected = getInstrumentation().getUiAutomation()
4298                 .executeAndWaitForEvent(new Runnable() {
4299             @Override
4300             public void run() {
4301                 text.performAction(
4302                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
4303             }
4304         }, new UiAutomation.AccessibilityEventFilter() {
4305             @Override
4306             public boolean accept(AccessibilityEvent event) {
4307                 return
4308                 (event.getEventType() ==
4309                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
4310                         && event.getAction() ==
4311                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
4312                         && event.getPackageName().equals(getActivity().getPackageName())
4313                         && event.getClassName().equals(EditText.class.getName())
4314                         && event.getText().size() > 0
4315                         && event.getText().get(0).toString().equals(getString(
4316                                 R.string.android_wiki_paragraphs))
4317                         && event.getFromIndex() == 16
4318                         && event.getToIndex() == 32
4319                         && event.getMovementGranularity() ==
4320                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
4321             }
4322         }, TIMEOUT_ASYNC_PROCESSING);
4323 
4324         // Make sure we got the expected event.
4325         assertNotNull(eightExpected);
4326 
4327         // Verify the selection position.
4328         assertEquals(47, Selection.getSelectionStart(editText.getText()));
4329         assertEquals(16, Selection.getSelectionEnd(editText.getText()));
4330 
4331         // Move to the previous paragraph and wait for an event.
4332         AccessibilityEvent ninethExpected = getInstrumentation().getUiAutomation()
4333                 .executeAndWaitForEvent(new Runnable() {
4334             @Override
4335             public void run() {
4336                 text.performAction(
4337                         AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
4338             }
4339         }, new UiAutomation.AccessibilityEventFilter() {
4340             @Override
4341             public boolean accept(AccessibilityEvent event) {
4342                 return
4343                 (event.getEventType() ==
4344                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
4345                         && event.getAction() ==
4346                                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
4347                         && event.getPackageName().equals(getActivity().getPackageName())
4348                         && event.getClassName().equals(EditText.class.getName())
4349                         && event.getText().size() > 0
4350                         && event.getText().get(0).toString().equals(getString(
4351                                 R.string.android_wiki_paragraphs))
4352                         && event.getFromIndex() == 2
4353                         && event.getToIndex() == 14
4354                         && event.getMovementGranularity() ==
4355                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
4356             }
4357         }, TIMEOUT_ASYNC_PROCESSING);
4358 
4359         // Make sure we got the expected event.
4360         assertNotNull(ninethExpected);
4361 
4362         // Verify the selection position.
4363         assertEquals(47, Selection.getSelectionStart(editText.getText()));
4364         assertEquals(2, Selection.getSelectionEnd(editText.getText()));
4365 
4366         // Make sure there is no previous.
4367         assertFalse(text.performAction(
4368                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
4369 
4370         // Verify the selection position.
4371         assertEquals(47, Selection.getSelectionStart(editText.getText()));
4372         assertEquals(2, Selection.getSelectionEnd(editText.getText()));
4373 
4374         // Move to the next paragraph and wait for an event.
4375         AccessibilityEvent tenthExpected = getInstrumentation().getUiAutomation()
4376                 .executeAndWaitForEvent(new Runnable() {
4377             @Override
4378             public void run() {
4379                 text.performAction(
4380                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
4381             }
4382         }, new UiAutomation.AccessibilityEventFilter() {
4383             @Override
4384             public boolean accept(AccessibilityEvent event) {
4385                 return
4386                 (event.getEventType() ==
4387                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
4388                         && event.getAction() ==
4389                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
4390                         && event.getPackageName().equals(getActivity().getPackageName())
4391                         && event.getClassName().equals(EditText.class.getName())
4392                         && event.getText().size() > 0
4393                         && event.getText().get(0).toString().equals(getString(
4394                                 R.string.android_wiki_paragraphs))
4395                         && event.getFromIndex() == 2
4396                         && event.getToIndex() == 14
4397                         && event.getMovementGranularity() ==
4398                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
4399             }
4400         }, TIMEOUT_ASYNC_PROCESSING);
4401 
4402         // Make sure we got the expected event.
4403         assertNotNull(tenthExpected);
4404 
4405         // Verify the selection position.
4406         assertEquals(47, Selection.getSelectionStart(editText.getText()));
4407         assertEquals(14, Selection.getSelectionEnd(editText.getText()));
4408 
4409         // Move to the next paragraph and wait for an event.
4410         AccessibilityEvent eleventhExpected = getInstrumentation().getUiAutomation()
4411                 .executeAndWaitForEvent(new Runnable() {
4412             @Override
4413             public void run() {
4414                 text.performAction(
4415                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
4416             }
4417         }, new UiAutomation.AccessibilityEventFilter() {
4418             @Override
4419             public boolean accept(AccessibilityEvent event) {
4420                 return
4421                 (event.getEventType() ==
4422                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
4423                         && event.getAction() ==
4424                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
4425                         && event.getPackageName().equals(getActivity().getPackageName())
4426                         && event.getClassName().equals(EditText.class.getName())
4427                         && event.getText().size() > 0
4428                         && event.getText().get(0).toString().equals(getString(
4429                                 R.string.android_wiki_paragraphs))
4430                         && event.getFromIndex() == 16
4431                         && event.getToIndex() == 32
4432                         && event.getMovementGranularity() ==
4433                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
4434             }
4435         }, TIMEOUT_ASYNC_PROCESSING);
4436 
4437         // Make sure we got the expected event.
4438         assertNotNull(eleventhExpected);
4439 
4440         // Verify the selection position.
4441         assertEquals(47, Selection.getSelectionStart(editText.getText()));
4442         assertEquals(32, Selection.getSelectionEnd(editText.getText()));
4443 
4444         // Move to the next paragraph and wait for an event.
4445         AccessibilityEvent twlevethExpected = getInstrumentation().getUiAutomation()
4446                 .executeAndWaitForEvent(new Runnable() {
4447             @Override
4448             public void run() {
4449                 text.performAction(
4450                         AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
4451             }
4452         }, new UiAutomation.AccessibilityEventFilter() {
4453             @Override
4454             public boolean accept(AccessibilityEvent event) {
4455                 return
4456                 (event.getEventType() ==
4457                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
4458                         && event.getAction() ==
4459                                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
4460                         && event.getPackageName().equals(getActivity().getPackageName())
4461                         && event.getClassName().equals(EditText.class.getName())
4462                         && event.getText().size() > 0
4463                         && event.getText().get(0).toString().equals(getString(
4464                                 R.string.android_wiki_paragraphs))
4465                         && event.getFromIndex() == 33
4466                         && event.getToIndex() == 47
4467                         && event.getMovementGranularity() ==
4468                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
4469             }
4470         }, TIMEOUT_ASYNC_PROCESSING);
4471 
4472         // Make sure we got the expected event.
4473         assertNotNull(twlevethExpected);
4474 
4475         // Verify the selection position.
4476         assertEquals(47, Selection.getSelectionStart(editText.getText()));
4477         assertEquals(47, Selection.getSelectionEnd(editText.getText()));
4478 
4479         // Make sure there is no next.
4480         assertFalse(text.performAction(
4481                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
4482 
4483         // Verify the selection position.
4484         assertEquals(47, Selection.getSelectionStart(editText.getText()));
4485         assertEquals(47, Selection.getSelectionEnd(editText.getText()));
4486     }
4487 
4488     @MediumTest
testTextEditingActions()4489     public void testTextEditingActions() throws Exception {
4490         if (!getActivity().getPackageManager().hasSystemFeature(
4491                 PackageManager.FEATURE_INPUT_METHODS)) {
4492             return;
4493         }
4494 
4495         final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
4496         final String textContent = getString(R.string.foo_bar_baz);
4497 
4498         getInstrumentation().runOnMainSync(new Runnable() {
4499             @Override
4500             public void run() {
4501                 editText.setVisibility(View.VISIBLE);
4502                 editText.setFocusable(true);
4503                 editText.requestFocus();
4504                 editText.setText(getString(R.string.foo_bar_baz));
4505                 Selection.removeSelection(editText.getText());
4506             }
4507         });
4508 
4509         final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
4510                .getRootInActiveWindow().findAccessibilityNodeInfosByText(
4511                        getString(R.string.foo_bar_baz)).get(0);
4512 
4513         // Select all text.
4514         Bundle arguments = new Bundle();
4515         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 0);
4516         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT,
4517                 editText.getText().length());
4518         assertTrue(text.performAction(
4519                 AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments));
4520 
4521         // Copy the selected text.
4522         text.performAction(AccessibilityNodeInfo.ACTION_COPY);
4523 
4524         // Set selection at the end.
4525         final int textLength = editText.getText().length();
4526         // Verify the selection position.
4527         assertEquals(textLength, Selection.getSelectionStart(editText.getText()));
4528         assertEquals(textLength, Selection.getSelectionEnd(editText.getText()));
4529 
4530         // Paste the selected text.
4531         assertTrue(text.performAction(
4532                 AccessibilityNodeInfo.ACTION_PASTE));
4533 
4534         // Verify the content.
4535         assertEquals(editText.getText().toString(), textContent + textContent);
4536 
4537         // Select all text.
4538         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 0);
4539         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT,
4540                 editText.getText().length());
4541         assertTrue(text.performAction(
4542                 AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments));
4543 
4544         // Cut the selected text.
4545         assertTrue(text.performAction(
4546                 AccessibilityNodeInfo.ACTION_CUT));
4547 
4548         // Verify the content.
4549         assertTrue(TextUtils.isEmpty(editText.getText()));
4550     }
4551 
testSetSelectionInContentDescription()4552     public void testSetSelectionInContentDescription() throws Exception {
4553         final View view = getActivity().findViewById(R.id.view);
4554 
4555         getInstrumentation().runOnMainSync(new Runnable() {
4556             @Override
4557             public void run() {
4558                 view.setVisibility(View.VISIBLE);
4559                 view.setContentDescription(getString(R.string.foo_bar_baz));
4560             }
4561         });
4562 
4563         AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
4564                .getRootInActiveWindow().findAccessibilityNodeInfosByText(
4565                        getString(R.string.foo_bar_baz)).get(0);
4566 
4567         // Set the cursor position.
4568         Bundle arguments = new Bundle();
4569         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 4);
4570         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 4);
4571         assertTrue(text.performAction(
4572                 AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments));
4573 
4574         // Try and fail to set the selection longer than zero.
4575         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 4);
4576         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 5);
4577         assertFalse(text.performAction(
4578                 AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments));
4579     }
4580 
testSelectionPositionForNonEditableView()4581     public void testSelectionPositionForNonEditableView() throws Exception {
4582         final View view = getActivity().findViewById(R.id.view);
4583 
4584         getInstrumentation().runOnMainSync(new Runnable() {
4585             @Override
4586             public void run() {
4587                 view.setVisibility(View.VISIBLE);
4588                 view.setContentDescription(getString(R.string.foo_bar_baz));
4589             }
4590         });
4591 
4592         final AccessibilityNodeInfo text = getInstrumentation().getUiAutomation()
4593                .getRootInActiveWindow().findAccessibilityNodeInfosByText(
4594                        getString(R.string.foo_bar_baz)).get(0);
4595 
4596         // Check the initial node properties.
4597         assertFalse(text.isEditable());
4598         assertSame(text.getTextSelectionStart(), -1);
4599         assertSame(text.getTextSelectionEnd(), -1);
4600 
4601         // Set the cursor position.
4602         getInstrumentation().getUiAutomation().executeAndWaitForEvent(new Runnable() {
4603             @Override
4604             public void run() {
4605                 Bundle arguments = new Bundle();
4606                 arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 4);
4607                 arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 4);
4608                 assertTrue(text.performAction(
4609                         AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments));
4610             }
4611         }, new UiAutomation.AccessibilityEventFilter() {
4612             @Override
4613             public boolean accept(AccessibilityEvent event) {
4614                 return (event.getEventType()
4615                         == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
4616             }
4617         }, TIMEOUT_ASYNC_PROCESSING);
4618 
4619         // Refresh the node.
4620         AccessibilityNodeInfo refreshedText = getInstrumentation().getUiAutomation()
4621                 .getRootInActiveWindow().findAccessibilityNodeInfosByText(
4622                         getString(R.string.foo_bar_baz)).get(0);
4623 
4624         // Check the related node properties.
4625         assertFalse(refreshedText.isEditable());
4626         assertSame(refreshedText.getTextSelectionStart(), 4);
4627         assertSame(refreshedText.getTextSelectionEnd(), 4);
4628 
4629         // Try to set to an invalid cursor position.
4630         Bundle arguments = new Bundle();
4631         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, 4);
4632         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, 5);
4633         assertFalse(text.performAction(
4634                 AccessibilityNodeInfo.ACTION_SET_SELECTION, arguments));
4635 
4636         // Refresh the node.
4637         refreshedText = getInstrumentation().getUiAutomation()
4638                 .getRootInActiveWindow().findAccessibilityNodeInfosByText(
4639                         getString(R.string.foo_bar_baz)).get(0);
4640 
4641         // Check the related node properties.
4642         assertFalse(refreshedText.isEditable());
4643         assertSame(refreshedText.getTextSelectionStart(), 4);
4644         assertSame(refreshedText.getTextSelectionEnd(), 4);
4645     }
4646 }
4647