1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.widget.cts;
18 
19 import android.test.suitebuilder.annotation.MediumTest;
20 import android.widget.cts.R;
21 
22 import org.xmlpull.v1.XmlPullParser;
23 import org.xmlpull.v1.XmlPullParserException;
24 
25 import android.app.Activity;
26 import android.app.Instrumentation;
27 import android.content.Context;
28 import android.cts.util.PollingCheck;
29 import android.cts.util.WidgetTestUtils;
30 import android.graphics.Canvas;
31 import android.graphics.Color;
32 import android.graphics.Rect;
33 import android.graphics.drawable.Drawable;
34 import android.test.ActivityInstrumentationTestCase2;
35 import android.test.TouchUtils;
36 import android.text.Editable;
37 import android.text.SpannableStringBuilder;
38 import android.util.AttributeSet;
39 import android.util.Xml;
40 import android.view.ContextMenu.ContextMenuInfo;
41 import android.view.View;
42 import android.view.ViewGroup;
43 import android.widget.AbsListView;
44 import android.widget.AbsListView.OnScrollListener;
45 import android.widget.AbsListView.RecyclerListener;
46 import android.widget.AdapterView;
47 import android.widget.AdapterView.OnItemLongClickListener;
48 import android.widget.ArrayAdapter;
49 import android.widget.ListAdapter;
50 import android.widget.ListView;
51 import android.widget.TextView;
52 
53 import java.io.IOException;
54 import java.util.ArrayList;
55 import java.util.List;
56 
57 public class AbsListViewTest extends ActivityInstrumentationTestCase2<ListViewCtsActivity> {
58     private final String[] mShortList = new String[] {
59         "This", "is", "short", "!",
60     };
61     private final String[] mCountryList = new String[] {
62         "Argentina", "Australia", "China", "France", "Germany", "Italy", "Japan", "United States",
63         "Argentina", "Australia", "China", "France", "Germany", "Italy", "Japan", "United States",
64         "Argentina", "Australia", "China", "France", "Germany", "Italy", "Japan", "United States"
65     };
66 
67     private ListView mListView;
68     private Activity mActivity;
69     private Instrumentation mInstrumentation;
70     private AttributeSet mAttributeSet;
71     private ArrayAdapter<String> mAdapter_short;
72     private ArrayAdapter<String> mAdapter_countries;
73 
74     private static final float DELTA = 0.001f;
75 
AbsListViewTest()76     public AbsListViewTest() {
77         super("android.widget.cts", ListViewCtsActivity.class);
78     }
79 
80 
81     @Override
setUp()82     protected void setUp() throws Exception {
83         super.setUp();
84 
85         mActivity = getActivity();
86         new PollingCheck() {
87             @Override
88                 protected boolean check() {
89                 return mActivity.hasWindowFocus();
90             }
91         }.run();
92         mInstrumentation = getInstrumentation();
93 
94         XmlPullParser parser = mActivity.getResources().getXml(R.layout.listview_layout);
95         WidgetTestUtils.beginDocument(parser, "LinearLayout");
96         mAttributeSet = Xml.asAttributeSet(parser);
97 
98         mAdapter_short = new ArrayAdapter<String>(mActivity,
99                 android.R.layout.simple_list_item_1, mShortList);
100         mAdapter_countries = new ArrayAdapter<String>(mActivity,
101                 android.R.layout.simple_list_item_1, mCountryList);
102 
103         mListView = (ListView)mActivity.findViewById(R.id.listview_default);
104     }
105 
testConstructor()106     public void testConstructor() {
107         /**
108          * We can not test the constructors.
109          */
110     }
111 
testAccessFastScrollEnabled()112     public void testAccessFastScrollEnabled() {
113         mListView.setFastScrollEnabled(false);
114         assertFalse(mListView.isFastScrollEnabled());
115 
116         mListView.setFastScrollEnabled(true);
117         assertTrue(mListView.isFastScrollEnabled());
118     }
119 
testAccessSmoothScrollbarEnabled()120     public void testAccessSmoothScrollbarEnabled() {
121         mListView.setSmoothScrollbarEnabled(false);
122         assertFalse(mListView.isSmoothScrollbarEnabled());
123 
124         mListView.setSmoothScrollbarEnabled(true);
125         assertTrue(mListView.isSmoothScrollbarEnabled());
126     }
127 
testAccessScrollingCacheEnabled()128     public void testAccessScrollingCacheEnabled() {
129         mListView.setScrollingCacheEnabled(false);
130         assertFalse(mListView.isScrollingCacheEnabled());
131 
132         mListView.setScrollingCacheEnabled(true);
133         assertTrue(mListView.isScrollingCacheEnabled());
134     }
135 
setAdapter()136     private void setAdapter() throws Throwable {
137         setAdapter(mAdapter_countries);
138     }
139 
setAdapter(final ListAdapter adapter)140     private void setAdapter(final ListAdapter adapter) throws Throwable {
141         runTestOnUiThread(new Runnable() {
142             public void run() {
143                 mListView.setAdapter(adapter);
144             }
145         });
146         mInstrumentation.waitForIdleSync();
147     }
148 
setListSelection(int index)149     private void setListSelection(int index) throws Throwable {
150         final int i = index;
151 
152         runTestOnUiThread(new Runnable() {
153             public void run() {
154                 mListView.setSelection(i);
155             }
156         });
157         mInstrumentation.waitForIdleSync();
158     }
testSetOnScrollListener()159     public void testSetOnScrollListener() throws Throwable {
160         MockOnScrollListener onScrollListener = new MockOnScrollListener();
161 
162         assertNull(onScrollListener.getView());
163         assertEquals(0, onScrollListener.getFirstVisibleItem());
164         assertEquals(0, onScrollListener.getVisibleItemCount());
165         assertEquals(0, onScrollListener.getTotalItemCount());
166         assertEquals(-1, onScrollListener.getScrollState());
167 
168         assertFalse(onScrollListener.isOnScrollCalled());
169         assertFalse(onScrollListener.isOnScrollStateChangedCalled());
170 
171         mListView.setOnScrollListener(onScrollListener);
172         assertSame(mListView, onScrollListener.getView());
173         assertEquals(0, onScrollListener.getFirstVisibleItem());
174         assertEquals(0, onScrollListener.getVisibleItemCount());
175         assertEquals(0, onScrollListener.getTotalItemCount());
176         assertEquals(-1, onScrollListener.getScrollState());
177 
178         assertTrue(onScrollListener.isOnScrollCalled());
179         assertFalse(onScrollListener.isOnScrollStateChangedCalled());
180         onScrollListener.reset();
181 
182         setAdapter();
183 
184         assertSame(mListView, onScrollListener.getView());
185         assertEquals(0, onScrollListener.getFirstVisibleItem());
186         assertEquals(mListView.getChildCount(), onScrollListener.getVisibleItemCount());
187         assertEquals(mCountryList.length, onScrollListener.getTotalItemCount());
188         assertEquals(-1, onScrollListener.getScrollState());
189 
190         assertTrue(onScrollListener.isOnScrollCalled());
191         assertFalse(onScrollListener.isOnScrollStateChangedCalled());
192         onScrollListener.reset();
193 
194         TouchUtils.scrollToBottom(this, mActivity, mListView);
195         assertSame(mListView, onScrollListener.getView());
196         assertEquals(mListView.getChildCount(), onScrollListener.getVisibleItemCount());
197         assertEquals(mCountryList.length, onScrollListener.getTotalItemCount());
198 
199         assertTrue(onScrollListener.isOnScrollCalled());
200         assertTrue(onScrollListener.isOnScrollStateChangedCalled());
201     }
202 
testFling()203     public void testFling() throws Throwable {
204         MockOnScrollListener onScrollListener = new MockOnScrollListener();
205         mListView.setOnScrollListener(onScrollListener);
206 
207         setAdapter();
208 
209         // Fling down from top, expect a scroll.
210         fling(10000, onScrollListener);
211         assertTrue(onScrollListener.isOnScrollCalled());
212         assertTrue(0 < onScrollListener.getFirstVisibleItem());
213 
214         // Fling up the same amount, expect a scroll to the original position.
215         fling(-10000, onScrollListener);
216         assertTrue(onScrollListener.isOnScrollCalled());
217         assertEquals(0, onScrollListener.getFirstVisibleItem());
218 
219         // Fling up again, expect no scroll, as the viewport is already at top.
220         fling(-10000, onScrollListener);
221         assertFalse(onScrollListener.isOnScrollCalled());
222         assertEquals(0, onScrollListener.getFirstVisibleItem());
223 
224         // Fling up again with a huge velocity, expect no scroll.
225         fling(-50000, onScrollListener);
226         assertFalse(onScrollListener.isOnScrollCalled());
227         assertEquals(0, onScrollListener.getFirstVisibleItem());
228     }
229 
fling(int velocityY, MockOnScrollListener onScrollListener)230     private void fling(int velocityY, MockOnScrollListener onScrollListener) throws Throwable {
231         onScrollListener.reset();
232 
233         final int v = velocityY;
234         runTestOnUiThread(new Runnable() {
235             public void run() {
236                 mListView.fling(v);
237             }
238         });
239 
240         do {
241             mInstrumentation.waitForIdleSync();
242         } while (onScrollListener.getScrollState() != OnScrollListener.SCROLL_STATE_IDLE);
243     }
244 
testGetFocusedRect()245     public void testGetFocusedRect() throws Throwable {
246         setAdapter(mAdapter_short);
247         setListSelection(0);
248 
249         Rect r1 = new Rect();
250         mListView.getFocusedRect(r1);
251 
252         assertEquals(0, r1.top);
253         assertTrue(r1.bottom > 0);
254         assertEquals(0, r1.left);
255         assertTrue(r1.right > 0);
256 
257         setListSelection(3);
258         Rect r2 = new Rect();
259         mListView.getFocusedRect(r2);
260         assertTrue(r2.top > 0);
261         assertTrue(r2.bottom > 0);
262         assertEquals(0, r2.left);
263         assertTrue(r2.right > 0);
264 
265         assertTrue(r2.top > r1.top);
266         assertEquals(r1.bottom - r1.top, r2.bottom - r2.top);
267         assertEquals(r1.right, r2.right);
268     }
269 
testAccessStackFromBottom()270     public void testAccessStackFromBottom() throws Throwable {
271         setAdapter();
272 
273         runTestOnUiThread(new Runnable() {
274             public void run() {
275                 mListView.setStackFromBottom(false);
276             }
277         });
278         assertFalse(mListView.isStackFromBottom());
279         assertEquals(0, mListView.getSelectedItemPosition());
280 
281         runTestOnUiThread(new Runnable() {
282             public void run() {
283                 mListView.setStackFromBottom(true);
284             }
285         });
286 
287         mInstrumentation.waitForIdleSync();
288         assertTrue(mListView.isStackFromBottom());
289         // ensure last item in list is selected
290         assertEquals(mCountryList.length-1, mListView.getSelectedItemPosition());
291     }
292 
testAccessSelectedItem()293     public void testAccessSelectedItem() throws Throwable {
294         assertNull(mListView.getSelectedView());
295 
296         setAdapter();
297         TextView tv = (TextView) mListView.getSelectedView();
298         assertEquals(mCountryList[0], tv.getText().toString());
299 
300         setListSelection(5);
301         tv = (TextView) mListView.getSelectedView();
302         assertEquals(mCountryList[5], tv.getText().toString());
303 
304         setListSelection(2);
305         tv = (TextView) mListView.getSelectedView();
306         assertEquals(mCountryList[2], tv.getText().toString());
307     }
308 
testAccessListPadding()309     public void testAccessListPadding() throws Throwable {
310         setAdapter();
311 
312         assertEquals(0, mListView.getListPaddingLeft());
313         assertEquals(0, mListView.getListPaddingTop());
314         assertEquals(0, mListView.getListPaddingRight());
315         assertEquals(0, mListView.getListPaddingBottom());
316 
317         final Rect r = new Rect(0, 0, 40, 60);
318         runTestOnUiThread(new Runnable() {
319             public void run() {
320                 mListView.setPadding(r.left, r.top, r.right, r.bottom);
321             }
322         });
323         mInstrumentation.waitForIdleSync();
324 
325         assertEquals(r.left, mListView.getListPaddingLeft());
326         assertEquals(r.top, mListView.getListPaddingTop());
327         assertEquals(r.right, mListView.getListPaddingRight());
328         assertEquals(r.bottom, mListView.getListPaddingBottom());
329     }
330 
testAccessSelector()331     public void testAccessSelector() throws Throwable {
332         setAdapter();
333 
334         final Drawable d = mActivity.getResources().getDrawable(R.drawable.pass);
335         mListView.setSelector(d);
336 
337         runTestOnUiThread(new Runnable() {
338             public void run() {
339                 mListView.requestLayout();
340             }
341         });
342         mInstrumentation.waitForIdleSync();
343         assertSame(d, mListView.getSelector());
344         assertTrue(mListView.verifyDrawable(d));
345 
346         mListView.setSelector(R.drawable.failed);
347         mListView.setDrawSelectorOnTop(true);
348 
349         runTestOnUiThread(new Runnable() {
350             public void run() {
351                 mListView.requestLayout();
352             }
353         });
354         mInstrumentation.waitForIdleSync();
355 
356         Drawable drawable = mListView.getSelector();
357         assertNotNull(drawable);
358         final Rect r = drawable.getBounds();
359 
360         final TextView v = (TextView) mListView.getSelectedView();
361         new PollingCheck() {
362             @Override
363             protected boolean check() {
364                 return v.getRight() == r.right;
365             }
366         }.run();
367         assertEquals(v.getLeft(), r.left);
368         assertEquals(v.getTop(), r.top);
369         assertEquals(v.getBottom(), r.bottom);
370     }
371 
testSetScrollIndicators()372     public void testSetScrollIndicators() throws Throwable {
373         TextView tv1 = (TextView) mActivity.findViewById(R.id.headerview1);
374         TextView tv2 = (TextView) mActivity.findViewById(R.id.footerview1);
375 
376         setAdapter();
377 
378         mListView.setScrollIndicators(tv1, tv2);
379 
380         runTestOnUiThread(new Runnable() {
381             public void run() {
382                 mListView.requestLayout();
383             }
384         });
385         mInstrumentation.waitForIdleSync();
386     }
387 
testShowContextMenuForChild()388     public void testShowContextMenuForChild() throws Throwable {
389         setAdapter();
390         setListSelection(1);
391 
392         TextView tv = (TextView) mListView.getSelectedView();
393         assertFalse(mListView.showContextMenuForChild(tv));
394 
395         // TODO: how to show the contextMenu success
396     }
397 
testPointToPosition()398     public void testPointToPosition() throws Throwable {
399         assertEquals(AbsListView.INVALID_POSITION, mListView.pointToPosition(-1, -1));
400         assertEquals(AbsListView.INVALID_ROW_ID, mListView.pointToRowId(-1, -1));
401 
402         setAdapter();
403 
404         View row = mListView.getChildAt(0);
405         int rowHeight = row.getHeight();
406         int middleOfSecondRow = rowHeight + rowHeight/2;
407 
408         int position1 = mListView.pointToPosition(0, 0);
409         int position2 = mListView.pointToPosition(50, middleOfSecondRow);
410 
411         assertEquals(mAdapter_countries.getItemId(position1), mListView.pointToRowId(0, 0));
412         assertEquals(mAdapter_countries.getItemId(position2),
413                 mListView.pointToRowId(50, middleOfSecondRow));
414 
415         assertTrue(position2 > position1);
416     }
417 
testDraw()418     public void testDraw() {
419         Canvas canvas = new Canvas();
420         mListView.draw(canvas);
421 
422         MyListView listView = new MyListView(mActivity);
423         listView.dispatchDraw(canvas);
424 
425         // TODO: how to check
426     }
427 
testSetRecyclerListener()428     public void testSetRecyclerListener() throws Throwable {
429         setAdapter();
430 
431         MockRecyclerListener recyclerListener = new MockRecyclerListener();
432         List<View> views = new ArrayList<View>();
433 
434         assertNull(recyclerListener.getView());
435         mListView.setRecyclerListener(recyclerListener);
436         mListView.reclaimViews(views);
437 
438         assertTrue(views.size() > 0);
439         assertNotNull(recyclerListener.getView());
440 
441         assertSame(recyclerListener.getView(), views.get(views.size() - 1));
442     }
443 
testAccessCacheColorHint()444     public void testAccessCacheColorHint() {
445         mListView.setCacheColorHint(Color.RED);
446         assertEquals(Color.RED, mListView.getCacheColorHint());
447         assertEquals(Color.RED, mListView.getSolidColor());
448 
449         mListView.setCacheColorHint(Color.LTGRAY);
450         assertEquals(Color.LTGRAY, mListView.getCacheColorHint());
451         assertEquals(Color.LTGRAY, mListView.getSolidColor());
452 
453         mListView.setCacheColorHint(Color.GRAY);
454         assertEquals(Color.GRAY, mListView.getCacheColorHint());
455         assertEquals(Color.GRAY, mListView.getSolidColor());
456     }
457 
testAccessTranscriptMode()458     public void testAccessTranscriptMode() {
459         mListView.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
460         assertEquals(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL, mListView.getTranscriptMode());
461 
462         mListView.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_DISABLED);
463         assertEquals(AbsListView.TRANSCRIPT_MODE_DISABLED, mListView.getTranscriptMode());
464 
465         mListView.setTranscriptMode(AbsListView.TRANSCRIPT_MODE_NORMAL);
466         assertEquals(AbsListView.TRANSCRIPT_MODE_NORMAL, mListView.getTranscriptMode());
467     }
468 
testCheckLayoutParams()469     public void testCheckLayoutParams() {
470         MyListView listView = new MyListView(mActivity);
471 
472         AbsListView.LayoutParams param1 = new AbsListView.LayoutParams(10, 10);
473         assertTrue(listView.checkLayoutParams(param1));
474 
475         ViewGroup.LayoutParams param2 = new ViewGroup.LayoutParams(10, 10);
476         assertFalse(listView.checkLayoutParams(param2));
477     }
478 
testComputeVerticalScrollValues()479     public void testComputeVerticalScrollValues() {
480         MyListView listView = new MyListView(mActivity);
481         assertEquals(0, listView.computeVerticalScrollRange());
482         assertEquals(0, listView.computeVerticalScrollOffset());
483         assertEquals(0, listView.computeVerticalScrollExtent());
484 
485         listView.setAdapter(mAdapter_countries);
486         listView.setSmoothScrollbarEnabled(false);
487         assertEquals(mAdapter_countries.getCount(), listView.computeVerticalScrollRange());
488         assertEquals(0, listView.computeVerticalScrollOffset());
489         assertEquals(0, listView.computeVerticalScrollExtent());
490 
491         listView.setSmoothScrollbarEnabled(true);
492         assertEquals(0, listView.computeVerticalScrollOffset());
493         assertEquals(0, listView.computeVerticalScrollExtent());
494     }
495 
testGenerateLayoutParams()496     public void testGenerateLayoutParams() throws XmlPullParserException, IOException {
497         ViewGroup.LayoutParams res = mListView.generateLayoutParams(mAttributeSet);
498         assertNotNull(res);
499         assertTrue(res instanceof AbsListView.LayoutParams);
500 
501         MyListView listView = new MyListView(mActivity);
502         ViewGroup.LayoutParams p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
503                                                               ViewGroup.LayoutParams.WRAP_CONTENT);
504 
505         res = listView.generateLayoutParams(p);
506         assertNotNull(res);
507         assertTrue(res instanceof AbsListView.LayoutParams);
508         assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, res.width);
509         assertEquals(ViewGroup.LayoutParams.WRAP_CONTENT, res.height);
510     }
511 
testBeforeAndAfterTextChanged()512     public void testBeforeAndAfterTextChanged() {
513         // The java doc says these two methods do nothing
514         CharSequence str = "test";
515         SpannableStringBuilder sb = new SpannableStringBuilder();
516 
517         mListView.beforeTextChanged(str, 0, str.length(), str.length());
518         mListView.afterTextChanged(sb);
519 
520         // test callback
521         MyListView listView = new MyListView(mActivity);
522         TextView tv = new TextView(mActivity);
523 
524         assertFalse(listView.isBeforeTextChangedCalled());
525         assertFalse(listView.isOnTextChangedCalled());
526         assertFalse(listView.isAfterTextChangedCalled());
527 
528         tv.addTextChangedListener(listView);
529         assertFalse(listView.isBeforeTextChangedCalled());
530         assertFalse(listView.isOnTextChangedCalled());
531         assertFalse(listView.isAfterTextChangedCalled());
532 
533         tv.setText("abc");
534         assertTrue(listView.isBeforeTextChangedCalled());
535         assertTrue(listView.isOnTextChangedCalled());
536         assertTrue(listView.isAfterTextChangedCalled());
537     }
538 
testAddTouchables()539     public void testAddTouchables() throws Throwable {
540         ArrayList<View> views = new ArrayList<View>();
541         assertEquals(0, views.size());
542 
543         setAdapter();
544 
545         mListView.addTouchables(views);
546         assertEquals(mListView.getChildCount(), views.size());
547     }
548 
testInvalidateViews()549     public void testInvalidateViews() throws Throwable {
550         TextView tv1 = (TextView) mActivity.findViewById(R.id.headerview1);
551         TextView tv2 = (TextView) mActivity.findViewById(R.id.footerview1);
552 
553         setAdapter();
554 
555         mListView.setScrollIndicators(tv1, tv2);
556 
557         runTestOnUiThread(new Runnable() {
558             public void run() {
559                 mListView.invalidateViews();
560             }
561         });
562         mInstrumentation.waitForIdleSync();
563     }
564 
testGetContextMenuInfo()565     public void testGetContextMenuInfo() throws Throwable {
566         final MyListView listView = new MyListView(mActivity, mAttributeSet);
567 
568         runTestOnUiThread(new Runnable() {
569             public void run() {
570                 mActivity.setContentView(listView);
571                 listView.setAdapter(mAdapter_countries);
572                 listView.setSelection(2);
573             }
574         });
575         mInstrumentation.waitForIdleSync();
576 
577         final TextView v = (TextView) listView.getSelectedView();
578         assertNull(listView.getContextMenuInfo());
579 
580         final MockOnItemLongClickListener listener = new MockOnItemLongClickListener();
581         listView.setOnItemLongClickListener(listener);
582 
583         assertNull(listener.getParent());
584         assertNull(listener.getView());
585         assertEquals(0, listener.getPosition());
586         assertEquals(0, listener.getID());
587 
588         mInstrumentation.waitForIdleSync();
589         TouchUtils.longClickView(this, v);
590 
591         new PollingCheck() {
592             @Override
593             protected boolean check() {
594                 return v == listener.getView();
595             }
596         }.run();
597 
598         assertSame(listView, listener.getParent());
599         assertEquals(2, listener.getPosition());
600         assertEquals(listView.getItemIdAtPosition(2), listener.getID());
601 
602         ContextMenuInfo cmi = listView.getContextMenuInfo();
603         assertNotNull(cmi);
604     }
605 
testGetTopBottomFadingEdgeStrength()606     public void testGetTopBottomFadingEdgeStrength() {
607         MyListView listView = new MyListView(mActivity);
608 
609         assertEquals(0.0f, listView.getTopFadingEdgeStrength(), DELTA);
610         assertEquals(0.0f, listView.getBottomFadingEdgeStrength(), DELTA);
611     }
612 
testHandleDataChanged()613     public void testHandleDataChanged() {
614         MyListView listView = new MyListView(mActivity, mAttributeSet, 0);
615         listView.handleDataChanged();
616         // TODO: how to check?
617     }
618 
testSetFilterText()619     public void testSetFilterText() {
620         MyListView listView = new MyListView(mActivity, mAttributeSet, 0);
621         String filterText = "xyz";
622 
623         assertFalse(listView.isTextFilterEnabled());
624         assertFalse(listView.hasTextFilter());
625         assertFalse(listView.isInFilterMode());
626         assertTrue(mListView.checkInputConnectionProxy(null));
627 
628         listView.setTextFilterEnabled(false);
629         listView.setFilterText(filterText);
630         assertFalse(listView.isTextFilterEnabled());
631         assertFalse(listView.hasTextFilter());
632         assertFalse(listView.isInFilterMode());
633 
634         listView.setTextFilterEnabled(true);
635         listView.setFilterText(null);
636         assertTrue(listView.isTextFilterEnabled());
637         assertFalse(listView.hasTextFilter());
638         assertFalse(listView.isInFilterMode());
639 
640         listView.setTextFilterEnabled(true);
641         listView.setFilterText(filterText);
642         assertTrue(listView.isTextFilterEnabled());
643         assertTrue(listView.hasTextFilter());
644         assertTrue(listView.isInFilterMode());
645 
646         listView.clearTextFilter();
647         assertTrue(listView.isTextFilterEnabled());
648         assertFalse(listView.hasTextFilter());
649         assertFalse(listView.isInFilterMode());
650     }
651 
652     @MediumTest
testSetItemChecked_multipleModeSameValue()653     public void testSetItemChecked_multipleModeSameValue()
654             throws Throwable {
655         // Calling setItemChecked with the same value in multiple choice mode should not cause
656         // requestLayout
657         mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
658         runTestOnUiThread(new Runnable() {
659             @Override
660             public void run() {
661                 mListView.setItemChecked(0, false);
662             }
663         });
664         mInstrumentation.waitForIdleSync();
665         assertFalse(mListView.isLayoutRequested());
666         runTestOnUiThread(new Runnable() {
667             @Override
668             public void run() {
669                 mListView.setItemChecked(0, false);
670             }
671         });
672         assertFalse(mListView.isLayoutRequested());
673     }
674 
675     @MediumTest
testSetItemChecked_singleModeSameValue()676     public void testSetItemChecked_singleModeSameValue()
677             throws Throwable {
678         // Calling setItemChecked with the same value in single choice mode should not cause
679         // requestLayout
680         mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
681         runTestOnUiThread(new Runnable() {
682             @Override
683             public void run() {
684                 mListView.setItemChecked(0, false);
685             }
686         });
687         mInstrumentation.waitForIdleSync();
688         assertFalse(mListView.isLayoutRequested());
689         runTestOnUiThread(new Runnable() {
690             @Override
691             public void run() {
692                 mListView.setItemChecked(0, false);
693             }
694         });
695         assertFalse(mListView.isLayoutRequested());
696     }
697 
698     @MediumTest
testSetItemChecked_multipleModeDifferentValue()699     public void testSetItemChecked_multipleModeDifferentValue()
700             throws Throwable {
701         // Calling setItemChecked with a different value in multiple choice mode should cause
702         // requestLayout
703         mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
704         runTestOnUiThread(new Runnable() {
705             @Override
706             public void run() {
707                 mListView.setItemChecked(0, false);
708             }
709         });
710         mInstrumentation.waitForIdleSync();
711         assertFalse(mListView.isLayoutRequested());
712         runTestOnUiThread(new Runnable() {
713             @Override
714             public void run() {
715                 mListView.setItemChecked(0, true);
716             }
717         });
718         assertTrue(mListView.isLayoutRequested());
719     }
720 
721     @MediumTest
testSetItemChecked_singleModeDifferentValue()722     public void testSetItemChecked_singleModeDifferentValue()
723             throws Throwable {
724         // Calling setItemChecked with a different value in single choice mode should cause
725         // requestLayout
726         mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
727         runTestOnUiThread(new Runnable() {
728             @Override
729             public void run() {
730                 mListView.setItemChecked(0, false);
731             }
732         });
733         mInstrumentation.waitForIdleSync();
734         assertFalse(mListView.isLayoutRequested());
735         runTestOnUiThread(new Runnable() {
736             @Override
737             public void run() {
738                 mListView.setItemChecked(0, true);
739             }
740         });
741         assertTrue(mListView.isLayoutRequested());
742     }
743 
testLayoutChildren()744     public void testLayoutChildren() {
745         /**
746          * the subclass ListView and GridView override this method, so we can not test
747          * this method.
748          */
749     }
750 
testFoo()751     public void testFoo() {
752         /**
753          * Do not test these APIs. They are callbacks which:
754          *
755          * 1. The callback machanism has been tested in super class
756          * 2. The functionality is implmentation details, no need to test
757          */
758     }
759 
760     private static class MockOnScrollListener implements OnScrollListener {
761         private AbsListView mView;
762         private int mFirstVisibleItem;
763         private int mVisibleItemCount;
764         private int mTotalItemCount;
765         private int mScrollState;
766 
767         private boolean mIsOnScrollCalled;
768         private boolean mIsOnScrollStateChangedCalled;
769 
MockOnScrollListener()770         private MockOnScrollListener() {
771             mView = null;
772             mFirstVisibleItem = 0;
773             mVisibleItemCount = 0;
774             mTotalItemCount = 0;
775             mScrollState = -1;
776 
777             mIsOnScrollCalled = false;
778             mIsOnScrollStateChangedCalled = false;
779         }
780 
onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)781         public void onScroll(AbsListView view, int firstVisibleItem,
782                 int visibleItemCount, int totalItemCount) {
783             mView = view;
784             mFirstVisibleItem = firstVisibleItem;
785             mVisibleItemCount = visibleItemCount;
786             mTotalItemCount = totalItemCount;
787             mIsOnScrollCalled = true;
788         }
789 
onScrollStateChanged(AbsListView view, int scrollState)790         public void onScrollStateChanged(AbsListView view, int scrollState) {
791             mScrollState = scrollState;
792             mIsOnScrollStateChangedCalled = true;
793         }
794 
getView()795         public AbsListView getView() {
796             return mView;
797         }
798 
getFirstVisibleItem()799         public int getFirstVisibleItem() {
800             return mFirstVisibleItem;
801         }
802 
getVisibleItemCount()803         public int getVisibleItemCount() {
804             return mVisibleItemCount;
805         }
806 
getTotalItemCount()807         public int getTotalItemCount() {
808             return mTotalItemCount;
809         }
810 
getScrollState()811         public int getScrollState() {
812             return mScrollState;
813         }
814 
isOnScrollCalled()815         public boolean isOnScrollCalled() {
816             return mIsOnScrollCalled;
817         }
818 
isOnScrollStateChangedCalled()819         public boolean isOnScrollStateChangedCalled() {
820             return mIsOnScrollStateChangedCalled;
821         }
822 
reset()823         public void reset() {
824             mIsOnScrollCalled = false;
825             mIsOnScrollStateChangedCalled = false;
826         }
827     }
828 
829     private static class MockRecyclerListener implements RecyclerListener {
830         private View mView;
831 
MockRecyclerListener()832         private MockRecyclerListener() {
833             mView = null;
834         }
835 
onMovedToScrapHeap(View view)836         public void onMovedToScrapHeap(View view) {
837             mView = view;
838         }
839 
getView()840         public View getView() {
841             return mView;
842         }
843     }
844 
845     private static class MockOnItemLongClickListener implements OnItemLongClickListener {
846         private AdapterView<?> parent;
847         private View view;
848         private int position;
849         private long id;
850 
onItemLongClick(AdapterView<?> parent, View view, int position, long id)851         public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
852             this.parent = parent;
853             this.view = view;
854             this.position = position;
855             this.id = id;
856             return false;
857         }
858 
getParent()859         public AdapterView<?> getParent() {
860             return parent;
861         }
862 
getView()863         public View getView() {
864             return view;
865         }
866 
getPosition()867         public int getPosition() {
868             return position;
869         }
870 
getID()871         public long getID() {
872             return id;
873         }
874     }
875 
876     /**
877      * MyListView for test
878      */
879     private static class MyListView extends ListView {
MyListView(Context context)880         public MyListView(Context context) {
881             super(context);
882         }
883 
MyListView(Context context, AttributeSet attrs)884         public MyListView(Context context, AttributeSet attrs) {
885             super(context, attrs);
886         }
887 
MyListView(Context context, AttributeSet attrs, int defStyle)888         public MyListView(Context context, AttributeSet attrs, int defStyle) {
889             super(context, attrs, defStyle);
890         }
891 
892         @Override
checkLayoutParams(ViewGroup.LayoutParams p)893         protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
894             return super.checkLayoutParams(p);
895         }
896 
897         @Override
computeVerticalScrollExtent()898         protected int computeVerticalScrollExtent() {
899             return super.computeVerticalScrollExtent();
900         }
901 
902         @Override
computeVerticalScrollOffset()903         protected int computeVerticalScrollOffset() {
904             return super.computeVerticalScrollOffset();
905         }
906 
907         @Override
computeVerticalScrollRange()908         protected int computeVerticalScrollRange() {
909             return super.computeVerticalScrollRange();
910         }
911 
912         @Override
dispatchDraw(Canvas canvas)913         protected void dispatchDraw(Canvas canvas) {
914             super.dispatchDraw(canvas);
915         }
916 
917         @Override
dispatchSetPressed(boolean pressed)918         protected void dispatchSetPressed(boolean pressed) {
919             super.dispatchSetPressed(pressed);
920         }
921 
922         @Override
generateLayoutParams(ViewGroup.LayoutParams p)923         protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
924             return super.generateLayoutParams(p);
925         }
926 
927         @Override
getBottomFadingEdgeStrength()928         protected float getBottomFadingEdgeStrength() {
929             return super.getBottomFadingEdgeStrength();
930         }
931 
932         @Override
getContextMenuInfo()933         protected ContextMenuInfo getContextMenuInfo() {
934             return super.getContextMenuInfo();
935         }
936 
937         @Override
getTopFadingEdgeStrength()938         protected float getTopFadingEdgeStrength() {
939             return super.getTopFadingEdgeStrength();
940         }
941 
942         @Override
handleDataChanged()943         protected void handleDataChanged() {
944             super.handleDataChanged();
945         }
946 
947         @Override
isInFilterMode()948         protected boolean isInFilterMode() {
949             return super.isInFilterMode();
950         }
951 
952         private boolean mIsBeforeTextChangedCalled;
953         private boolean mIsOnTextChangedCalled;
954         private boolean mIsAfterTextChangedCalled;
955 
956         @Override
beforeTextChanged(CharSequence s, int start, int count, int after)957         public void beforeTextChanged(CharSequence s, int start, int count, int after) {
958             mIsBeforeTextChangedCalled = true;
959             super.beforeTextChanged(s, start, count, after);
960         }
961 
962         @Override
onTextChanged(CharSequence s, int start, int before, int count)963         public void onTextChanged(CharSequence s, int start, int before, int count) {
964             mIsOnTextChangedCalled = true;
965             super.onTextChanged(s, start, before, count);
966         }
967 
968         @Override
afterTextChanged(Editable s)969         public void afterTextChanged(Editable s) {
970             mIsAfterTextChangedCalled = true;
971             super.afterTextChanged(s);
972         }
973 
isBeforeTextChangedCalled()974         public boolean isBeforeTextChangedCalled() {
975             return mIsBeforeTextChangedCalled;
976         }
977 
isOnTextChangedCalled()978         public boolean isOnTextChangedCalled() {
979             return mIsOnTextChangedCalled;
980         }
981 
isAfterTextChangedCalled()982         public boolean isAfterTextChangedCalled() {
983             return mIsAfterTextChangedCalled;
984         }
985     }
986 }
987