blob: 414b69fabdc825c34adda4091cd06c16147499d4 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 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.server;
18
Joe Onorato8a9b2202010-02-26 18:56:32 -080019import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import android.view.Display;
21import android.view.MotionEvent;
22import android.view.Surface;
23import android.view.WindowManagerPolicy;
24
Dianne Hackborna2e92262010-03-02 17:19:29 -080025import java.io.PrintWriter;
26
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027public class InputDevice {
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -070028 static final boolean DEBUG_POINTERS = false;
Dianne Hackborn1411d1c2009-10-12 23:21:18 -070029 static final boolean DEBUG_HACKS = false;
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -070030
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031 /** Amount that trackball needs to move in order to generate a key event. */
32 static final int TRACKBALL_MOVEMENT_THRESHOLD = 6;
33
Dianne Hackborn9822d2b2009-07-20 17:33:15 -070034 /** Maximum number of pointers we will track and report. */
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -070035 static final int MAX_POINTERS = 10;
Dianne Hackborn9822d2b2009-07-20 17:33:15 -070036
Adam Powellf5bcc6a2010-03-02 10:42:16 -080037 /**
38 * Slop distance for jumpy pointer detection.
Adam Powell6651a132010-03-03 20:43:16 -080039 * The vertical range of the screen divided by this is our epsilon value.
Adam Powellf5bcc6a2010-03-02 10:42:16 -080040 */
Adam Powell6651a132010-03-03 20:43:16 -080041 private static final int JUMPY_EPSILON_DIVISOR = 212;
Adam Powellf5bcc6a2010-03-02 10:42:16 -080042
43 /** Number of jumpy points to drop for touchscreens that need it. */
44 private static final int JUMPY_TRANSITION_DROPS = 3;
45 private static final int JUMPY_DROP_LIMIT = 3;
46
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047 final int id;
48 final int classes;
49 final String name;
50 final AbsoluteInfo absX;
51 final AbsoluteInfo absY;
52 final AbsoluteInfo absPressure;
53 final AbsoluteInfo absSize;
54
Dianne Hackborn9822d2b2009-07-20 17:33:15 -070055 long mKeyDownTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056 int mMetaKeysState = 0;
57
Dianne Hackborn2a2b34432009-08-12 17:13:55 -070058 // For use by KeyInputQueue for keeping track of the current touch
59 // data in the old non-multi-touch protocol.
60 final int[] curTouchVals = new int[MotionEvent.NUM_SAMPLE_DATA * 2];
61
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062 final MotionState mAbs = new MotionState(0, 0);
63 final MotionState mRel = new MotionState(TRACKBALL_MOVEMENT_THRESHOLD,
64 TRACKBALL_MOVEMENT_THRESHOLD);
65
66 static class MotionState {
67 int xPrecision;
68 int yPrecision;
69 float xMoveScale;
70 float yMoveScale;
71 MotionEvent currentMove = null;
72 boolean changed = false;
Dianne Hackborna2e92262010-03-02 17:19:29 -080073 boolean everChanged = false;
Dianne Hackborn9822d2b2009-07-20 17:33:15 -070074 long mDownTime = 0;
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -070075
76 // The currently assigned pointer IDs, corresponding to the last data.
77 int[] mPointerIds = new int[MAX_POINTERS];
78
79 // This is the last generated pointer data, ordered to match
80 // mPointerIds.
Dianne Hackborndc953722009-10-19 11:24:39 -070081 boolean mSkipLastPointers;
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -070082 int mLastNumPointers = 0;
Dianne Hackborn9822d2b2009-07-20 17:33:15 -070083 final int[] mLastData = new int[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS];
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -070084
85 // This is the next set of pointer data being generated. It is not
86 // in any known order, and will be propagated in to mLastData
87 // as part of mapping it to the appropriate pointer IDs.
88 // Note that we have one extra sample of data here, to help clients
89 // avoid doing bounds checking.
90 int mNextNumPointers = 0;
91 final int[] mNextData = new int[(MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS)
92 + MotionEvent.NUM_SAMPLE_DATA];
93
Dianne Hackborn1411d1c2009-10-12 23:21:18 -070094 // Used to determine whether we dropped bad data, to avoid doing
95 // it repeatedly.
96 final boolean[] mDroppedBadPoint = new boolean[MAX_POINTERS];
Adam Powellf5bcc6a2010-03-02 10:42:16 -080097
98 // Used to count the number of jumpy points dropped.
99 private int mJumpyPointsDropped = 0;
Dianne Hackborn1411d1c2009-10-12 23:21:18 -0700100
101 // Used to perform averaging of reported coordinates, to smooth
102 // the data and filter out transients during a release.
103 static final int HISTORY_SIZE = 5;
104 int[] mHistoryDataStart = new int[MAX_POINTERS];
105 int[] mHistoryDataEnd = new int[MAX_POINTERS];
106 final int[] mHistoryData = new int[(MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS)
107 * HISTORY_SIZE];
108 final int[] mAveragedData = new int[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS];
109
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700110 // Temporary data structures for doing the pointer ID mapping.
111 final int[] mLast2Next = new int[MAX_POINTERS];
112 final int[] mNext2Last = new int[MAX_POINTERS];
113 final long[] mNext2LastDistance = new long[MAX_POINTERS];
114
115 // Temporary data structure for generating the final motion data.
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700116 final float[] mReportData = new float[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700118 // This is not used here, but can be used by callers for state tracking.
119 int mAddingPointerOffset = 0;
120 final boolean[] mDown = new boolean[MAX_POINTERS];
121
Dianne Hackborna2e92262010-03-02 17:19:29 -0800122 void dumpIntArray(PrintWriter pw, int[] array) {
123 pw.print("[");
124 for (int i=0; i<array.length; i++) {
125 if (i > 0) pw.print(", ");
126 pw.print(array[i]);
127 }
128 pw.print("]");
129 }
130
131 void dumpBooleanArray(PrintWriter pw, boolean[] array) {
132 pw.print("[");
133 for (int i=0; i<array.length; i++) {
134 if (i > 0) pw.print(", ");
135 pw.print(array[i] ? "true" : "false");
136 }
137 pw.print("]");
138 }
139
140 void dump(PrintWriter pw, String prefix) {
141 pw.print(prefix); pw.print("xPrecision="); pw.print(xPrecision);
142 pw.print(" yPrecision="); pw.println(yPrecision);
143 pw.print(prefix); pw.print("xMoveScale="); pw.print(xMoveScale);
144 pw.print(" yMoveScale="); pw.println(yMoveScale);
145 if (currentMove != null) {
146 pw.print(prefix); pw.print("currentMove="); pw.println(currentMove);
147 }
148 if (changed || mDownTime != 0) {
149 pw.print(prefix); pw.print("changed="); pw.print(changed);
150 pw.print(" mDownTime="); pw.println(mDownTime);
151 }
152 pw.print(prefix); pw.print("mPointerIds="); dumpIntArray(pw, mPointerIds);
153 pw.println("");
154 if (mSkipLastPointers || mLastNumPointers != 0) {
155 pw.print(prefix); pw.print("mSkipLastPointers="); pw.print(mSkipLastPointers);
156 pw.print(" mLastNumPointers="); pw.println(mLastNumPointers);
157 pw.print(prefix); pw.print("mLastData="); dumpIntArray(pw, mLastData);
158 pw.println("");
159 }
160 if (mNextNumPointers != 0) {
161 pw.print(prefix); pw.print("mNextNumPointers="); pw.println(mNextNumPointers);
162 pw.print(prefix); pw.print("mNextData="); dumpIntArray(pw, mNextData);
163 pw.println("");
164 }
165 pw.print(prefix); pw.print("mDroppedBadPoint=");
166 dumpBooleanArray(pw, mDroppedBadPoint); pw.println("");
167 pw.print(prefix); pw.print("mAddingPointerOffset="); pw.println(mAddingPointerOffset);
168 pw.print(prefix); pw.print("mDown=");
169 dumpBooleanArray(pw, mDown); pw.println("");
170 }
171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172 MotionState(int mx, int my) {
173 xPrecision = mx;
174 yPrecision = my;
175 xMoveScale = mx != 0 ? (1.0f/mx) : 1.0f;
176 yMoveScale = my != 0 ? (1.0f/my) : 1.0f;
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700177 for (int i=0; i<MAX_POINTERS; i++) {
178 mPointerIds[i] = i;
179 }
180 }
181
Dianne Hackborn1411d1c2009-10-12 23:21:18 -0700182 /**
183 * Special hack for devices that have bad screen data: if one of the
184 * points has moved more than a screen height from the last position,
185 * then drop it.
186 */
187 void dropBadPoint(InputDevice dev) {
188 // We should always have absY, but let's be paranoid.
189 if (dev.absY == null) {
190 return;
191 }
192 // Don't do anything if a finger is going down or up. We run
193 // here before assigning pointer IDs, so there isn't a good
194 // way to do per-finger matching.
195 if (mNextNumPointers != mLastNumPointers) {
196 return;
197 }
198
199 // We consider a single movement across more than a 7/16 of
200 // the long size of the screen to be bad. This was a magic value
201 // determined by looking at the maximum distance it is feasible
202 // to actually move in one sample.
203 final int maxDy = ((dev.absY.maxValue-dev.absY.minValue)*7)/16;
204
205 // Look through all new points and see if any are farther than
206 // acceptable from all previous points.
207 for (int i=mNextNumPointers-1; i>=0; i--) {
208 final int ioff = i * MotionEvent.NUM_SAMPLE_DATA;
209 //final int x = mNextData[ioff + MotionEvent.SAMPLE_X];
210 final int y = mNextData[ioff + MotionEvent.SAMPLE_Y];
Joe Onorato8a9b2202010-02-26 18:56:32 -0800211 if (DEBUG_HACKS) Slog.v("InputDevice", "Looking at next point #" + i + ": y=" + y);
Dianne Hackborn1411d1c2009-10-12 23:21:18 -0700212 boolean dropped = false;
213 if (!mDroppedBadPoint[i] && mLastNumPointers > 0) {
214 dropped = true;
215 int closestDy = -1;
216 int closestY = -1;
217 // We will drop this new point if it is sufficiently
218 // far away from -all- last points.
219 for (int j=mLastNumPointers-1; j>=0; j--) {
220 final int joff = j * MotionEvent.NUM_SAMPLE_DATA;
221 //int dx = x - mLastData[joff + MotionEvent.SAMPLE_X];
222 int dy = y - mLastData[joff + MotionEvent.SAMPLE_Y];
223 //if (dx < 0) dx = -dx;
224 if (dy < 0) dy = -dy;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800225 if (DEBUG_HACKS) Slog.v("InputDevice", "Comparing with last point #" + j
Dianne Hackborn1411d1c2009-10-12 23:21:18 -0700226 + ": y=" + mLastData[joff] + " dy=" + dy);
227 if (dy < maxDy) {
228 dropped = false;
229 break;
230 } else if (closestDy < 0 || dy < closestDy) {
231 closestDy = dy;
232 closestY = mLastData[joff + MotionEvent.SAMPLE_Y];
233 }
234 }
235 if (dropped) {
236 dropped = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800237 Slog.i("InputDevice", "Dropping bad point #" + i
Dianne Hackborn1411d1c2009-10-12 23:21:18 -0700238 + ": newY=" + y + " closestDy=" + closestDy
239 + " maxDy=" + maxDy);
240 mNextData[ioff + MotionEvent.SAMPLE_Y] = closestY;
241 break;
242 }
243 }
244 mDroppedBadPoint[i] = dropped;
245 }
246 }
247
Adam Powellf5bcc6a2010-03-02 10:42:16 -0800248 void dropJumpyPoint(InputDevice dev) {
Adam Powell6651a132010-03-03 20:43:16 -0800249 // We should always have absY, but let's be paranoid.
250 if (dev.absY == null) {
251 return;
252 }
253 final int jumpyEpsilon = dev.absY.range / JUMPY_EPSILON_DIVISOR;
254
Adam Powellf5bcc6a2010-03-02 10:42:16 -0800255 final int nextNumPointers = mNextNumPointers;
256 final int lastNumPointers = mLastNumPointers;
257 final int[] nextData = mNextData;
258 final int[] lastData = mLastData;
Adam Powell6651a132010-03-03 20:43:16 -0800259
Adam Powellf5bcc6a2010-03-02 10:42:16 -0800260 if (nextNumPointers != mLastNumPointers) {
261 if (DEBUG_HACKS) {
262 Slog.d("InputDevice", "Different pointer count " + lastNumPointers +
263 " -> " + nextNumPointers);
264 for (int i = 0; i < nextNumPointers; i++) {
265 int ioff = i * MotionEvent.NUM_SAMPLE_DATA;
266 Slog.d("InputDevice", "Pointer " + i + " (" +
267 mNextData[ioff + MotionEvent.SAMPLE_X] + ", " +
268 mNextData[ioff + MotionEvent.SAMPLE_Y] + ")");
269 }
270 }
271
272 // Just drop the first few events going from 1 to 2 pointers.
273 // They're bad often enough that they're not worth considering.
274 if (lastNumPointers == 1 && nextNumPointers == 2
275 && mJumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
276 mNextNumPointers = 1;
277 mJumpyPointsDropped++;
278 } else if (lastNumPointers == 2 && nextNumPointers == 1
279 && mJumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
280 // The event when we go from 2 -> 1 tends to be messed up too
281 System.arraycopy(lastData, 0, nextData, 0,
282 lastNumPointers * MotionEvent.NUM_SAMPLE_DATA);
283 mNextNumPointers = lastNumPointers;
284 mJumpyPointsDropped++;
285
286 if (DEBUG_HACKS) {
287 for (int i = 0; i < mNextNumPointers; i++) {
288 int ioff = i * MotionEvent.NUM_SAMPLE_DATA;
289 Slog.d("InputDevice", "Pointer " + i + " replaced (" +
290 mNextData[ioff + MotionEvent.SAMPLE_X] + ", " +
291 mNextData[ioff + MotionEvent.SAMPLE_Y] + ")");
292 }
293 }
294 } else {
295 mJumpyPointsDropped = 0;
296
297 if (DEBUG_HACKS) {
298 Slog.d("InputDevice", "Transition - drop limit reset");
299 }
300 }
301 return;
302 }
303
304 // A 'jumpy' point is one where the coordinate value for one axis
305 // has jumped to the other pointer's location. No need to do anything
306 // else if we only have one pointer.
307 if (nextNumPointers < 2) {
308 return;
309 }
310
311 int badPointerIndex = -1;
312 int badPointerReplaceXWith = 0;
313 int badPointerReplaceYWith = 0;
314 int badPointerDistance = Integer.MIN_VALUE;
315 for (int i = nextNumPointers - 1; i >= 0; i--) {
316 boolean dropx = false;
317 boolean dropy = false;
318
319 // Limit how many times a jumpy point can get dropped.
320 if (mJumpyPointsDropped < JUMPY_DROP_LIMIT) {
321 final int ioff = i * MotionEvent.NUM_SAMPLE_DATA;
322 final int x = nextData[ioff + MotionEvent.SAMPLE_X];
323 final int y = nextData[ioff + MotionEvent.SAMPLE_Y];
324
325 if (DEBUG_HACKS) {
326 Slog.d("InputDevice", "Point " + i + " (" + x + ", " + y + ")");
327 }
328
329 // Check if a touch point is too close to another's coordinates
330 for (int j = 0; j < nextNumPointers && !dropx && !dropy; j++) {
331 if (j == i) {
332 continue;
333 }
334
335 final int joff = j * MotionEvent.NUM_SAMPLE_DATA;
336 final int xOther = nextData[joff + MotionEvent.SAMPLE_X];
337 final int yOther = nextData[joff + MotionEvent.SAMPLE_Y];
338
Adam Powell6651a132010-03-03 20:43:16 -0800339 dropx = Math.abs(x - xOther) <= jumpyEpsilon;
340 dropy = Math.abs(y - yOther) <= jumpyEpsilon;
Adam Powellf5bcc6a2010-03-02 10:42:16 -0800341 }
342
343 if (dropx) {
344 int xreplace = lastData[MotionEvent.SAMPLE_X];
345 int yreplace = lastData[MotionEvent.SAMPLE_Y];
346 int distance = Math.abs(yreplace - y);
347 for (int j = 1; j < lastNumPointers; j++) {
348 final int joff = j * MotionEvent.NUM_SAMPLE_DATA;
349 int lasty = lastData[joff + MotionEvent.SAMPLE_Y];
350 int currDist = Math.abs(lasty - y);
351 if (currDist < distance) {
352 xreplace = lastData[joff + MotionEvent.SAMPLE_X];
353 yreplace = lasty;
354 distance = currDist;
355 }
356 }
357
358 int badXDelta = Math.abs(xreplace - x);
359 if (badXDelta > badPointerDistance) {
360 badPointerDistance = badXDelta;
361 badPointerIndex = i;
362 badPointerReplaceXWith = xreplace;
363 badPointerReplaceYWith = yreplace;
364 }
365 } else if (dropy) {
366 int xreplace = lastData[MotionEvent.SAMPLE_X];
367 int yreplace = lastData[MotionEvent.SAMPLE_Y];
368 int distance = Math.abs(xreplace - x);
369 for (int j = 1; j < lastNumPointers; j++) {
370 final int joff = j * MotionEvent.NUM_SAMPLE_DATA;
371 int lastx = lastData[joff + MotionEvent.SAMPLE_X];
372 int currDist = Math.abs(lastx - x);
373 if (currDist < distance) {
374 xreplace = lastx;
375 yreplace = lastData[joff + MotionEvent.SAMPLE_Y];
376 distance = currDist;
377 }
378 }
379
380 int badYDelta = Math.abs(yreplace - y);
381 if (badYDelta > badPointerDistance) {
382 badPointerDistance = badYDelta;
383 badPointerIndex = i;
384 badPointerReplaceXWith = xreplace;
385 badPointerReplaceYWith = yreplace;
386 }
387 }
388 }
389 }
390 if (badPointerIndex >= 0) {
391 if (DEBUG_HACKS) {
392 Slog.d("InputDevice", "Replacing bad pointer " + badPointerIndex +
393 " with (" + badPointerReplaceXWith + ", " + badPointerReplaceYWith +
394 ")");
395 }
396
397 final int offset = badPointerIndex * MotionEvent.NUM_SAMPLE_DATA;
398 nextData[offset + MotionEvent.SAMPLE_X] = badPointerReplaceXWith;
399 nextData[offset + MotionEvent.SAMPLE_Y] = badPointerReplaceYWith;
400 mJumpyPointsDropped++;
401 } else {
402 mJumpyPointsDropped = 0;
403 }
404 }
405
Dianne Hackborn1411d1c2009-10-12 23:21:18 -0700406 /**
407 * Special hack for devices that have bad screen data: aggregate and
408 * compute averages of the coordinate data, to reduce the amount of
409 * jitter seen by applications.
410 */
411 int[] generateAveragedData(int upOrDownPointer, int lastNumPointers,
412 int nextNumPointers) {
413 final int numPointers = mLastNumPointers;
414 final int[] rawData = mLastData;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800415 if (DEBUG_HACKS) Slog.v("InputDevice", "lastNumPointers=" + lastNumPointers
Dianne Hackborn1411d1c2009-10-12 23:21:18 -0700416 + " nextNumPointers=" + nextNumPointers
417 + " numPointers=" + numPointers);
418 for (int i=0; i<numPointers; i++) {
419 final int ioff = i * MotionEvent.NUM_SAMPLE_DATA;
420 // We keep the average data in offsets based on the pointer
421 // ID, so we don't need to move it around as fingers are
422 // pressed and released.
423 final int p = mPointerIds[i];
424 final int poff = p * MotionEvent.NUM_SAMPLE_DATA * HISTORY_SIZE;
425 if (i == upOrDownPointer && lastNumPointers != nextNumPointers) {
426 if (lastNumPointers < nextNumPointers) {
427 // This pointer is going down. Clear its history
428 // and start fresh.
Joe Onorato8a9b2202010-02-26 18:56:32 -0800429 if (DEBUG_HACKS) Slog.v("InputDevice", "Pointer down @ index "
Dianne Hackborn1411d1c2009-10-12 23:21:18 -0700430 + upOrDownPointer + " id " + mPointerIds[i]);
431 mHistoryDataStart[i] = 0;
432 mHistoryDataEnd[i] = 0;
433 System.arraycopy(rawData, ioff, mHistoryData, poff,
434 MotionEvent.NUM_SAMPLE_DATA);
435 System.arraycopy(rawData, ioff, mAveragedData, ioff,
436 MotionEvent.NUM_SAMPLE_DATA);
437 continue;
438 } else {
439 // The pointer is going up. Just fall through to
440 // recompute the last averaged point (and don't add
441 // it as a new point to include in the average).
Joe Onorato8a9b2202010-02-26 18:56:32 -0800442 if (DEBUG_HACKS) Slog.v("InputDevice", "Pointer up @ index "
Dianne Hackborn1411d1c2009-10-12 23:21:18 -0700443 + upOrDownPointer + " id " + mPointerIds[i]);
444 }
445 } else {
446 int end = mHistoryDataEnd[i];
447 int eoff = poff + (end*MotionEvent.NUM_SAMPLE_DATA);
448 int oldX = mHistoryData[eoff + MotionEvent.SAMPLE_X];
449 int oldY = mHistoryData[eoff + MotionEvent.SAMPLE_Y];
450 int newX = rawData[ioff + MotionEvent.SAMPLE_X];
451 int newY = rawData[ioff + MotionEvent.SAMPLE_Y];
452 int dx = newX-oldX;
453 int dy = newY-oldY;
454 int delta = dx*dx + dy*dy;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800455 if (DEBUG_HACKS) Slog.v("InputDevice", "Delta from last: " + delta);
Dianne Hackborn1411d1c2009-10-12 23:21:18 -0700456 if (delta >= (75*75)) {
457 // Magic number, if moving farther than this, turn
458 // off filtering to avoid lag in response.
459 mHistoryDataStart[i] = 0;
460 mHistoryDataEnd[i] = 0;
461 System.arraycopy(rawData, ioff, mHistoryData, poff,
462 MotionEvent.NUM_SAMPLE_DATA);
463 System.arraycopy(rawData, ioff, mAveragedData, ioff,
464 MotionEvent.NUM_SAMPLE_DATA);
465 continue;
466 } else {
467 end++;
468 if (end >= HISTORY_SIZE) {
469 end -= HISTORY_SIZE;
470 }
471 mHistoryDataEnd[i] = end;
472 int noff = poff + (end*MotionEvent.NUM_SAMPLE_DATA);
473 mHistoryData[noff + MotionEvent.SAMPLE_X] = newX;
474 mHistoryData[noff + MotionEvent.SAMPLE_Y] = newY;
475 mHistoryData[noff + MotionEvent.SAMPLE_PRESSURE]
476 = rawData[ioff + MotionEvent.SAMPLE_PRESSURE];
477 int start = mHistoryDataStart[i];
478 if (end == start) {
479 start++;
480 if (start >= HISTORY_SIZE) {
481 start -= HISTORY_SIZE;
482 }
483 mHistoryDataStart[i] = start;
484 }
485 }
486 }
487
488 // Now compute the average.
489 int start = mHistoryDataStart[i];
490 int end = mHistoryDataEnd[i];
491 int x=0, y=0;
492 int totalPressure = 0;
493 while (start != end) {
494 int soff = poff + (start*MotionEvent.NUM_SAMPLE_DATA);
495 int pressure = mHistoryData[soff + MotionEvent.SAMPLE_PRESSURE];
Dianne Hackborn53cd57942009-10-13 19:50:51 -0700496 if (pressure <= 0) pressure = 1;
Dianne Hackborn1411d1c2009-10-12 23:21:18 -0700497 x += mHistoryData[soff + MotionEvent.SAMPLE_X] * pressure;
498 y += mHistoryData[soff + MotionEvent.SAMPLE_Y] * pressure;
499 totalPressure += pressure;
500 start++;
501 if (start >= HISTORY_SIZE) start = 0;
502 }
503 int eoff = poff + (end*MotionEvent.NUM_SAMPLE_DATA);
504 int pressure = mHistoryData[eoff + MotionEvent.SAMPLE_PRESSURE];
Dianne Hackborn53cd57942009-10-13 19:50:51 -0700505 if (pressure <= 0) pressure = 1;
Dianne Hackborn1411d1c2009-10-12 23:21:18 -0700506 x += mHistoryData[eoff + MotionEvent.SAMPLE_X] * pressure;
507 y += mHistoryData[eoff + MotionEvent.SAMPLE_Y] * pressure;
508 totalPressure += pressure;
509 x /= totalPressure;
510 y /= totalPressure;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800511 if (DEBUG_HACKS) Slog.v("InputDevice", "Averaging " + totalPressure
Dianne Hackborn1411d1c2009-10-12 23:21:18 -0700512 + " weight: (" + x + "," + y + ")");
513 mAveragedData[ioff + MotionEvent.SAMPLE_X] = x;
514 mAveragedData[ioff + MotionEvent.SAMPLE_Y] = y;
Dianne Hackborn05799982009-11-23 13:08:14 -0800515 mAveragedData[ioff + MotionEvent.SAMPLE_PRESSURE] =
516 rawData[ioff + MotionEvent.SAMPLE_PRESSURE];
517 mAveragedData[ioff + MotionEvent.SAMPLE_SIZE] =
518 rawData[ioff + MotionEvent.SAMPLE_SIZE];
Dianne Hackborn1411d1c2009-10-12 23:21:18 -0700519 }
520 return mAveragedData;
521 }
522
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700523 private boolean assignPointer(int nextIndex, boolean allowOverlap) {
524 final int lastNumPointers = mLastNumPointers;
525 final int[] next2Last = mNext2Last;
526 final long[] next2LastDistance = mNext2LastDistance;
527 final int[] last2Next = mLast2Next;
528 final int[] lastData = mLastData;
529 final int[] nextData = mNextData;
530 final int id = nextIndex * MotionEvent.NUM_SAMPLE_DATA;
531
Joe Onorato8a9b2202010-02-26 18:56:32 -0800532 if (DEBUG_POINTERS) Slog.v("InputDevice", "assignPointer: nextIndex="
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700533 + nextIndex + " dataOff=" + id);
534 final int x1 = nextData[id + MotionEvent.SAMPLE_X];
535 final int y1 = nextData[id + MotionEvent.SAMPLE_Y];
536
537 long bestDistance = -1;
538 int bestIndex = -1;
539 for (int j=0; j<lastNumPointers; j++) {
Dianne Hackborn709d6db2009-12-02 18:42:39 -0800540 // If we are not allowing multiple new points to be assigned
541 // to the same old pointer, then skip this one if it is already
542 // detected as a conflict (-2).
543 if (!allowOverlap && last2Next[j] < -1) {
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700544 continue;
545 }
546 final int jd = j * MotionEvent.NUM_SAMPLE_DATA;
547 final int xd = lastData[jd + MotionEvent.SAMPLE_X] - x1;
548 final int yd = lastData[jd + MotionEvent.SAMPLE_Y] - y1;
549 final long distance = xd*(long)xd + yd*(long)yd;
Dianne Hackborn709d6db2009-12-02 18:42:39 -0800550 if (bestDistance == -1 || distance < bestDistance) {
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700551 bestDistance = distance;
552 bestIndex = j;
553 }
554 }
555
Joe Onorato8a9b2202010-02-26 18:56:32 -0800556 if (DEBUG_POINTERS) Slog.v("InputDevice", "New index " + nextIndex
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700557 + " best old index=" + bestIndex + " (distance="
558 + bestDistance + ")");
559 next2Last[nextIndex] = bestIndex;
560 next2LastDistance[nextIndex] = bestDistance;
561
562 if (bestIndex < 0) {
563 return true;
564 }
565
566 if (last2Next[bestIndex] == -1) {
567 last2Next[bestIndex] = nextIndex;
568 return false;
569 }
570
Joe Onorato8a9b2202010-02-26 18:56:32 -0800571 if (DEBUG_POINTERS) Slog.v("InputDevice", "Old index " + bestIndex
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700572 + " has multiple best new pointers!");
573
574 last2Next[bestIndex] = -2;
575 return true;
576 }
577
578 private int updatePointerIdentifiers() {
579 final int[] lastData = mLastData;
580 final int[] nextData = mNextData;
581 final int nextNumPointers = mNextNumPointers;
582 final int lastNumPointers = mLastNumPointers;
583
584 if (nextNumPointers == 1 && lastNumPointers == 1) {
585 System.arraycopy(nextData, 0, lastData, 0,
586 MotionEvent.NUM_SAMPLE_DATA);
587 return -1;
588 }
589
590 // Clear our old state.
591 final int[] last2Next = mLast2Next;
592 for (int i=0; i<lastNumPointers; i++) {
593 last2Next[i] = -1;
594 }
595
Joe Onorato8a9b2202010-02-26 18:56:32 -0800596 if (DEBUG_POINTERS) Slog.v("InputDevice",
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700597 "Update pointers: lastNumPointers=" + lastNumPointers
598 + " nextNumPointers=" + nextNumPointers);
599
600 // Figure out the closes new points to the previous points.
601 final int[] next2Last = mNext2Last;
602 final long[] next2LastDistance = mNext2LastDistance;
603 boolean conflicts = false;
604 for (int i=0; i<nextNumPointers; i++) {
605 conflicts |= assignPointer(i, true);
606 }
607
608 // Resolve ambiguities in pointer mappings, when two or more
609 // new pointer locations find their best previous location is
610 // the same.
611 if (conflicts) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800612 if (DEBUG_POINTERS) Slog.v("InputDevice", "Resolving conflicts");
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700613
614 for (int i=0; i<lastNumPointers; i++) {
615 if (last2Next[i] != -2) {
616 continue;
617 }
618
619 // Note that this algorithm is far from perfect. Ideally
620 // we should do something like the one described at
621 // http://portal.acm.org/citation.cfm?id=997856
622
Joe Onorato8a9b2202010-02-26 18:56:32 -0800623 if (DEBUG_POINTERS) Slog.v("InputDevice",
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700624 "Resolving last index #" + i);
625
626 int numFound;
627 do {
628 numFound = 0;
629 long worstDistance = 0;
630 int worstJ = -1;
631 for (int j=0; j<nextNumPointers; j++) {
632 if (next2Last[j] != i) {
633 continue;
634 }
635 numFound++;
636 if (worstDistance < next2LastDistance[j]) {
637 worstDistance = next2LastDistance[j];
638 worstJ = j;
639 }
640 }
641
642 if (worstJ >= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800643 if (DEBUG_POINTERS) Slog.v("InputDevice",
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700644 "Worst new pointer: " + worstJ
645 + " (distance=" + worstDistance + ")");
646 if (assignPointer(worstJ, false)) {
647 // In this case there is no last pointer
648 // remaining for this new one!
649 next2Last[worstJ] = -1;
650 }
651 }
652 } while (numFound > 2);
653 }
654 }
655
656 int retIndex = -1;
657
658 if (lastNumPointers < nextNumPointers) {
659 // We have one or more new pointers that are down. Create a
660 // new pointer identifier for one of them.
Joe Onorato8a9b2202010-02-26 18:56:32 -0800661 if (DEBUG_POINTERS) Slog.v("InputDevice", "Adding new pointer");
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700662 int nextId = 0;
663 int i=0;
664 while (i < lastNumPointers) {
665 if (mPointerIds[i] > nextId) {
666 // Found a hole, insert the pointer here.
Joe Onorato8a9b2202010-02-26 18:56:32 -0800667 if (DEBUG_POINTERS) Slog.v("InputDevice",
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700668 "Inserting new pointer at hole " + i);
669 System.arraycopy(mPointerIds, i, mPointerIds,
670 i+1, lastNumPointers-i);
671 System.arraycopy(lastData, i*MotionEvent.NUM_SAMPLE_DATA,
672 lastData, (i+1)*MotionEvent.NUM_SAMPLE_DATA,
673 (lastNumPointers-i)*MotionEvent.NUM_SAMPLE_DATA);
Adam Powell5cd88cf2010-06-09 17:10:04 -0700674 System.arraycopy(next2Last, i, next2Last,
675 i+1, lastNumPointers-i);
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700676 break;
677 }
678 i++;
679 nextId++;
680 }
681
Joe Onorato8a9b2202010-02-26 18:56:32 -0800682 if (DEBUG_POINTERS) Slog.v("InputDevice",
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700683 "New pointer id " + nextId + " at index " + i);
684
685 mLastNumPointers++;
686 retIndex = i;
687 mPointerIds[i] = nextId;
688
689 // And assign this identifier to the first new pointer.
690 for (int j=0; j<nextNumPointers; j++) {
691 if (next2Last[j] < 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800692 if (DEBUG_POINTERS) Slog.v("InputDevice",
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700693 "Assigning new id to new pointer index " + j);
694 next2Last[j] = i;
695 break;
696 }
697 }
698 }
699
700 // Propagate all of the current data into the appropriate
701 // location in the old data to match the pointer ID that was
702 // assigned to it.
703 for (int i=0; i<nextNumPointers; i++) {
704 int lastIndex = next2Last[i];
705 if (lastIndex >= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800706 if (DEBUG_POINTERS) Slog.v("InputDevice",
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700707 "Copying next pointer index " + i
708 + " to last index " + lastIndex);
709 System.arraycopy(nextData, i*MotionEvent.NUM_SAMPLE_DATA,
710 lastData, lastIndex*MotionEvent.NUM_SAMPLE_DATA,
711 MotionEvent.NUM_SAMPLE_DATA);
712 }
713 }
714
715 if (lastNumPointers > nextNumPointers) {
716 // One or more pointers has gone up. Find the first one,
717 // and adjust accordingly.
Joe Onorato8a9b2202010-02-26 18:56:32 -0800718 if (DEBUG_POINTERS) Slog.v("InputDevice", "Removing old pointer");
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700719 for (int i=0; i<lastNumPointers; i++) {
720 if (last2Next[i] == -1) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800721 if (DEBUG_POINTERS) Slog.v("InputDevice",
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700722 "Removing old pointer at index " + i);
723 retIndex = i;
724 break;
725 }
726 }
727 }
728
729 return retIndex;
730 }
731
732 void removeOldPointer(int index) {
733 final int lastNumPointers = mLastNumPointers;
734 if (index >= 0 && index < lastNumPointers) {
735 System.arraycopy(mPointerIds, index+1, mPointerIds,
736 index, lastNumPointers-index-1);
737 System.arraycopy(mLastData, (index+1)*MotionEvent.NUM_SAMPLE_DATA,
738 mLastData, (index)*MotionEvent.NUM_SAMPLE_DATA,
739 (lastNumPointers-index-1)*MotionEvent.NUM_SAMPLE_DATA);
740 mLastNumPointers--;
741 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800742 }
743
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700744 MotionEvent generateAbsMotion(InputDevice device, long curTime,
745 long curTimeNano, Display display, int orientation,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800746 int metaState) {
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700747
Dianne Hackborndc953722009-10-19 11:24:39 -0700748 if (mSkipLastPointers) {
749 mSkipLastPointers = false;
750 mLastNumPointers = 0;
751 }
752
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700753 if (mNextNumPointers <= 0 && mLastNumPointers <= 0) {
754 return null;
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700755 }
756
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700757 final int lastNumPointers = mLastNumPointers;
758 final int nextNumPointers = mNextNumPointers;
759 if (mNextNumPointers > MAX_POINTERS) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800760 Slog.w("InputDevice", "Number of pointers " + mNextNumPointers
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700761 + " exceeded maximum of " + MAX_POINTERS);
762 mNextNumPointers = MAX_POINTERS;
763 }
764
765 int upOrDownPointer = updatePointerIdentifiers();
766
767 final float[] reportData = mReportData;
Dianne Hackborn1411d1c2009-10-12 23:21:18 -0700768 final int[] rawData;
769 if (KeyInputQueue.BAD_TOUCH_HACK) {
770 rawData = generateAveragedData(upOrDownPointer, lastNumPointers,
771 nextNumPointers);
772 } else {
773 rawData = mLastData;
774 }
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700775
776 final int numPointers = mLastNumPointers;
777
Joe Onorato8a9b2202010-02-26 18:56:32 -0800778 if (DEBUG_POINTERS) Slog.v("InputDevice", "Processing "
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700779 + numPointers + " pointers (going from " + lastNumPointers
780 + " to " + nextNumPointers + ")");
781
782 for (int i=0; i<numPointers; i++) {
783 final int pos = i * MotionEvent.NUM_SAMPLE_DATA;
784 reportData[pos + MotionEvent.SAMPLE_X] = rawData[pos + MotionEvent.SAMPLE_X];
785 reportData[pos + MotionEvent.SAMPLE_Y] = rawData[pos + MotionEvent.SAMPLE_Y];
786 reportData[pos + MotionEvent.SAMPLE_PRESSURE] = rawData[pos + MotionEvent.SAMPLE_PRESSURE];
787 reportData[pos + MotionEvent.SAMPLE_SIZE] = rawData[pos + MotionEvent.SAMPLE_SIZE];
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700788 }
789
790 int action;
791 int edgeFlags = 0;
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700792 if (nextNumPointers != lastNumPointers) {
793 if (nextNumPointers > lastNumPointers) {
794 if (lastNumPointers == 0) {
795 action = MotionEvent.ACTION_DOWN;
796 mDownTime = curTime;
797 } else {
798 action = MotionEvent.ACTION_POINTER_DOWN
Dianne Hackbornb125dc52010-02-12 15:52:09 -0800799 | (upOrDownPointer << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700800 }
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700801 } else {
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700802 if (numPointers == 1) {
803 action = MotionEvent.ACTION_UP;
804 } else {
805 action = MotionEvent.ACTION_POINTER_UP
Dianne Hackbornb125dc52010-02-12 15:52:09 -0800806 | (upOrDownPointer << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700807 }
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700808 }
809 currentMove = null;
810 } else {
811 action = MotionEvent.ACTION_MOVE;
812 }
813
814 final int dispW = display.getWidth()-1;
815 final int dispH = display.getHeight()-1;
816 int w = dispW;
817 int h = dispH;
818 if (orientation == Surface.ROTATION_90
819 || orientation == Surface.ROTATION_270) {
820 int tmp = w;
821 w = h;
822 h = tmp;
823 }
824
825 final AbsoluteInfo absX = device.absX;
826 final AbsoluteInfo absY = device.absY;
827 final AbsoluteInfo absPressure = device.absPressure;
828 final AbsoluteInfo absSize = device.absSize;
829 for (int i=0; i<numPointers; i++) {
830 final int j = i * MotionEvent.NUM_SAMPLE_DATA;
831
832 if (absX != null) {
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700833 reportData[j + MotionEvent.SAMPLE_X] =
834 ((reportData[j + MotionEvent.SAMPLE_X]-absX.minValue)
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700835 / absX.range) * w;
836 }
837 if (absY != null) {
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700838 reportData[j + MotionEvent.SAMPLE_Y] =
839 ((reportData[j + MotionEvent.SAMPLE_Y]-absY.minValue)
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700840 / absY.range) * h;
841 }
842 if (absPressure != null) {
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700843 reportData[j + MotionEvent.SAMPLE_PRESSURE] =
844 ((reportData[j + MotionEvent.SAMPLE_PRESSURE]-absPressure.minValue)
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700845 / (float)absPressure.range);
846 }
847 if (absSize != null) {
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700848 reportData[j + MotionEvent.SAMPLE_SIZE] =
849 ((reportData[j + MotionEvent.SAMPLE_SIZE]-absSize.minValue)
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700850 / (float)absSize.range);
851 }
852
853 switch (orientation) {
854 case Surface.ROTATION_90: {
Dianne Hackborn2a2b34432009-08-12 17:13:55 -0700855 final float temp = reportData[j + MotionEvent.SAMPLE_X];
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700856 reportData[j + MotionEvent.SAMPLE_X] = reportData[j + MotionEvent.SAMPLE_Y];
857 reportData[j + MotionEvent.SAMPLE_Y] = w-temp;
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700858 break;
859 }
860 case Surface.ROTATION_180: {
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700861 reportData[j + MotionEvent.SAMPLE_X] = w-reportData[j + MotionEvent.SAMPLE_X];
862 reportData[j + MotionEvent.SAMPLE_Y] = h-reportData[j + MotionEvent.SAMPLE_Y];
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700863 break;
864 }
865 case Surface.ROTATION_270: {
Dianne Hackborn2a2b34432009-08-12 17:13:55 -0700866 final float temp = reportData[j + MotionEvent.SAMPLE_X];
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700867 reportData[j + MotionEvent.SAMPLE_X] = h-reportData[j + MotionEvent.SAMPLE_Y];
868 reportData[j + MotionEvent.SAMPLE_Y] = temp;
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700869 break;
870 }
871 }
872 }
873
874 // We only consider the first pointer when computing the edge
875 // flags, since they are global to the event.
Dianne Hackbornddca3ee2009-07-23 19:01:31 -0700876 if (action == MotionEvent.ACTION_DOWN) {
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700877 if (reportData[MotionEvent.SAMPLE_X] <= 0) {
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700878 edgeFlags |= MotionEvent.EDGE_LEFT;
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700879 } else if (reportData[MotionEvent.SAMPLE_X] >= dispW) {
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700880 edgeFlags |= MotionEvent.EDGE_RIGHT;
881 }
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700882 if (reportData[MotionEvent.SAMPLE_Y] <= 0) {
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700883 edgeFlags |= MotionEvent.EDGE_TOP;
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700884 } else if (reportData[MotionEvent.SAMPLE_Y] >= dispH) {
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700885 edgeFlags |= MotionEvent.EDGE_BOTTOM;
886 }
887 }
888
889 if (currentMove != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800890 if (false) Slog.i("InputDevice", "Adding batch x="
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700891 + reportData[MotionEvent.SAMPLE_X]
892 + " y=" + reportData[MotionEvent.SAMPLE_Y]
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700893 + " to " + currentMove);
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700894 currentMove.addBatch(curTime, reportData, metaState);
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700895 if (WindowManagerPolicy.WATCH_POINTER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800896 Slog.i("KeyInputQueue", "Updating: " + currentMove);
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700897 }
898 return null;
899 }
900
901 MotionEvent me = MotionEvent.obtainNano(mDownTime, curTime,
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700902 curTimeNano, action, numPointers, mPointerIds, reportData,
903 metaState, xPrecision, yPrecision, device.id, edgeFlags);
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700904 if (action == MotionEvent.ACTION_MOVE) {
905 currentMove = me;
906 }
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700907
908 if (nextNumPointers < lastNumPointers) {
909 removeOldPointer(upOrDownPointer);
910 }
911
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700912 return me;
913 }
914
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700915 boolean hasMore() {
916 return mLastNumPointers != mNextNumPointers;
917 }
918
919 void finish() {
920 mNextNumPointers = mAddingPointerOffset = 0;
921 mNextData[MotionEvent.SAMPLE_PRESSURE] = 0;
922 }
923
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700924 MotionEvent generateRelMotion(InputDevice device, long curTime,
925 long curTimeNano, int orientation, int metaState) {
926
927 final float[] scaled = mReportData;
928
929 // For now we only support 1 pointer with relative motions.
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700930 scaled[MotionEvent.SAMPLE_X] = mNextData[MotionEvent.SAMPLE_X];
931 scaled[MotionEvent.SAMPLE_Y] = mNextData[MotionEvent.SAMPLE_Y];
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700932 scaled[MotionEvent.SAMPLE_PRESSURE] = 1.0f;
933 scaled[MotionEvent.SAMPLE_SIZE] = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800934 int edgeFlags = 0;
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700935
936 int action;
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700937 if (mNextNumPointers != mLastNumPointers) {
938 mNextData[MotionEvent.SAMPLE_X] =
939 mNextData[MotionEvent.SAMPLE_Y] = 0;
940 if (mNextNumPointers > 0 && mLastNumPointers == 0) {
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700941 action = MotionEvent.ACTION_DOWN;
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700942 mDownTime = curTime;
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700943 } else if (mNextNumPointers == 0) {
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700944 action = MotionEvent.ACTION_UP;
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700945 } else {
946 action = MotionEvent.ACTION_MOVE;
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700947 }
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700948 mLastNumPointers = mNextNumPointers;
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700949 currentMove = null;
950 } else {
951 action = MotionEvent.ACTION_MOVE;
952 }
953
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700954 scaled[MotionEvent.SAMPLE_X] *= xMoveScale;
955 scaled[MotionEvent.SAMPLE_Y] *= yMoveScale;
956 switch (orientation) {
957 case Surface.ROTATION_90: {
958 final float temp = scaled[MotionEvent.SAMPLE_X];
959 scaled[MotionEvent.SAMPLE_X] = scaled[MotionEvent.SAMPLE_Y];
960 scaled[MotionEvent.SAMPLE_Y] = -temp;
961 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800962 }
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700963 case Surface.ROTATION_180: {
964 scaled[MotionEvent.SAMPLE_X] = -scaled[MotionEvent.SAMPLE_X];
965 scaled[MotionEvent.SAMPLE_Y] = -scaled[MotionEvent.SAMPLE_Y];
966 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967 }
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700968 case Surface.ROTATION_270: {
969 final float temp = scaled[MotionEvent.SAMPLE_X];
970 scaled[MotionEvent.SAMPLE_X] = -scaled[MotionEvent.SAMPLE_Y];
971 scaled[MotionEvent.SAMPLE_Y] = temp;
972 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 }
974 }
975
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700976 if (currentMove != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800977 if (false) Slog.i("InputDevice", "Adding batch x="
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700978 + scaled[MotionEvent.SAMPLE_X]
979 + " y=" + scaled[MotionEvent.SAMPLE_Y]
980 + " to " + currentMove);
981 currentMove.addBatch(curTime, scaled, metaState);
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700982 if (WindowManagerPolicy.WATCH_POINTER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800983 Slog.i("KeyInputQueue", "Updating: " + currentMove);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 }
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700985 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800986 }
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700987
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700988 MotionEvent me = MotionEvent.obtainNano(mDownTime, curTime,
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700989 curTimeNano, action, 1, mPointerIds, scaled, metaState,
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700990 xPrecision, yPrecision, device.id, edgeFlags);
991 if (action == MotionEvent.ACTION_MOVE) {
992 currentMove = me;
993 }
994 return me;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800995 }
996 }
997
998 static class AbsoluteInfo {
999 int minValue;
1000 int maxValue;
1001 int range;
1002 int flat;
1003 int fuzz;
Dianne Hackborna2e92262010-03-02 17:19:29 -08001004
1005 final void dump(PrintWriter pw) {
1006 pw.print("minValue="); pw.print(minValue);
1007 pw.print(" maxValue="); pw.print(maxValue);
1008 pw.print(" range="); pw.print(range);
1009 pw.print(" flat="); pw.print(flat);
1010 pw.print(" fuzz="); pw.print(fuzz);
1011 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001012 };
1013
1014 InputDevice(int _id, int _classes, String _name,
1015 AbsoluteInfo _absX, AbsoluteInfo _absY,
1016 AbsoluteInfo _absPressure, AbsoluteInfo _absSize) {
1017 id = _id;
1018 classes = _classes;
1019 name = _name;
1020 absX = _absX;
1021 absY = _absY;
1022 absPressure = _absPressure;
1023 absSize = _absSize;
1024 }
1025};