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