1 /*
2  * Copyright (C) 2008 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.commands.monkey;
18 
19 import android.app.IActivityManager;
20 import android.hardware.input.InputManager;
21 import android.os.SystemClock;
22 import android.util.SparseArray;
23 import android.view.IWindowManager;
24 import android.view.MotionEvent;
25 
26 
27 /**
28  * monkey motion event
29  */
30 public abstract class MonkeyMotionEvent extends MonkeyEvent {
31     private long mDownTime;
32     private long mEventTime;
33     private int mAction;
34     private SparseArray<MotionEvent.PointerCoords> mPointers;
35     private int mMetaState;
36     private float mXPrecision;
37     private float mYPrecision;
38     private int mDeviceId;
39     private int mSource;
40     private int mFlags;
41     private int mEdgeFlags;
42 
43     //If true, this is an intermediate step (more verbose logging, only)
44     private boolean mIntermediateNote;
45 
MonkeyMotionEvent(int type, int source, int action)46     protected MonkeyMotionEvent(int type, int source, int action) {
47         super(type);
48         mSource = source;
49         mDownTime = -1;
50         mEventTime = -1;
51         mAction = action;
52         mPointers = new SparseArray<MotionEvent.PointerCoords>();
53         mXPrecision = 1;
54         mYPrecision = 1;
55     }
56 
addPointer(int id, float x, float y)57     public MonkeyMotionEvent addPointer(int id, float x, float y) {
58         return addPointer(id, x, y, 0, 0);
59     }
60 
addPointer(int id, float x, float y, float pressure, float size)61     public MonkeyMotionEvent addPointer(int id, float x, float y,
62             float pressure, float size) {
63         MotionEvent.PointerCoords c = new MotionEvent.PointerCoords();
64         c.x = x;
65         c.y = y;
66         c.pressure = pressure;
67         c.size = size;
68         mPointers.append(id, c);
69         return this;
70     }
71 
setIntermediateNote(boolean b)72     public MonkeyMotionEvent setIntermediateNote(boolean b) {
73         mIntermediateNote = b;
74         return this;
75     }
76 
getIntermediateNote()77     public boolean getIntermediateNote() {
78         return mIntermediateNote;
79     }
80 
getAction()81     public int getAction() {
82         return mAction;
83     }
84 
getDownTime()85     public long getDownTime() {
86         return mDownTime;
87     }
88 
getEventTime()89     public long getEventTime() {
90         return mEventTime;
91     }
92 
setDownTime(long downTime)93     public MonkeyMotionEvent setDownTime(long downTime) {
94         mDownTime = downTime;
95         return this;
96     }
97 
setEventTime(long eventTime)98     public MonkeyMotionEvent setEventTime(long eventTime) {
99         mEventTime = eventTime;
100         return this;
101     }
102 
setMetaState(int metaState)103     public MonkeyMotionEvent setMetaState(int metaState) {
104         mMetaState = metaState;
105         return this;
106     }
107 
setPrecision(float xPrecision, float yPrecision)108     public MonkeyMotionEvent setPrecision(float xPrecision, float yPrecision) {
109         mXPrecision = xPrecision;
110         mYPrecision = yPrecision;
111         return this;
112     }
113 
setDeviceId(int deviceId)114     public MonkeyMotionEvent setDeviceId(int deviceId) {
115         mDeviceId = deviceId;
116         return this;
117     }
118 
setEdgeFlags(int edgeFlags)119     public MonkeyMotionEvent setEdgeFlags(int edgeFlags) {
120         mEdgeFlags = edgeFlags;
121         return this;
122     }
123 
124     /**
125      *
126      * @return instance of a motion event
127      */
getEvent()128     private MotionEvent getEvent() {
129         int pointerCount = mPointers.size();
130         int[] pointerIds = new int[pointerCount];
131         MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[pointerCount];
132         for (int i = 0; i < pointerCount; i++) {
133             pointerIds[i] = mPointers.keyAt(i);
134             pointerCoords[i] = mPointers.valueAt(i);
135         }
136 
137         MotionEvent ev = MotionEvent.obtain(mDownTime,
138                 mEventTime < 0 ? SystemClock.uptimeMillis() : mEventTime,
139                 mAction, pointerCount, pointerIds, pointerCoords,
140                 mMetaState, mXPrecision, mYPrecision, mDeviceId, mEdgeFlags, mSource, mFlags);
141         return ev;
142     }
143 
144     @Override
isThrottlable()145     public boolean isThrottlable() {
146         return (getAction() == MotionEvent.ACTION_UP);
147     }
148 
149     @Override
injectEvent(IWindowManager iwm, IActivityManager iam, int verbose)150     public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) {
151         MotionEvent me = getEvent();
152         if ((verbose > 0 && !mIntermediateNote) || verbose > 1) {
153             StringBuilder msg = new StringBuilder(":Sending ");
154             msg.append(getTypeLabel()).append(" (");
155             switch (me.getActionMasked()) {
156                 case MotionEvent.ACTION_DOWN:
157                     msg.append("ACTION_DOWN");
158                     break;
159                 case MotionEvent.ACTION_MOVE:
160                     msg.append("ACTION_MOVE");
161                     break;
162                 case MotionEvent.ACTION_UP:
163                     msg.append("ACTION_UP");
164                     break;
165                 case MotionEvent.ACTION_CANCEL:
166                     msg.append("ACTION_CANCEL");
167                     break;
168                 case MotionEvent.ACTION_POINTER_DOWN:
169                     msg.append("ACTION_POINTER_DOWN ").append(me.getPointerId(me.getActionIndex()));
170                     break;
171                 case MotionEvent.ACTION_POINTER_UP:
172                     msg.append("ACTION_POINTER_UP ").append(me.getPointerId(me.getActionIndex()));
173                     break;
174                 default:
175                     msg.append(me.getAction());
176                     break;
177             }
178             msg.append("):");
179 
180             int pointerCount = me.getPointerCount();
181             for (int i = 0; i < pointerCount; i++) {
182                 msg.append(" ").append(me.getPointerId(i));
183                 msg.append(":(").append(me.getX(i)).append(",").append(me.getY(i)).append(")");
184             }
185             Logger.out.println(msg.toString());
186         }
187         try {
188             if (!InputManager.getInstance().injectInputEvent(me,
189                     InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT)) {
190                 return MonkeyEvent.INJECT_FAIL;
191             }
192         } finally {
193             me.recycle();
194         }
195         return MonkeyEvent.INJECT_SUCCESS;
196     }
197 
getTypeLabel()198     protected abstract String getTypeLabel();
199 }
200