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
17package com.android.commands.monkey;
18
19import android.app.IActivityManager;
20import android.hardware.input.InputManager;
21import android.os.SystemClock;
22import android.util.SparseArray;
23import android.view.IWindowManager;
24import android.view.MotionEvent;
25
26
27/**
28 * monkey motion event
29 */
30public 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
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
57    public MonkeyMotionEvent addPointer(int id, float x, float y) {
58        return addPointer(id, x, y, 0, 0);
59    }
60
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
72    public MonkeyMotionEvent setIntermediateNote(boolean b) {
73        mIntermediateNote = b;
74        return this;
75    }
76
77    public boolean getIntermediateNote() {
78        return mIntermediateNote;
79    }
80
81    public int getAction() {
82        return mAction;
83    }
84
85    public long getDownTime() {
86        return mDownTime;
87    }
88
89    public long getEventTime() {
90        return mEventTime;
91    }
92
93    public MonkeyMotionEvent setDownTime(long downTime) {
94        mDownTime = downTime;
95        return this;
96    }
97
98    public MonkeyMotionEvent setEventTime(long eventTime) {
99        mEventTime = eventTime;
100        return this;
101    }
102
103    public MonkeyMotionEvent setMetaState(int metaState) {
104        mMetaState = metaState;
105        return this;
106    }
107
108    public MonkeyMotionEvent setPrecision(float xPrecision, float yPrecision) {
109        mXPrecision = xPrecision;
110        mYPrecision = yPrecision;
111        return this;
112    }
113
114    public MonkeyMotionEvent setDeviceId(int deviceId) {
115        mDeviceId = deviceId;
116        return this;
117    }
118
119    public MonkeyMotionEvent setEdgeFlags(int edgeFlags) {
120        mEdgeFlags = edgeFlags;
121        return this;
122    }
123
124    /**
125     *
126     * @return instance of a motion event
127     */
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
145    public boolean isThrottlable() {
146        return (getAction() == MotionEvent.ACTION_UP);
147    }
148
149    @Override
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            System.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
198    protected abstract String getTypeLabel();
199}
200