Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7c1c0f8b authored by Dave Mankoff's avatar Dave Mankoff Committed by Android (Google) Code Review
Browse files

Merge "Add test for DoubleTapHelper."

parents 77b77c35 660d4689
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ public class DoubleTapHelper {
                                    event.getY() - mActivationY);
                        }
                        if (withinDoubleTapSlop) {
                            makeInactive();
                            if (!mDoubleTapListener.onDoubleTap()) {
                                return false;
                            }
@@ -134,6 +135,7 @@ public class DoubleTapHelper {
        if (mActivated) {
            mActivated = false;
            mActivationListener.onActiveChanged(false);
            mView.removeCallbacks(mTapTimeoutRunnable);
        }
    }

+369 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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 com.android.systemui.statusbar.phone;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.res.Resources;
import android.os.SystemClock;
import android.testing.AndroidTestingRunner;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

import androidx.test.filters.SmallTest;

import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

@SmallTest
@RunWith(AndroidTestingRunner.class)
public class DoubleTapHelperTest extends SysuiTestCase {

    private DoubleTapHelper mDoubleTapHelper;
    private int mTouchSlop;
    private int mDoubleTouchSlop;
    @Mock private View mView;
    @Mock private DoubleTapHelper.ActivationListener mActivationListener;
    @Mock private DoubleTapHelper.DoubleTapListener mDoubleTapListener;
    @Mock private DoubleTapHelper.SlideBackListener mSlideBackListener;
    @Mock private DoubleTapHelper.DoubleTapLogListener mDoubleTapLogListener;
    @Mock private Resources mResources;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
        // The double tap slop has to be less than the regular slop, otherwise it has no effect.
        mDoubleTouchSlop = mTouchSlop - 1;
        when(mView.getContext()).thenReturn(mContext);
        when(mView.getResources()).thenReturn(mResources);
        when(mResources.getDimension(R.dimen.double_tap_slop))
                .thenReturn((float) mDoubleTouchSlop);

        mDoubleTapHelper = new DoubleTapHelper(mView,
                                               mActivationListener,
                                               mDoubleTapListener,
                                               mSlideBackListener, mDoubleTapLogListener);
    }

    @Test
    public void testDoubleTap_success() {
        long downtimeA = SystemClock.uptimeMillis();
        long downtimeB = downtimeA + 100;

        MotionEvent evDownA = MotionEvent.obtain(downtimeA,
                                                 downtimeA,
                                                 MotionEvent.ACTION_DOWN,
                                                 1,
                                                 1,
                                                 0);
        MotionEvent evUpA = MotionEvent.obtain(downtimeA,
                                               downtimeA + 1,
                                               MotionEvent.ACTION_UP,
                                               1,
                                               1,
                                               0);
        MotionEvent evDownB = MotionEvent.obtain(downtimeB,
                                                 downtimeB,
                                                 MotionEvent.ACTION_DOWN,
                                                 1,
                                                 1,
                                                 0);
        MotionEvent evUpB = MotionEvent.obtain(downtimeB,
                                               downtimeB + 1,
                                               MotionEvent.ACTION_UP,
                                               1,
                                               1,
                                               0);

        mDoubleTapHelper.onTouchEvent(evDownA);
        mDoubleTapHelper.onTouchEvent(evUpA);
        verify(mActivationListener).onActiveChanged(true);
        verify(mView).postDelayed(any(Runnable.class), anyLong());
        verify(mDoubleTapLogListener, never()).onDoubleTapLog(anyBoolean(), anyFloat(), anyFloat());
        verify(mDoubleTapListener, never()).onDoubleTap();

        mDoubleTapHelper.onTouchEvent(evDownB);
        mDoubleTapHelper.onTouchEvent(evUpB);
        verify(mDoubleTapLogListener).onDoubleTapLog(true, 0, 0);
        verify(mDoubleTapListener).onDoubleTap();

        evDownA.recycle();
        evUpA.recycle();
        evDownB.recycle();
        evUpB.recycle();
    }

    @Test
    public void testSingleTap_timeout() {
        long downtimeA = SystemClock.uptimeMillis();

        MotionEvent evDownA = MotionEvent.obtain(downtimeA,
                                                 downtimeA,
                                                 MotionEvent.ACTION_DOWN,
                                                 1,
                                                 1,
                                                 0);
        MotionEvent evUpA = MotionEvent.obtain(downtimeA,
                                               downtimeA + 1,
                                               MotionEvent.ACTION_UP,
                                               1,
                                               1,
                                               0);

        ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
        mDoubleTapHelper.onTouchEvent(evDownA);
        mDoubleTapHelper.onTouchEvent(evUpA);
        verify(mActivationListener).onActiveChanged(true);
        verify(mView).postDelayed(runnableCaptor.capture(), anyLong());
        runnableCaptor.getValue().run();
        verify(mActivationListener).onActiveChanged(true);

        evDownA.recycle();
        evUpA.recycle();
    }

    @Test
    public void testSingleTap_slop() {
        long downtimeA = SystemClock.uptimeMillis();

        MotionEvent evDownA = MotionEvent.obtain(downtimeA,
                                                 downtimeA,
                                                 MotionEvent.ACTION_DOWN,
                                                 1,
                                                 1,
                                                 0);
        MotionEvent evUpA = MotionEvent.obtain(downtimeA,
                                               downtimeA + 1,
                                               MotionEvent.ACTION_UP,
                                               1 + mTouchSlop,
                                               1,
                                               0);

        ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
        mDoubleTapHelper.onTouchEvent(evDownA);
        mDoubleTapHelper.onTouchEvent(evUpA);
        verify(mActivationListener, never()).onActiveChanged(true);
        verify(mDoubleTapListener, never()).onDoubleTap();

        evDownA.recycle();
        evUpA.recycle();
    }

    @Test
    public void testDoubleTap_slop() {
        long downtimeA = SystemClock.uptimeMillis();
        long downtimeB = downtimeA + 100;

        MotionEvent evDownA = MotionEvent.obtain(downtimeA,
                                                 downtimeA,
                                                 MotionEvent.ACTION_DOWN,
                                                 1,
                                                 1,
                                                 0);
        MotionEvent evUpA = MotionEvent.obtain(downtimeA,
                                               downtimeA + 1,
                                               MotionEvent.ACTION_UP,
                                               1,
                                               1,
                                               0);
        MotionEvent evDownB = MotionEvent.obtain(downtimeB,
                                                 downtimeB,
                                                 MotionEvent.ACTION_DOWN,
                                                 1,
                                                 1,
                                                 0);
        MotionEvent evUpB = MotionEvent.obtain(downtimeB,
                                               downtimeB + 1,
                                               MotionEvent.ACTION_UP,
                                               1,
                                               1 + mDoubleTouchSlop,
                                               0);

        mDoubleTapHelper.onTouchEvent(evDownA);
        mDoubleTapHelper.onTouchEvent(evUpA);
        verify(mActivationListener).onActiveChanged(true);
        verify(mView).postDelayed(any(Runnable.class), anyLong());

        mDoubleTapHelper.onTouchEvent(evDownB);
        mDoubleTapHelper.onTouchEvent(evUpB);
        verify(mDoubleTapLogListener).onDoubleTapLog(false, 0, mDoubleTouchSlop);
        verify(mActivationListener).onActiveChanged(false);
        verify(mDoubleTapListener, never()).onDoubleTap();

        evDownA.recycle();
        evUpA.recycle();
        evDownB.recycle();
        evUpB.recycle();
    }

    @Test
    public void testSlideBack() {
        long downtimeA = SystemClock.uptimeMillis();
        long downtimeB = downtimeA + 100;

        MotionEvent evDownA = MotionEvent.obtain(downtimeA,
                                                 downtimeA,
                                                 MotionEvent.ACTION_DOWN,
                                                 1,
                                                 1,
                                                 0);
        MotionEvent evUpA = MotionEvent.obtain(downtimeA,
                                               downtimeA + 1,
                                               MotionEvent.ACTION_UP,
                                               1,
                                               1,
                                               0);
        MotionEvent evDownB = MotionEvent.obtain(downtimeB,
                                                 downtimeB,
                                                 MotionEvent.ACTION_DOWN,
                                                 1,
                                                 1,
                                                 0);
        MotionEvent evUpB = MotionEvent.obtain(downtimeB,
                                               downtimeB + 1,
                                               MotionEvent.ACTION_UP,
                                               1,
                                               1,
                                               0);

        when(mSlideBackListener.onSlideBack()).thenReturn(true);

        mDoubleTapHelper.onTouchEvent(evDownA);
        mDoubleTapHelper.onTouchEvent(evUpA);
        verify(mActivationListener, never()).onActiveChanged(true);
        verify(mActivationListener, never()).onActiveChanged(false);
        verify(mDoubleTapListener, never()).onDoubleTap();
        mDoubleTapHelper.onTouchEvent(evDownB);
        mDoubleTapHelper.onTouchEvent(evUpB);
        verify(mActivationListener, never()).onActiveChanged(true);
        verify(mActivationListener, never()).onActiveChanged(false);
        verify(mDoubleTapListener, never()).onDoubleTap();

        evDownA.recycle();
        evUpA.recycle();
        evDownB.recycle();
        evUpB.recycle();
    }


    @Test
    public void testMoreThanTwoTaps() {
        long downtimeA = SystemClock.uptimeMillis();
        long downtimeB = downtimeA + 100;
        long downtimeC = downtimeB + 100;
        long downtimeD = downtimeC + 100;

        MotionEvent evDownA = MotionEvent.obtain(downtimeA,
                                                 downtimeA,
                                                 MotionEvent.ACTION_DOWN,
                                                 1,
                                                 1,
                                                 0);
        MotionEvent evUpA = MotionEvent.obtain(downtimeA,
                                               downtimeA + 1,
                                               MotionEvent.ACTION_UP,
                                               1,
                                               1,
                                               0);
        MotionEvent evDownB = MotionEvent.obtain(downtimeB,
                                                 downtimeB,
                                                 MotionEvent.ACTION_DOWN,
                                                 1,
                                                 1,
                                                 0);
        MotionEvent evUpB = MotionEvent.obtain(downtimeB,
                                               downtimeB + 1,
                                               MotionEvent.ACTION_UP,
                                               1,
                                               1,
                                               0);
        MotionEvent evDownC = MotionEvent.obtain(downtimeC,
                                                 downtimeC,
                                                 MotionEvent.ACTION_DOWN,
                                                 1,
                                                 1,
                                                 0);
        MotionEvent evUpC = MotionEvent.obtain(downtimeC,
                                               downtimeC + 1,
                                               MotionEvent.ACTION_UP,
                                               1,
                                               1,
                                               0);
        MotionEvent evDownD = MotionEvent.obtain(downtimeD,
                                                 downtimeD,
                                                 MotionEvent.ACTION_DOWN,
                                                 1,
                                                 1,
                                                 0);
        MotionEvent evUpD = MotionEvent.obtain(downtimeD,
                                               downtimeD + 1,
                                               MotionEvent.ACTION_UP,
                                               1,
                                               1,
                                               0);

        mDoubleTapHelper.onTouchEvent(evDownA);
        mDoubleTapHelper.onTouchEvent(evUpA);
        verify(mActivationListener).onActiveChanged(true);
        verify(mView).postDelayed(any(Runnable.class), anyLong());
        verify(mDoubleTapLogListener, never()).onDoubleTapLog(anyBoolean(), anyFloat(), anyFloat());
        verify(mDoubleTapListener, never()).onDoubleTap();

        mDoubleTapHelper.onTouchEvent(evDownB);
        mDoubleTapHelper.onTouchEvent(evUpB);
        verify(mDoubleTapLogListener).onDoubleTapLog(true, 0, 0);
        verify(mDoubleTapListener).onDoubleTap();

        reset(mView);
        reset(mActivationListener);
        reset(mDoubleTapLogListener);
        reset(mDoubleTapListener);

        mDoubleTapHelper.onTouchEvent(evDownC);
        mDoubleTapHelper.onTouchEvent(evUpC);
        verify(mActivationListener).onActiveChanged(true);
        verify(mView).postDelayed(any(Runnable.class), anyLong());
        verify(mDoubleTapLogListener, never()).onDoubleTapLog(anyBoolean(), anyFloat(), anyFloat());
        verify(mDoubleTapListener, never()).onDoubleTap();

        mDoubleTapHelper.onTouchEvent(evDownD);
        mDoubleTapHelper.onTouchEvent(evUpD);
        verify(mDoubleTapLogListener).onDoubleTapLog(true, 0, 0);
        verify(mDoubleTapListener).onDoubleTap();

        evDownA.recycle();
        evUpA.recycle();
        evDownB.recycle();
        evUpB.recycle();
    }
}