1a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar/*
2a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * Copyright (C) 2014 The Android Open Source Project
3a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar *
4a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
5a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * you may not use this file except in compliance with the License.
6a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * You may obtain a copy of the License at
7a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar *
8a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
9a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar *
10a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * Unless required by applicable law or agreed to in writing, software
11a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
12a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * See the License for the specific language governing permissions and
14a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar * limitations under the License.
15a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar */
16a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar
17a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyarpackage android.support.v7.widget;
18a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar
190a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport org.junit.Test;
200a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport org.junit.runner.RunWith;
210a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport org.junit.runners.Parameterized;
220a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar
23a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyarimport android.support.v4.view.AccessibilityDelegateCompat;
24a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyarimport android.support.v4.view.accessibility.AccessibilityEventCompat;
25a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyarimport android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
26a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyarimport android.support.v4.view.accessibility.AccessibilityRecordCompat;
27f1b288ec2104488f4a92e911b0ab80c8f0f3e9d1Yigit Boyarimport android.test.suitebuilder.annotation.MediumTest;
28a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyarimport android.view.View;
29a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyarimport android.view.accessibility.AccessibilityEvent;
30a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar
310a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport java.util.ArrayList;
320a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport java.util.Arrays;
330a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport java.util.List;
34a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyarimport java.util.concurrent.atomic.AtomicBoolean;
35a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar
360a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport static org.junit.Assert.assertEquals;
370a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport static org.junit.Assert.assertFalse;
380a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport static org.junit.Assert.assertNotNull;
390a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport static org.junit.Assert.assertTrue;
400a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar
41f1b288ec2104488f4a92e911b0ab80c8f0f3e9d1Yigit Boyar@MediumTest
420a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar@RunWith(Parameterized.class)
43a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyarpublic class RecyclerViewAccessibilityTest extends BaseRecyclerViewInstrumentationTest {
44da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar
450a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    final boolean verticalScrollBefore, horizontalScrollBefore, verticalScrollAfter,
460a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar            horizontalScrollAfter;
470a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar
480a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public RecyclerViewAccessibilityTest(boolean verticalScrollBefore,
490a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar            boolean horizontalScrollBefore, boolean verticalScrollAfter,
500a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar            boolean horizontalScrollAfter) {
510a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar        this.verticalScrollBefore = verticalScrollBefore;
520a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar        this.horizontalScrollBefore = horizontalScrollBefore;
530a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar        this.verticalScrollAfter = verticalScrollAfter;
540a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar        this.horizontalScrollAfter = horizontalScrollAfter;
55da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar    }
56da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar
570a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Parameterized.Parameters(name = "vBefore={0} vAfter={1} hBefore={2} hAfter={3}")
580a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public static List<Object[]> getParams() {
590a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar        List<Object[]> params = new ArrayList<>();
60a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        for (boolean vBefore : new boolean[]{true, false}) {
61a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            for (boolean vAfter : new boolean[]{true, false}) {
62a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                for (boolean hBefore : new boolean[]{true, false}) {
63a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                    for (boolean hAfter : new boolean[]{true, false}) {
640a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar                        params.add(new Object[]{vBefore, hBefore, vAfter, hAfter});
65a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                    }
66a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                }
67a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            }
68a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        }
690a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar        return params;
70a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar    }
71da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar
720a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
730a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void onInitializeAccessibilityNodeInfoTest() throws Throwable {
74a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        final RecyclerView recyclerView = new RecyclerView(getActivity()) {
75a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            //@Override
76a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            public boolean canScrollHorizontally(int direction) {
77a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                return direction < 0 && horizontalScrollBefore ||
78a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                        direction > 0 && horizontalScrollAfter;
79a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            }
80a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar
81a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            //@Override
82a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            public boolean canScrollVertically(int direction) {
83a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                return direction < 0 && verticalScrollBefore ||
84a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                        direction > 0 && verticalScrollAfter;
85a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            }
86a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        };
87a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        final TestAdapter adapter = new TestAdapter(10);
88a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        final AtomicBoolean hScrolledBack = new AtomicBoolean(false);
89a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        final AtomicBoolean vScrolledBack = new AtomicBoolean(false);
90a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        final AtomicBoolean hScrolledFwd = new AtomicBoolean(false);
91a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        final AtomicBoolean vScrolledFwd = new AtomicBoolean(false);
92a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        recyclerView.setAdapter(adapter);
93a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        recyclerView.setLayoutManager(new TestLayoutManager() {
94a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar
95a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            @Override
96a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
97a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                layoutRange(recycler, 0, 5);
98a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            }
99a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar
100a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            @Override
101a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            public RecyclerView.LayoutParams generateDefaultLayoutParams() {
102a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                return new RecyclerView.LayoutParams(-1, -1);
103a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            }
104a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar
105a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            @Override
106a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            public boolean canScrollVertically() {
107a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                return verticalScrollAfter || verticalScrollBefore;
108a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            }
109a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar
110a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            @Override
111a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler,
112a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                    RecyclerView.State state) {
113a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                if (dx > 0) {
114a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                    hScrolledFwd.set(true);
115a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                } else if (dx < 0) {
116a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                    hScrolledBack.set(true);
117a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                }
118a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                return 0;
119a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            }
120a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar
121a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            @Override
122a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler,
123a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                    RecyclerView.State state) {
124a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                if (dy > 0) {
125a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                    vScrolledFwd.set(true);
126a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                } else if (dy < 0) {
127a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                    vScrolledBack.set(true);
128a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                }
129a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                return 0;
130a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            }
131a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar
132a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            @Override
133a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            public boolean canScrollHorizontally() {
134a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                return horizontalScrollAfter || horizontalScrollBefore;
135a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            }
136a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        });
137a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        setRecyclerView(recyclerView);
138a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        final RecyclerViewAccessibilityDelegate delegateCompat = recyclerView
139a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                .getCompatAccessibilityDelegate();
140a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        final AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain();
141a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        runTestOnUiThread(new Runnable() {
142a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            @Override
143a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            public void run() {
144a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                delegateCompat.onInitializeAccessibilityNodeInfo(recyclerView, info);
145a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            }
146a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        });
147a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        assertEquals(horizontalScrollAfter || horizontalScrollBefore
148a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                || verticalScrollAfter || verticalScrollBefore, info.isScrollable());
149a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        assertEquals(horizontalScrollBefore || verticalScrollBefore,
150a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                (info.getActions() & AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD) != 0);
151a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        assertEquals(horizontalScrollAfter || verticalScrollAfter,
152a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                (info.getActions() & AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD) != 0);
153a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        final AccessibilityNodeInfoCompat.CollectionInfoCompat collectionInfo = info
154a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                .getCollectionInfo();
155a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        assertNotNull(collectionInfo);
156a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        if (recyclerView.getLayoutManager().canScrollVertically()) {
157a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            assertEquals(adapter.getItemCount(), collectionInfo.getRowCount());
158a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        }
159a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        if (recyclerView.getLayoutManager().canScrollHorizontally()) {
160a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            assertEquals(adapter.getItemCount(), collectionInfo.getColumnCount());
161a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        }
162a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar
163a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        final AccessibilityEvent event = AccessibilityEvent.obtain();
164a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        runTestOnUiThread(new Runnable() {
165a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            @Override
166a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            public void run() {
167a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                delegateCompat.onInitializeAccessibilityEvent(recyclerView, event);
168a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            }
169a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        });
170a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        final AccessibilityRecordCompat record = AccessibilityEventCompat
171a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                .asRecord(event);
172a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        assertEquals(record.isScrollable(), verticalScrollAfter || horizontalScrollAfter ||
1730a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar                verticalScrollBefore || horizontalScrollBefore);
174a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        assertEquals(record.getItemCount(), adapter.getItemCount());
175a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar
176a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        getInstrumentation().waitForIdleSync();
1770a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar        for (int i = 0; i < mRecyclerView.getChildCount(); i++) {
178a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            final View view = mRecyclerView.getChildAt(i);
179a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            final AccessibilityNodeInfoCompat childInfo = AccessibilityNodeInfoCompat.obtain();
180a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            runTestOnUiThread(new Runnable() {
181a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                @Override
182a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                public void run() {
183a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                    delegateCompat.getItemDelegate().
184a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                            onInitializeAccessibilityNodeInfo(view, childInfo);
185a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                }
186a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            });
187a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            final AccessibilityNodeInfoCompat.CollectionItemInfoCompat collectionItemInfo
188a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                    = childInfo.getCollectionItemInfo();
189a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            assertNotNull(collectionItemInfo);
190a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            if (recyclerView.getLayoutManager().canScrollHorizontally()) {
191a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                assertEquals(i, collectionItemInfo.getColumnIndex());
192a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            } else {
193a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                assertEquals(0, collectionItemInfo.getColumnIndex());
194a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            }
195a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar
196a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            if (recyclerView.getLayoutManager().canScrollVertically()) {
197a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                assertEquals(i, collectionItemInfo.getRowIndex());
198a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            } else {
199a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                assertEquals(0, collectionItemInfo.getRowIndex());
200a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            }
201a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        }
202a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar
203a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        runTestOnUiThread(new Runnable() {
204a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            @Override
205a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            public void run() {
206a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar
207a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            }
208a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        });
209a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        hScrolledBack.set(false);
210a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        vScrolledBack.set(false);
211a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        hScrolledFwd.set(false);
212a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        vScrolledBack.set(false);
213a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        performAccessibilityAction(delegateCompat, recyclerView,
214a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD);
215a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        assertEquals(horizontalScrollBefore, hScrolledBack.get());
216a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        assertEquals(verticalScrollBefore, vScrolledBack.get());
217a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        assertEquals(false, hScrolledFwd.get());
218a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        assertEquals(false, vScrolledFwd.get());
219a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar
220a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        hScrolledBack.set(false);
221a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        vScrolledBack.set(false);
222a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        hScrolledFwd.set(false);
223a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        vScrolledBack.set(false);
224a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        performAccessibilityAction(delegateCompat, recyclerView,
225a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar                AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD);
226a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        assertEquals(false, hScrolledBack.get());
227a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        assertEquals(false, vScrolledBack.get());
228a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        assertEquals(horizontalScrollAfter, hScrolledFwd.get());
229a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        assertEquals(verticalScrollAfter, vScrolledFwd.get());
230a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar    }
231a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar
2320a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    @Test
2330a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar    public void ignoreAccessibilityIfAdapterHasChanged() throws Throwable {
234da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        final RecyclerView recyclerView = new RecyclerView(getActivity()) {
235da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar            //@Override
236da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar            public boolean canScrollHorizontally(int direction) {
237da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar                return true;
238da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar            }
239da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar
240da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar            //@Override
241da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar            public boolean canScrollVertically(int direction) {
242da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar                return true;
243da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar            }
244da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        };
245da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        final DumbLayoutManager layoutManager = new DumbLayoutManager();
246da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        final TestAdapter adapter = new TestAdapter(10);
247da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        recyclerView.setAdapter(adapter);
248da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        recyclerView.setLayoutManager(layoutManager);
249da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        layoutManager.expectLayouts(1);
250da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        setRecyclerView(recyclerView);
251da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        layoutManager.waitForLayout(1);
252da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar
253da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        final RecyclerViewAccessibilityDelegate delegateCompat = recyclerView
254da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar                .getCompatAccessibilityDelegate();
255da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        final AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain();
256da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        runTestOnUiThread(new Runnable() {
257da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar            @Override
258da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar            public void run() {
259da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar                delegateCompat.onInitializeAccessibilityNodeInfo(recyclerView, info);
260da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar            }
261da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        });
262da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        assertTrue("test sanity", info.isScrollable());
263da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        final AccessibilityNodeInfoCompat info2 = AccessibilityNodeInfoCompat.obtain();
26466826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar        runTestOnUiThread(new Runnable() {
26566826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar            @Override
26666826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar            public void run() {
26766826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar                try {
26866826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar                    adapter.deleteAndNotify(1, 1);
26966826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar                } catch (Throwable throwable) {
27066826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar                    postExceptionToInstrumentation(throwable);
27166826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar                }
27266826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar                delegateCompat.onInitializeAccessibilityNodeInfo(recyclerView, info2);
27366826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar                assertFalse("info should not be filled if data is out of date",
27466826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar                        info2.isScrollable());
27566826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar            }
27666826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar        });
27766826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar        checkForMainThreadException();
278da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar    }
279da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar
280da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar    boolean performAccessibilityAction(final AccessibilityDelegateCompat delegate,
2810a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar            final RecyclerView recyclerView, final int action) throws Throwable {
282da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        final boolean[] result = new boolean[1];
283a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        runTestOnUiThread(new Runnable() {
284a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            @Override
285a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            public void run() {
286da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar                result[0] = delegate.performAccessibilityAction(recyclerView, action, null);
287a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar            }
288a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        });
289a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        getInstrumentation().waitForIdleSync();
290a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar        Thread.sleep(250);
291da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar        return result[0];
292a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar    }
293a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar}
294