1 /*
2  * Copyright (C) 2020 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 com.android.server.accessibility.magnification;
18 
19 import static android.view.MotionEvent.ACTION_CANCEL;
20 import static android.view.MotionEvent.ACTION_DOWN;
21 import static android.view.MotionEvent.ACTION_UP;
22 
23 import static org.mockito.ArgumentMatchers.eq;
24 import static org.mockito.Mockito.verify;
25 import static org.testng.AssertJUnit.assertTrue;
26 
27 import android.annotation.NonNull;
28 import android.provider.Settings;
29 import android.view.InputDevice;
30 import android.view.MotionEvent;
31 
32 import androidx.test.runner.AndroidJUnit4;
33 
34 import com.android.server.accessibility.AccessibilityTraceManager;
35 
36 import org.junit.Before;
37 import org.junit.Test;
38 import org.junit.runner.RunWith;
39 import org.mockito.Mock;
40 import org.mockito.MockitoAnnotations;
41 
42 /**
43  * Tests for {@link MagnificationGestureHandler}.
44  */
45 @RunWith(AndroidJUnit4.class)
46 public class MagnificationGestureHandlerTest {
47 
48     private TestMagnificationGestureHandler mMgh;
49     private static final int DISPLAY_0 = 0;
50     private static final int FULLSCREEN_MODE =
51             Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
52 
53     @Mock
54     AccessibilityTraceManager mTraceManager;
55     @Mock
56     MagnificationGestureHandler.Callback mCallback;
57 
58     @Before
setUp()59     public void setUp() {
60         MockitoAnnotations.initMocks(this);
61         mMgh = new TestMagnificationGestureHandler(DISPLAY_0,
62                 /* detectTripleTap= */true,
63                 /* detectShortcutTrigger= */true,
64                 mTraceManager,
65                 mCallback);
66     }
67 
68     @Test
onMotionEvent_isFromScreen_onMotionEventInternal()69     public void onMotionEvent_isFromScreen_onMotionEventInternal() {
70         final MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0);
71         downEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
72 
73         mMgh.onMotionEvent(downEvent, downEvent, /* policyFlags= */ 0);
74 
75         try {
76             assertTrue(mMgh.mIsInternalMethodCalled);
77         } finally {
78             downEvent.recycle();
79         }
80     }
81 
82     @Test
onMotionEvent_downEvent_handleInteractionStart()83     public void onMotionEvent_downEvent_handleInteractionStart() {
84         final MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0);
85         downEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
86 
87         mMgh.onMotionEvent(downEvent, downEvent, /* policyFlags= */ 0);
88 
89         try {
90             verify(mCallback).onTouchInteractionStart(eq(DISPLAY_0), eq(mMgh.getMode()));
91         } finally {
92             downEvent.recycle();
93         }
94     }
95 
96     @Test
onMotionEvent_upEvent_handleInteractionEnd()97     public void onMotionEvent_upEvent_handleInteractionEnd() {
98         final MotionEvent upEvent = MotionEvent.obtain(0, 0, ACTION_UP, 0, 0, 0);
99         upEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
100 
101         mMgh.onMotionEvent(upEvent, upEvent, /* policyFlags= */ 0);
102 
103         try {
104             verify(mCallback).onTouchInteractionEnd(eq(DISPLAY_0), eq(mMgh.getMode()));
105         } finally {
106             upEvent.recycle();
107         }
108     }
109 
110     @Test
onMotionEvent_cancelEvent_handleInteractionEnd()111     public void onMotionEvent_cancelEvent_handleInteractionEnd() {
112         final MotionEvent cancelEvent = MotionEvent.obtain(0, 0, ACTION_CANCEL, 0, 0, 0);
113         cancelEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
114 
115         mMgh.onMotionEvent(cancelEvent, cancelEvent, /* policyFlags= */ 0);
116 
117         try {
118             verify(mCallback).onTouchInteractionEnd(eq(DISPLAY_0), eq(mMgh.getMode()));
119         } finally {
120             cancelEvent.recycle();
121         }
122     }
123 
124     private static class TestMagnificationGestureHandler extends MagnificationGestureHandler {
125 
126         boolean mIsInternalMethodCalled = false;
127 
TestMagnificationGestureHandler(int displayId, boolean detectTripleTap, boolean detectShortcutTrigger, @NonNull AccessibilityTraceManager trace, @NonNull Callback callback)128         TestMagnificationGestureHandler(int displayId, boolean detectTripleTap,
129                 boolean detectShortcutTrigger, @NonNull AccessibilityTraceManager trace,
130                 @NonNull Callback callback) {
131             super(displayId, detectTripleTap, detectShortcutTrigger, trace, callback);
132         }
133 
134         @Override
onMotionEventInternal(MotionEvent event, MotionEvent rawEvent, int policyFlags)135         void onMotionEventInternal(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
136             mIsInternalMethodCalled = true;
137         }
138 
139         @Override
notifyShortcutTriggered()140         public void notifyShortcutTriggered() {
141             super.notifyShortcutTriggered();
142         }
143 
144         @Override
handleShortcutTriggered()145         public void handleShortcutTriggered() {
146         }
147 
148         @Override
getMode()149         public int getMode() {
150             return FULLSCREEN_MODE;
151         }
152     }
153 }
154