/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.widget.cts;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.os.SystemClock;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.LargeTest;
import android.support.test.filters.Suppress;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.android.compatibility.common.util.CtsTouchUtils;
import com.android.compatibility.common.util.PollingCheck;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

@LargeTest
@RunWith(AndroidJUnit4.class)
public class AbsListView_ScrollTest {
    private static final String[] COUNTRY_LIST = new String[] {
            "Argentina", "Armenia", "Aruba", "Australia", "Belarus", "Belgium", "Belize", "Benin",
            "Botswana", "Brazil", "Cameroon", "China", "Colombia", "Costa Rica", "Cyprus",
            "Denmark", "Djibouti", "Ethiopia", "Fiji", "Finland", "France", "Gabon", "Germany",
            "Ghana", "Haiti", "Honduras", "Iceland", "India", "Indonesia", "Ireland", "Italy",
            "Japan", "Kiribati", "Laos", "Lesotho", "Liberia", "Malaysia", "Mongolia", "Myanmar",
            "Nauru", "Norway", "Oman", "Pakistan", "Philippines", "Portugal", "Romania", "Russia",
            "Rwanda", "Singapore", "Slovakia", "Slovenia", "Somalia", "Swaziland", "Togo", "Tuvalu",
            "Uganda", "Ukraine", "United States", "Vanuatu", "Venezuela", "Zimbabwe"
    };

    @Rule
    public ActivityTestRule<ListViewFixedCtsActivity> mActivityRule =
            new ActivityTestRule<>(ListViewFixedCtsActivity.class);

    private Instrumentation mInstrumentation;
    private AbsListView mListView;
    private Context mContext;
    private ArrayAdapter<String> mCountriesAdapter;
    private int mRowHeightPx;

    @Before
    public void setup() throws Throwable {
        mInstrumentation = InstrumentationRegistry.getInstrumentation();
        mContext = mInstrumentation.getTargetContext();

        final Activity activity = mActivityRule.getActivity();

        PollingCheck.waitFor(() -> activity.hasWindowFocus());

        mCountriesAdapter = new ArrayAdapter<>(mContext,
                R.layout.listitemfixed_layout, COUNTRY_LIST);

        mListView = (ListView) activity.findViewById(R.id.listview_default);
        mActivityRule.runOnUiThread(() -> mListView.setAdapter(mCountriesAdapter));
        mInstrumentation.waitForIdleSync();

        mRowHeightPx = activity.getResources().getDimensionPixelSize(R.dimen.listrow_height);
    }

    /**
     * Listener that allows waiting for the end of a scroll. When the tracked
     * {@link AbsListView} transitions to idle state, the passed {@link CountDownLatch}
     * is notified.
     */
    private class ScrollIdleListListener implements OnScrollListener {
        private CountDownLatch mLatchToNotify;

        public ScrollIdleListListener(CountDownLatch latchToNotify) {
            mLatchToNotify = latchToNotify;
        }

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) {
                mListView.setOnScrollListener(null);
                mLatchToNotify.countDown();
            }
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
                int totalItemCount) {
        }
    }

    /**
     * Listener that allows waiting until a specific position in the list becomes visible.
     * When the tracked position in the {@link AbsListView} becomes visible, the passed
     * {@link CountDownLatch} is notified.
     */
    private class ScrollPositionListListener implements AbsListView.OnScrollListener {
        private CountDownLatch mLatchToNotify;
        private int mTargetPosition;

        public ScrollPositionListListener(CountDownLatch latchToNotify, int targetPosition) {
            mLatchToNotify = latchToNotify;
            mTargetPosition = targetPosition;
        }

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
                int totalItemCount) {
            // Is our target in current visible range?
            int lastVisibleItem = firstVisibleItem + visibleItemCount - 1;
            boolean isInRange = (mTargetPosition >= firstVisibleItem) &&
                    (mTargetPosition <= lastVisibleItem);
            if (!isInRange) {
                return;
            }

            // Is our target also fully visible?
            int visibleIndexOfTarget = mTargetPosition - firstVisibleItem;
            View targetChild = mListView.getChildAt(visibleIndexOfTarget);
            boolean isTargetFullyVisible = (targetChild.getTop() >= 0) &&
                    (targetChild.getBottom() <= mListView.getHeight());
            if (isTargetFullyVisible) {
                mListView.setOnScrollListener(null);
                mLatchToNotify.countDown();
            }
        }
    }

    private boolean isItemVisible(int position) {
        return (position >= mListView.getFirstVisiblePosition()) &&
                (position <= mListView.getLastVisiblePosition());
    }

    private void verifyScrollToPosition(int positionToScrollTo) throws Throwable {
        final int firstVisiblePosition = mListView.getFirstVisiblePosition();
        final int lastVisiblePosition = mListView.getLastVisiblePosition();

        if ((positionToScrollTo >= firstVisiblePosition) &&
                (positionToScrollTo <= lastVisiblePosition)) {
            // If it's already on the screen, we won't have any real scrolling taking
            // place, so our tracking based on scroll state change will time out. This
            // is why we're returning here early.
            return;
        }

        // Register a scroll listener on our ListView. The listener will notify our latch
        // when the scroll state changes to IDLE. If that never happens, the latch will
        // time out and fail the test.
        final CountDownLatch latch = new CountDownLatch(1);
        mListView.setOnScrollListener(new ScrollIdleListListener(latch));
        mActivityRule.runOnUiThread(() -> mListView.smoothScrollToPosition(
                positionToScrollTo));

        assertTrue("Timed out while waiting for the scroll to complete",
                latch.await(2, TimeUnit.SECONDS));

        // Verify that the position we've been asked to scroll to is visible
        assertTrue("Asked to scroll to " + positionToScrollTo + ", first visible is "
                + mListView.getFirstVisiblePosition() + ", last visible is "
                + mListView.getLastVisiblePosition(), isItemVisible(positionToScrollTo));
    }

    @Test
    public void testSmoothScrollToPositionDownUpDown() throws Throwable {
        final int itemCount = COUNTRY_LIST.length;

        // Scroll closer to the end of the list
        verifyScrollToPosition(itemCount - 10);
        // Scroll back towards the beginning of the list
        verifyScrollToPosition(5);
        // And then towards the end of the list again
        verifyScrollToPosition(itemCount - 1);
        // And back up to the middle of the list
        verifyScrollToPosition(itemCount / 2);
    }

    @Test
    public void testSmoothScrollToPositionEveryRow() throws Throwable {
        final int itemCount = COUNTRY_LIST.length;

        for (int i = 0; i < itemCount; i++) {
            // Scroll one row down
            verifyScrollToPosition(i);
        }

        for (int i = itemCount - 1; i >= 0; i--) {
            // Scroll one row up
            verifyScrollToPosition(i);
        }
    }

    private void verifyScrollToPositionWithBound(int positionToScrollTo, int boundPosition,
            boolean expectTargetPositionToBeVisibleAtEnd) throws Throwable {
        final int firstVisiblePosition = mListView.getFirstVisiblePosition();
        final int lastVisiblePosition = mListView.getLastVisiblePosition();

        if ((positionToScrollTo >= firstVisiblePosition) &&
                (positionToScrollTo <= lastVisiblePosition)) {
            // If it's already on the screen, we won't have any real scrolling taking
            // place, so our tracking based on scroll state change will time out. This
            // is why we're returning here early.
            return;
        }

        // Register a scroll listener on our ListView. The listener will notify our latch
        // when the scroll state changes to IDLE. If that never happens, the latch will
        // time out and fail the test.
        final CountDownLatch latch = new CountDownLatch(1);
        mListView.setOnScrollListener(new ScrollIdleListListener(latch));
        mActivityRule.runOnUiThread(() -> mListView.smoothScrollToPosition(
                positionToScrollTo, boundPosition));

        assertTrue("Timed out while waiting for the scroll to complete",
                latch.await(2, TimeUnit.SECONDS));

        // Verify that the bound position is visible
        assertTrue("Asked to scroll to " + positionToScrollTo + " with bound " + boundPosition
                + ", first visible is " + mListView.getFirstVisiblePosition()
                + ", last visible is " + mListView.getLastVisiblePosition(),
                isItemVisible(boundPosition));

        assertEquals("Asked to scroll to " + positionToScrollTo + " with bound " + boundPosition
                + ", first visible is " + mListView.getFirstVisiblePosition()
                + ", last visible is " + mListView.getLastVisiblePosition(),
                expectTargetPositionToBeVisibleAtEnd, isItemVisible(positionToScrollTo));
    }

    @Test
    public void testSmoothScrollToPositionWithBound() throws Throwable {
        // Our list is 300dp high and each row is 40dp high. Without being too precise,
        // the logic in this method relies on at least 8 and at most 10 items on the screen
        // at any time.

        // Scroll to 20 with bound at 6. This should result in the scroll stopping before it
        // gets to 20 so that 6 is still visible
        verifyScrollToPositionWithBound(20, 6, false);

        // Scroll to 40 with bound at 35. This should result in the scroll getting to 40 becoming
        // visible with 35 visible as well
        verifyScrollToPositionWithBound(40, 35, true);

        // Scroll to 10 with bound at 25. This should result in the scroll stopping before it
        // gets to 10 so that 25 is still visible
        verifyScrollToPositionWithBound(10, 25, false);

        // Scroll to 5 with bound at 8. This should result in the scroll getting to 5 becoming
        // visible with 8 visible as well
        verifyScrollToPositionWithBound(5, 8, true);
    }

    private void verifyScrollToPositionFromTop(int positionToScrollTo, int offset,
            int durationMs) throws Throwable {
        final int startTopPositionInListCoordinates =
                mListView.getFirstVisiblePosition() * mRowHeightPx -
                        mListView.getChildAt(0).getTop();
        int targetTopPositionInListCoordinates = positionToScrollTo * mRowHeightPx - offset;
        // Need to clamp it to account for requests that would scroll the content outside
        // of the available bounds
        targetTopPositionInListCoordinates = Math.max(0, targetTopPositionInListCoordinates);
        targetTopPositionInListCoordinates = Math.min(
                COUNTRY_LIST.length * mRowHeightPx - mListView.getHeight(),
                targetTopPositionInListCoordinates);

        if (targetTopPositionInListCoordinates == startTopPositionInListCoordinates) {
            // If it's already at the target state, we won't have any real scrolling taking
            // place, so our tracking based on scroll state change will time out. This
            // is why we're returning here early.
            return;
        }

        // Register a scroll listener on our ListView. The listener will notify our latch
        // when the scroll state changes to IDLE. If that never happens, the latch will
        // time out and fail the test.
        final CountDownLatch latch = new CountDownLatch(1);
        mListView.setOnScrollListener(new ScrollIdleListListener(latch));
        if (durationMs > 0) {
            mActivityRule.runOnUiThread(() -> mListView.smoothScrollToPositionFromTop(
                    positionToScrollTo, offset, durationMs));
        } else {
            mActivityRule.runOnUiThread(() -> mListView.smoothScrollToPositionFromTop(
                    positionToScrollTo, offset));
        }

        // Since position-based scroll is emulated as a series of mini-flings, scrolling
        // might take considerable time.
        int timeoutMs = durationMs > 0 ? 5000 + durationMs : 5000;
        assertTrue("Timed out while waiting for the scroll to complete",
                latch.await(timeoutMs, TimeUnit.MILLISECONDS));

        final int endTopPositionInListCoordinates =
                mListView.getFirstVisiblePosition() * mRowHeightPx -
                        mListView.getChildAt(0).getTop();

        assertEquals(targetTopPositionInListCoordinates, endTopPositionInListCoordinates);
    }

    @Test
    public void testSmoothScrollToPositionFromTop() throws Throwable {
        // Ask to scroll so that the top of position 5 is 10 pixels below the top edge of the list
        verifyScrollToPositionFromTop(5, 10, -1);

        // Ask to scroll so that the top of position 10 is right at the top edge of the list
        verifyScrollToPositionFromTop(10, 0, -1);

        // Ask to scroll so that the top of position 5 is 80 dps below the top edge of the list
        // (which means that since row height is 40 dps high, the top item should be 3
        verifyScrollToPositionFromTop(5, 2 * mRowHeightPx, -1);

        // Ask to scroll so that the top of position 20 is 20 pixels above the top edge of the list
        verifyScrollToPositionFromTop(20, 20, -1);

        // Ask to scroll so that the top of position 20 is right at the top edge of the list
        verifyScrollToPositionFromTop(20, 0, -1);

        // Ask to scroll so that the top of position 20 is 20 pixels below the top edge of the list
        verifyScrollToPositionFromTop(20, 20, -1);

        // Ask to scroll beyond the top of the content
        verifyScrollToPositionFromTop(0, -20, -1);
        verifyScrollToPositionFromTop(0, -60, -1);

        // Ask to scroll beyond the bottom of the content
        final int itemCount = COUNTRY_LIST.length;
        verifyScrollToPositionFromTop(itemCount - 1, 0, -1);
        verifyScrollToPositionFromTop(itemCount - 1, mListView.getHeight(), -1);
    }

    @Test
    public void testSmoothScrollToPositionFromTopWithTime() throws Throwable {
        // Ask to scroll so that the top of position 5 is 20 pixels below the top edge of the list
        verifyScrollToPositionFromTop(5, 10, 200);

        // Ask to scroll so that the top of position 10 is right at the top edge of the list
        verifyScrollToPositionFromTop(10, 0, 1000);

        // Ask to scroll so that the top of position 5 is 80 dps below the top edge of the list
        // (which means that since row height is 40 dps high, the top item should be 3
        verifyScrollToPositionFromTop(5, 2 * mRowHeightPx, 500);

        // Ask to scroll so that the top of position 20 is 20 pixels above the top edge of the list
        verifyScrollToPositionFromTop(20, 20, 100);

        // Ask to scroll so that the top of position 20 is right at the top edge of the list
        verifyScrollToPositionFromTop(20, 0, 700);

        // Ask to scroll so that the top of position 20 is 20 pixels below the top edge of the list
        verifyScrollToPositionFromTop(20, 20, 600);

        // Ask to scroll beyond the top of the content
        verifyScrollToPositionFromTop(0, -20, 2000);
        verifyScrollToPositionFromTop(0, -60, 300);

        // Ask to scroll beyond the bottom of the content
        final int itemCount = COUNTRY_LIST.length;
        verifyScrollToPositionFromTop(itemCount - 1, 0, 600);
        verifyScrollToPositionFromTop(itemCount - 1, mListView.getHeight(), 200);
    }

    @Test
    public void testCanScrollList() throws Throwable {
        final int itemCount = COUNTRY_LIST.length;

        assertEquals(0, mListView.getFirstVisiblePosition());

        // Verify that when we're at the top of the list, we can't scroll up but we can scroll
        // down.
        assertFalse(mListView.canScrollList(-1));
        assertTrue(mListView.canScrollList(1));

        // Scroll down to the very end of the list
        verifyScrollToPosition(itemCount - 1);
        assertEquals(itemCount - 1, mListView.getLastVisiblePosition());

        // Verify that when we're at the bottom of the list, we can't scroll down but we can scroll
        // up.
        assertFalse(mListView.canScrollList(1));
        assertTrue(mListView.canScrollList(-1));

        // Scroll up to the middle of the list
        final int itemInTheMiddle = itemCount / 2;
        verifyScrollToPosition(itemInTheMiddle);

        // Verify that when we're in the middle of the list, we can scroll both up and down.
        assertTrue(mListView.canScrollList(-1));
        assertTrue(mListView.canScrollList(1));
    }

    private void verifyScrollBy(int y) throws Throwable {
        // Here we rely on knowing the fixed pixel height of each row
        final int startTopPositionInListCoordinates =
                mListView.getFirstVisiblePosition() * mRowHeightPx -
                        mListView.getChildAt(0).getTop();

        // Since scrollListBy is a synchronous operation, we do not need to wait
        // until we can proceed to test the result
        mActivityRule.runOnUiThread(() -> mListView.scrollListBy(y));

        final int endTopPositionInListCoordinates =
                mListView.getFirstVisiblePosition() * mRowHeightPx -
                        mListView.getChildAt(0).getTop();

        // As specified in the Javadocs of AbsListView.scrollListBy, the actual scroll amount
        // will be capped by the list height minus one pixel
        final int listHeight = mListView.getHeight();
        final int expectedScrollAmount = (y > 0) ? Math.min(y, listHeight - 1)
                : Math.max(y, -(listHeight - 1));
        int expectedTopPositionInListCoordinates =
                startTopPositionInListCoordinates + expectedScrollAmount;
        // Need to clamp it to account for requests that would scroll the content outside
        // of the available bounds
        expectedTopPositionInListCoordinates = Math.max(0, expectedTopPositionInListCoordinates);
        expectedTopPositionInListCoordinates = Math.min(
                COUNTRY_LIST.length * mRowHeightPx - mListView.getHeight(),
                expectedTopPositionInListCoordinates);

        assertEquals(expectedTopPositionInListCoordinates, endTopPositionInListCoordinates);
    }

    @Test
    public void testScrollListBy() throws Throwable {
        final int listHeight = mListView.getHeight();
        final int itemCount = COUNTRY_LIST.length;

        // Scroll down by half row height
        verifyScrollBy(mRowHeightPx / 2);

        // Scroll up by full row height - verifying that we're going to stop at the top of the first
        // row
        verifyScrollBy(-mRowHeightPx);

        // Scroll down by slightly more than a screenful of rows - we expect it to be capped
        // by the list height minus one pixel.
        verifyScrollBy(listHeight + mRowHeightPx);

        // Scroll down by another half row
        verifyScrollBy(mRowHeightPx / 2);

        // Scroll up by full row height
        verifyScrollBy(-mRowHeightPx);

        // Now scroll all the way down (using position-based scrolling)
        verifyScrollToPosition(itemCount - 1);
        assertEquals(itemCount - 1, mListView.getLastVisiblePosition());

        // Scroll up by half row height
        verifyScrollBy(-mRowHeightPx / 2);

        // Scroll down by full row height - verifying that we're going to stop at the bottom of the
        // last row
        verifyScrollBy(mRowHeightPx);

        // Scroll up halfway into the list - we expect it to be capped by the list height minus
        // one pixel.
        verifyScrollBy(-itemCount * mRowHeightPx / 2);
    }

    @Test
    public void testListScrollAndTap() throws Throwable {
        // Start a programmatic scroll to position 30. We register a scroll listener on the list
        // to notify us when position 15 becomes visible.
        final CountDownLatch scrollLatch = new CountDownLatch(1);
        mListView.setOnScrollListener(new ScrollPositionListListener(scrollLatch, 15));
        mActivityRule.runOnUiThread(() -> mListView.smoothScrollToPosition(30));

        // Since position-based scroll is emulated as a series of mini-flings, scrolling
        // might take considerable time.
        assertTrue("Timed out while waiting for the scroll to complete",
                scrollLatch.await(5, TimeUnit.SECONDS));

        // Verify that we're here in the middle of the programmatic scroll
        assertTrue(mListView.getLastVisiblePosition() < 30);

        // Emulate tap in the middle of the list - this should stop our programmatic scroll.
        // Note that due to asynchronous nature of the moving pieces, we might still get one
        // more scroll frame as the injected motion events that constitute an emulated tap
        // are being processed by our list view.
        CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mListView);

        // Sleep for a second
        SystemClock.sleep(1000);

        // and verify that we're still haven't scrolled down to position 30
        assertTrue(mListView.getLastVisiblePosition() < 30);
    }

    private void verifyListScrollAndEmulateFlingGesture(boolean isDownwardsFlingGesture)
            throws Throwable {
        // Start a programmatic scroll to position 30. We register a scroll listener on the list
        // to notify us when position 15 becomes visible.
        final CountDownLatch scrollLatch = new CountDownLatch(1);
        mListView.setOnScrollListener(new ScrollPositionListListener(scrollLatch, 15));
        mActivityRule.runOnUiThread(() -> mListView.smoothScrollToPosition(30));

        // Since position-based scroll is emulated as a series of mini-flings, scrolling
        // might take considerable time.
        assertTrue("Timed out while waiting for the scroll to complete",
                scrollLatch.await(5, TimeUnit.SECONDS));

        // Verify that we're here in the middle of the programmatic scroll
        assertTrue(mListView.getLastVisiblePosition() < 30);

        final int firstVisiblePositionBeforeFling = mListView.getFirstVisiblePosition();

        // At this point the programmatic scroll is still going. Now emulate a fling
        // gesture and verify that we're going to get to the IDLE state
        final CountDownLatch flingLatch = new CountDownLatch(1);
        mListView.setOnScrollListener(new ScrollIdleListListener(flingLatch));
        CtsTouchUtils.emulateFlingGesture(mInstrumentation, mListView, isDownwardsFlingGesture);

        assertTrue("Timed out while waiting for the fling to complete",
                flingLatch.await(5, TimeUnit.SECONDS));

        // Note that the actual position in the list at the end of the fling depends on
        // the processing of the injected sequence of motion events that might differ at milli/micro
        // second level from run to run
        if (isDownwardsFlingGesture) {
            // Verify that the fling gesture has been processed, getting us closer to the
            // beginning of the list.
            assertTrue(mListView.getFirstVisiblePosition() < firstVisiblePositionBeforeFling);
        } else {
            // Verify that the fling gesture has been processed, getting us closer to the
            // end of the list.
            assertTrue(mListView.getFirstVisiblePosition() > firstVisiblePositionBeforeFling);
        }
    }

    @Test
    public void testListScrollAndEmulateDownwardsFlingGesture() throws Throwable {
        verifyListScrollAndEmulateFlingGesture(true);
    }

    @Test
    public void testListScrollAndEmulateUpwardsFlingGesture() throws Throwable {
        verifyListScrollAndEmulateFlingGesture(false);
    }

    @Test
    public void testListFlingWithZeroVelocity() throws Throwable {
        mListView.setVelocityScale(0.0f);

        final CountDownLatch flingLatch = new CountDownLatch(1);
        mListView.setOnScrollListener(new ScrollIdleListListener(flingLatch));
        final int flingAmount =
                CtsTouchUtils.emulateFlingGesture(mInstrumentation, mListView, false);

        assertTrue("Timed out while waiting for the fling to complete",
                flingLatch.await(5, TimeUnit.SECONDS));

        // Since our velocity scale is 0, we expect that the emulated fling gesture didn't
        // result in any fling, but just a simple scroll that stopped at the ACTION_UP
        // event.
        final int expectedTopOffsetAtFlingEnd = -flingAmount;
        final int expectedBottomOffsetAtFlingEnd = mListView.getHeight() - flingAmount;
        final int expectedTopPositionAtFlingEnd = expectedTopOffsetAtFlingEnd / mRowHeightPx;
        final int expectedBottomPositionAtFlingEnd = expectedBottomOffsetAtFlingEnd / mRowHeightPx;

        assertEquals(expectedTopPositionAtFlingEnd, mListView.getFirstVisiblePosition());
        assertEquals(expectedBottomPositionAtFlingEnd, mListView.getLastVisiblePosition());
    }

    private static class LargeContentAdapter extends BaseAdapter {
        private final Context mContext;
        private final int mCount;
        private final LayoutInflater mLayoutInflater;

        public LargeContentAdapter(Context context, int count) {
            mContext = context;
            mCount = count;
            mLayoutInflater = LayoutInflater.from(mContext);
        }

        @Override
        public int getCount() {
            return mCount;
        }

        @Override
        public boolean hasStableIds() {
            return true;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            final TextView textView = (convertView != null) ? (TextView) convertView
                    : (TextView) mLayoutInflater.inflate(R.layout.listitemfixed_layout,
                            parent, false);
            textView.setText("Item " + position);
            return textView;
        }
    }

    @Suppress
    @Test
    // Disabled due to flakiness. CtsTouchUtils cannot guarantee the amount of scroll since it is
    // using sleeps and it is unreliable on cloud devices.
    public void testFriction() throws Throwable {
        // Set an adapter with 100K items so that no matter how fast our fling is, we won't
        // get to the bottom of the list in one fling
        mActivityRule.runOnUiThread(
                () -> mListView.setAdapter(new LargeContentAdapter(mContext, 100000)));
        mInstrumentation.waitForIdleSync();

        final CountDownLatch initialFlingLatch = new CountDownLatch(1);
        mListView.setOnScrollListener(new ScrollIdleListListener(initialFlingLatch));
        CtsTouchUtils.emulateFlingGesture(mInstrumentation, mListView, false);
        assertTrue("Timed out while waiting for the fling to complete",
                initialFlingLatch.await(5, TimeUnit.SECONDS));

        final int lastVisiblePositionAfterDefaultFling = mListView.getLastVisiblePosition();

        // Scroll back to the top of the list
        verifyScrollToPosition(0);
        // configure the fling to have less friction
        mListView.setFriction(ViewConfiguration.getScrollFriction() / 4.0f);
        // and do the fling again
        final CountDownLatch fastFlingLatch = new CountDownLatch(1);
        mListView.setOnScrollListener(new ScrollIdleListListener(fastFlingLatch));
        CtsTouchUtils.emulateFlingGesture(mInstrumentation, mListView, false);
        assertTrue("Timed out while waiting for the fling to complete",
                fastFlingLatch.await(5, TimeUnit.SECONDS));

        final int lastVisiblePositionAfterFastFling = mListView.getLastVisiblePosition();

        // We expect a fast fling (with lower scroll friction) to end up scrolling more
        // of our content
        assertTrue("Default fling ended at " + lastVisiblePositionAfterDefaultFling
                        + ", while fast fling ended at " + lastVisiblePositionAfterFastFling,
                lastVisiblePositionAfterFastFling > lastVisiblePositionAfterDefaultFling);

        // Scroll back to the top of the list
        verifyScrollToPosition(0);
        // configure the fling to have more friction
        mListView.setFriction(ViewConfiguration.getScrollFriction() * 4.0f);
        // and do the fling again
        final CountDownLatch slowFlingLatch = new CountDownLatch(1);
        mListView.setOnScrollListener(new ScrollIdleListListener(slowFlingLatch));
        CtsTouchUtils.emulateFlingGesture(mInstrumentation, mListView, false);
        assertTrue("Timed out while waiting for the fling to complete",
                slowFlingLatch.await(5, TimeUnit.SECONDS));

        final int lastVisiblePositionAfterSlowFling = mListView.getLastVisiblePosition();

        // We expect a slow fling (with higher scroll friction) to end up scrolling less
        // of our content
        assertTrue("Default fling ended at " + lastVisiblePositionAfterDefaultFling
                        + ", while slow fling ended at " + lastVisiblePositionAfterSlowFling,
                lastVisiblePositionAfterSlowFling < lastVisiblePositionAfterDefaultFling);
    }
}
