/*
 * 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.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 androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.filters.Suppress;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;

import com.android.compatibility.common.util.CtsTouchUtils;
import com.android.compatibility.common.util.CtsTouchUtils.EventInjectionListener;
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;

    private static class ListScrollPosition {
        public int mFirstVisiblePosition;
        public int mFirstViewVerticalOffset;
    }

    @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);
    }

    private ListScrollPosition getCurrentScrollPosition() {
        ListScrollPosition result = new ListScrollPosition();
        result.mFirstVisiblePosition = mListView.getFirstVisiblePosition();
        result.mFirstViewVerticalOffset = mListView.getChildAt(0).getTop();
        return result;
    }

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

        final CountDownLatch flingLatch = new CountDownLatch(2);
        mListView.setOnScrollListener(new ScrollIdleListListener(flingLatch));

        final ListScrollPosition[] scrollPositionAfterUpEvent =
                new ListScrollPosition[1];
        final EventInjectionListener eventInjectionListener =
                new EventInjectionListener() {
                    @Override
                    public void onDownInjected(int xOnScreen, int yOnScreen) {
                    }

                    @Override
                    public void onMoveInjected(int[] xOnScreen, int[] yOnScreen) {
                    }

                    @Override
                    public void onUpInjected(int xOnScreen, int yOnScreen) {
                        scrollPositionAfterUpEvent[0] = getCurrentScrollPosition();
                        flingLatch.countDown();
                    }
                };
        CtsTouchUtils.emulateFlingGesture(mInstrumentation, mListView, false,
                eventInjectionListener);

        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 ListScrollPosition scrollPositionAtRest = getCurrentScrollPosition();

        assertEquals("First visible position", scrollPositionAtRest.mFirstVisiblePosition,
                scrollPositionAfterUpEvent[0].mFirstVisiblePosition);
        assertEquals("First view offset", scrollPositionAtRest.mFirstViewVerticalOffset,
                scrollPositionAfterUpEvent[0].mFirstViewVerticalOffset);
    }

    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);
    }
}
