blob: a04bcc0b29c5a18181d2426f2f2bcdd767030600 [file] [log] [blame]
/*
* Copyright (C) 2017 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.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.res.Configuration;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
import android.view.MotionEvent;
import android.view.View;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@SmallTest
public class NearestTouchFrameTest extends SysuiTestCase {
private NearestTouchFrame mNearestTouchFrame;
@Before
public void setup() {
Configuration c = new Configuration(mContext.getResources().getConfiguration());
c.smallestScreenWidthDp = 500;
mNearestTouchFrame = new NearestTouchFrame(mContext, null, c);
}
@Test
public void testNoActionOnLargeDevices() {
Configuration c = new Configuration(mContext.getResources().getConfiguration());
c.smallestScreenWidthDp = 700;
mNearestTouchFrame = new NearestTouchFrame(mContext, null, c);
View left = mockViewAt(0, 0, 10, 10);
View right = mockViewAt(20, 0, 10, 10);
mNearestTouchFrame.addView(left);
mNearestTouchFrame.addView(right);
mNearestTouchFrame.onMeasure(0, 0);
MotionEvent ev = MotionEvent.obtain(0, 0, 0,
12 /* x */, 5 /* y */, 0);
mNearestTouchFrame.onTouchEvent(ev);
verify(left, never()).onTouchEvent(eq(ev));
ev.recycle();
}
@Test
public void testInvisibleViews() {
View left = mockViewAt(0, 0, 10, 10);
View right = mockViewAt(20, 0, 10, 10);
when(left.getVisibility()).thenReturn(View.INVISIBLE);
mNearestTouchFrame.addView(left);
mNearestTouchFrame.addView(right);
mNearestTouchFrame.onMeasure(0, 0);
MotionEvent ev = MotionEvent.obtain(0, 0, 0,
12 /* x */, 5 /* y */, 0);
mNearestTouchFrame.onTouchEvent(ev);
verify(left, never()).onTouchEvent(eq(ev));
verify(right, never()).onTouchEvent(eq(ev));
ev.recycle();
}
@Test
public void testNearestView_DetachedViewsExcluded() {
View left = mockViewAt(0, 0, 10, 10);
when(left.isAttachedToWindow()).thenReturn(false);
View right = mockViewAt(20, 0, 10, 10);
mNearestTouchFrame.addView(left);
mNearestTouchFrame.addView(right);
mNearestTouchFrame.onMeasure(0, 0);
// Would go to left view if attached, but goes to right instead as left should be detached.
MotionEvent ev = MotionEvent.obtain(0, 0, 0,
12 /* x */, 5 /* y */, 0);
mNearestTouchFrame.onTouchEvent(ev);
verify(right).onTouchEvent(eq(ev));
ev.recycle();
}
@Test
public void testHorizontalSelection_Left() {
View left = mockViewAt(0, 0, 10, 10);
View right = mockViewAt(20, 0, 10, 10);
mNearestTouchFrame.addView(left);
mNearestTouchFrame.addView(right);
mNearestTouchFrame.onMeasure(0, 0);
MotionEvent ev = MotionEvent.obtain(0, 0, 0,
12 /* x */, 5 /* y */, 0);
mNearestTouchFrame.onTouchEvent(ev);
verify(left).onTouchEvent(eq(ev));
ev.recycle();
}
@Test
public void testHorizontalSelection_Right() {
View left = mockViewAt(0, 0, 10, 10);
View right = mockViewAt(20, 0, 10, 10);
mNearestTouchFrame.addView(left);
mNearestTouchFrame.addView(right);
mNearestTouchFrame.onMeasure(0, 0);
MotionEvent ev = MotionEvent.obtain(0, 0, 0,
18 /* x */, 5 /* y */, 0);
mNearestTouchFrame.onTouchEvent(ev);
verify(right).onTouchEvent(eq(ev));
ev.recycle();
}
@Test
public void testVerticalSelection_Top() {
View top = mockViewAt(0, 0, 10, 10);
View bottom = mockViewAt(0, 20, 10, 10);
mNearestTouchFrame.addView(top);
mNearestTouchFrame.addView(bottom);
mNearestTouchFrame.onMeasure(0, 0);
MotionEvent ev = MotionEvent.obtain(0, 0, 0,
5 /* x */, 12 /* y */, 0);
mNearestTouchFrame.onTouchEvent(ev);
verify(top).onTouchEvent(eq(ev));
ev.recycle();
}
@Test
public void testVerticalSelection_Bottom() {
View top = mockViewAt(0, 0, 10, 10);
View bottom = mockViewAt(0, 20, 10, 10);
mNearestTouchFrame.addView(top);
mNearestTouchFrame.addView(bottom);
mNearestTouchFrame.onMeasure(0, 0);
MotionEvent ev = MotionEvent.obtain(0, 0, 0,
5 /* x */, 18 /* y */, 0);
mNearestTouchFrame.onTouchEvent(ev);
verify(bottom).onTouchEvent(eq(ev));
ev.recycle();
}
@Test
public void testViewNotAttachedNoCrash() {
View view = mockViewAt(0, 20, 10, 10);
when(view.isAttachedToWindow()).thenReturn(false);
mNearestTouchFrame.addView(view);
mNearestTouchFrame.onMeasure(0, 0);
MotionEvent ev = MotionEvent.obtain(0, 0, 0, 5 /* x */, 18 /* y */, 0);
mNearestTouchFrame.onTouchEvent(ev);
verify(view, never()).onTouchEvent(eq(ev));
ev.recycle();
}
private View mockViewAt(int x, int y, int width, int height) {
View v = spy(new View(mContext));
doAnswer(invocation -> {
int[] pos = (int[]) invocation.getArguments()[0];
pos[0] = x;
pos[1] = y;
return null;
}).when(v).getLocationInWindow(any());
when(v.isClickable()).thenReturn(true);
when(v.isAttachedToWindow()).thenReturn(true);
// Stupid final methods.
v.setLeft(0);
v.setRight(width);
v.setTop(0);
v.setBottom(height);
return v;
}
}