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.systemui.classifier; 18 19 import android.hardware.devicestate.DeviceStateManager.FoldStateListener; 20 import android.util.DisplayMetrics; 21 import android.view.InputDevice; 22 import android.view.MotionEvent; 23 24 import androidx.test.uiautomator.Configurator; 25 26 import com.android.systemui.SysuiTestCase; 27 import com.android.systemui.dock.DockManagerFake; 28 import com.android.systemui.statusbar.policy.BatteryController; 29 30 import org.junit.After; 31 import org.mockito.Mock; 32 import org.mockito.MockitoAnnotations; 33 34 import java.util.ArrayList; 35 import java.util.List; 36 37 public class ClassifierTest extends SysuiTestCase { 38 39 private FalsingDataProvider mDataProvider; 40 private final List<MotionEvent> mMotionEvents = new ArrayList<>(); 41 private float mOffsetX = 0; 42 private float mOffsetY = 0; 43 @Mock 44 private BatteryController mBatteryController; 45 private FoldStateListener mFoldStateListener = new FoldStateListener(mContext); 46 private final DockManagerFake mDockManager = new DockManagerFake(); 47 setup()48 public void setup() { 49 MockitoAnnotations.initMocks(this); 50 DisplayMetrics displayMetrics = new DisplayMetrics(); 51 displayMetrics.xdpi = 100; 52 displayMetrics.ydpi = 100; 53 displayMetrics.widthPixels = 1000; 54 displayMetrics.heightPixels = 1000; 55 mDataProvider = new FalsingDataProvider( 56 displayMetrics, mBatteryController, mFoldStateListener, mDockManager, false); 57 } 58 59 @After tearDown()60 public void tearDown() { 61 resetDataProvider(); 62 } 63 getDataProvider()64 protected FalsingDataProvider getDataProvider() { 65 return mDataProvider; 66 } 67 setOffsetX(float offsetX)68 protected void setOffsetX(float offsetX) { 69 mOffsetX = offsetX; 70 } 71 setOffsetY(float offsetY)72 protected void setOffsetY(float offsetY) { 73 mOffsetY = offsetY; 74 } 75 resetDataProvider()76 protected void resetDataProvider() { 77 for (MotionEvent motionEvent : mMotionEvents) { 78 motionEvent.recycle(); 79 } 80 81 mMotionEvents.clear(); 82 83 mDataProvider.onSessionEnd(); 84 } 85 getPointerAction(int actionType, int index)86 protected static int getPointerAction(int actionType, int index) { 87 return actionType + (index << MotionEvent.ACTION_POINTER_INDEX_SHIFT); 88 } 89 appendDownEvent(float x, float y)90 protected MotionEvent appendDownEvent(float x, float y) { 91 return appendMotionEvent(MotionEvent.ACTION_DOWN, x, y); 92 } 93 appendDownEvent(float x, float y, long eventTime)94 protected MotionEvent appendDownEvent(float x, float y, long eventTime) { 95 return appendMotionEvent(MotionEvent.ACTION_DOWN, x, y, eventTime); 96 } 97 appendMoveEvent(float x, float y)98 protected MotionEvent appendMoveEvent(float x, float y) { 99 return appendMotionEvent(MotionEvent.ACTION_MOVE, x, y); 100 } 101 appendMoveEvent(float x, float y, long eventTime)102 protected MotionEvent appendMoveEvent(float x, float y, long eventTime) { 103 return appendMotionEvent(MotionEvent.ACTION_MOVE, x, y, eventTime); 104 } 105 106 appendUpEvent(float x, float y)107 protected MotionEvent appendUpEvent(float x, float y) { 108 return appendMotionEvent(MotionEvent.ACTION_UP, x, y); 109 } 110 appendUpEvent(float x, float y, long eventTime)111 protected MotionEvent appendUpEvent(float x, float y, long eventTime) { 112 return appendMotionEvent(MotionEvent.ACTION_UP, x, y, eventTime); 113 } 114 appendMotionEvent(int actionType, float x, float y)115 private MotionEvent appendMotionEvent(int actionType, float x, float y) { 116 117 long eventTime = mMotionEvents.isEmpty() ? 1 : mMotionEvents.get( 118 mMotionEvents.size() - 1).getEventTime() + 1; 119 return appendMotionEvent(actionType, x, y, eventTime); 120 } 121 appendMotionEvent(int actionType, float x, float y, long eventTime)122 private MotionEvent appendMotionEvent(int actionType, float x, float y, long eventTime) { 123 x += mOffsetX; 124 y += mOffsetY; 125 126 MotionEvent motionEvent = MotionEvent.obtain(1, eventTime, actionType, x, y, 127 0); 128 mMotionEvents.add(motionEvent); 129 130 mDataProvider.onMotionEvent(motionEvent); 131 132 return motionEvent; 133 } 134 appendTrackpadDownEvent(float x, float y)135 protected MotionEvent appendTrackpadDownEvent(float x, float y) { 136 return appendTrackpadMotionEvent(MotionEvent.ACTION_DOWN, x, y, 1); 137 } 138 appendTrackpadMoveEvent(float x, float y, int pointerCount)139 protected MotionEvent appendTrackpadMoveEvent(float x, float y, int pointerCount) { 140 return appendTrackpadMotionEvent(MotionEvent.ACTION_MOVE, x, y, pointerCount); 141 } 142 appendTrackpadPointerDownEvent(int actionType, float x, float y, int pointerCount)143 protected MotionEvent appendTrackpadPointerDownEvent(int actionType, float x, float y, 144 int pointerCount) { 145 return appendTrackpadMotionEvent(actionType, x, y, pointerCount); 146 } 147 appendTrackpadMotionEvent(int actionType, float x, float y, int pointerCount)148 private MotionEvent appendTrackpadMotionEvent(int actionType, float x, float y, 149 int pointerCount) { 150 long eventTime = mMotionEvents.isEmpty() ? 1 : mMotionEvents.get( 151 mMotionEvents.size() - 1).getEventTime() + 1; 152 return appendTrackpadMotionEvent(actionType, x, y, pointerCount, eventTime); 153 } 154 appendTrackpadMotionEvent(int actionType, float x, float y, int pointerCount, long eventTime)155 private MotionEvent appendTrackpadMotionEvent(int actionType, float x, float y, 156 int pointerCount, long eventTime) { 157 MotionEvent.PointerProperties[] pointerProperties = 158 new MotionEvent.PointerProperties[pointerCount]; 159 MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[pointerCount]; 160 for (int i = 0; i < pointerCount; i++) { 161 pointerProperties[i] = getPointerProperties(i); 162 pointerCoords[i] = getPointerCoords(x, y); 163 } 164 return MotionEvent.obtain(1, eventTime, actionType, pointerCount, pointerProperties, 165 pointerCoords, 0, 0, 1.0f, 1.0f, 0, 0, 166 InputDevice.SOURCE_TOUCHPAD | InputDevice.SOURCE_MOUSE, 0, 0, 167 MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE); 168 } 169 getPointerProperties(int pointerId)170 private static MotionEvent.PointerProperties getPointerProperties(int pointerId) { 171 MotionEvent.PointerProperties properties = new MotionEvent.PointerProperties(); 172 properties.id = pointerId; 173 properties.toolType = Configurator.getInstance().getToolType(); 174 return properties; 175 } 176 getPointerCoords(float x, float y)177 private static MotionEvent.PointerCoords getPointerCoords(float x, float y) { 178 MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords(); 179 coords.pressure = 1; 180 coords.size = 1; 181 coords.x = x; 182 coords.y = y; 183 return coords; 184 } 185 } 186