blob: 42512d84832b84da8ec1bb5333961975e5bc7467 [file] [log] [blame]
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001/*
2 * Copyright (C) 2010 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
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070017#define LOG_TAG "InputReader"
18
19//#define LOG_NDEBUG 0
20
21// Log debug messages for each raw event received from the EventHub.
22#define DEBUG_RAW_EVENTS 0
23
24// Log debug messages about touch screen filtering hacks.
Jeff Brown349703e2010-06-22 01:27:15 -070025#define DEBUG_HACKS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070026
27// Log debug messages about virtual key processing.
Jeff Brown349703e2010-06-22 01:27:15 -070028#define DEBUG_VIRTUAL_KEYS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070029
30// Log debug messages about pointers.
Jeff Brown9f2106f2011-05-24 14:40:35 -070031#define DEBUG_POINTERS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070032
Jeff Brown5c225b12010-06-16 01:53:36 -070033// Log debug messages about pointer assignment calculations.
34#define DEBUG_POINTER_ASSIGNMENT 0
35
Jeff Brownace13b12011-03-09 17:39:48 -080036// Log debug messages about gesture detection.
37#define DEBUG_GESTURES 0
38
Jeff Brownb4ff35d2011-01-02 16:37:43 -080039#include "InputReader.h"
40
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070041#include <cutils/log.h>
Mathias Agopianb93a03f82012-02-17 15:34:57 -080042#include <androidfw/Keyboard.h>
43#include <androidfw/VirtualKeyMap.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070044
45#include <stddef.h>
Jeff Brown8d608662010-08-30 03:02:23 -070046#include <stdlib.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070047#include <unistd.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070048#include <errno.h>
49#include <limits.h>
Jeff Brownc5ed5912010-07-14 18:48:53 -070050#include <math.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070051
Jeff Brown8d608662010-08-30 03:02:23 -070052#define INDENT " "
Jeff Brownef3d7e82010-09-30 14:33:04 -070053#define INDENT2 " "
54#define INDENT3 " "
55#define INDENT4 " "
Jeff Brownaba321a2011-06-28 20:34:40 -070056#define INDENT5 " "
Jeff Brown8d608662010-08-30 03:02:23 -070057
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070058namespace android {
59
Jeff Brownace13b12011-03-09 17:39:48 -080060// --- Constants ---
61
Jeff Brown80fd47c2011-05-24 01:07:44 -070062// Maximum number of slots supported when using the slot-based Multitouch Protocol B.
63static const size_t MAX_SLOTS = 32;
64
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070065// --- Static Functions ---
66
67template<typename T>
68inline static T abs(const T& value) {
69 return value < 0 ? - value : value;
70}
71
72template<typename T>
73inline static T min(const T& a, const T& b) {
74 return a < b ? a : b;
75}
76
Jeff Brown5c225b12010-06-16 01:53:36 -070077template<typename T>
78inline static void swap(T& a, T& b) {
79 T temp = a;
80 a = b;
81 b = temp;
82}
83
Jeff Brown8d608662010-08-30 03:02:23 -070084inline static float avg(float x, float y) {
85 return (x + y) / 2;
86}
87
Jeff Brown2352b972011-04-12 22:39:53 -070088inline static float distance(float x1, float y1, float x2, float y2) {
89 return hypotf(x1 - x2, y1 - y2);
Jeff Brownace13b12011-03-09 17:39:48 -080090}
91
Jeff Brown517bb4c2011-01-14 19:09:23 -080092inline static int32_t signExtendNybble(int32_t value) {
93 return value >= 8 ? value - 16 : value;
94}
95
Jeff Brownef3d7e82010-09-30 14:33:04 -070096static inline const char* toString(bool value) {
97 return value ? "true" : "false";
98}
99
Jeff Brown9626b142011-03-03 02:09:54 -0800100static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation,
101 const int32_t map[][4], size_t mapSize) {
102 if (orientation != DISPLAY_ORIENTATION_0) {
103 for (size_t i = 0; i < mapSize; i++) {
104 if (value == map[i][0]) {
105 return map[i][orientation];
106 }
107 }
108 }
109 return value;
110}
111
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700112static const int32_t keyCodeRotationMap[][4] = {
113 // key codes enumerated counter-clockwise with the original (unrotated) key first
114 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
Jeff Brownfd035822010-06-30 16:10:35 -0700115 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
116 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
117 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
118 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700119};
Jeff Brown9626b142011-03-03 02:09:54 -0800120static const size_t keyCodeRotationMapSize =
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700121 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
122
Jeff Brown60691392011-07-15 19:08:26 -0700123static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brown9626b142011-03-03 02:09:54 -0800124 return rotateValueUsingRotationMap(keyCode, orientation,
125 keyCodeRotationMap, keyCodeRotationMapSize);
126}
127
Jeff Brown612891e2011-07-15 20:44:17 -0700128static void rotateDelta(int32_t orientation, float* deltaX, float* deltaY) {
129 float temp;
130 switch (orientation) {
131 case DISPLAY_ORIENTATION_90:
132 temp = *deltaX;
133 *deltaX = *deltaY;
134 *deltaY = -temp;
135 break;
136
137 case DISPLAY_ORIENTATION_180:
138 *deltaX = -*deltaX;
139 *deltaY = -*deltaY;
140 break;
141
142 case DISPLAY_ORIENTATION_270:
143 temp = *deltaX;
144 *deltaX = -*deltaY;
145 *deltaY = temp;
146 break;
147 }
148}
149
Jeff Brown6d0fec22010-07-23 21:28:06 -0700150static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
151 return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
152}
153
Jeff Brownefd32662011-03-08 15:13:06 -0800154// Returns true if the pointer should be reported as being down given the specified
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700155// button states. This determines whether the event is reported as a touch event.
156static bool isPointerDown(int32_t buttonState) {
157 return buttonState &
158 (AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY
Jeff Brown53ca3f12011-06-27 18:36:00 -0700159 | AMOTION_EVENT_BUTTON_TERTIARY);
Jeff Brownefd32662011-03-08 15:13:06 -0800160}
161
Jeff Brown2352b972011-04-12 22:39:53 -0700162static float calculateCommonVector(float a, float b) {
163 if (a > 0 && b > 0) {
164 return a < b ? a : b;
165 } else if (a < 0 && b < 0) {
166 return a > b ? a : b;
167 } else {
168 return 0;
169 }
170}
171
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700172static void synthesizeButtonKey(InputReaderContext* context, int32_t action,
173 nsecs_t when, int32_t deviceId, uint32_t source,
174 uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState,
175 int32_t buttonState, int32_t keyCode) {
176 if (
177 (action == AKEY_EVENT_ACTION_DOWN
178 && !(lastButtonState & buttonState)
179 && (currentButtonState & buttonState))
180 || (action == AKEY_EVENT_ACTION_UP
181 && (lastButtonState & buttonState)
182 && !(currentButtonState & buttonState))) {
Jeff Brownbe1aa822011-07-27 16:04:54 -0700183 NotifyKeyArgs args(when, deviceId, source, policyFlags,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700184 action, 0, keyCode, 0, context->getGlobalMetaState(), when);
Jeff Brownbe1aa822011-07-27 16:04:54 -0700185 context->getListener()->notifyKey(&args);
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700186 }
187}
188
189static void synthesizeButtonKeys(InputReaderContext* context, int32_t action,
190 nsecs_t when, int32_t deviceId, uint32_t source,
191 uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState) {
192 synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
193 lastButtonState, currentButtonState,
194 AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK);
195 synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
196 lastButtonState, currentButtonState,
197 AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD);
198}
199
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700200
Jeff Brown65fd2512011-08-18 11:20:58 -0700201// --- InputReaderConfiguration ---
202
203bool InputReaderConfiguration::getDisplayInfo(int32_t displayId, bool external,
204 int32_t* width, int32_t* height, int32_t* orientation) const {
205 if (displayId == 0) {
206 const DisplayInfo& info = external ? mExternalDisplay : mInternalDisplay;
207 if (info.width > 0 && info.height > 0) {
208 if (width) {
209 *width = info.width;
210 }
211 if (height) {
212 *height = info.height;
213 }
214 if (orientation) {
215 *orientation = info.orientation;
216 }
217 return true;
218 }
219 }
220 return false;
221}
222
223void InputReaderConfiguration::setDisplayInfo(int32_t displayId, bool external,
224 int32_t width, int32_t height, int32_t orientation) {
225 if (displayId == 0) {
226 DisplayInfo& info = external ? mExternalDisplay : mInternalDisplay;
227 info.width = width;
228 info.height = height;
229 info.orientation = orientation;
230 }
231}
232
233
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700234// --- InputReader ---
235
236InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown9c3cda02010-06-15 01:31:58 -0700237 const sp<InputReaderPolicyInterface>& policy,
Jeff Brownbe1aa822011-07-27 16:04:54 -0700238 const sp<InputListenerInterface>& listener) :
239 mContext(this), mEventHub(eventHub), mPolicy(policy),
Jeff Brown1a84fd12011-06-02 01:26:32 -0700240 mGlobalMetaState(0), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
Jeff Brown474dcb52011-06-14 20:22:50 -0700241 mConfigurationChangesToRefresh(0) {
Jeff Brownbe1aa822011-07-27 16:04:54 -0700242 mQueuedListener = new QueuedInputListener(listener);
243
244 { // acquire lock
245 AutoMutex _l(mLock);
246
247 refreshConfigurationLocked(0);
248 updateGlobalMetaStateLocked();
249 updateInputConfigurationLocked();
250 } // release lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700251}
252
253InputReader::~InputReader() {
254 for (size_t i = 0; i < mDevices.size(); i++) {
255 delete mDevices.valueAt(i);
256 }
257}
258
259void InputReader::loopOnce() {
Jeff Brownbe1aa822011-07-27 16:04:54 -0700260 int32_t timeoutMillis;
Jeff Brown474dcb52011-06-14 20:22:50 -0700261 { // acquire lock
Jeff Brownbe1aa822011-07-27 16:04:54 -0700262 AutoMutex _l(mLock);
Jeff Brown474dcb52011-06-14 20:22:50 -0700263
Jeff Brownbe1aa822011-07-27 16:04:54 -0700264 uint32_t changes = mConfigurationChangesToRefresh;
265 if (changes) {
266 mConfigurationChangesToRefresh = 0;
267 refreshConfigurationLocked(changes);
268 }
269
270 timeoutMillis = -1;
271 if (mNextTimeout != LLONG_MAX) {
272 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
273 timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
274 }
Jeff Brown474dcb52011-06-14 20:22:50 -0700275 } // release lock
276
Jeff Brownb7198742011-03-18 18:14:26 -0700277 size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
Jeff Brownbe1aa822011-07-27 16:04:54 -0700278
279 { // acquire lock
280 AutoMutex _l(mLock);
Jeff Brown112b5f52012-01-27 17:32:06 -0800281 mReaderIsAliveCondition.broadcast();
Jeff Brownbe1aa822011-07-27 16:04:54 -0700282
283 if (count) {
284 processEventsLocked(mEventBuffer, count);
285 }
286 if (!count || timeoutMillis == 0) {
287 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown112b5f52012-01-27 17:32:06 -0800288 if (now >= mNextTimeout) {
Jeff Brownaa3855d2011-03-17 01:34:19 -0700289#if DEBUG_RAW_EVENTS
Jeff Brown112b5f52012-01-27 17:32:06 -0800290 ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
Jeff Brownaa3855d2011-03-17 01:34:19 -0700291#endif
Jeff Brown112b5f52012-01-27 17:32:06 -0800292 mNextTimeout = LLONG_MAX;
293 timeoutExpiredLocked(now);
294 }
Jeff Brownbe1aa822011-07-27 16:04:54 -0700295 }
296 } // release lock
297
298 // Flush queued events out to the listener.
299 // This must happen outside of the lock because the listener could potentially call
300 // back into the InputReader's methods, such as getScanCodeState, or become blocked
301 // on another thread similarly waiting to acquire the InputReader lock thereby
302 // resulting in a deadlock. This situation is actually quite plausible because the
303 // listener is actually the input dispatcher, which calls into the window manager,
304 // which occasionally calls into the input reader.
305 mQueuedListener->flush();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700306}
307
Jeff Brownbe1aa822011-07-27 16:04:54 -0700308void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
Jeff Brownb7198742011-03-18 18:14:26 -0700309 for (const RawEvent* rawEvent = rawEvents; count;) {
310 int32_t type = rawEvent->type;
311 size_t batchSize = 1;
312 if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
313 int32_t deviceId = rawEvent->deviceId;
314 while (batchSize < count) {
315 if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
316 || rawEvent[batchSize].deviceId != deviceId) {
317 break;
318 }
319 batchSize += 1;
320 }
321#if DEBUG_RAW_EVENTS
Steve Block5baa3a62011-12-20 16:23:08 +0000322 ALOGD("BatchSize: %d Count: %d", batchSize, count);
Jeff Brownb7198742011-03-18 18:14:26 -0700323#endif
Jeff Brownbe1aa822011-07-27 16:04:54 -0700324 processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
Jeff Brownb7198742011-03-18 18:14:26 -0700325 } else {
326 switch (rawEvent->type) {
327 case EventHubInterface::DEVICE_ADDED:
Jeff Brown65fd2512011-08-18 11:20:58 -0700328 addDeviceLocked(rawEvent->when, rawEvent->deviceId);
Jeff Brownb7198742011-03-18 18:14:26 -0700329 break;
330 case EventHubInterface::DEVICE_REMOVED:
Jeff Brown65fd2512011-08-18 11:20:58 -0700331 removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
Jeff Brownb7198742011-03-18 18:14:26 -0700332 break;
333 case EventHubInterface::FINISHED_DEVICE_SCAN:
Jeff Brownbe1aa822011-07-27 16:04:54 -0700334 handleConfigurationChangedLocked(rawEvent->when);
Jeff Brownb7198742011-03-18 18:14:26 -0700335 break;
336 default:
Steve Blockec193de2012-01-09 18:35:44 +0000337 ALOG_ASSERT(false); // can't happen
Jeff Brownb7198742011-03-18 18:14:26 -0700338 break;
339 }
340 }
341 count -= batchSize;
342 rawEvent += batchSize;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700343 }
344}
345
Jeff Brown65fd2512011-08-18 11:20:58 -0700346void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
Jeff Browne38fdfa2012-04-06 14:51:01 -0700347 InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700348 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
349
Jeff Browne38fdfa2012-04-06 14:51:01 -0700350 InputDevice* device = createDeviceLocked(deviceId, identifier, classes);
Jeff Brown65fd2512011-08-18 11:20:58 -0700351 device->configure(when, &mConfig, 0);
352 device->reset(when);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700353
Jeff Brown8d608662010-08-30 03:02:23 -0700354 if (device->isIgnored()) {
Jeff Browne38fdfa2012-04-06 14:51:01 -0700355 ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
356 identifier.name.string());
Jeff Brown8d608662010-08-30 03:02:23 -0700357 } else {
Jeff Browne38fdfa2012-04-06 14:51:01 -0700358 ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,
359 identifier.name.string(), device->getSources());
Jeff Brown8d608662010-08-30 03:02:23 -0700360 }
361
Jeff Brownbe1aa822011-07-27 16:04:54 -0700362 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
363 if (deviceIndex < 0) {
364 mDevices.add(deviceId, device);
365 } else {
Steve Block8564c8d2012-01-05 23:22:43 +0000366 ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700367 delete device;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700368 return;
369 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700370}
371
Jeff Brown65fd2512011-08-18 11:20:58 -0700372void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700373 InputDevice* device = NULL;
Jeff Brownbe1aa822011-07-27 16:04:54 -0700374 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
375 if (deviceIndex >= 0) {
376 device = mDevices.valueAt(deviceIndex);
377 mDevices.removeItemsAt(deviceIndex, 1);
378 } else {
Steve Block8564c8d2012-01-05 23:22:43 +0000379 ALOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700380 return;
381 }
382
Jeff Brown6d0fec22010-07-23 21:28:06 -0700383 if (device->isIgnored()) {
Steve Block6215d3f2012-01-04 20:05:49 +0000384 ALOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700385 device->getId(), device->getName().string());
386 } else {
Steve Block6215d3f2012-01-04 20:05:49 +0000387 ALOGI("Device removed: id=%d, name='%s', sources=0x%08x",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700388 device->getId(), device->getName().string(), device->getSources());
389 }
390
Jeff Brown65fd2512011-08-18 11:20:58 -0700391 device->reset(when);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700392 delete device;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700393}
394
Jeff Brownbe1aa822011-07-27 16:04:54 -0700395InputDevice* InputReader::createDeviceLocked(int32_t deviceId,
Jeff Browne38fdfa2012-04-06 14:51:01 -0700396 const InputDeviceIdentifier& identifier, uint32_t classes) {
397 InputDevice* device = new InputDevice(&mContext, deviceId, identifier, classes);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700398
Jeff Brown56194eb2011-03-02 19:23:13 -0800399 // External devices.
400 if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
401 device->setExternal(true);
402 }
403
Jeff Brown6d0fec22010-07-23 21:28:06 -0700404 // Switch-like devices.
405 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
406 device->addMapper(new SwitchInputMapper(device));
407 }
408
409 // Keyboard-like devices.
Jeff Brownefd32662011-03-08 15:13:06 -0800410 uint32_t keyboardSource = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700411 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
412 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
Jeff Brownefd32662011-03-08 15:13:06 -0800413 keyboardSource |= AINPUT_SOURCE_KEYBOARD;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700414 }
415 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
416 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
417 }
418 if (classes & INPUT_DEVICE_CLASS_DPAD) {
Jeff Brownefd32662011-03-08 15:13:06 -0800419 keyboardSource |= AINPUT_SOURCE_DPAD;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700420 }
Jeff Browncb1404e2011-01-15 18:14:15 -0800421 if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
Jeff Brownefd32662011-03-08 15:13:06 -0800422 keyboardSource |= AINPUT_SOURCE_GAMEPAD;
Jeff Browncb1404e2011-01-15 18:14:15 -0800423 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700424
Jeff Brownefd32662011-03-08 15:13:06 -0800425 if (keyboardSource != 0) {
426 device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700427 }
428
Jeff Brown83c09682010-12-23 17:50:18 -0800429 // Cursor-like devices.
430 if (classes & INPUT_DEVICE_CLASS_CURSOR) {
431 device->addMapper(new CursorInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700432 }
433
Jeff Brown58a2da82011-01-25 16:02:22 -0800434 // Touchscreens and touchpad devices.
435 if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800436 device->addMapper(new MultiTouchInputMapper(device));
Jeff Brown58a2da82011-01-25 16:02:22 -0800437 } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800438 device->addMapper(new SingleTouchInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700439 }
440
Jeff Browncb1404e2011-01-15 18:14:15 -0800441 // Joystick-like devices.
442 if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
443 device->addMapper(new JoystickInputMapper(device));
444 }
445
Jeff Brown6d0fec22010-07-23 21:28:06 -0700446 return device;
447}
448
Jeff Brownbe1aa822011-07-27 16:04:54 -0700449void InputReader::processEventsForDeviceLocked(int32_t deviceId,
Jeff Brownb7198742011-03-18 18:14:26 -0700450 const RawEvent* rawEvents, size_t count) {
Jeff Brownbe1aa822011-07-27 16:04:54 -0700451 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
452 if (deviceIndex < 0) {
Steve Block8564c8d2012-01-05 23:22:43 +0000453 ALOGW("Discarding event for unknown deviceId %d.", deviceId);
Jeff Brownbe1aa822011-07-27 16:04:54 -0700454 return;
455 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700456
Jeff Brownbe1aa822011-07-27 16:04:54 -0700457 InputDevice* device = mDevices.valueAt(deviceIndex);
458 if (device->isIgnored()) {
Steve Block5baa3a62011-12-20 16:23:08 +0000459 //ALOGD("Discarding event for ignored deviceId %d.", deviceId);
Jeff Brownbe1aa822011-07-27 16:04:54 -0700460 return;
461 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700462
Jeff Brownbe1aa822011-07-27 16:04:54 -0700463 device->process(rawEvents, count);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700464}
465
Jeff Brownbe1aa822011-07-27 16:04:54 -0700466void InputReader::timeoutExpiredLocked(nsecs_t when) {
467 for (size_t i = 0; i < mDevices.size(); i++) {
468 InputDevice* device = mDevices.valueAt(i);
469 if (!device->isIgnored()) {
470 device->timeoutExpired(when);
Jeff Brownaa3855d2011-03-17 01:34:19 -0700471 }
Jeff Brownbe1aa822011-07-27 16:04:54 -0700472 }
Jeff Brownaa3855d2011-03-17 01:34:19 -0700473}
474
Jeff Brownbe1aa822011-07-27 16:04:54 -0700475void InputReader::handleConfigurationChangedLocked(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700476 // Reset global meta state because it depends on the list of all configured devices.
Jeff Brownbe1aa822011-07-27 16:04:54 -0700477 updateGlobalMetaStateLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700478
479 // Update input configuration.
Jeff Brownbe1aa822011-07-27 16:04:54 -0700480 updateInputConfigurationLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700481
482 // Enqueue configuration changed.
Jeff Brownbe1aa822011-07-27 16:04:54 -0700483 NotifyConfigurationChangedArgs args(when);
484 mQueuedListener->notifyConfigurationChanged(&args);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700485}
486
Jeff Brownbe1aa822011-07-27 16:04:54 -0700487void InputReader::refreshConfigurationLocked(uint32_t changes) {
Jeff Brown1a84fd12011-06-02 01:26:32 -0700488 mPolicy->getReaderConfiguration(&mConfig);
489 mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
490
Jeff Brown474dcb52011-06-14 20:22:50 -0700491 if (changes) {
Steve Block6215d3f2012-01-04 20:05:49 +0000492 ALOGI("Reconfiguring input devices. changes=0x%08x", changes);
Jeff Brown65fd2512011-08-18 11:20:58 -0700493 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown474dcb52011-06-14 20:22:50 -0700494
495 if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {
496 mEventHub->requestReopenDevices();
497 } else {
Jeff Brownbe1aa822011-07-27 16:04:54 -0700498 for (size_t i = 0; i < mDevices.size(); i++) {
499 InputDevice* device = mDevices.valueAt(i);
Jeff Brown65fd2512011-08-18 11:20:58 -0700500 device->configure(now, &mConfig, changes);
Jeff Brownbe1aa822011-07-27 16:04:54 -0700501 }
Jeff Brown474dcb52011-06-14 20:22:50 -0700502 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700503 }
504}
505
Jeff Brownbe1aa822011-07-27 16:04:54 -0700506void InputReader::updateGlobalMetaStateLocked() {
507 mGlobalMetaState = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700508
Jeff Brownbe1aa822011-07-27 16:04:54 -0700509 for (size_t i = 0; i < mDevices.size(); i++) {
510 InputDevice* device = mDevices.valueAt(i);
511 mGlobalMetaState |= device->getMetaState();
512 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700513}
514
Jeff Brownbe1aa822011-07-27 16:04:54 -0700515int32_t InputReader::getGlobalMetaStateLocked() {
516 return mGlobalMetaState;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700517}
518
Jeff Brownbe1aa822011-07-27 16:04:54 -0700519void InputReader::updateInputConfigurationLocked() {
520 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
521 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
522 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
523 InputDeviceInfo deviceInfo;
524 for (size_t i = 0; i < mDevices.size(); i++) {
525 InputDevice* device = mDevices.valueAt(i);
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700526 if (!(device->getClasses() & INPUT_DEVICE_CLASS_VIRTUAL)) {
527 device->getDeviceInfo(& deviceInfo);
528 uint32_t sources = deviceInfo.getSources();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700529
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700530 if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
531 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
532 }
533 if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
534 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
535 } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
536 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
537 }
538 if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
539 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
540 }
Jeff Brownbe1aa822011-07-27 16:04:54 -0700541 }
542 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700543
Jeff Brownbe1aa822011-07-27 16:04:54 -0700544 mInputConfiguration.touchScreen = touchScreenConfig;
545 mInputConfiguration.keyboard = keyboardConfig;
546 mInputConfiguration.navigation = navigationConfig;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700547}
548
Jeff Brownbe1aa822011-07-27 16:04:54 -0700549void InputReader::disableVirtualKeysUntilLocked(nsecs_t time) {
Jeff Brownfe508922011-01-18 15:10:10 -0800550 mDisableVirtualKeysTimeout = time;
551}
552
Jeff Brownbe1aa822011-07-27 16:04:54 -0700553bool InputReader::shouldDropVirtualKeyLocked(nsecs_t now,
Jeff Brownfe508922011-01-18 15:10:10 -0800554 InputDevice* device, int32_t keyCode, int32_t scanCode) {
555 if (now < mDisableVirtualKeysTimeout) {
Steve Block6215d3f2012-01-04 20:05:49 +0000556 ALOGI("Dropping virtual key from device %s because virtual keys are "
Jeff Brownfe508922011-01-18 15:10:10 -0800557 "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d",
558 device->getName().string(),
559 (mDisableVirtualKeysTimeout - now) * 0.000001,
560 keyCode, scanCode);
561 return true;
562 } else {
563 return false;
564 }
565}
566
Jeff Brownbe1aa822011-07-27 16:04:54 -0700567void InputReader::fadePointerLocked() {
568 for (size_t i = 0; i < mDevices.size(); i++) {
569 InputDevice* device = mDevices.valueAt(i);
570 device->fadePointer();
571 }
Jeff Brown05dc66a2011-03-02 14:41:58 -0800572}
573
Jeff Brownbe1aa822011-07-27 16:04:54 -0700574void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) {
Jeff Brownaa3855d2011-03-17 01:34:19 -0700575 if (when < mNextTimeout) {
576 mNextTimeout = when;
577 }
578}
579
Jeff Brown6d0fec22010-07-23 21:28:06 -0700580void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
Jeff Brownbe1aa822011-07-27 16:04:54 -0700581 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700582
Jeff Brownbe1aa822011-07-27 16:04:54 -0700583 *outConfiguration = mInputConfiguration;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700584}
585
586status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
Jeff Brownbe1aa822011-07-27 16:04:54 -0700587 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700588
Jeff Brownbe1aa822011-07-27 16:04:54 -0700589 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
590 if (deviceIndex < 0) {
591 return NAME_NOT_FOUND;
592 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700593
Jeff Brownbe1aa822011-07-27 16:04:54 -0700594 InputDevice* device = mDevices.valueAt(deviceIndex);
595 if (device->isIgnored()) {
596 return NAME_NOT_FOUND;
597 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700598
Jeff Brownbe1aa822011-07-27 16:04:54 -0700599 device->getDeviceInfo(outDeviceInfo);
600 return OK;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700601}
602
603void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
Jeff Brownbe1aa822011-07-27 16:04:54 -0700604 AutoMutex _l(mLock);
605
Jeff Brown6d0fec22010-07-23 21:28:06 -0700606 outDeviceIds.clear();
607
Jeff Brownbe1aa822011-07-27 16:04:54 -0700608 size_t numDevices = mDevices.size();
609 for (size_t i = 0; i < numDevices; i++) {
610 InputDevice* device = mDevices.valueAt(i);
611 if (!device->isIgnored()) {
612 outDeviceIds.add(device->getId());
Jeff Brown6d0fec22010-07-23 21:28:06 -0700613 }
Jeff Brownbe1aa822011-07-27 16:04:54 -0700614 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700615}
616
617int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
618 int32_t keyCode) {
Jeff Brownbe1aa822011-07-27 16:04:54 -0700619 AutoMutex _l(mLock);
620
621 return getStateLocked(deviceId, sourceMask, keyCode, &InputDevice::getKeyCodeState);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700622}
623
624int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
625 int32_t scanCode) {
Jeff Brownbe1aa822011-07-27 16:04:54 -0700626 AutoMutex _l(mLock);
627
628 return getStateLocked(deviceId, sourceMask, scanCode, &InputDevice::getScanCodeState);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700629}
630
631int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
Jeff Brownbe1aa822011-07-27 16:04:54 -0700632 AutoMutex _l(mLock);
633
634 return getStateLocked(deviceId, sourceMask, switchCode, &InputDevice::getSwitchState);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700635}
636
Jeff Brownbe1aa822011-07-27 16:04:54 -0700637int32_t InputReader::getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code,
Jeff Brown6d0fec22010-07-23 21:28:06 -0700638 GetStateFunc getStateFunc) {
Jeff Brownbe1aa822011-07-27 16:04:54 -0700639 int32_t result = AKEY_STATE_UNKNOWN;
640 if (deviceId >= 0) {
641 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
642 if (deviceIndex >= 0) {
643 InputDevice* device = mDevices.valueAt(deviceIndex);
644 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
645 result = (device->*getStateFunc)(sourceMask, code);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700646 }
Jeff Brownbe1aa822011-07-27 16:04:54 -0700647 }
648 } else {
649 size_t numDevices = mDevices.size();
650 for (size_t i = 0; i < numDevices; i++) {
651 InputDevice* device = mDevices.valueAt(i);
652 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
David Deephanphongsfbca5962011-11-14 14:50:45 -0800653 // If any device reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
654 // value. Otherwise, return AKEY_STATE_UP as long as one device reports it.
655 int32_t currentResult = (device->*getStateFunc)(sourceMask, code);
656 if (currentResult >= AKEY_STATE_DOWN) {
657 return currentResult;
658 } else if (currentResult == AKEY_STATE_UP) {
659 result = currentResult;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700660 }
661 }
662 }
Jeff Brownbe1aa822011-07-27 16:04:54 -0700663 }
664 return result;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700665}
666
667bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
668 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brownbe1aa822011-07-27 16:04:54 -0700669 AutoMutex _l(mLock);
670
Jeff Brown6d0fec22010-07-23 21:28:06 -0700671 memset(outFlags, 0, numCodes);
Jeff Brownbe1aa822011-07-27 16:04:54 -0700672 return markSupportedKeyCodesLocked(deviceId, sourceMask, numCodes, keyCodes, outFlags);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700673}
674
Jeff Brownbe1aa822011-07-27 16:04:54 -0700675bool InputReader::markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask,
676 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
677 bool result = false;
678 if (deviceId >= 0) {
679 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
680 if (deviceIndex >= 0) {
681 InputDevice* device = mDevices.valueAt(deviceIndex);
682 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
683 result = device->markSupportedKeyCodes(sourceMask,
684 numCodes, keyCodes, outFlags);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700685 }
686 }
Jeff Brownbe1aa822011-07-27 16:04:54 -0700687 } else {
688 size_t numDevices = mDevices.size();
689 for (size_t i = 0; i < numDevices; i++) {
690 InputDevice* device = mDevices.valueAt(i);
691 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
692 result |= device->markSupportedKeyCodes(sourceMask,
693 numCodes, keyCodes, outFlags);
694 }
695 }
696 }
697 return result;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700698}
699
Jeff Brown474dcb52011-06-14 20:22:50 -0700700void InputReader::requestRefreshConfiguration(uint32_t changes) {
Jeff Brownbe1aa822011-07-27 16:04:54 -0700701 AutoMutex _l(mLock);
Jeff Brown93fa9b32011-06-14 17:09:25 -0700702
Jeff Brownbe1aa822011-07-27 16:04:54 -0700703 if (changes) {
704 bool needWake = !mConfigurationChangesToRefresh;
705 mConfigurationChangesToRefresh |= changes;
Jeff Brown474dcb52011-06-14 20:22:50 -0700706
707 if (needWake) {
708 mEventHub->wake();
709 }
710 }
Jeff Brown1a84fd12011-06-02 01:26:32 -0700711}
712
Jeff Brownb88102f2010-09-08 11:49:43 -0700713void InputReader::dump(String8& dump) {
Jeff Brownbe1aa822011-07-27 16:04:54 -0700714 AutoMutex _l(mLock);
715
Jeff Brownf2f487182010-10-01 17:46:21 -0700716 mEventHub->dump(dump);
717 dump.append("\n");
718
719 dump.append("Input Reader State:\n");
720
Jeff Brownbe1aa822011-07-27 16:04:54 -0700721 for (size_t i = 0; i < mDevices.size(); i++) {
722 mDevices.valueAt(i)->dump(dump);
723 }
Jeff Brown214eaf42011-05-26 19:17:02 -0700724
725 dump.append(INDENT "Configuration:\n");
726 dump.append(INDENT2 "ExcludedDeviceNames: [");
727 for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
728 if (i != 0) {
729 dump.append(", ");
730 }
731 dump.append(mConfig.excludedDeviceNames.itemAt(i).string());
732 }
733 dump.append("]\n");
Jeff Brown214eaf42011-05-26 19:17:02 -0700734 dump.appendFormat(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
735 mConfig.virtualKeyQuietTime * 0.000001f);
736
Jeff Brown19c97d462011-06-01 12:33:19 -0700737 dump.appendFormat(INDENT2 "PointerVelocityControlParameters: "
738 "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
739 mConfig.pointerVelocityControlParameters.scale,
740 mConfig.pointerVelocityControlParameters.lowThreshold,
741 mConfig.pointerVelocityControlParameters.highThreshold,
742 mConfig.pointerVelocityControlParameters.acceleration);
743
744 dump.appendFormat(INDENT2 "WheelVelocityControlParameters: "
745 "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
746 mConfig.wheelVelocityControlParameters.scale,
747 mConfig.wheelVelocityControlParameters.lowThreshold,
748 mConfig.wheelVelocityControlParameters.highThreshold,
749 mConfig.wheelVelocityControlParameters.acceleration);
750
Jeff Brown214eaf42011-05-26 19:17:02 -0700751 dump.appendFormat(INDENT2 "PointerGesture:\n");
Jeff Brown474dcb52011-06-14 20:22:50 -0700752 dump.appendFormat(INDENT3 "Enabled: %s\n",
753 toString(mConfig.pointerGesturesEnabled));
Jeff Brown214eaf42011-05-26 19:17:02 -0700754 dump.appendFormat(INDENT3 "QuietInterval: %0.1fms\n",
755 mConfig.pointerGestureQuietInterval * 0.000001f);
756 dump.appendFormat(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n",
757 mConfig.pointerGestureDragMinSwitchSpeed);
758 dump.appendFormat(INDENT3 "TapInterval: %0.1fms\n",
759 mConfig.pointerGestureTapInterval * 0.000001f);
760 dump.appendFormat(INDENT3 "TapDragInterval: %0.1fms\n",
761 mConfig.pointerGestureTapDragInterval * 0.000001f);
762 dump.appendFormat(INDENT3 "TapSlop: %0.1fpx\n",
763 mConfig.pointerGestureTapSlop);
764 dump.appendFormat(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
765 mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -0700766 dump.appendFormat(INDENT3 "MultitouchMinDistance: %0.1fpx\n",
767 mConfig.pointerGestureMultitouchMinDistance);
Jeff Brown214eaf42011-05-26 19:17:02 -0700768 dump.appendFormat(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
769 mConfig.pointerGestureSwipeTransitionAngleCosine);
770 dump.appendFormat(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
771 mConfig.pointerGestureSwipeMaxWidthRatio);
772 dump.appendFormat(INDENT3 "MovementSpeedRatio: %0.1f\n",
773 mConfig.pointerGestureMovementSpeedRatio);
774 dump.appendFormat(INDENT3 "ZoomSpeedRatio: %0.1f\n",
775 mConfig.pointerGestureZoomSpeedRatio);
Jeff Brownb88102f2010-09-08 11:49:43 -0700776}
777
Jeff Brown89ef0722011-08-10 16:25:21 -0700778void InputReader::monitor() {
779 // Acquire and release the lock to ensure that the reader has not deadlocked.
780 mLock.lock();
Jeff Brown112b5f52012-01-27 17:32:06 -0800781 mEventHub->wake();
782 mReaderIsAliveCondition.wait(mLock);
Jeff Brown89ef0722011-08-10 16:25:21 -0700783 mLock.unlock();
784
785 // Check the EventHub
786 mEventHub->monitor();
787}
788
Jeff Brown6d0fec22010-07-23 21:28:06 -0700789
Jeff Brownbe1aa822011-07-27 16:04:54 -0700790// --- InputReader::ContextImpl ---
791
792InputReader::ContextImpl::ContextImpl(InputReader* reader) :
793 mReader(reader) {
794}
795
796void InputReader::ContextImpl::updateGlobalMetaState() {
797 // lock is already held by the input loop
798 mReader->updateGlobalMetaStateLocked();
799}
800
801int32_t InputReader::ContextImpl::getGlobalMetaState() {
802 // lock is already held by the input loop
803 return mReader->getGlobalMetaStateLocked();
804}
805
806void InputReader::ContextImpl::disableVirtualKeysUntil(nsecs_t time) {
807 // lock is already held by the input loop
808 mReader->disableVirtualKeysUntilLocked(time);
809}
810
811bool InputReader::ContextImpl::shouldDropVirtualKey(nsecs_t now,
812 InputDevice* device, int32_t keyCode, int32_t scanCode) {
813 // lock is already held by the input loop
814 return mReader->shouldDropVirtualKeyLocked(now, device, keyCode, scanCode);
815}
816
817void InputReader::ContextImpl::fadePointer() {
818 // lock is already held by the input loop
819 mReader->fadePointerLocked();
820}
821
822void InputReader::ContextImpl::requestTimeoutAtTime(nsecs_t when) {
823 // lock is already held by the input loop
824 mReader->requestTimeoutAtTimeLocked(when);
825}
826
827InputReaderPolicyInterface* InputReader::ContextImpl::getPolicy() {
828 return mReader->mPolicy.get();
829}
830
831InputListenerInterface* InputReader::ContextImpl::getListener() {
832 return mReader->mQueuedListener.get();
833}
834
835EventHubInterface* InputReader::ContextImpl::getEventHub() {
836 return mReader->mEventHub.get();
837}
838
839
Jeff Brown6d0fec22010-07-23 21:28:06 -0700840// --- InputReaderThread ---
841
842InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
843 Thread(/*canCallJava*/ true), mReader(reader) {
844}
845
846InputReaderThread::~InputReaderThread() {
847}
848
849bool InputReaderThread::threadLoop() {
850 mReader->loopOnce();
851 return true;
852}
853
854
855// --- InputDevice ---
856
Jeff Browne38fdfa2012-04-06 14:51:01 -0700857InputDevice::InputDevice(InputReaderContext* context, int32_t id,
858 const InputDeviceIdentifier& identifier, uint32_t classes) :
859 mContext(context), mId(id), mIdentifier(identifier), mClasses(classes),
Jeff Brown9ee285af2011-08-31 12:56:34 -0700860 mSources(0), mIsExternal(false), mDropUntilNextSync(false) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700861}
862
863InputDevice::~InputDevice() {
864 size_t numMappers = mMappers.size();
865 for (size_t i = 0; i < numMappers; i++) {
866 delete mMappers[i];
867 }
868 mMappers.clear();
869}
870
Jeff Brownef3d7e82010-09-30 14:33:04 -0700871void InputDevice::dump(String8& dump) {
872 InputDeviceInfo deviceInfo;
873 getDeviceInfo(& deviceInfo);
874
Jeff Brown90655042010-12-02 13:50:46 -0800875 dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700876 deviceInfo.getName().string());
Jeff Brown56194eb2011-03-02 19:23:13 -0800877 dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
Jeff Brownef3d7e82010-09-30 14:33:04 -0700878 dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
879 dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
Jeff Browncc0c1592011-02-19 05:07:28 -0800880
Jeff Brownefd32662011-03-08 15:13:06 -0800881 const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
Jeff Browncc0c1592011-02-19 05:07:28 -0800882 if (!ranges.isEmpty()) {
Jeff Brownef3d7e82010-09-30 14:33:04 -0700883 dump.append(INDENT2 "Motion Ranges:\n");
Jeff Browncc0c1592011-02-19 05:07:28 -0800884 for (size_t i = 0; i < ranges.size(); i++) {
Jeff Brownefd32662011-03-08 15:13:06 -0800885 const InputDeviceInfo::MotionRange& range = ranges.itemAt(i);
886 const char* label = getAxisLabel(range.axis);
Jeff Browncc0c1592011-02-19 05:07:28 -0800887 char name[32];
888 if (label) {
889 strncpy(name, label, sizeof(name));
890 name[sizeof(name) - 1] = '\0';
891 } else {
Jeff Brownefd32662011-03-08 15:13:06 -0800892 snprintf(name, sizeof(name), "%d", range.axis);
Jeff Browncc0c1592011-02-19 05:07:28 -0800893 }
Jeff Brownefd32662011-03-08 15:13:06 -0800894 dump.appendFormat(INDENT3 "%s: source=0x%08x, "
895 "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
896 name, range.source, range.min, range.max, range.flat, range.fuzz);
Jeff Browncc0c1592011-02-19 05:07:28 -0800897 }
Jeff Brownef3d7e82010-09-30 14:33:04 -0700898 }
899
900 size_t numMappers = mMappers.size();
901 for (size_t i = 0; i < numMappers; i++) {
902 InputMapper* mapper = mMappers[i];
903 mapper->dump(dump);
904 }
905}
906
Jeff Brown6d0fec22010-07-23 21:28:06 -0700907void InputDevice::addMapper(InputMapper* mapper) {
908 mMappers.add(mapper);
909}
910
Jeff Brown65fd2512011-08-18 11:20:58 -0700911void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700912 mSources = 0;
913
Jeff Brown474dcb52011-06-14 20:22:50 -0700914 if (!isIgnored()) {
915 if (!changes) { // first time only
916 mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
917 }
918
919 size_t numMappers = mMappers.size();
920 for (size_t i = 0; i < numMappers; i++) {
921 InputMapper* mapper = mMappers[i];
Jeff Brown65fd2512011-08-18 11:20:58 -0700922 mapper->configure(when, config, changes);
Jeff Brown474dcb52011-06-14 20:22:50 -0700923 mSources |= mapper->getSources();
924 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700925 }
926}
927
Jeff Brown65fd2512011-08-18 11:20:58 -0700928void InputDevice::reset(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700929 size_t numMappers = mMappers.size();
930 for (size_t i = 0; i < numMappers; i++) {
931 InputMapper* mapper = mMappers[i];
Jeff Brown65fd2512011-08-18 11:20:58 -0700932 mapper->reset(when);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700933 }
Jeff Brown65fd2512011-08-18 11:20:58 -0700934
935 mContext->updateGlobalMetaState();
936
937 notifyReset(when);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700938}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700939
Jeff Brownb7198742011-03-18 18:14:26 -0700940void InputDevice::process(const RawEvent* rawEvents, size_t count) {
941 // Process all of the events in order for each mapper.
942 // We cannot simply ask each mapper to process them in bulk because mappers may
943 // have side-effects that must be interleaved. For example, joystick movement events and
944 // gamepad button presses are handled by different mappers but they should be dispatched
945 // in the order received.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700946 size_t numMappers = mMappers.size();
Jeff Brownb7198742011-03-18 18:14:26 -0700947 for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
948#if DEBUG_RAW_EVENTS
Steve Block5baa3a62011-12-20 16:23:08 +0000949 ALOGD("Input event: device=%d type=0x%04x scancode=0x%04x "
Jeff Brown2e45fb62011-06-29 21:19:05 -0700950 "keycode=0x%04x value=0x%08x flags=0x%08x",
Jeff Brownb7198742011-03-18 18:14:26 -0700951 rawEvent->deviceId, rawEvent->type, rawEvent->scanCode, rawEvent->keyCode,
952 rawEvent->value, rawEvent->flags);
953#endif
954
Jeff Brown80fd47c2011-05-24 01:07:44 -0700955 if (mDropUntilNextSync) {
956 if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
957 mDropUntilNextSync = false;
958#if DEBUG_RAW_EVENTS
Steve Block5baa3a62011-12-20 16:23:08 +0000959 ALOGD("Recovered from input event buffer overrun.");
Jeff Brown80fd47c2011-05-24 01:07:44 -0700960#endif
961 } else {
962#if DEBUG_RAW_EVENTS
Steve Block5baa3a62011-12-20 16:23:08 +0000963 ALOGD("Dropped input event while waiting for next input sync.");
Jeff Brown80fd47c2011-05-24 01:07:44 -0700964#endif
965 }
966 } else if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_DROPPED) {
Jeff Browne38fdfa2012-04-06 14:51:01 -0700967 ALOGI("Detected input event buffer overrun for device %s.", getName().string());
Jeff Brown80fd47c2011-05-24 01:07:44 -0700968 mDropUntilNextSync = true;
Jeff Brown65fd2512011-08-18 11:20:58 -0700969 reset(rawEvent->when);
Jeff Brown80fd47c2011-05-24 01:07:44 -0700970 } else {
971 for (size_t i = 0; i < numMappers; i++) {
972 InputMapper* mapper = mMappers[i];
973 mapper->process(rawEvent);
974 }
Jeff Brownb7198742011-03-18 18:14:26 -0700975 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700976 }
977}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700978
Jeff Brownaa3855d2011-03-17 01:34:19 -0700979void InputDevice::timeoutExpired(nsecs_t when) {
980 size_t numMappers = mMappers.size();
981 for (size_t i = 0; i < numMappers; i++) {
982 InputMapper* mapper = mMappers[i];
983 mapper->timeoutExpired(when);
984 }
985}
986
Jeff Brown6d0fec22010-07-23 21:28:06 -0700987void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
Jeff Browne38fdfa2012-04-06 14:51:01 -0700988 outDeviceInfo->initialize(mId, mIdentifier.name, mIdentifier.descriptor);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700989
990 size_t numMappers = mMappers.size();
991 for (size_t i = 0; i < numMappers; i++) {
992 InputMapper* mapper = mMappers[i];
993 mapper->populateDeviceInfo(outDeviceInfo);
994 }
995}
996
997int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
998 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
999}
1000
1001int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1002 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
1003}
1004
1005int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
1006 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
1007}
1008
1009int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
1010 int32_t result = AKEY_STATE_UNKNOWN;
1011 size_t numMappers = mMappers.size();
1012 for (size_t i = 0; i < numMappers; i++) {
1013 InputMapper* mapper = mMappers[i];
1014 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
David Deephanphongsfbca5962011-11-14 14:50:45 -08001015 // If any mapper reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
1016 // value. Otherwise, return AKEY_STATE_UP as long as one mapper reports it.
1017 int32_t currentResult = (mapper->*getStateFunc)(sourceMask, code);
1018 if (currentResult >= AKEY_STATE_DOWN) {
1019 return currentResult;
1020 } else if (currentResult == AKEY_STATE_UP) {
1021 result = currentResult;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001022 }
1023 }
1024 }
1025 return result;
1026}
1027
1028bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1029 const int32_t* keyCodes, uint8_t* outFlags) {
1030 bool result = false;
1031 size_t numMappers = mMappers.size();
1032 for (size_t i = 0; i < numMappers; i++) {
1033 InputMapper* mapper = mMappers[i];
1034 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
1035 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
1036 }
1037 }
1038 return result;
1039}
1040
1041int32_t InputDevice::getMetaState() {
1042 int32_t result = 0;
1043 size_t numMappers = mMappers.size();
1044 for (size_t i = 0; i < numMappers; i++) {
1045 InputMapper* mapper = mMappers[i];
1046 result |= mapper->getMetaState();
1047 }
1048 return result;
1049}
1050
Jeff Brown05dc66a2011-03-02 14:41:58 -08001051void InputDevice::fadePointer() {
1052 size_t numMappers = mMappers.size();
1053 for (size_t i = 0; i < numMappers; i++) {
1054 InputMapper* mapper = mMappers[i];
1055 mapper->fadePointer();
1056 }
1057}
1058
Jeff Brown65fd2512011-08-18 11:20:58 -07001059void InputDevice::notifyReset(nsecs_t when) {
1060 NotifyDeviceResetArgs args(when, mId);
1061 mContext->getListener()->notifyDeviceReset(&args);
1062}
1063
Jeff Brown6d0fec22010-07-23 21:28:06 -07001064
Jeff Brown49754db2011-07-01 17:37:58 -07001065// --- CursorButtonAccumulator ---
1066
1067CursorButtonAccumulator::CursorButtonAccumulator() {
1068 clearButtons();
1069}
1070
Jeff Brown65fd2512011-08-18 11:20:58 -07001071void CursorButtonAccumulator::reset(InputDevice* device) {
1072 mBtnLeft = device->isKeyPressed(BTN_LEFT);
1073 mBtnRight = device->isKeyPressed(BTN_RIGHT);
1074 mBtnMiddle = device->isKeyPressed(BTN_MIDDLE);
1075 mBtnBack = device->isKeyPressed(BTN_BACK);
1076 mBtnSide = device->isKeyPressed(BTN_SIDE);
1077 mBtnForward = device->isKeyPressed(BTN_FORWARD);
1078 mBtnExtra = device->isKeyPressed(BTN_EXTRA);
1079 mBtnTask = device->isKeyPressed(BTN_TASK);
1080}
1081
Jeff Brown49754db2011-07-01 17:37:58 -07001082void CursorButtonAccumulator::clearButtons() {
1083 mBtnLeft = 0;
1084 mBtnRight = 0;
1085 mBtnMiddle = 0;
1086 mBtnBack = 0;
1087 mBtnSide = 0;
1088 mBtnForward = 0;
1089 mBtnExtra = 0;
1090 mBtnTask = 0;
1091}
1092
1093void CursorButtonAccumulator::process(const RawEvent* rawEvent) {
1094 if (rawEvent->type == EV_KEY) {
1095 switch (rawEvent->scanCode) {
1096 case BTN_LEFT:
1097 mBtnLeft = rawEvent->value;
1098 break;
1099 case BTN_RIGHT:
1100 mBtnRight = rawEvent->value;
1101 break;
1102 case BTN_MIDDLE:
1103 mBtnMiddle = rawEvent->value;
1104 break;
1105 case BTN_BACK:
1106 mBtnBack = rawEvent->value;
1107 break;
1108 case BTN_SIDE:
1109 mBtnSide = rawEvent->value;
1110 break;
1111 case BTN_FORWARD:
1112 mBtnForward = rawEvent->value;
1113 break;
1114 case BTN_EXTRA:
1115 mBtnExtra = rawEvent->value;
1116 break;
1117 case BTN_TASK:
1118 mBtnTask = rawEvent->value;
1119 break;
1120 }
1121 }
1122}
1123
1124uint32_t CursorButtonAccumulator::getButtonState() const {
1125 uint32_t result = 0;
1126 if (mBtnLeft) {
1127 result |= AMOTION_EVENT_BUTTON_PRIMARY;
1128 }
1129 if (mBtnRight) {
1130 result |= AMOTION_EVENT_BUTTON_SECONDARY;
1131 }
1132 if (mBtnMiddle) {
1133 result |= AMOTION_EVENT_BUTTON_TERTIARY;
1134 }
1135 if (mBtnBack || mBtnSide) {
1136 result |= AMOTION_EVENT_BUTTON_BACK;
1137 }
1138 if (mBtnForward || mBtnExtra) {
1139 result |= AMOTION_EVENT_BUTTON_FORWARD;
1140 }
1141 return result;
1142}
1143
1144
1145// --- CursorMotionAccumulator ---
1146
Jeff Brown65fd2512011-08-18 11:20:58 -07001147CursorMotionAccumulator::CursorMotionAccumulator() {
Jeff Brown49754db2011-07-01 17:37:58 -07001148 clearRelativeAxes();
1149}
1150
Jeff Brown65fd2512011-08-18 11:20:58 -07001151void CursorMotionAccumulator::reset(InputDevice* device) {
1152 clearRelativeAxes();
Jeff Brown49754db2011-07-01 17:37:58 -07001153}
1154
1155void CursorMotionAccumulator::clearRelativeAxes() {
1156 mRelX = 0;
1157 mRelY = 0;
Jeff Brown49754db2011-07-01 17:37:58 -07001158}
1159
1160void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
1161 if (rawEvent->type == EV_REL) {
1162 switch (rawEvent->scanCode) {
1163 case REL_X:
1164 mRelX = rawEvent->value;
1165 break;
1166 case REL_Y:
1167 mRelY = rawEvent->value;
1168 break;
Jeff Brown65fd2512011-08-18 11:20:58 -07001169 }
1170 }
1171}
1172
1173void CursorMotionAccumulator::finishSync() {
1174 clearRelativeAxes();
1175}
1176
1177
1178// --- CursorScrollAccumulator ---
1179
1180CursorScrollAccumulator::CursorScrollAccumulator() :
1181 mHaveRelWheel(false), mHaveRelHWheel(false) {
1182 clearRelativeAxes();
1183}
1184
1185void CursorScrollAccumulator::configure(InputDevice* device) {
1186 mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL);
1187 mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL);
1188}
1189
1190void CursorScrollAccumulator::reset(InputDevice* device) {
1191 clearRelativeAxes();
1192}
1193
1194void CursorScrollAccumulator::clearRelativeAxes() {
1195 mRelWheel = 0;
1196 mRelHWheel = 0;
1197}
1198
1199void CursorScrollAccumulator::process(const RawEvent* rawEvent) {
1200 if (rawEvent->type == EV_REL) {
1201 switch (rawEvent->scanCode) {
Jeff Brown49754db2011-07-01 17:37:58 -07001202 case REL_WHEEL:
1203 mRelWheel = rawEvent->value;
1204 break;
1205 case REL_HWHEEL:
1206 mRelHWheel = rawEvent->value;
1207 break;
1208 }
1209 }
1210}
1211
Jeff Brown65fd2512011-08-18 11:20:58 -07001212void CursorScrollAccumulator::finishSync() {
1213 clearRelativeAxes();
1214}
1215
Jeff Brown49754db2011-07-01 17:37:58 -07001216
1217// --- TouchButtonAccumulator ---
1218
1219TouchButtonAccumulator::TouchButtonAccumulator() :
1220 mHaveBtnTouch(false) {
1221 clearButtons();
1222}
1223
1224void TouchButtonAccumulator::configure(InputDevice* device) {
Jeff Brown65fd2512011-08-18 11:20:58 -07001225 mHaveBtnTouch = device->hasKey(BTN_TOUCH);
1226}
1227
1228void TouchButtonAccumulator::reset(InputDevice* device) {
1229 mBtnTouch = device->isKeyPressed(BTN_TOUCH);
1230 mBtnStylus = device->isKeyPressed(BTN_STYLUS);
1231 mBtnStylus2 = device->isKeyPressed(BTN_STYLUS);
1232 mBtnToolFinger = device->isKeyPressed(BTN_TOOL_FINGER);
1233 mBtnToolPen = device->isKeyPressed(BTN_TOOL_PEN);
1234 mBtnToolRubber = device->isKeyPressed(BTN_TOOL_RUBBER);
1235 mBtnToolBrush = device->isKeyPressed(BTN_TOOL_BRUSH);
1236 mBtnToolPencil = device->isKeyPressed(BTN_TOOL_PENCIL);
1237 mBtnToolAirbrush = device->isKeyPressed(BTN_TOOL_AIRBRUSH);
1238 mBtnToolMouse = device->isKeyPressed(BTN_TOOL_MOUSE);
1239 mBtnToolLens = device->isKeyPressed(BTN_TOOL_LENS);
Jeff Brownea6892e2011-08-23 17:31:25 -07001240 mBtnToolDoubleTap = device->isKeyPressed(BTN_TOOL_DOUBLETAP);
1241 mBtnToolTripleTap = device->isKeyPressed(BTN_TOOL_TRIPLETAP);
1242 mBtnToolQuadTap = device->isKeyPressed(BTN_TOOL_QUADTAP);
Jeff Brown49754db2011-07-01 17:37:58 -07001243}
1244
1245void TouchButtonAccumulator::clearButtons() {
1246 mBtnTouch = 0;
1247 mBtnStylus = 0;
1248 mBtnStylus2 = 0;
1249 mBtnToolFinger = 0;
1250 mBtnToolPen = 0;
1251 mBtnToolRubber = 0;
Jeff Brown65fd2512011-08-18 11:20:58 -07001252 mBtnToolBrush = 0;
1253 mBtnToolPencil = 0;
1254 mBtnToolAirbrush = 0;
1255 mBtnToolMouse = 0;
1256 mBtnToolLens = 0;
Jeff Brownea6892e2011-08-23 17:31:25 -07001257 mBtnToolDoubleTap = 0;
1258 mBtnToolTripleTap = 0;
1259 mBtnToolQuadTap = 0;
Jeff Brown49754db2011-07-01 17:37:58 -07001260}
1261
1262void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
1263 if (rawEvent->type == EV_KEY) {
1264 switch (rawEvent->scanCode) {
1265 case BTN_TOUCH:
1266 mBtnTouch = rawEvent->value;
1267 break;
1268 case BTN_STYLUS:
1269 mBtnStylus = rawEvent->value;
1270 break;
1271 case BTN_STYLUS2:
1272 mBtnStylus2 = rawEvent->value;
1273 break;
1274 case BTN_TOOL_FINGER:
1275 mBtnToolFinger = rawEvent->value;
1276 break;
1277 case BTN_TOOL_PEN:
1278 mBtnToolPen = rawEvent->value;
1279 break;
1280 case BTN_TOOL_RUBBER:
1281 mBtnToolRubber = rawEvent->value;
1282 break;
Jeff Brown65fd2512011-08-18 11:20:58 -07001283 case BTN_TOOL_BRUSH:
1284 mBtnToolBrush = rawEvent->value;
1285 break;
1286 case BTN_TOOL_PENCIL:
1287 mBtnToolPencil = rawEvent->value;
1288 break;
1289 case BTN_TOOL_AIRBRUSH:
1290 mBtnToolAirbrush = rawEvent->value;
1291 break;
1292 case BTN_TOOL_MOUSE:
1293 mBtnToolMouse = rawEvent->value;
1294 break;
1295 case BTN_TOOL_LENS:
1296 mBtnToolLens = rawEvent->value;
1297 break;
Jeff Brownea6892e2011-08-23 17:31:25 -07001298 case BTN_TOOL_DOUBLETAP:
1299 mBtnToolDoubleTap = rawEvent->value;
1300 break;
1301 case BTN_TOOL_TRIPLETAP:
1302 mBtnToolTripleTap = rawEvent->value;
1303 break;
1304 case BTN_TOOL_QUADTAP:
1305 mBtnToolQuadTap = rawEvent->value;
1306 break;
Jeff Brown49754db2011-07-01 17:37:58 -07001307 }
1308 }
1309}
1310
1311uint32_t TouchButtonAccumulator::getButtonState() const {
1312 uint32_t result = 0;
1313 if (mBtnStylus) {
1314 result |= AMOTION_EVENT_BUTTON_SECONDARY;
1315 }
1316 if (mBtnStylus2) {
1317 result |= AMOTION_EVENT_BUTTON_TERTIARY;
1318 }
1319 return result;
1320}
1321
1322int32_t TouchButtonAccumulator::getToolType() const {
Jeff Brown65fd2512011-08-18 11:20:58 -07001323 if (mBtnToolMouse || mBtnToolLens) {
1324 return AMOTION_EVENT_TOOL_TYPE_MOUSE;
1325 }
Jeff Brown49754db2011-07-01 17:37:58 -07001326 if (mBtnToolRubber) {
1327 return AMOTION_EVENT_TOOL_TYPE_ERASER;
1328 }
Jeff Brown65fd2512011-08-18 11:20:58 -07001329 if (mBtnToolPen || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush) {
Jeff Brown49754db2011-07-01 17:37:58 -07001330 return AMOTION_EVENT_TOOL_TYPE_STYLUS;
1331 }
Jeff Brownea6892e2011-08-23 17:31:25 -07001332 if (mBtnToolFinger || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap) {
Jeff Brown49754db2011-07-01 17:37:58 -07001333 return AMOTION_EVENT_TOOL_TYPE_FINGER;
1334 }
1335 return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
1336}
1337
Jeff Brownd87c6d52011-08-10 14:55:59 -07001338bool TouchButtonAccumulator::isToolActive() const {
Jeff Brown65fd2512011-08-18 11:20:58 -07001339 return mBtnTouch || mBtnToolFinger || mBtnToolPen || mBtnToolRubber
1340 || mBtnToolBrush || mBtnToolPencil || mBtnToolAirbrush
Jeff Brownea6892e2011-08-23 17:31:25 -07001341 || mBtnToolMouse || mBtnToolLens
1342 || mBtnToolDoubleTap || mBtnToolTripleTap || mBtnToolQuadTap;
Jeff Brown49754db2011-07-01 17:37:58 -07001343}
1344
1345bool TouchButtonAccumulator::isHovering() const {
1346 return mHaveBtnTouch && !mBtnTouch;
1347}
1348
1349
Jeff Brownbe1aa822011-07-27 16:04:54 -07001350// --- RawPointerAxes ---
1351
1352RawPointerAxes::RawPointerAxes() {
1353 clear();
1354}
1355
1356void RawPointerAxes::clear() {
1357 x.clear();
1358 y.clear();
1359 pressure.clear();
1360 touchMajor.clear();
1361 touchMinor.clear();
1362 toolMajor.clear();
1363 toolMinor.clear();
1364 orientation.clear();
1365 distance.clear();
Jeff Brown65fd2512011-08-18 11:20:58 -07001366 tiltX.clear();
1367 tiltY.clear();
Jeff Brownbe1aa822011-07-27 16:04:54 -07001368 trackingId.clear();
1369 slot.clear();
1370}
1371
1372
1373// --- RawPointerData ---
1374
1375RawPointerData::RawPointerData() {
1376 clear();
1377}
1378
1379void RawPointerData::clear() {
1380 pointerCount = 0;
1381 clearIdBits();
1382}
1383
1384void RawPointerData::copyFrom(const RawPointerData& other) {
1385 pointerCount = other.pointerCount;
1386 hoveringIdBits = other.hoveringIdBits;
1387 touchingIdBits = other.touchingIdBits;
1388
1389 for (uint32_t i = 0; i < pointerCount; i++) {
1390 pointers[i] = other.pointers[i];
1391
1392 int id = pointers[i].id;
1393 idToIndex[id] = other.idToIndex[id];
1394 }
1395}
1396
1397void RawPointerData::getCentroidOfTouchingPointers(float* outX, float* outY) const {
1398 float x = 0, y = 0;
1399 uint32_t count = touchingIdBits.count();
1400 if (count) {
1401 for (BitSet32 idBits(touchingIdBits); !idBits.isEmpty(); ) {
1402 uint32_t id = idBits.clearFirstMarkedBit();
1403 const Pointer& pointer = pointerForId(id);
1404 x += pointer.x;
1405 y += pointer.y;
1406 }
1407 x /= count;
1408 y /= count;
1409 }
1410 *outX = x;
1411 *outY = y;
1412}
1413
1414
1415// --- CookedPointerData ---
1416
1417CookedPointerData::CookedPointerData() {
1418 clear();
1419}
1420
1421void CookedPointerData::clear() {
1422 pointerCount = 0;
1423 hoveringIdBits.clear();
1424 touchingIdBits.clear();
1425}
1426
1427void CookedPointerData::copyFrom(const CookedPointerData& other) {
1428 pointerCount = other.pointerCount;
1429 hoveringIdBits = other.hoveringIdBits;
1430 touchingIdBits = other.touchingIdBits;
1431
1432 for (uint32_t i = 0; i < pointerCount; i++) {
1433 pointerProperties[i].copyFrom(other.pointerProperties[i]);
1434 pointerCoords[i].copyFrom(other.pointerCoords[i]);
1435
1436 int id = pointerProperties[i].id;
1437 idToIndex[id] = other.idToIndex[id];
1438 }
1439}
1440
1441
Jeff Brown49754db2011-07-01 17:37:58 -07001442// --- SingleTouchMotionAccumulator ---
1443
1444SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() {
1445 clearAbsoluteAxes();
1446}
1447
Jeff Brown65fd2512011-08-18 11:20:58 -07001448void SingleTouchMotionAccumulator::reset(InputDevice* device) {
1449 mAbsX = device->getAbsoluteAxisValue(ABS_X);
1450 mAbsY = device->getAbsoluteAxisValue(ABS_Y);
1451 mAbsPressure = device->getAbsoluteAxisValue(ABS_PRESSURE);
1452 mAbsToolWidth = device->getAbsoluteAxisValue(ABS_TOOL_WIDTH);
1453 mAbsDistance = device->getAbsoluteAxisValue(ABS_DISTANCE);
1454 mAbsTiltX = device->getAbsoluteAxisValue(ABS_TILT_X);
1455 mAbsTiltY = device->getAbsoluteAxisValue(ABS_TILT_Y);
1456}
1457
Jeff Brown49754db2011-07-01 17:37:58 -07001458void SingleTouchMotionAccumulator::clearAbsoluteAxes() {
1459 mAbsX = 0;
1460 mAbsY = 0;
1461 mAbsPressure = 0;
1462 mAbsToolWidth = 0;
1463 mAbsDistance = 0;
Jeff Brown65fd2512011-08-18 11:20:58 -07001464 mAbsTiltX = 0;
1465 mAbsTiltY = 0;
Jeff Brown49754db2011-07-01 17:37:58 -07001466}
1467
1468void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
1469 if (rawEvent->type == EV_ABS) {
1470 switch (rawEvent->scanCode) {
1471 case ABS_X:
1472 mAbsX = rawEvent->value;
1473 break;
1474 case ABS_Y:
1475 mAbsY = rawEvent->value;
1476 break;
1477 case ABS_PRESSURE:
1478 mAbsPressure = rawEvent->value;
1479 break;
1480 case ABS_TOOL_WIDTH:
1481 mAbsToolWidth = rawEvent->value;
1482 break;
1483 case ABS_DISTANCE:
1484 mAbsDistance = rawEvent->value;
1485 break;
Jeff Brown65fd2512011-08-18 11:20:58 -07001486 case ABS_TILT_X:
1487 mAbsTiltX = rawEvent->value;
1488 break;
1489 case ABS_TILT_Y:
1490 mAbsTiltY = rawEvent->value;
1491 break;
Jeff Brown49754db2011-07-01 17:37:58 -07001492 }
1493 }
1494}
1495
1496
1497// --- MultiTouchMotionAccumulator ---
1498
1499MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() :
1500 mCurrentSlot(-1), mSlots(NULL), mSlotCount(0), mUsingSlotsProtocol(false) {
1501}
1502
1503MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
1504 delete[] mSlots;
1505}
1506
1507void MultiTouchMotionAccumulator::configure(size_t slotCount, bool usingSlotsProtocol) {
1508 mSlotCount = slotCount;
1509 mUsingSlotsProtocol = usingSlotsProtocol;
1510
1511 delete[] mSlots;
1512 mSlots = new Slot[slotCount];
1513}
1514
Jeff Brown65fd2512011-08-18 11:20:58 -07001515void MultiTouchMotionAccumulator::reset(InputDevice* device) {
1516 // Unfortunately there is no way to read the initial contents of the slots.
1517 // So when we reset the accumulator, we must assume they are all zeroes.
1518 if (mUsingSlotsProtocol) {
1519 // Query the driver for the current slot index and use it as the initial slot
1520 // before we start reading events from the device. It is possible that the
1521 // current slot index will not be the same as it was when the first event was
1522 // written into the evdev buffer, which means the input mapper could start
1523 // out of sync with the initial state of the events in the evdev buffer.
1524 // In the extremely unlikely case that this happens, the data from
1525 // two slots will be confused until the next ABS_MT_SLOT event is received.
1526 // This can cause the touch point to "jump", but at least there will be
1527 // no stuck touches.
1528 int32_t initialSlot;
1529 status_t status = device->getEventHub()->getAbsoluteAxisValue(device->getId(),
1530 ABS_MT_SLOT, &initialSlot);
1531 if (status) {
Steve Block5baa3a62011-12-20 16:23:08 +00001532 ALOGD("Could not retrieve current multitouch slot index. status=%d", status);
Jeff Brown65fd2512011-08-18 11:20:58 -07001533 initialSlot = -1;
1534 }
1535 clearSlots(initialSlot);
1536 } else {
1537 clearSlots(-1);
1538 }
1539}
1540
Jeff Brown49754db2011-07-01 17:37:58 -07001541void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
Jeff Brown65fd2512011-08-18 11:20:58 -07001542 if (mSlots) {
1543 for (size_t i = 0; i < mSlotCount; i++) {
1544 mSlots[i].clear();
1545 }
Jeff Brown49754db2011-07-01 17:37:58 -07001546 }
1547 mCurrentSlot = initialSlot;
1548}
1549
1550void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
1551 if (rawEvent->type == EV_ABS) {
1552 bool newSlot = false;
1553 if (mUsingSlotsProtocol) {
1554 if (rawEvent->scanCode == ABS_MT_SLOT) {
1555 mCurrentSlot = rawEvent->value;
1556 newSlot = true;
1557 }
1558 } else if (mCurrentSlot < 0) {
1559 mCurrentSlot = 0;
1560 }
1561
1562 if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
1563#if DEBUG_POINTERS
1564 if (newSlot) {
Steve Block8564c8d2012-01-05 23:22:43 +00001565 ALOGW("MultiTouch device emitted invalid slot index %d but it "
Jeff Brown49754db2011-07-01 17:37:58 -07001566 "should be between 0 and %d; ignoring this slot.",
1567 mCurrentSlot, mSlotCount - 1);
1568 }
1569#endif
1570 } else {
1571 Slot* slot = &mSlots[mCurrentSlot];
1572
1573 switch (rawEvent->scanCode) {
1574 case ABS_MT_POSITION_X:
1575 slot->mInUse = true;
1576 slot->mAbsMTPositionX = rawEvent->value;
1577 break;
1578 case ABS_MT_POSITION_Y:
1579 slot->mInUse = true;
1580 slot->mAbsMTPositionY = rawEvent->value;
1581 break;
1582 case ABS_MT_TOUCH_MAJOR:
1583 slot->mInUse = true;
1584 slot->mAbsMTTouchMajor = rawEvent->value;
1585 break;
1586 case ABS_MT_TOUCH_MINOR:
1587 slot->mInUse = true;
1588 slot->mAbsMTTouchMinor = rawEvent->value;
1589 slot->mHaveAbsMTTouchMinor = true;
1590 break;
1591 case ABS_MT_WIDTH_MAJOR:
1592 slot->mInUse = true;
1593 slot->mAbsMTWidthMajor = rawEvent->value;
1594 break;
1595 case ABS_MT_WIDTH_MINOR:
1596 slot->mInUse = true;
1597 slot->mAbsMTWidthMinor = rawEvent->value;
1598 slot->mHaveAbsMTWidthMinor = true;
1599 break;
1600 case ABS_MT_ORIENTATION:
1601 slot->mInUse = true;
1602 slot->mAbsMTOrientation = rawEvent->value;
1603 break;
1604 case ABS_MT_TRACKING_ID:
1605 if (mUsingSlotsProtocol && rawEvent->value < 0) {
Jeff Brown8bcbbef2011-08-11 15:49:09 -07001606 // The slot is no longer in use but it retains its previous contents,
1607 // which may be reused for subsequent touches.
1608 slot->mInUse = false;
Jeff Brown49754db2011-07-01 17:37:58 -07001609 } else {
1610 slot->mInUse = true;
1611 slot->mAbsMTTrackingId = rawEvent->value;
1612 }
1613 break;
1614 case ABS_MT_PRESSURE:
1615 slot->mInUse = true;
1616 slot->mAbsMTPressure = rawEvent->value;
1617 break;
Jeff Brownbe1aa822011-07-27 16:04:54 -07001618 case ABS_MT_DISTANCE:
1619 slot->mInUse = true;
1620 slot->mAbsMTDistance = rawEvent->value;
1621 break;
Jeff Brown49754db2011-07-01 17:37:58 -07001622 case ABS_MT_TOOL_TYPE:
1623 slot->mInUse = true;
1624 slot->mAbsMTToolType = rawEvent->value;
1625 slot->mHaveAbsMTToolType = true;
1626 break;
1627 }
1628 }
1629 } else if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_MT_REPORT) {
1630 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
1631 mCurrentSlot += 1;
1632 }
1633}
1634
Jeff Brown65fd2512011-08-18 11:20:58 -07001635void MultiTouchMotionAccumulator::finishSync() {
1636 if (!mUsingSlotsProtocol) {
1637 clearSlots(-1);
1638 }
1639}
1640
Jeff Brown49754db2011-07-01 17:37:58 -07001641
1642// --- MultiTouchMotionAccumulator::Slot ---
1643
1644MultiTouchMotionAccumulator::Slot::Slot() {
1645 clear();
1646}
1647
Jeff Brown49754db2011-07-01 17:37:58 -07001648void MultiTouchMotionAccumulator::Slot::clear() {
1649 mInUse = false;
1650 mHaveAbsMTTouchMinor = false;
1651 mHaveAbsMTWidthMinor = false;
1652 mHaveAbsMTToolType = false;
1653 mAbsMTPositionX = 0;
1654 mAbsMTPositionY = 0;
1655 mAbsMTTouchMajor = 0;
1656 mAbsMTTouchMinor = 0;
1657 mAbsMTWidthMajor = 0;
1658 mAbsMTWidthMinor = 0;
1659 mAbsMTOrientation = 0;
1660 mAbsMTTrackingId = -1;
1661 mAbsMTPressure = 0;
Jeff Brown49754db2011-07-01 17:37:58 -07001662 mAbsMTDistance = 0;
Jeff Brownbe1aa822011-07-27 16:04:54 -07001663 mAbsMTToolType = 0;
Jeff Brown49754db2011-07-01 17:37:58 -07001664}
1665
1666int32_t MultiTouchMotionAccumulator::Slot::getToolType() const {
1667 if (mHaveAbsMTToolType) {
1668 switch (mAbsMTToolType) {
1669 case MT_TOOL_FINGER:
1670 return AMOTION_EVENT_TOOL_TYPE_FINGER;
1671 case MT_TOOL_PEN:
1672 return AMOTION_EVENT_TOOL_TYPE_STYLUS;
1673 }
1674 }
1675 return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
1676}
1677
1678
Jeff Brown6d0fec22010-07-23 21:28:06 -07001679// --- InputMapper ---
1680
1681InputMapper::InputMapper(InputDevice* device) :
1682 mDevice(device), mContext(device->getContext()) {
1683}
1684
1685InputMapper::~InputMapper() {
1686}
1687
1688void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1689 info->addSource(getSources());
1690}
1691
Jeff Brownef3d7e82010-09-30 14:33:04 -07001692void InputMapper::dump(String8& dump) {
1693}
1694
Jeff Brown65fd2512011-08-18 11:20:58 -07001695void InputMapper::configure(nsecs_t when,
1696 const InputReaderConfiguration* config, uint32_t changes) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001697}
1698
Jeff Brown65fd2512011-08-18 11:20:58 -07001699void InputMapper::reset(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001700}
1701
Jeff Brownaa3855d2011-03-17 01:34:19 -07001702void InputMapper::timeoutExpired(nsecs_t when) {
1703}
1704
Jeff Brown6d0fec22010-07-23 21:28:06 -07001705int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1706 return AKEY_STATE_UNKNOWN;
1707}
1708
1709int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1710 return AKEY_STATE_UNKNOWN;
1711}
1712
1713int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
1714 return AKEY_STATE_UNKNOWN;
1715}
1716
1717bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1718 const int32_t* keyCodes, uint8_t* outFlags) {
1719 return false;
1720}
1721
1722int32_t InputMapper::getMetaState() {
1723 return 0;
1724}
1725
Jeff Brown05dc66a2011-03-02 14:41:58 -08001726void InputMapper::fadePointer() {
1727}
1728
Jeff Brownbe1aa822011-07-27 16:04:54 -07001729status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo) {
1730 return getEventHub()->getAbsoluteAxisInfo(getDeviceId(), axis, axisInfo);
1731}
1732
Jeff Browncb1404e2011-01-15 18:14:15 -08001733void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
1734 const RawAbsoluteAxisInfo& axis, const char* name) {
1735 if (axis.valid) {
Jeff Brownb3a2d132011-06-12 18:14:50 -07001736 dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d, resolution=%d\n",
1737 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz, axis.resolution);
Jeff Browncb1404e2011-01-15 18:14:15 -08001738 } else {
1739 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
1740 }
1741}
1742
Jeff Brown6d0fec22010-07-23 21:28:06 -07001743
1744// --- SwitchInputMapper ---
1745
1746SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
1747 InputMapper(device) {
1748}
1749
1750SwitchInputMapper::~SwitchInputMapper() {
1751}
1752
1753uint32_t SwitchInputMapper::getSources() {
Jeff Brown89de57a2011-01-19 18:41:38 -08001754 return AINPUT_SOURCE_SWITCH;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001755}
1756
1757void SwitchInputMapper::process(const RawEvent* rawEvent) {
1758 switch (rawEvent->type) {
1759 case EV_SW:
1760 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
1761 break;
1762 }
1763}
1764
1765void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07001766 NotifySwitchArgs args(when, 0, switchCode, switchValue);
1767 getListener()->notifySwitch(&args);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001768}
1769
1770int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
1771 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
1772}
1773
1774
1775// --- KeyboardInputMapper ---
1776
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001777KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
Jeff Brownefd32662011-03-08 15:13:06 -08001778 uint32_t source, int32_t keyboardType) :
1779 InputMapper(device), mSource(source),
Jeff Brown6d0fec22010-07-23 21:28:06 -07001780 mKeyboardType(keyboardType) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001781}
1782
1783KeyboardInputMapper::~KeyboardInputMapper() {
1784}
1785
Jeff Brown6d0fec22010-07-23 21:28:06 -07001786uint32_t KeyboardInputMapper::getSources() {
Jeff Brownefd32662011-03-08 15:13:06 -08001787 return mSource;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001788}
1789
1790void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1791 InputMapper::populateDeviceInfo(info);
1792
1793 info->setKeyboardType(mKeyboardType);
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001794 info->setKeyCharacterMap(getEventHub()->getKeyCharacterMap(getDeviceId()));
Jeff Brown6d0fec22010-07-23 21:28:06 -07001795}
1796
Jeff Brownef3d7e82010-09-30 14:33:04 -07001797void KeyboardInputMapper::dump(String8& dump) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07001798 dump.append(INDENT2 "Keyboard Input Mapper:\n");
1799 dumpParameters(dump);
1800 dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
Jeff Brown65fd2512011-08-18 11:20:58 -07001801 dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
Jeff Brownbe1aa822011-07-27 16:04:54 -07001802 dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mKeyDowns.size());
1803 dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mMetaState);
1804 dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001805}
1806
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001807
Jeff Brown65fd2512011-08-18 11:20:58 -07001808void KeyboardInputMapper::configure(nsecs_t when,
1809 const InputReaderConfiguration* config, uint32_t changes) {
1810 InputMapper::configure(when, config, changes);
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001811
Jeff Brown474dcb52011-06-14 20:22:50 -07001812 if (!changes) { // first time only
1813 // Configure basic parameters.
1814 configureParameters();
Jeff Brown65fd2512011-08-18 11:20:58 -07001815 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001816
Jeff Brown65fd2512011-08-18 11:20:58 -07001817 if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
1818 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
1819 if (!config->getDisplayInfo(mParameters.associatedDisplayId,
1820 false /*external*/, NULL, NULL, &mOrientation)) {
1821 mOrientation = DISPLAY_ORIENTATION_0;
1822 }
1823 } else {
1824 mOrientation = DISPLAY_ORIENTATION_0;
1825 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001826 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001827}
1828
1829void KeyboardInputMapper::configureParameters() {
1830 mParameters.orientationAware = false;
1831 getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
1832 mParameters.orientationAware);
1833
Jeff Brownbc68a592011-07-25 12:58:12 -07001834 mParameters.associatedDisplayId = -1;
1835 if (mParameters.orientationAware) {
1836 mParameters.associatedDisplayId = 0;
1837 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001838}
1839
1840void KeyboardInputMapper::dumpParameters(String8& dump) {
1841 dump.append(INDENT3 "Parameters:\n");
1842 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1843 mParameters.associatedDisplayId);
1844 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1845 toString(mParameters.orientationAware));
1846}
1847
Jeff Brown65fd2512011-08-18 11:20:58 -07001848void KeyboardInputMapper::reset(nsecs_t when) {
1849 mMetaState = AMETA_NONE;
1850 mDownTime = 0;
1851 mKeyDowns.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001852
Jeff Brownbe1aa822011-07-27 16:04:54 -07001853 resetLedState();
1854
Jeff Brown65fd2512011-08-18 11:20:58 -07001855 InputMapper::reset(when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001856}
1857
1858void KeyboardInputMapper::process(const RawEvent* rawEvent) {
1859 switch (rawEvent->type) {
1860 case EV_KEY: {
1861 int32_t scanCode = rawEvent->scanCode;
1862 if (isKeyboardOrGamepadKey(scanCode)) {
1863 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
1864 rawEvent->flags);
1865 }
1866 break;
1867 }
1868 }
1869}
1870
1871bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
1872 return scanCode < BTN_MOUSE
1873 || scanCode >= KEY_OK
Jeff Brown9e8e40c2011-03-03 03:39:29 -08001874 || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE)
Jeff Browncb1404e2011-01-15 18:14:15 -08001875 || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001876}
1877
Jeff Brown6328cdc2010-07-29 18:18:33 -07001878void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
1879 int32_t scanCode, uint32_t policyFlags) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001880
Jeff Brownbe1aa822011-07-27 16:04:54 -07001881 if (down) {
1882 // Rotate key codes according to orientation if needed.
Jeff Brownbe1aa822011-07-27 16:04:54 -07001883 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
Jeff Brown65fd2512011-08-18 11:20:58 -07001884 keyCode = rotateKeyCode(keyCode, mOrientation);
Jeff Brownbe1aa822011-07-27 16:04:54 -07001885 }
Jeff Brownfe508922011-01-18 15:10:10 -08001886
Jeff Brownbe1aa822011-07-27 16:04:54 -07001887 // Add key down.
1888 ssize_t keyDownIndex = findKeyDown(scanCode);
1889 if (keyDownIndex >= 0) {
1890 // key repeat, be sure to use same keycode as before in case of rotation
1891 keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001892 } else {
Jeff Brownbe1aa822011-07-27 16:04:54 -07001893 // key down
1894 if ((policyFlags & POLICY_FLAG_VIRTUAL)
1895 && mContext->shouldDropVirtualKey(when,
1896 getDevice(), keyCode, scanCode)) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001897 return;
1898 }
Jeff Brownbe1aa822011-07-27 16:04:54 -07001899
1900 mKeyDowns.push();
1901 KeyDown& keyDown = mKeyDowns.editTop();
1902 keyDown.keyCode = keyCode;
1903 keyDown.scanCode = scanCode;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001904 }
1905
Jeff Brownbe1aa822011-07-27 16:04:54 -07001906 mDownTime = when;
1907 } else {
1908 // Remove key down.
1909 ssize_t keyDownIndex = findKeyDown(scanCode);
1910 if (keyDownIndex >= 0) {
1911 // key up, be sure to use same keycode as before in case of rotation
1912 keyCode = mKeyDowns.itemAt(keyDownIndex).keyCode;
1913 mKeyDowns.removeAt(size_t(keyDownIndex));
1914 } else {
1915 // key was not actually down
Steve Block6215d3f2012-01-04 20:05:49 +00001916 ALOGI("Dropping key up from device %s because the key was not down. "
Jeff Brownbe1aa822011-07-27 16:04:54 -07001917 "keyCode=%d, scanCode=%d",
1918 getDeviceName().string(), keyCode, scanCode);
1919 return;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001920 }
Jeff Brownbe1aa822011-07-27 16:04:54 -07001921 }
Jeff Brownfd035822010-06-30 16:10:35 -07001922
Jeff Brownbe1aa822011-07-27 16:04:54 -07001923 bool metaStateChanged = false;
1924 int32_t oldMetaState = mMetaState;
1925 int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);
1926 if (oldMetaState != newMetaState) {
1927 mMetaState = newMetaState;
1928 metaStateChanged = true;
1929 updateLedState(false);
1930 }
1931
1932 nsecs_t downTime = mDownTime;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001933
Jeff Brown56194eb2011-03-02 19:23:13 -08001934 // Key down on external an keyboard should wake the device.
1935 // We don't do this for internal keyboards to prevent them from waking up in your pocket.
1936 // For internal keyboards, the key layout file should specify the policy flags for
1937 // each wake key individually.
1938 // TODO: Use the input device configuration to control this behavior more finely.
1939 if (down && getDevice()->isExternal()
1940 && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) {
1941 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
1942 }
1943
Jeff Brown6328cdc2010-07-29 18:18:33 -07001944 if (metaStateChanged) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001945 getContext()->updateGlobalMetaState();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001946 }
1947
Jeff Brown05dc66a2011-03-02 14:41:58 -08001948 if (down && !isMetaKey(keyCode)) {
1949 getContext()->fadePointer();
1950 }
1951
Jeff Brownbe1aa822011-07-27 16:04:54 -07001952 NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
Jeff Brownb6997262010-10-08 22:31:17 -07001953 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
1954 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
Jeff Brownbe1aa822011-07-27 16:04:54 -07001955 getListener()->notifyKey(&args);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001956}
1957
Jeff Brownbe1aa822011-07-27 16:04:54 -07001958ssize_t KeyboardInputMapper::findKeyDown(int32_t scanCode) {
1959 size_t n = mKeyDowns.size();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001960 for (size_t i = 0; i < n; i++) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07001961 if (mKeyDowns[i].scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001962 return i;
1963 }
1964 }
1965 return -1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001966}
1967
Jeff Brown6d0fec22010-07-23 21:28:06 -07001968int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1969 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
1970}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001971
Jeff Brown6d0fec22010-07-23 21:28:06 -07001972int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1973 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1974}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001975
Jeff Brown6d0fec22010-07-23 21:28:06 -07001976bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1977 const int32_t* keyCodes, uint8_t* outFlags) {
1978 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1979}
1980
1981int32_t KeyboardInputMapper::getMetaState() {
Jeff Brownbe1aa822011-07-27 16:04:54 -07001982 return mMetaState;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001983}
1984
Jeff Brownbe1aa822011-07-27 16:04:54 -07001985void KeyboardInputMapper::resetLedState() {
1986 initializeLedState(mCapsLockLedState, LED_CAPSL);
1987 initializeLedState(mNumLockLedState, LED_NUML);
1988 initializeLedState(mScrollLockLedState, LED_SCROLLL);
Jeff Brown49ed71d2010-12-06 17:13:33 -08001989
Jeff Brownbe1aa822011-07-27 16:04:54 -07001990 updateLedState(true);
Jeff Brown49ed71d2010-12-06 17:13:33 -08001991}
1992
Jeff Brownbe1aa822011-07-27 16:04:54 -07001993void KeyboardInputMapper::initializeLedState(LedState& ledState, int32_t led) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08001994 ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
1995 ledState.on = false;
1996}
1997
Jeff Brownbe1aa822011-07-27 16:04:54 -07001998void KeyboardInputMapper::updateLedState(bool reset) {
1999 updateLedStateForModifier(mCapsLockLedState, LED_CAPSL,
Jeff Brown51e7fe72010-10-29 22:19:53 -07002000 AMETA_CAPS_LOCK_ON, reset);
Jeff Brownbe1aa822011-07-27 16:04:54 -07002001 updateLedStateForModifier(mNumLockLedState, LED_NUML,
Jeff Brown51e7fe72010-10-29 22:19:53 -07002002 AMETA_NUM_LOCK_ON, reset);
Jeff Brownbe1aa822011-07-27 16:04:54 -07002003 updateLedStateForModifier(mScrollLockLedState, LED_SCROLLL,
Jeff Brown51e7fe72010-10-29 22:19:53 -07002004 AMETA_SCROLL_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07002005}
2006
Jeff Brownbe1aa822011-07-27 16:04:54 -07002007void KeyboardInputMapper::updateLedStateForModifier(LedState& ledState,
Jeff Brown497a92c2010-09-12 17:55:08 -07002008 int32_t led, int32_t modifier, bool reset) {
2009 if (ledState.avail) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07002010 bool desiredState = (mMetaState & modifier) != 0;
Jeff Brown49ed71d2010-12-06 17:13:33 -08002011 if (reset || ledState.on != desiredState) {
Jeff Brown497a92c2010-09-12 17:55:08 -07002012 getEventHub()->setLedState(getDeviceId(), led, desiredState);
2013 ledState.on = desiredState;
2014 }
2015 }
2016}
2017
Jeff Brown6d0fec22010-07-23 21:28:06 -07002018
Jeff Brown83c09682010-12-23 17:50:18 -08002019// --- CursorInputMapper ---
Jeff Brown6d0fec22010-07-23 21:28:06 -07002020
Jeff Brown83c09682010-12-23 17:50:18 -08002021CursorInputMapper::CursorInputMapper(InputDevice* device) :
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002022 InputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002023}
2024
Jeff Brown83c09682010-12-23 17:50:18 -08002025CursorInputMapper::~CursorInputMapper() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002026}
2027
Jeff Brown83c09682010-12-23 17:50:18 -08002028uint32_t CursorInputMapper::getSources() {
Jeff Brownefd32662011-03-08 15:13:06 -08002029 return mSource;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002030}
2031
Jeff Brown83c09682010-12-23 17:50:18 -08002032void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002033 InputMapper::populateDeviceInfo(info);
2034
Jeff Brown83c09682010-12-23 17:50:18 -08002035 if (mParameters.mode == Parameters::MODE_POINTER) {
2036 float minX, minY, maxX, maxY;
2037 if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
Jeff Brownefd32662011-03-08 15:13:06 -08002038 info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f);
2039 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f);
Jeff Brown83c09682010-12-23 17:50:18 -08002040 }
2041 } else {
Jeff Brownefd32662011-03-08 15:13:06 -08002042 info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale);
2043 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale);
Jeff Brown83c09682010-12-23 17:50:18 -08002044 }
Jeff Brownefd32662011-03-08 15:13:06 -08002045 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08002046
Jeff Brown65fd2512011-08-18 11:20:58 -07002047 if (mCursorScrollAccumulator.haveRelativeVWheel()) {
Jeff Brownefd32662011-03-08 15:13:06 -08002048 info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08002049 }
Jeff Brown65fd2512011-08-18 11:20:58 -07002050 if (mCursorScrollAccumulator.haveRelativeHWheel()) {
Jeff Brownefd32662011-03-08 15:13:06 -08002051 info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08002052 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002053}
2054
Jeff Brown83c09682010-12-23 17:50:18 -08002055void CursorInputMapper::dump(String8& dump) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07002056 dump.append(INDENT2 "Cursor Input Mapper:\n");
2057 dumpParameters(dump);
2058 dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale);
2059 dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
2060 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
2061 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
2062 dump.appendFormat(INDENT3 "HaveVWheel: %s\n",
Jeff Brown65fd2512011-08-18 11:20:58 -07002063 toString(mCursorScrollAccumulator.haveRelativeVWheel()));
Jeff Brownbe1aa822011-07-27 16:04:54 -07002064 dump.appendFormat(INDENT3 "HaveHWheel: %s\n",
Jeff Brown65fd2512011-08-18 11:20:58 -07002065 toString(mCursorScrollAccumulator.haveRelativeHWheel()));
Jeff Brownbe1aa822011-07-27 16:04:54 -07002066 dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
2067 dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
Jeff Brown65fd2512011-08-18 11:20:58 -07002068 dump.appendFormat(INDENT3 "Orientation: %d\n", mOrientation);
Jeff Brownbe1aa822011-07-27 16:04:54 -07002069 dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
2070 dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
2071 dump.appendFormat(INDENT3 "DownTime: %lld\n", mDownTime);
Jeff Brownef3d7e82010-09-30 14:33:04 -07002072}
2073
Jeff Brown65fd2512011-08-18 11:20:58 -07002074void CursorInputMapper::configure(nsecs_t when,
2075 const InputReaderConfiguration* config, uint32_t changes) {
2076 InputMapper::configure(when, config, changes);
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002077
Jeff Brown474dcb52011-06-14 20:22:50 -07002078 if (!changes) { // first time only
Jeff Brown65fd2512011-08-18 11:20:58 -07002079 mCursorScrollAccumulator.configure(getDevice());
Jeff Brown49754db2011-07-01 17:37:58 -07002080
Jeff Brown474dcb52011-06-14 20:22:50 -07002081 // Configure basic parameters.
2082 configureParameters();
Jeff Brown83c09682010-12-23 17:50:18 -08002083
Jeff Brown474dcb52011-06-14 20:22:50 -07002084 // Configure device mode.
2085 switch (mParameters.mode) {
2086 case Parameters::MODE_POINTER:
2087 mSource = AINPUT_SOURCE_MOUSE;
2088 mXPrecision = 1.0f;
2089 mYPrecision = 1.0f;
2090 mXScale = 1.0f;
2091 mYScale = 1.0f;
2092 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
2093 break;
2094 case Parameters::MODE_NAVIGATION:
2095 mSource = AINPUT_SOURCE_TRACKBALL;
2096 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
2097 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
2098 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
2099 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
2100 break;
2101 }
2102
2103 mVWheelScale = 1.0f;
2104 mHWheelScale = 1.0f;
Jeff Brown83c09682010-12-23 17:50:18 -08002105 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08002106
Jeff Brown474dcb52011-06-14 20:22:50 -07002107 if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
2108 mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters);
2109 mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters);
2110 mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters);
2111 }
Jeff Brown65fd2512011-08-18 11:20:58 -07002112
2113 if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
2114 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
2115 if (!config->getDisplayInfo(mParameters.associatedDisplayId,
2116 false /*external*/, NULL, NULL, &mOrientation)) {
2117 mOrientation = DISPLAY_ORIENTATION_0;
2118 }
2119 } else {
2120 mOrientation = DISPLAY_ORIENTATION_0;
2121 }
2122 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002123}
2124
Jeff Brown83c09682010-12-23 17:50:18 -08002125void CursorInputMapper::configureParameters() {
2126 mParameters.mode = Parameters::MODE_POINTER;
2127 String8 cursorModeString;
2128 if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
2129 if (cursorModeString == "navigation") {
2130 mParameters.mode = Parameters::MODE_NAVIGATION;
2131 } else if (cursorModeString != "pointer" && cursorModeString != "default") {
Steve Block8564c8d2012-01-05 23:22:43 +00002132 ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
Jeff Brown83c09682010-12-23 17:50:18 -08002133 }
2134 }
2135
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002136 mParameters.orientationAware = false;
Jeff Brown83c09682010-12-23 17:50:18 -08002137 getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002138 mParameters.orientationAware);
2139
Jeff Brownbc68a592011-07-25 12:58:12 -07002140 mParameters.associatedDisplayId = -1;
2141 if (mParameters.mode == Parameters::MODE_POINTER || mParameters.orientationAware) {
2142 mParameters.associatedDisplayId = 0;
2143 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002144}
2145
Jeff Brown83c09682010-12-23 17:50:18 -08002146void CursorInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002147 dump.append(INDENT3 "Parameters:\n");
2148 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
2149 mParameters.associatedDisplayId);
Jeff Brown83c09682010-12-23 17:50:18 -08002150
2151 switch (mParameters.mode) {
2152 case Parameters::MODE_POINTER:
2153 dump.append(INDENT4 "Mode: pointer\n");
2154 break;
2155 case Parameters::MODE_NAVIGATION:
2156 dump.append(INDENT4 "Mode: navigation\n");
2157 break;
2158 default:
Steve Blockec193de2012-01-09 18:35:44 +00002159 ALOG_ASSERT(false);
Jeff Brown83c09682010-12-23 17:50:18 -08002160 }
2161
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002162 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
2163 toString(mParameters.orientationAware));
2164}
2165
Jeff Brown65fd2512011-08-18 11:20:58 -07002166void CursorInputMapper::reset(nsecs_t when) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07002167 mButtonState = 0;
2168 mDownTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002169
Jeff Brownbe1aa822011-07-27 16:04:54 -07002170 mPointerVelocityControl.reset();
2171 mWheelXVelocityControl.reset();
2172 mWheelYVelocityControl.reset();
Jeff Brown6328cdc2010-07-29 18:18:33 -07002173
Jeff Brown65fd2512011-08-18 11:20:58 -07002174 mCursorButtonAccumulator.reset(getDevice());
2175 mCursorMotionAccumulator.reset(getDevice());
2176 mCursorScrollAccumulator.reset(getDevice());
Jeff Brown6328cdc2010-07-29 18:18:33 -07002177
Jeff Brown65fd2512011-08-18 11:20:58 -07002178 InputMapper::reset(when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002179}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002180
Jeff Brown83c09682010-12-23 17:50:18 -08002181void CursorInputMapper::process(const RawEvent* rawEvent) {
Jeff Brown49754db2011-07-01 17:37:58 -07002182 mCursorButtonAccumulator.process(rawEvent);
2183 mCursorMotionAccumulator.process(rawEvent);
Jeff Brown65fd2512011-08-18 11:20:58 -07002184 mCursorScrollAccumulator.process(rawEvent);
Jeff Brownefd32662011-03-08 15:13:06 -08002185
Jeff Brown49754db2011-07-01 17:37:58 -07002186 if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
2187 sync(rawEvent->when);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002188 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002189}
2190
Jeff Brown83c09682010-12-23 17:50:18 -08002191void CursorInputMapper::sync(nsecs_t when) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07002192 int32_t lastButtonState = mButtonState;
2193 int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();
2194 mButtonState = currentButtonState;
2195
2196 bool wasDown = isPointerDown(lastButtonState);
2197 bool down = isPointerDown(currentButtonState);
2198 bool downChanged;
2199 if (!wasDown && down) {
2200 mDownTime = when;
2201 downChanged = true;
2202 } else if (wasDown && !down) {
2203 downChanged = true;
2204 } else {
2205 downChanged = false;
2206 }
2207 nsecs_t downTime = mDownTime;
2208 bool buttonsChanged = currentButtonState != lastButtonState;
Jeff Brownc28306a2011-08-23 21:32:42 -07002209 bool buttonsPressed = currentButtonState & ~lastButtonState;
Jeff Brownbe1aa822011-07-27 16:04:54 -07002210
2211 float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
2212 float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
2213 bool moved = deltaX != 0 || deltaY != 0;
2214
Jeff Brown65fd2512011-08-18 11:20:58 -07002215 // Rotate delta according to orientation if needed.
Jeff Brownbe1aa822011-07-27 16:04:54 -07002216 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
2217 && (deltaX != 0.0f || deltaY != 0.0f)) {
Jeff Brown65fd2512011-08-18 11:20:58 -07002218 rotateDelta(mOrientation, &deltaX, &deltaY);
Jeff Brownbe1aa822011-07-27 16:04:54 -07002219 }
2220
Jeff Brown65fd2512011-08-18 11:20:58 -07002221 // Move the pointer.
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07002222 PointerProperties pointerProperties;
Jeff Brownbe1aa822011-07-27 16:04:54 -07002223 pointerProperties.clear();
2224 pointerProperties.id = 0;
2225 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
2226
Jeff Brown6328cdc2010-07-29 18:18:33 -07002227 PointerCoords pointerCoords;
Jeff Brownbe1aa822011-07-27 16:04:54 -07002228 pointerCoords.clear();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002229
Jeff Brown65fd2512011-08-18 11:20:58 -07002230 float vscroll = mCursorScrollAccumulator.getRelativeVWheel();
2231 float hscroll = mCursorScrollAccumulator.getRelativeHWheel();
Jeff Brownbe1aa822011-07-27 16:04:54 -07002232 bool scrolled = vscroll != 0 || hscroll != 0;
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07002233
Jeff Brownbe1aa822011-07-27 16:04:54 -07002234 mWheelYVelocityControl.move(when, NULL, &vscroll);
2235 mWheelXVelocityControl.move(when, &hscroll, NULL);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002236
Jeff Brownbe1aa822011-07-27 16:04:54 -07002237 mPointerVelocityControl.move(when, &deltaX, &deltaY);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002238
Jeff Brownbe1aa822011-07-27 16:04:54 -07002239 if (mPointerController != NULL) {
2240 if (moved || scrolled || buttonsChanged) {
2241 mPointerController->setPresentation(
2242 PointerControllerInterface::PRESENTATION_POINTER);
Jeff Brown49754db2011-07-01 17:37:58 -07002243
Jeff Brownbe1aa822011-07-27 16:04:54 -07002244 if (moved) {
2245 mPointerController->move(deltaX, deltaY);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002246 }
2247
Jeff Brownbe1aa822011-07-27 16:04:54 -07002248 if (buttonsChanged) {
2249 mPointerController->setButtonState(currentButtonState);
Jeff Brown83c09682010-12-23 17:50:18 -08002250 }
Jeff Brownefd32662011-03-08 15:13:06 -08002251
Jeff Brownbe1aa822011-07-27 16:04:54 -07002252 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
Jeff Brown83c09682010-12-23 17:50:18 -08002253 }
2254
Jeff Brownbe1aa822011-07-27 16:04:54 -07002255 float x, y;
2256 mPointerController->getPosition(&x, &y);
2257 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
2258 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
2259 } else {
2260 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
2261 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
2262 }
2263
2264 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002265
Jeff Brown56194eb2011-03-02 19:23:13 -08002266 // Moving an external trackball or mouse should wake the device.
2267 // We don't do this for internal cursor devices to prevent them from waking up
2268 // the device in your pocket.
2269 // TODO: Use the input device configuration to control this behavior more finely.
2270 uint32_t policyFlags = 0;
Jeff Brownc28306a2011-08-23 21:32:42 -07002271 if ((buttonsPressed || moved || scrolled) && getDevice()->isExternal()) {
Jeff Brown56194eb2011-03-02 19:23:13 -08002272 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
2273 }
2274
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07002275 // Synthesize key down from buttons if needed.
2276 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
2277 policyFlags, lastButtonState, currentButtonState);
2278
2279 // Send motion event.
Jeff Brownbe1aa822011-07-27 16:04:54 -07002280 if (downChanged || moved || scrolled || buttonsChanged) {
2281 int32_t metaState = mContext->getGlobalMetaState();
2282 int32_t motionEventAction;
2283 if (downChanged) {
2284 motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
2285 } else if (down || mPointerController == NULL) {
2286 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
2287 } else {
2288 motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
2289 }
Jeff Brownb6997262010-10-08 22:31:17 -07002290
Jeff Brownbe1aa822011-07-27 16:04:54 -07002291 NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
2292 motionEventAction, 0, metaState, currentButtonState, 0,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07002293 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime);
Jeff Brownbe1aa822011-07-27 16:04:54 -07002294 getListener()->notifyMotion(&args);
Jeff Brown33bbfd22011-02-24 20:55:35 -08002295
Jeff Brownbe1aa822011-07-27 16:04:54 -07002296 // Send hover move after UP to tell the application that the mouse is hovering now.
2297 if (motionEventAction == AMOTION_EVENT_ACTION_UP
2298 && mPointerController != NULL) {
2299 NotifyMotionArgs hoverArgs(when, getDeviceId(), mSource, policyFlags,
2300 AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
2301 metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE,
2302 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime);
2303 getListener()->notifyMotion(&hoverArgs);
2304 }
Jeff Brown33bbfd22011-02-24 20:55:35 -08002305
Jeff Brownbe1aa822011-07-27 16:04:54 -07002306 // Send scroll events.
2307 if (scrolled) {
2308 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
2309 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
2310
2311 NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags,
2312 AMOTION_EVENT_ACTION_SCROLL, 0, metaState, currentButtonState,
2313 AMOTION_EVENT_EDGE_FLAG_NONE,
2314 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime);
2315 getListener()->notifyMotion(&scrollArgs);
2316 }
Jeff Brown33bbfd22011-02-24 20:55:35 -08002317 }
Jeff Browna032cc02011-03-07 16:56:21 -08002318
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07002319 // Synthesize key up from buttons if needed.
2320 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
2321 policyFlags, lastButtonState, currentButtonState);
2322
Jeff Brown65fd2512011-08-18 11:20:58 -07002323 mCursorMotionAccumulator.finishSync();
2324 mCursorScrollAccumulator.finishSync();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002325}
2326
Jeff Brown83c09682010-12-23 17:50:18 -08002327int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownc3fc2d02010-08-10 15:47:53 -07002328 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
2329 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
2330 } else {
2331 return AKEY_STATE_UNKNOWN;
2332 }
2333}
2334
Jeff Brown05dc66a2011-03-02 14:41:58 -08002335void CursorInputMapper::fadePointer() {
Jeff Brownbe1aa822011-07-27 16:04:54 -07002336 if (mPointerController != NULL) {
2337 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
2338 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08002339}
2340
Jeff Brown6d0fec22010-07-23 21:28:06 -07002341
2342// --- TouchInputMapper ---
2343
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002344TouchInputMapper::TouchInputMapper(InputDevice* device) :
Jeff Brownbe1aa822011-07-27 16:04:54 -07002345 InputMapper(device),
Jeff Brown65fd2512011-08-18 11:20:58 -07002346 mSource(0), mDeviceMode(DEVICE_MODE_DISABLED),
Jeff Brownbe1aa822011-07-27 16:04:54 -07002347 mSurfaceOrientation(-1), mSurfaceWidth(-1), mSurfaceHeight(-1) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002348}
2349
2350TouchInputMapper::~TouchInputMapper() {
2351}
2352
2353uint32_t TouchInputMapper::getSources() {
Jeff Brown65fd2512011-08-18 11:20:58 -07002354 return mSource;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002355}
2356
2357void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
2358 InputMapper::populateDeviceInfo(info);
2359
Jeff Brown65fd2512011-08-18 11:20:58 -07002360 if (mDeviceMode != DEVICE_MODE_DISABLED) {
2361 info->addMotionRange(mOrientedRanges.x);
2362 info->addMotionRange(mOrientedRanges.y);
Jeff Brownbe1aa822011-07-27 16:04:54 -07002363 info->addMotionRange(mOrientedRanges.pressure);
Jeff Brownbe1aa822011-07-27 16:04:54 -07002364
Jeff Brown65fd2512011-08-18 11:20:58 -07002365 if (mOrientedRanges.haveSize) {
2366 info->addMotionRange(mOrientedRanges.size);
Jeff Brownefd32662011-03-08 15:13:06 -08002367 }
Jeff Brown65fd2512011-08-18 11:20:58 -07002368
2369 if (mOrientedRanges.haveTouchSize) {
2370 info->addMotionRange(mOrientedRanges.touchMajor);
2371 info->addMotionRange(mOrientedRanges.touchMinor);
2372 }
2373
2374 if (mOrientedRanges.haveToolSize) {
2375 info->addMotionRange(mOrientedRanges.toolMajor);
2376 info->addMotionRange(mOrientedRanges.toolMinor);
2377 }
2378
2379 if (mOrientedRanges.haveOrientation) {
2380 info->addMotionRange(mOrientedRanges.orientation);
2381 }
2382
2383 if (mOrientedRanges.haveDistance) {
2384 info->addMotionRange(mOrientedRanges.distance);
2385 }
2386
2387 if (mOrientedRanges.haveTilt) {
2388 info->addMotionRange(mOrientedRanges.tilt);
2389 }
2390
2391 if (mCursorScrollAccumulator.haveRelativeVWheel()) {
2392 info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
2393 }
2394 if (mCursorScrollAccumulator.haveRelativeHWheel()) {
2395 info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
2396 }
Jeff Brownbe1aa822011-07-27 16:04:54 -07002397 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002398}
2399
Jeff Brownef3d7e82010-09-30 14:33:04 -07002400void TouchInputMapper::dump(String8& dump) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07002401 dump.append(INDENT2 "Touch Input Mapper:\n");
2402 dumpParameters(dump);
2403 dumpVirtualKeys(dump);
2404 dumpRawPointerAxes(dump);
2405 dumpCalibration(dump);
2406 dumpSurface(dump);
Jeff Brownefd32662011-03-08 15:13:06 -08002407
Jeff Brownbe1aa822011-07-27 16:04:54 -07002408 dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
2409 dump.appendFormat(INDENT4 "XScale: %0.3f\n", mXScale);
2410 dump.appendFormat(INDENT4 "YScale: %0.3f\n", mYScale);
2411 dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mXPrecision);
2412 dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mYPrecision);
2413 dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mGeometricScale);
Jeff Brownbe1aa822011-07-27 16:04:54 -07002414 dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mPressureScale);
2415 dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mSizeScale);
Jeff Brown65fd2512011-08-18 11:20:58 -07002416 dump.appendFormat(INDENT4 "OrientationCenter: %0.3f\n", mOrientationCenter);
Jeff Brownbe1aa822011-07-27 16:04:54 -07002417 dump.appendFormat(INDENT4 "OrientationScale: %0.3f\n", mOrientationScale);
2418 dump.appendFormat(INDENT4 "DistanceScale: %0.3f\n", mDistanceScale);
Jeff Brown65fd2512011-08-18 11:20:58 -07002419 dump.appendFormat(INDENT4 "HaveTilt: %s\n", toString(mHaveTilt));
2420 dump.appendFormat(INDENT4 "TiltXCenter: %0.3f\n", mTiltXCenter);
2421 dump.appendFormat(INDENT4 "TiltXScale: %0.3f\n", mTiltXScale);
2422 dump.appendFormat(INDENT4 "TiltYCenter: %0.3f\n", mTiltYCenter);
2423 dump.appendFormat(INDENT4 "TiltYScale: %0.3f\n", mTiltYScale);
Jeff Brownefd32662011-03-08 15:13:06 -08002424
Jeff Brownbe1aa822011-07-27 16:04:54 -07002425 dump.appendFormat(INDENT3 "Last Button State: 0x%08x\n", mLastButtonState);
Jeff Brownace13b12011-03-09 17:39:48 -08002426
Jeff Brownbe1aa822011-07-27 16:04:54 -07002427 dump.appendFormat(INDENT3 "Last Raw Touch: pointerCount=%d\n",
2428 mLastRawPointerData.pointerCount);
2429 for (uint32_t i = 0; i < mLastRawPointerData.pointerCount; i++) {
2430 const RawPointerData::Pointer& pointer = mLastRawPointerData.pointers[i];
2431 dump.appendFormat(INDENT4 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
2432 "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
Jeff Brown65fd2512011-08-18 11:20:58 -07002433 "orientation=%d, tiltX=%d, tiltY=%d, distance=%d, "
2434 "toolType=%d, isHovering=%s\n", i,
Jeff Brownbe1aa822011-07-27 16:04:54 -07002435 pointer.id, pointer.x, pointer.y, pointer.pressure,
2436 pointer.touchMajor, pointer.touchMinor,
2437 pointer.toolMajor, pointer.toolMinor,
Jeff Brown65fd2512011-08-18 11:20:58 -07002438 pointer.orientation, pointer.tiltX, pointer.tiltY, pointer.distance,
Jeff Brownbe1aa822011-07-27 16:04:54 -07002439 pointer.toolType, toString(pointer.isHovering));
2440 }
2441
2442 dump.appendFormat(INDENT3 "Last Cooked Touch: pointerCount=%d\n",
2443 mLastCookedPointerData.pointerCount);
2444 for (uint32_t i = 0; i < mLastCookedPointerData.pointerCount; i++) {
2445 const PointerProperties& pointerProperties = mLastCookedPointerData.pointerProperties[i];
2446 const PointerCoords& pointerCoords = mLastCookedPointerData.pointerCoords[i];
2447 dump.appendFormat(INDENT4 "[%d]: id=%d, x=%0.3f, y=%0.3f, pressure=%0.3f, "
2448 "touchMajor=%0.3f, touchMinor=%0.3f, toolMajor=%0.3f, toolMinor=%0.3f, "
Jeff Brown65fd2512011-08-18 11:20:58 -07002449 "orientation=%0.3f, tilt=%0.3f, distance=%0.3f, "
2450 "toolType=%d, isHovering=%s\n", i,
Jeff Brownbe1aa822011-07-27 16:04:54 -07002451 pointerProperties.id,
2452 pointerCoords.getX(),
2453 pointerCoords.getY(),
2454 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
2455 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
2456 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
2457 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
2458 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
2459 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION),
Jeff Brown65fd2512011-08-18 11:20:58 -07002460 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_TILT),
Jeff Brownbe1aa822011-07-27 16:04:54 -07002461 pointerCoords.getAxisValue(AMOTION_EVENT_AXIS_DISTANCE),
2462 pointerProperties.toolType,
2463 toString(mLastCookedPointerData.isHovering(i)));
2464 }
2465
Jeff Brown65fd2512011-08-18 11:20:58 -07002466 if (mDeviceMode == DEVICE_MODE_POINTER) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07002467 dump.appendFormat(INDENT3 "Pointer Gesture Detector:\n");
2468 dump.appendFormat(INDENT4 "XMovementScale: %0.3f\n",
Jeff Brown65fd2512011-08-18 11:20:58 -07002469 mPointerXMovementScale);
Jeff Brownbe1aa822011-07-27 16:04:54 -07002470 dump.appendFormat(INDENT4 "YMovementScale: %0.3f\n",
Jeff Brown65fd2512011-08-18 11:20:58 -07002471 mPointerYMovementScale);
Jeff Brownbe1aa822011-07-27 16:04:54 -07002472 dump.appendFormat(INDENT4 "XZoomScale: %0.3f\n",
Jeff Brown65fd2512011-08-18 11:20:58 -07002473 mPointerXZoomScale);
Jeff Brownbe1aa822011-07-27 16:04:54 -07002474 dump.appendFormat(INDENT4 "YZoomScale: %0.3f\n",
Jeff Brown65fd2512011-08-18 11:20:58 -07002475 mPointerYZoomScale);
Jeff Brownbe1aa822011-07-27 16:04:54 -07002476 dump.appendFormat(INDENT4 "MaxSwipeWidth: %f\n",
2477 mPointerGestureMaxSwipeWidth);
2478 }
Jeff Brownef3d7e82010-09-30 14:33:04 -07002479}
2480
Jeff Brown65fd2512011-08-18 11:20:58 -07002481void TouchInputMapper::configure(nsecs_t when,
2482 const InputReaderConfiguration* config, uint32_t changes) {
2483 InputMapper::configure(when, config, changes);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002484
Jeff Brown474dcb52011-06-14 20:22:50 -07002485 mConfig = *config;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002486
Jeff Brown474dcb52011-06-14 20:22:50 -07002487 if (!changes) { // first time only
2488 // Configure basic parameters.
2489 configureParameters();
2490
Jeff Brown65fd2512011-08-18 11:20:58 -07002491 // Configure common accumulators.
2492 mCursorScrollAccumulator.configure(getDevice());
2493 mTouchButtonAccumulator.configure(getDevice());
Jeff Brown474dcb52011-06-14 20:22:50 -07002494
2495 // Configure absolute axis information.
Jeff Brownbe1aa822011-07-27 16:04:54 -07002496 configureRawPointerAxes();
Jeff Brown474dcb52011-06-14 20:22:50 -07002497
2498 // Prepare input device calibration.
2499 parseCalibration();
2500 resolveCalibration();
Jeff Brown83c09682010-12-23 17:50:18 -08002501 }
2502
Jeff Brown474dcb52011-06-14 20:22:50 -07002503 if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
Jeff Brown65fd2512011-08-18 11:20:58 -07002504 // Update pointer speed.
2505 mPointerVelocityControl.setParameters(mConfig.pointerVelocityControlParameters);
2506 mWheelXVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
2507 mWheelYVelocityControl.setParameters(mConfig.wheelVelocityControlParameters);
Jeff Brown474dcb52011-06-14 20:22:50 -07002508 }
Jeff Brown8d608662010-08-30 03:02:23 -07002509
Jeff Brown65fd2512011-08-18 11:20:58 -07002510 bool resetNeeded = false;
2511 if (!changes || (changes & (InputReaderConfiguration::CHANGE_DISPLAY_INFO
Jeff Browndaf4a122011-08-26 17:14:14 -07002512 | InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT
2513 | InputReaderConfiguration::CHANGE_SHOW_TOUCHES))) {
Jeff Brown65fd2512011-08-18 11:20:58 -07002514 // Configure device sources, surface dimensions, orientation and
2515 // scaling factors.
2516 configureSurface(when, &resetNeeded);
2517 }
2518
2519 if (changes && resetNeeded) {
2520 // Send reset, unless this is the first time the device has been configured,
2521 // in which case the reader will call reset itself after all mappers are ready.
2522 getDevice()->notifyReset(when);
Jeff Brown474dcb52011-06-14 20:22:50 -07002523 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002524}
2525
Jeff Brown8d608662010-08-30 03:02:23 -07002526void TouchInputMapper::configureParameters() {
Jeff Brownb1268222011-06-03 17:06:16 -07002527 // Use the pointer presentation mode for devices that do not support distinct
2528 // multitouch. The spot-based presentation relies on being able to accurately
2529 // locate two or more fingers on the touch pad.
2530 mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT)
2531 ? Parameters::GESTURE_MODE_POINTER : Parameters::GESTURE_MODE_SPOTS;
Jeff Brown2352b972011-04-12 22:39:53 -07002532
Jeff Brown538881e2011-05-25 18:23:38 -07002533 String8 gestureModeString;
2534 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
2535 gestureModeString)) {
2536 if (gestureModeString == "pointer") {
2537 mParameters.gestureMode = Parameters::GESTURE_MODE_POINTER;
2538 } else if (gestureModeString == "spots") {
2539 mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS;
2540 } else if (gestureModeString != "default") {
Steve Block8564c8d2012-01-05 23:22:43 +00002541 ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
Jeff Brown538881e2011-05-25 18:23:38 -07002542 }
2543 }
2544
Jeff Browndeffe072011-08-26 18:38:46 -07002545 if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) {
2546 // The device is a touch screen.
2547 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
2548 } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_POINTER)) {
2549 // The device is a pointing device like a track pad.
2550 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
2551 } else if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X)
Jeff Brownace13b12011-03-09 17:39:48 -08002552 || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
2553 // The device is a cursor device with a touch pad attached.
2554 // By default don't use the touch pad to move the pointer.
2555 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
2556 } else {
Jeff Brown80fd47c2011-05-24 01:07:44 -07002557 // The device is a touch pad of unknown purpose.
Jeff Brownace13b12011-03-09 17:39:48 -08002558 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
2559 }
2560
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002561 String8 deviceTypeString;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002562 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
2563 deviceTypeString)) {
Jeff Brown58a2da82011-01-25 16:02:22 -08002564 if (deviceTypeString == "touchScreen") {
2565 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
Jeff Brownefd32662011-03-08 15:13:06 -08002566 } else if (deviceTypeString == "touchPad") {
2567 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
Jeff Brownace13b12011-03-09 17:39:48 -08002568 } else if (deviceTypeString == "pointer") {
2569 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
Jeff Brown538881e2011-05-25 18:23:38 -07002570 } else if (deviceTypeString != "default") {
Steve Block8564c8d2012-01-05 23:22:43 +00002571 ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002572 }
2573 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002574
Jeff Brownefd32662011-03-08 15:13:06 -08002575 mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002576 getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
2577 mParameters.orientationAware);
2578
Jeff Brownbc68a592011-07-25 12:58:12 -07002579 mParameters.associatedDisplayId = -1;
2580 mParameters.associatedDisplayIsExternal = false;
2581 if (mParameters.orientationAware
Jeff Brownefd32662011-03-08 15:13:06 -08002582 || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
Jeff Brownbc68a592011-07-25 12:58:12 -07002583 || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
2584 mParameters.associatedDisplayIsExternal =
2585 mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
2586 && getDevice()->isExternal();
2587 mParameters.associatedDisplayId = 0;
2588 }
Jeff Brown8d608662010-08-30 03:02:23 -07002589}
2590
Jeff Brownef3d7e82010-09-30 14:33:04 -07002591void TouchInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002592 dump.append(INDENT3 "Parameters:\n");
2593
Jeff Brown538881e2011-05-25 18:23:38 -07002594 switch (mParameters.gestureMode) {
2595 case Parameters::GESTURE_MODE_POINTER:
2596 dump.append(INDENT4 "GestureMode: pointer\n");
2597 break;
2598 case Parameters::GESTURE_MODE_SPOTS:
2599 dump.append(INDENT4 "GestureMode: spots\n");
2600 break;
2601 default:
2602 assert(false);
2603 }
2604
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002605 switch (mParameters.deviceType) {
2606 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
2607 dump.append(INDENT4 "DeviceType: touchScreen\n");
2608 break;
2609 case Parameters::DEVICE_TYPE_TOUCH_PAD:
2610 dump.append(INDENT4 "DeviceType: touchPad\n");
2611 break;
Jeff Brownace13b12011-03-09 17:39:48 -08002612 case Parameters::DEVICE_TYPE_POINTER:
2613 dump.append(INDENT4 "DeviceType: pointer\n");
2614 break;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002615 default:
Steve Blockec193de2012-01-09 18:35:44 +00002616 ALOG_ASSERT(false);
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002617 }
2618
Jeff Brown65fd2512011-08-18 11:20:58 -07002619 dump.appendFormat(INDENT4 "AssociatedDisplay: id=%d, isExternal=%s\n",
2620 mParameters.associatedDisplayId, toString(mParameters.associatedDisplayIsExternal));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002621 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
2622 toString(mParameters.orientationAware));
Jeff Brownb88102f2010-09-08 11:49:43 -07002623}
2624
Jeff Brownbe1aa822011-07-27 16:04:54 -07002625void TouchInputMapper::configureRawPointerAxes() {
2626 mRawPointerAxes.clear();
Jeff Brown8d608662010-08-30 03:02:23 -07002627}
2628
Jeff Brownbe1aa822011-07-27 16:04:54 -07002629void TouchInputMapper::dumpRawPointerAxes(String8& dump) {
2630 dump.append(INDENT3 "Raw Touch Axes:\n");
2631 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.x, "X");
2632 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.y, "Y");
2633 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.pressure, "Pressure");
2634 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMajor, "TouchMajor");
2635 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.touchMinor, "TouchMinor");
2636 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMajor, "ToolMajor");
2637 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.toolMinor, "ToolMinor");
2638 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.orientation, "Orientation");
2639 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.distance, "Distance");
Jeff Brown65fd2512011-08-18 11:20:58 -07002640 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltX, "TiltX");
2641 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.tiltY, "TiltY");
Jeff Brownbe1aa822011-07-27 16:04:54 -07002642 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.trackingId, "TrackingId");
2643 dumpRawAbsoluteAxisInfo(dump, mRawPointerAxes.slot, "Slot");
Jeff Brown6d0fec22010-07-23 21:28:06 -07002644}
2645
Jeff Brown65fd2512011-08-18 11:20:58 -07002646void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
2647 int32_t oldDeviceMode = mDeviceMode;
2648
2649 // Determine device mode.
2650 if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
2651 && mConfig.pointerGesturesEnabled) {
2652 mSource = AINPUT_SOURCE_MOUSE;
2653 mDeviceMode = DEVICE_MODE_POINTER;
2654 } else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
2655 && mParameters.associatedDisplayId >= 0) {
2656 mSource = AINPUT_SOURCE_TOUCHSCREEN;
2657 mDeviceMode = DEVICE_MODE_DIRECT;
2658 } else {
2659 mSource = AINPUT_SOURCE_TOUCHPAD;
2660 mDeviceMode = DEVICE_MODE_UNSCALED;
2661 }
2662
Jeff Brown9626b142011-03-03 02:09:54 -08002663 // Ensure we have valid X and Y axes.
Jeff Brownbe1aa822011-07-27 16:04:54 -07002664 if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
Steve Block8564c8d2012-01-05 23:22:43 +00002665 ALOGW(INDENT "Touch device '%s' did not report support for X or Y axis! "
Jeff Brown9626b142011-03-03 02:09:54 -08002666 "The device will be inoperable.", getDeviceName().string());
Jeff Brown65fd2512011-08-18 11:20:58 -07002667 mDeviceMode = DEVICE_MODE_DISABLED;
2668 return;
Jeff Brown9626b142011-03-03 02:09:54 -08002669 }
2670
Jeff Brown65fd2512011-08-18 11:20:58 -07002671 // Get associated display dimensions.
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002672 if (mParameters.associatedDisplayId >= 0) {
Jeff Brown65fd2512011-08-18 11:20:58 -07002673 if (!mConfig.getDisplayInfo(mParameters.associatedDisplayId,
Jeff Brownbc68a592011-07-25 12:58:12 -07002674 mParameters.associatedDisplayIsExternal,
Jeff Brownbe1aa822011-07-27 16:04:54 -07002675 &mAssociatedDisplayWidth, &mAssociatedDisplayHeight,
2676 &mAssociatedDisplayOrientation)) {
Steve Block6215d3f2012-01-04 20:05:49 +00002677 ALOGI(INDENT "Touch device '%s' could not query the properties of its associated "
Jeff Brown65fd2512011-08-18 11:20:58 -07002678 "display %d. The device will be inoperable until the display size "
2679 "becomes available.",
2680 getDeviceName().string(), mParameters.associatedDisplayId);
2681 mDeviceMode = DEVICE_MODE_DISABLED;
2682 return;
Jeff Brownefd32662011-03-08 15:13:06 -08002683 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002684 }
2685
Jeff Brown65fd2512011-08-18 11:20:58 -07002686 // Configure dimensions.
2687 int32_t width, height, orientation;
2688 if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) {
2689 width = mAssociatedDisplayWidth;
2690 height = mAssociatedDisplayHeight;
2691 orientation = mParameters.orientationAware ?
2692 mAssociatedDisplayOrientation : DISPLAY_ORIENTATION_0;
2693 } else {
2694 width = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
2695 height = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
2696 orientation = DISPLAY_ORIENTATION_0;
2697 }
2698
2699 // If moving between pointer modes, need to reset some state.
2700 bool deviceModeChanged;
2701 if (mDeviceMode != oldDeviceMode) {
2702 deviceModeChanged = true;
Jeff Brown65fd2512011-08-18 11:20:58 -07002703 mOrientedRanges.clear();
Jeff Brownace13b12011-03-09 17:39:48 -08002704 }
2705
Jeff Browndaf4a122011-08-26 17:14:14 -07002706 // Create pointer controller if needed.
2707 if (mDeviceMode == DEVICE_MODE_POINTER ||
2708 (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
2709 if (mPointerController == NULL) {
2710 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
2711 }
2712 } else {
2713 mPointerController.clear();
2714 }
2715
Jeff Brownbe1aa822011-07-27 16:04:54 -07002716 bool orientationChanged = mSurfaceOrientation != orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002717 if (orientationChanged) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07002718 mSurfaceOrientation = orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002719 }
2720
Jeff Brownbe1aa822011-07-27 16:04:54 -07002721 bool sizeChanged = mSurfaceWidth != width || mSurfaceHeight != height;
Jeff Brown65fd2512011-08-18 11:20:58 -07002722 if (sizeChanged || deviceModeChanged) {
Steve Block6215d3f2012-01-04 20:05:49 +00002723 ALOGI("Device reconfigured: id=%d, name='%s', surface size is now %dx%d, mode is %d",
Jeff Brown65fd2512011-08-18 11:20:58 -07002724 getDeviceId(), getDeviceName().string(), width, height, mDeviceMode);
Jeff Brown8d608662010-08-30 03:02:23 -07002725
Jeff Brownbe1aa822011-07-27 16:04:54 -07002726 mSurfaceWidth = width;
2727 mSurfaceHeight = height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002728
Jeff Brown8d608662010-08-30 03:02:23 -07002729 // Configure X and Y factors.
Jeff Brownbe1aa822011-07-27 16:04:54 -07002730 mXScale = float(width) / (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1);
2731 mYScale = float(height) / (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1);
2732 mXPrecision = 1.0f / mXScale;
2733 mYPrecision = 1.0f / mYScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002734
Jeff Brownbe1aa822011-07-27 16:04:54 -07002735 mOrientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
Jeff Brown65fd2512011-08-18 11:20:58 -07002736 mOrientedRanges.x.source = mSource;
Jeff Brownbe1aa822011-07-27 16:04:54 -07002737 mOrientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
Jeff Brown65fd2512011-08-18 11:20:58 -07002738 mOrientedRanges.y.source = mSource;
Jeff Brownefd32662011-03-08 15:13:06 -08002739
Jeff Brownbe1aa822011-07-27 16:04:54 -07002740 configureVirtualKeys();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002741
Jeff Brown8d608662010-08-30 03:02:23 -07002742 // Scale factor for terms that are not oriented in a particular axis.
2743 // If the pixels are square then xScale == yScale otherwise we fake it
2744 // by choosing an average.
Jeff Brownbe1aa822011-07-27 16:04:54 -07002745 mGeometricScale = avg(mXScale, mYScale);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002746
Jeff Brown8d608662010-08-30 03:02:23 -07002747 // Size of diagonal axis.
Jeff Brown2352b972011-04-12 22:39:53 -07002748 float diagonalSize = hypotf(width, height);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002749
Jeff Browna1f89ce2011-08-11 00:05:01 -07002750 // Size factors.
2751 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
2752 if (mRawPointerAxes.touchMajor.valid
2753 && mRawPointerAxes.touchMajor.maxValue != 0) {
2754 mSizeScale = 1.0f / mRawPointerAxes.touchMajor.maxValue;
2755 } else if (mRawPointerAxes.toolMajor.valid
2756 && mRawPointerAxes.toolMajor.maxValue != 0) {
2757 mSizeScale = 1.0f / mRawPointerAxes.toolMajor.maxValue;
2758 } else {
2759 mSizeScale = 0.0f;
2760 }
2761
Jeff Brownbe1aa822011-07-27 16:04:54 -07002762 mOrientedRanges.haveTouchSize = true;
Jeff Browna1f89ce2011-08-11 00:05:01 -07002763 mOrientedRanges.haveToolSize = true;
2764 mOrientedRanges.haveSize = true;
Jeff Brownefd32662011-03-08 15:13:06 -08002765
Jeff Brownbe1aa822011-07-27 16:04:54 -07002766 mOrientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
Jeff Brown65fd2512011-08-18 11:20:58 -07002767 mOrientedRanges.touchMajor.source = mSource;
Jeff Brownbe1aa822011-07-27 16:04:54 -07002768 mOrientedRanges.touchMajor.min = 0;
2769 mOrientedRanges.touchMajor.max = diagonalSize;
2770 mOrientedRanges.touchMajor.flat = 0;
2771 mOrientedRanges.touchMajor.fuzz = 0;
Jeff Brownefd32662011-03-08 15:13:06 -08002772
Jeff Brownbe1aa822011-07-27 16:04:54 -07002773 mOrientedRanges.touchMinor = mOrientedRanges.touchMajor;
2774 mOrientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
Jeff Brownefd32662011-03-08 15:13:06 -08002775
Jeff Brownbe1aa822011-07-27 16:04:54 -07002776 mOrientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
Jeff Brown65fd2512011-08-18 11:20:58 -07002777 mOrientedRanges.toolMajor.source = mSource;
Jeff Brownbe1aa822011-07-27 16:04:54 -07002778 mOrientedRanges.toolMajor.min = 0;
2779 mOrientedRanges.toolMajor.max = diagonalSize;
2780 mOrientedRanges.toolMajor.flat = 0;
2781 mOrientedRanges.toolMajor.fuzz = 0;
Jeff Brownefd32662011-03-08 15:13:06 -08002782
Jeff Brownbe1aa822011-07-27 16:04:54 -07002783 mOrientedRanges.toolMinor = mOrientedRanges.toolMajor;
2784 mOrientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
Jeff Browna1f89ce2011-08-11 00:05:01 -07002785
2786 mOrientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
Jeff Brown65fd2512011-08-18 11:20:58 -07002787 mOrientedRanges.size.source = mSource;
Jeff Browna1f89ce2011-08-11 00:05:01 -07002788 mOrientedRanges.size.min = 0;
2789 mOrientedRanges.size.max = 1.0;
2790 mOrientedRanges.size.flat = 0;
2791 mOrientedRanges.size.fuzz = 0;
2792 } else {
2793 mSizeScale = 0.0f;
Jeff Brown8d608662010-08-30 03:02:23 -07002794 }
2795
2796 // Pressure factors.
Jeff Brownbe1aa822011-07-27 16:04:54 -07002797 mPressureScale = 0;
Jeff Brown65fd2512011-08-18 11:20:58 -07002798 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
2799 || mCalibration.pressureCalibration
2800 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
2801 if (mCalibration.havePressureScale) {
2802 mPressureScale = mCalibration.pressureScale;
2803 } else if (mRawPointerAxes.pressure.valid
2804 && mRawPointerAxes.pressure.maxValue != 0) {
2805 mPressureScale = 1.0f / mRawPointerAxes.pressure.maxValue;
Jeff Brown8d608662010-08-30 03:02:23 -07002806 }
Jeff Brown65fd2512011-08-18 11:20:58 -07002807 }
Jeff Brown8d608662010-08-30 03:02:23 -07002808
Jeff Brown65fd2512011-08-18 11:20:58 -07002809 mOrientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
2810 mOrientedRanges.pressure.source = mSource;
2811 mOrientedRanges.pressure.min = 0;
2812 mOrientedRanges.pressure.max = 1.0;
2813 mOrientedRanges.pressure.flat = 0;
2814 mOrientedRanges.pressure.fuzz = 0;
Jeff Brownefd32662011-03-08 15:13:06 -08002815
Jeff Brown65fd2512011-08-18 11:20:58 -07002816 // Tilt
2817 mTiltXCenter = 0;
2818 mTiltXScale = 0;
2819 mTiltYCenter = 0;
2820 mTiltYScale = 0;
2821 mHaveTilt = mRawPointerAxes.tiltX.valid && mRawPointerAxes.tiltY.valid;
2822 if (mHaveTilt) {
2823 mTiltXCenter = avg(mRawPointerAxes.tiltX.minValue,
2824 mRawPointerAxes.tiltX.maxValue);
2825 mTiltYCenter = avg(mRawPointerAxes.tiltY.minValue,
2826 mRawPointerAxes.tiltY.maxValue);
2827 mTiltXScale = M_PI / 180;
2828 mTiltYScale = M_PI / 180;
2829
2830 mOrientedRanges.haveTilt = true;
2831
2832 mOrientedRanges.tilt.axis = AMOTION_EVENT_AXIS_TILT;
2833 mOrientedRanges.tilt.source = mSource;
2834 mOrientedRanges.tilt.min = 0;
2835 mOrientedRanges.tilt.max = M_PI_2;
2836 mOrientedRanges.tilt.flat = 0;
2837 mOrientedRanges.tilt.fuzz = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07002838 }
2839
Jeff Brown8d608662010-08-30 03:02:23 -07002840 // Orientation
Jeff Brown65fd2512011-08-18 11:20:58 -07002841 mOrientationCenter = 0;
Jeff Brownbe1aa822011-07-27 16:04:54 -07002842 mOrientationScale = 0;
Jeff Brown65fd2512011-08-18 11:20:58 -07002843 if (mHaveTilt) {
2844 mOrientedRanges.haveOrientation = true;
2845
2846 mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
2847 mOrientedRanges.orientation.source = mSource;
2848 mOrientedRanges.orientation.min = -M_PI;
2849 mOrientedRanges.orientation.max = M_PI;
2850 mOrientedRanges.orientation.flat = 0;
2851 mOrientedRanges.orientation.fuzz = 0;
2852 } else if (mCalibration.orientationCalibration !=
2853 Calibration::ORIENTATION_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07002854 if (mCalibration.orientationCalibration
2855 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
Jeff Brown65fd2512011-08-18 11:20:58 -07002856 if (mRawPointerAxes.orientation.valid) {
2857 mOrientationCenter = avg(mRawPointerAxes.orientation.minValue,
2858 mRawPointerAxes.orientation.maxValue);
2859 mOrientationScale = M_PI / (mRawPointerAxes.orientation.maxValue -
2860 mRawPointerAxes.orientation.minValue);
Jeff Brown8d608662010-08-30 03:02:23 -07002861 }
2862 }
2863
Jeff Brownbe1aa822011-07-27 16:04:54 -07002864 mOrientedRanges.haveOrientation = true;
Jeff Brown80fd47c2011-05-24 01:07:44 -07002865
Jeff Brownbe1aa822011-07-27 16:04:54 -07002866 mOrientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
Jeff Brown65fd2512011-08-18 11:20:58 -07002867 mOrientedRanges.orientation.source = mSource;
2868 mOrientedRanges.orientation.min = -M_PI_2;
Jeff Brownbe1aa822011-07-27 16:04:54 -07002869 mOrientedRanges.orientation.max = M_PI_2;
2870 mOrientedRanges.orientation.flat = 0;
2871 mOrientedRanges.orientation.fuzz = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07002872 }
Jeff Brown80fd47c2011-05-24 01:07:44 -07002873
2874 // Distance
Jeff Brownbe1aa822011-07-27 16:04:54 -07002875 mDistanceScale = 0;
Jeff Brown80fd47c2011-05-24 01:07:44 -07002876 if (mCalibration.distanceCalibration != Calibration::DISTANCE_CALIBRATION_NONE) {
2877 if (mCalibration.distanceCalibration
2878 == Calibration::DISTANCE_CALIBRATION_SCALED) {
2879 if (mCalibration.haveDistanceScale) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07002880 mDistanceScale = mCalibration.distanceScale;
Jeff Brown80fd47c2011-05-24 01:07:44 -07002881 } else {
Jeff Brownbe1aa822011-07-27 16:04:54 -07002882 mDistanceScale = 1.0f;
Jeff Brown80fd47c2011-05-24 01:07:44 -07002883 }
2884 }
2885
Jeff Brownbe1aa822011-07-27 16:04:54 -07002886 mOrientedRanges.haveDistance = true;
Jeff Brown80fd47c2011-05-24 01:07:44 -07002887
Jeff Brownbe1aa822011-07-27 16:04:54 -07002888 mOrientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE;
Jeff Brown65fd2512011-08-18 11:20:58 -07002889 mOrientedRanges.distance.source = mSource;
Jeff Brownbe1aa822011-07-27 16:04:54 -07002890 mOrientedRanges.distance.min =
2891 mRawPointerAxes.distance.minValue * mDistanceScale;
2892 mOrientedRanges.distance.max =
2893 mRawPointerAxes.distance.minValue * mDistanceScale;
2894 mOrientedRanges.distance.flat = 0;
2895 mOrientedRanges.distance.fuzz =
2896 mRawPointerAxes.distance.fuzz * mDistanceScale;
Jeff Brown80fd47c2011-05-24 01:07:44 -07002897 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002898 }
2899
Jeff Brown65fd2512011-08-18 11:20:58 -07002900 if (orientationChanged || sizeChanged || deviceModeChanged) {
Jeff Brown9626b142011-03-03 02:09:54 -08002901 // Compute oriented surface dimensions, precision, scales and ranges.
2902 // Note that the maximum value reported is an inclusive maximum value so it is one
2903 // unit less than the total width or height of surface.
Jeff Brownbe1aa822011-07-27 16:04:54 -07002904 switch (mSurfaceOrientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002905 case DISPLAY_ORIENTATION_90:
2906 case DISPLAY_ORIENTATION_270:
Jeff Brownbe1aa822011-07-27 16:04:54 -07002907 mOrientedSurfaceWidth = mSurfaceHeight;
2908 mOrientedSurfaceHeight = mSurfaceWidth;
Jeff Brown9626b142011-03-03 02:09:54 -08002909
Jeff Brownbe1aa822011-07-27 16:04:54 -07002910 mOrientedXPrecision = mYPrecision;
2911 mOrientedYPrecision = mXPrecision;
Jeff Brown9626b142011-03-03 02:09:54 -08002912
Jeff Brownbe1aa822011-07-27 16:04:54 -07002913 mOrientedRanges.x.min = 0;
2914 mOrientedRanges.x.max = (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue)
2915 * mYScale;
2916 mOrientedRanges.x.flat = 0;
2917 mOrientedRanges.x.fuzz = mYScale;
Jeff Brown9626b142011-03-03 02:09:54 -08002918
Jeff Brownbe1aa822011-07-27 16:04:54 -07002919 mOrientedRanges.y.min = 0;
2920 mOrientedRanges.y.max = (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue)
2921 * mXScale;
2922 mOrientedRanges.y.flat = 0;
2923 mOrientedRanges.y.fuzz = mXScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002924 break;
Jeff Brown9626b142011-03-03 02:09:54 -08002925
Jeff Brown6d0fec22010-07-23 21:28:06 -07002926 default:
Jeff Brownbe1aa822011-07-27 16:04:54 -07002927 mOrientedSurfaceWidth = mSurfaceWidth;
2928 mOrientedSurfaceHeight = mSurfaceHeight;
Jeff Brown9626b142011-03-03 02:09:54 -08002929
Jeff Brownbe1aa822011-07-27 16:04:54 -07002930 mOrientedXPrecision = mXPrecision;
2931 mOrientedYPrecision = mYPrecision;
Jeff Brown9626b142011-03-03 02:09:54 -08002932
Jeff Brownbe1aa822011-07-27 16:04:54 -07002933 mOrientedRanges.x.min = 0;
2934 mOrientedRanges.x.max = (mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue)
2935 * mXScale;
2936 mOrientedRanges.x.flat = 0;
2937 mOrientedRanges.x.fuzz = mXScale;
Jeff Brown9626b142011-03-03 02:09:54 -08002938
Jeff Brownbe1aa822011-07-27 16:04:54 -07002939 mOrientedRanges.y.min = 0;
2940 mOrientedRanges.y.max = (mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue)
2941 * mYScale;
2942 mOrientedRanges.y.flat = 0;
2943 mOrientedRanges.y.fuzz = mYScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002944 break;
2945 }
Jeff Brownace13b12011-03-09 17:39:48 -08002946
2947 // Compute pointer gesture detection parameters.
Jeff Brown65fd2512011-08-18 11:20:58 -07002948 if (mDeviceMode == DEVICE_MODE_POINTER) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07002949 int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
2950 int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
Jeff Brown2352b972011-04-12 22:39:53 -07002951 float rawDiagonal = hypotf(rawWidth, rawHeight);
Jeff Brownbe1aa822011-07-27 16:04:54 -07002952 float displayDiagonal = hypotf(mAssociatedDisplayWidth,
2953 mAssociatedDisplayHeight);
Jeff Brownace13b12011-03-09 17:39:48 -08002954
Jeff Brown2352b972011-04-12 22:39:53 -07002955 // Scale movements such that one whole swipe of the touch pad covers a
Jeff Brown19c97d462011-06-01 12:33:19 -07002956 // given area relative to the diagonal size of the display when no acceleration
2957 // is applied.
Jeff Brownace13b12011-03-09 17:39:48 -08002958 // Assume that the touch pad has a square aspect ratio such that movements in
2959 // X and Y of the same number of raw units cover the same physical distance.
Jeff Brown65fd2512011-08-18 11:20:58 -07002960 mPointerXMovementScale = mConfig.pointerGestureMovementSpeedRatio
Jeff Brown2352b972011-04-12 22:39:53 -07002961 * displayDiagonal / rawDiagonal;
Jeff Brown65fd2512011-08-18 11:20:58 -07002962 mPointerYMovementScale = mPointerXMovementScale;
Jeff Brownace13b12011-03-09 17:39:48 -08002963
2964 // Scale zooms to cover a smaller range of the display than movements do.
2965 // This value determines the area around the pointer that is affected by freeform
2966 // pointer gestures.
Jeff Brown65fd2512011-08-18 11:20:58 -07002967 mPointerXZoomScale = mConfig.pointerGestureZoomSpeedRatio
Jeff Brown2352b972011-04-12 22:39:53 -07002968 * displayDiagonal / rawDiagonal;
Jeff Brown65fd2512011-08-18 11:20:58 -07002969 mPointerYZoomScale = mPointerXZoomScale;
Jeff Brownace13b12011-03-09 17:39:48 -08002970
Jeff Brown2352b972011-04-12 22:39:53 -07002971 // Max width between pointers to detect a swipe gesture is more than some fraction
2972 // of the diagonal axis of the touch pad. Touches that are wider than this are
2973 // translated into freeform gestures.
Jeff Brownbe1aa822011-07-27 16:04:54 -07002974 mPointerGestureMaxSwipeWidth =
Jeff Brown474dcb52011-06-14 20:22:50 -07002975 mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal;
Jeff Brownace13b12011-03-09 17:39:48 -08002976 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002977
Jeff Brown65fd2512011-08-18 11:20:58 -07002978 // Abort current pointer usages because the state has changed.
2979 abortPointerUsage(when, 0 /*policyFlags*/);
2980
2981 // Inform the dispatcher about the changes.
2982 *outResetNeeded = true;
2983 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002984}
2985
Jeff Brownbe1aa822011-07-27 16:04:54 -07002986void TouchInputMapper::dumpSurface(String8& dump) {
2987 dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth);
2988 dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
2989 dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation);
Jeff Brownb88102f2010-09-08 11:49:43 -07002990}
2991
Jeff Brownbe1aa822011-07-27 16:04:54 -07002992void TouchInputMapper::configureVirtualKeys() {
Jeff Brown8d608662010-08-30 03:02:23 -07002993 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Brown90655042010-12-02 13:50:46 -08002994 getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002995
Jeff Brownbe1aa822011-07-27 16:04:54 -07002996 mVirtualKeys.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002997
Jeff Brown6328cdc2010-07-29 18:18:33 -07002998 if (virtualKeyDefinitions.size() == 0) {
2999 return;
3000 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003001
Jeff Brownbe1aa822011-07-27 16:04:54 -07003002 mVirtualKeys.setCapacity(virtualKeyDefinitions.size());
Jeff Brown6328cdc2010-07-29 18:18:33 -07003003
Jeff Brownbe1aa822011-07-27 16:04:54 -07003004 int32_t touchScreenLeft = mRawPointerAxes.x.minValue;
3005 int32_t touchScreenTop = mRawPointerAxes.y.minValue;
3006 int32_t touchScreenWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
3007 int32_t touchScreenHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
Jeff Brown6328cdc2010-07-29 18:18:33 -07003008
3009 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown8d608662010-08-30 03:02:23 -07003010 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brown6328cdc2010-07-29 18:18:33 -07003011 virtualKeyDefinitions[i];
3012
Jeff Brownbe1aa822011-07-27 16:04:54 -07003013 mVirtualKeys.add();
3014 VirtualKey& virtualKey = mVirtualKeys.editTop();
Jeff Brown6328cdc2010-07-29 18:18:33 -07003015
3016 virtualKey.scanCode = virtualKeyDefinition.scanCode;
3017 int32_t keyCode;
3018 uint32_t flags;
Jeff Brown6f2fba42011-02-19 01:08:02 -08003019 if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode,
Jeff Brown6328cdc2010-07-29 18:18:33 -07003020 & keyCode, & flags)) {
Steve Block8564c8d2012-01-05 23:22:43 +00003021 ALOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
Jeff Brown8d608662010-08-30 03:02:23 -07003022 virtualKey.scanCode);
Jeff Brownbe1aa822011-07-27 16:04:54 -07003023 mVirtualKeys.pop(); // drop the key
Jeff Brown6328cdc2010-07-29 18:18:33 -07003024 continue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003025 }
3026
Jeff Brown6328cdc2010-07-29 18:18:33 -07003027 virtualKey.keyCode = keyCode;
3028 virtualKey.flags = flags;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003029
Jeff Brown6328cdc2010-07-29 18:18:33 -07003030 // convert the key definition's display coordinates into touch coordinates for a hit box
3031 int32_t halfWidth = virtualKeyDefinition.width / 2;
3032 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003033
Jeff Brown6328cdc2010-07-29 18:18:33 -07003034 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
Jeff Brownbe1aa822011-07-27 16:04:54 -07003035 * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
Jeff Brown6328cdc2010-07-29 18:18:33 -07003036 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
Jeff Brownbe1aa822011-07-27 16:04:54 -07003037 * touchScreenWidth / mSurfaceWidth + touchScreenLeft;
Jeff Brown6328cdc2010-07-29 18:18:33 -07003038 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
Jeff Brownbe1aa822011-07-27 16:04:54 -07003039 * touchScreenHeight / mSurfaceHeight + touchScreenTop;
Jeff Brown6328cdc2010-07-29 18:18:33 -07003040 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
Jeff Brownbe1aa822011-07-27 16:04:54 -07003041 * touchScreenHeight / mSurfaceHeight + touchScreenTop;
Jeff Brownef3d7e82010-09-30 14:33:04 -07003042 }
3043}
3044
Jeff Brownbe1aa822011-07-27 16:04:54 -07003045void TouchInputMapper::dumpVirtualKeys(String8& dump) {
3046 if (!mVirtualKeys.isEmpty()) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07003047 dump.append(INDENT3 "Virtual Keys:\n");
3048
Jeff Brownbe1aa822011-07-27 16:04:54 -07003049 for (size_t i = 0; i < mVirtualKeys.size(); i++) {
3050 const VirtualKey& virtualKey = mVirtualKeys.itemAt(i);
Jeff Brownef3d7e82010-09-30 14:33:04 -07003051 dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
3052 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
3053 i, virtualKey.scanCode, virtualKey.keyCode,
3054 virtualKey.hitLeft, virtualKey.hitRight,
3055 virtualKey.hitTop, virtualKey.hitBottom);
3056 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003057 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003058}
3059
Jeff Brown8d608662010-08-30 03:02:23 -07003060void TouchInputMapper::parseCalibration() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08003061 const PropertyMap& in = getDevice()->getConfiguration();
Jeff Brown8d608662010-08-30 03:02:23 -07003062 Calibration& out = mCalibration;
3063
Jeff Browna1f89ce2011-08-11 00:05:01 -07003064 // Size
3065 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
3066 String8 sizeCalibrationString;
3067 if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
3068 if (sizeCalibrationString == "none") {
3069 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
3070 } else if (sizeCalibrationString == "geometric") {
3071 out.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
3072 } else if (sizeCalibrationString == "diameter") {
3073 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DIAMETER;
3074 } else if (sizeCalibrationString == "area") {
3075 out.sizeCalibration = Calibration::SIZE_CALIBRATION_AREA;
3076 } else if (sizeCalibrationString != "default") {
Steve Block8564c8d2012-01-05 23:22:43 +00003077 ALOGW("Invalid value for touch.size.calibration: '%s'",
Jeff Browna1f89ce2011-08-11 00:05:01 -07003078 sizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07003079 }
3080 }
3081
Jeff Browna1f89ce2011-08-11 00:05:01 -07003082 out.haveSizeScale = in.tryGetProperty(String8("touch.size.scale"),
3083 out.sizeScale);
3084 out.haveSizeBias = in.tryGetProperty(String8("touch.size.bias"),
3085 out.sizeBias);
3086 out.haveSizeIsSummed = in.tryGetProperty(String8("touch.size.isSummed"),
3087 out.sizeIsSummed);
Jeff Brown8d608662010-08-30 03:02:23 -07003088
3089 // Pressure
3090 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
3091 String8 pressureCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07003092 if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07003093 if (pressureCalibrationString == "none") {
3094 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
3095 } else if (pressureCalibrationString == "physical") {
3096 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
3097 } else if (pressureCalibrationString == "amplitude") {
3098 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
3099 } else if (pressureCalibrationString != "default") {
Steve Block8564c8d2012-01-05 23:22:43 +00003100 ALOGW("Invalid value for touch.pressure.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07003101 pressureCalibrationString.string());
3102 }
3103 }
3104
Jeff Brown8d608662010-08-30 03:02:23 -07003105 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
3106 out.pressureScale);
3107
Jeff Brown8d608662010-08-30 03:02:23 -07003108 // Orientation
3109 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
3110 String8 orientationCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07003111 if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07003112 if (orientationCalibrationString == "none") {
3113 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
3114 } else if (orientationCalibrationString == "interpolated") {
3115 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
Jeff Brown517bb4c2011-01-14 19:09:23 -08003116 } else if (orientationCalibrationString == "vector") {
3117 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
Jeff Brown8d608662010-08-30 03:02:23 -07003118 } else if (orientationCalibrationString != "default") {
Steve Block8564c8d2012-01-05 23:22:43 +00003119 ALOGW("Invalid value for touch.orientation.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07003120 orientationCalibrationString.string());
3121 }
3122 }
Jeff Brown80fd47c2011-05-24 01:07:44 -07003123
3124 // Distance
3125 out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_DEFAULT;
3126 String8 distanceCalibrationString;
3127 if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) {
3128 if (distanceCalibrationString == "none") {
3129 out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
3130 } else if (distanceCalibrationString == "scaled") {
3131 out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
3132 } else if (distanceCalibrationString != "default") {
Steve Block8564c8d2012-01-05 23:22:43 +00003133 ALOGW("Invalid value for touch.distance.calibration: '%s'",
Jeff Brown80fd47c2011-05-24 01:07:44 -07003134 distanceCalibrationString.string());
3135 }
3136 }
3137
3138 out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"),
3139 out.distanceScale);
Jeff Brown8d608662010-08-30 03:02:23 -07003140}
3141
3142void TouchInputMapper::resolveCalibration() {
Jeff Brown8d608662010-08-30 03:02:23 -07003143 // Size
Jeff Browna1f89ce2011-08-11 00:05:01 -07003144 if (mRawPointerAxes.touchMajor.valid || mRawPointerAxes.toolMajor.valid) {
3145 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DEFAULT) {
3146 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_GEOMETRIC;
Jeff Brown8d608662010-08-30 03:02:23 -07003147 }
Jeff Browna1f89ce2011-08-11 00:05:01 -07003148 } else {
3149 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
3150 }
Jeff Brown8d608662010-08-30 03:02:23 -07003151
Jeff Browna1f89ce2011-08-11 00:05:01 -07003152 // Pressure
3153 if (mRawPointerAxes.pressure.valid) {
3154 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_DEFAULT) {
3155 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
3156 }
3157 } else {
3158 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07003159 }
3160
3161 // Orientation
Jeff Browna1f89ce2011-08-11 00:05:01 -07003162 if (mRawPointerAxes.orientation.valid) {
3163 if (mCalibration.orientationCalibration == Calibration::ORIENTATION_CALIBRATION_DEFAULT) {
Jeff Brown8d608662010-08-30 03:02:23 -07003164 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
Jeff Brown8d608662010-08-30 03:02:23 -07003165 }
Jeff Browna1f89ce2011-08-11 00:05:01 -07003166 } else {
3167 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07003168 }
Jeff Brown80fd47c2011-05-24 01:07:44 -07003169
3170 // Distance
Jeff Browna1f89ce2011-08-11 00:05:01 -07003171 if (mRawPointerAxes.distance.valid) {
3172 if (mCalibration.distanceCalibration == Calibration::DISTANCE_CALIBRATION_DEFAULT) {
Jeff Brown80fd47c2011-05-24 01:07:44 -07003173 mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
Jeff Brown80fd47c2011-05-24 01:07:44 -07003174 }
Jeff Browna1f89ce2011-08-11 00:05:01 -07003175 } else {
3176 mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
Jeff Brown80fd47c2011-05-24 01:07:44 -07003177 }
Jeff Brown8d608662010-08-30 03:02:23 -07003178}
3179
Jeff Brownef3d7e82010-09-30 14:33:04 -07003180void TouchInputMapper::dumpCalibration(String8& dump) {
3181 dump.append(INDENT3 "Calibration:\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07003182
Jeff Browna1f89ce2011-08-11 00:05:01 -07003183 // Size
3184 switch (mCalibration.sizeCalibration) {
3185 case Calibration::SIZE_CALIBRATION_NONE:
3186 dump.append(INDENT4 "touch.size.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003187 break;
Jeff Browna1f89ce2011-08-11 00:05:01 -07003188 case Calibration::SIZE_CALIBRATION_GEOMETRIC:
3189 dump.append(INDENT4 "touch.size.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003190 break;
Jeff Browna1f89ce2011-08-11 00:05:01 -07003191 case Calibration::SIZE_CALIBRATION_DIAMETER:
3192 dump.append(INDENT4 "touch.size.calibration: diameter\n");
3193 break;
3194 case Calibration::SIZE_CALIBRATION_AREA:
3195 dump.append(INDENT4 "touch.size.calibration: area\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003196 break;
3197 default:
Steve Blockec193de2012-01-09 18:35:44 +00003198 ALOG_ASSERT(false);
Jeff Brown8d608662010-08-30 03:02:23 -07003199 }
3200
Jeff Browna1f89ce2011-08-11 00:05:01 -07003201 if (mCalibration.haveSizeScale) {
3202 dump.appendFormat(INDENT4 "touch.size.scale: %0.3f\n",
3203 mCalibration.sizeScale);
Jeff Brown8d608662010-08-30 03:02:23 -07003204 }
3205
Jeff Browna1f89ce2011-08-11 00:05:01 -07003206 if (mCalibration.haveSizeBias) {
3207 dump.appendFormat(INDENT4 "touch.size.bias: %0.3f\n",
3208 mCalibration.sizeBias);
Jeff Brown8d608662010-08-30 03:02:23 -07003209 }
3210
Jeff Browna1f89ce2011-08-11 00:05:01 -07003211 if (mCalibration.haveSizeIsSummed) {
3212 dump.appendFormat(INDENT4 "touch.size.isSummed: %s\n",
3213 toString(mCalibration.sizeIsSummed));
Jeff Brown8d608662010-08-30 03:02:23 -07003214 }
3215
3216 // Pressure
3217 switch (mCalibration.pressureCalibration) {
3218 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07003219 dump.append(INDENT4 "touch.pressure.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003220 break;
3221 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Brownef3d7e82010-09-30 14:33:04 -07003222 dump.append(INDENT4 "touch.pressure.calibration: physical\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003223 break;
3224 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07003225 dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003226 break;
3227 default:
Steve Blockec193de2012-01-09 18:35:44 +00003228 ALOG_ASSERT(false);
Jeff Brown8d608662010-08-30 03:02:23 -07003229 }
3230
Jeff Brown8d608662010-08-30 03:02:23 -07003231 if (mCalibration.havePressureScale) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07003232 dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
3233 mCalibration.pressureScale);
Jeff Brown8d608662010-08-30 03:02:23 -07003234 }
3235
Jeff Brown8d608662010-08-30 03:02:23 -07003236 // Orientation
3237 switch (mCalibration.orientationCalibration) {
3238 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07003239 dump.append(INDENT4 "touch.orientation.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003240 break;
3241 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07003242 dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003243 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08003244 case Calibration::ORIENTATION_CALIBRATION_VECTOR:
3245 dump.append(INDENT4 "touch.orientation.calibration: vector\n");
3246 break;
Jeff Brown8d608662010-08-30 03:02:23 -07003247 default:
Steve Blockec193de2012-01-09 18:35:44 +00003248 ALOG_ASSERT(false);
Jeff Brown8d608662010-08-30 03:02:23 -07003249 }
Jeff Brown80fd47c2011-05-24 01:07:44 -07003250
3251 // Distance
3252 switch (mCalibration.distanceCalibration) {
3253 case Calibration::DISTANCE_CALIBRATION_NONE:
3254 dump.append(INDENT4 "touch.distance.calibration: none\n");
3255 break;
3256 case Calibration::DISTANCE_CALIBRATION_SCALED:
3257 dump.append(INDENT4 "touch.distance.calibration: scaled\n");
3258 break;
3259 default:
Steve Blockec193de2012-01-09 18:35:44 +00003260 ALOG_ASSERT(false);
Jeff Brown80fd47c2011-05-24 01:07:44 -07003261 }
3262
3263 if (mCalibration.haveDistanceScale) {
3264 dump.appendFormat(INDENT4 "touch.distance.scale: %0.3f\n",
3265 mCalibration.distanceScale);
3266 }
Jeff Brown8d608662010-08-30 03:02:23 -07003267}
3268
Jeff Brown65fd2512011-08-18 11:20:58 -07003269void TouchInputMapper::reset(nsecs_t when) {
3270 mCursorButtonAccumulator.reset(getDevice());
3271 mCursorScrollAccumulator.reset(getDevice());
3272 mTouchButtonAccumulator.reset(getDevice());
3273
3274 mPointerVelocityControl.reset();
3275 mWheelXVelocityControl.reset();
3276 mWheelYVelocityControl.reset();
3277
Jeff Brownbe1aa822011-07-27 16:04:54 -07003278 mCurrentRawPointerData.clear();
Jeff Brown65fd2512011-08-18 11:20:58 -07003279 mLastRawPointerData.clear();
3280 mCurrentCookedPointerData.clear();
3281 mLastCookedPointerData.clear();
Jeff Brownbe1aa822011-07-27 16:04:54 -07003282 mCurrentButtonState = 0;
Jeff Brown65fd2512011-08-18 11:20:58 -07003283 mLastButtonState = 0;
3284 mCurrentRawVScroll = 0;
3285 mCurrentRawHScroll = 0;
3286 mCurrentFingerIdBits.clear();
3287 mLastFingerIdBits.clear();
3288 mCurrentStylusIdBits.clear();
3289 mLastStylusIdBits.clear();
3290 mCurrentMouseIdBits.clear();
3291 mLastMouseIdBits.clear();
3292 mPointerUsage = POINTER_USAGE_NONE;
3293 mSentHoverEnter = false;
3294 mDownTime = 0;
Jeff Brownbe1aa822011-07-27 16:04:54 -07003295
Jeff Brown65fd2512011-08-18 11:20:58 -07003296 mCurrentVirtualKey.down = false;
Jeff Brownbe1aa822011-07-27 16:04:54 -07003297
Jeff Brown65fd2512011-08-18 11:20:58 -07003298 mPointerGesture.reset();
3299 mPointerSimple.reset();
3300
3301 if (mPointerController != NULL) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07003302 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
3303 mPointerController->clearSpots();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003304 }
3305
Jeff Brown65fd2512011-08-18 11:20:58 -07003306 InputMapper::reset(when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003307}
3308
Jeff Brown65fd2512011-08-18 11:20:58 -07003309void TouchInputMapper::process(const RawEvent* rawEvent) {
3310 mCursorButtonAccumulator.process(rawEvent);
3311 mCursorScrollAccumulator.process(rawEvent);
3312 mTouchButtonAccumulator.process(rawEvent);
3313
3314 if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
3315 sync(rawEvent->when);
3316 }
3317}
3318
3319void TouchInputMapper::sync(nsecs_t when) {
3320 // Sync button state.
3321 mCurrentButtonState = mTouchButtonAccumulator.getButtonState()
3322 | mCursorButtonAccumulator.getButtonState();
3323
3324 // Sync scroll state.
3325 mCurrentRawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
3326 mCurrentRawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
3327 mCursorScrollAccumulator.finishSync();
3328
3329 // Sync touch state.
3330 bool havePointerIds = true;
3331 mCurrentRawPointerData.clear();
3332 syncTouch(when, &havePointerIds);
3333
Jeff Brownaa3855d2011-03-17 01:34:19 -07003334#if DEBUG_RAW_EVENTS
3335 if (!havePointerIds) {
Steve Block5baa3a62011-12-20 16:23:08 +00003336 ALOGD("syncTouch: pointerCount %d -> %d, no pointer ids",
Jeff Brownbe1aa822011-07-27 16:04:54 -07003337 mLastRawPointerData.pointerCount,
3338 mCurrentRawPointerData.pointerCount);
Jeff Brownaa3855d2011-03-17 01:34:19 -07003339 } else {
Steve Block5baa3a62011-12-20 16:23:08 +00003340 ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
Jeff Brownbe1aa822011-07-27 16:04:54 -07003341 "hovering ids 0x%08x -> 0x%08x",
3342 mLastRawPointerData.pointerCount,
3343 mCurrentRawPointerData.pointerCount,
3344 mLastRawPointerData.touchingIdBits.value,
3345 mCurrentRawPointerData.touchingIdBits.value,
3346 mLastRawPointerData.hoveringIdBits.value,
3347 mCurrentRawPointerData.hoveringIdBits.value);
Jeff Brownaa3855d2011-03-17 01:34:19 -07003348 }
3349#endif
3350
Jeff Brown65fd2512011-08-18 11:20:58 -07003351 // Reset state that we will compute below.
3352 mCurrentFingerIdBits.clear();
3353 mCurrentStylusIdBits.clear();
3354 mCurrentMouseIdBits.clear();
3355 mCurrentCookedPointerData.clear();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003356
Jeff Brown65fd2512011-08-18 11:20:58 -07003357 if (mDeviceMode == DEVICE_MODE_DISABLED) {
3358 // Drop all input if the device is disabled.
Jeff Brownbe1aa822011-07-27 16:04:54 -07003359 mCurrentRawPointerData.clear();
Jeff Brown65fd2512011-08-18 11:20:58 -07003360 mCurrentButtonState = 0;
3361 } else {
3362 // Preprocess pointer data.
3363 if (!havePointerIds) {
3364 assignPointerIds();
3365 }
3366
3367 // Handle policy on initial down or hover events.
3368 uint32_t policyFlags = 0;
Jeff Brownc28306a2011-08-23 21:32:42 -07003369 bool initialDown = mLastRawPointerData.pointerCount == 0
3370 && mCurrentRawPointerData.pointerCount != 0;
3371 bool buttonsPressed = mCurrentButtonState & ~mLastButtonState;
3372 if (initialDown || buttonsPressed) {
3373 // If this is a touch screen, hide the pointer on an initial down.
Jeff Brown65fd2512011-08-18 11:20:58 -07003374 if (mDeviceMode == DEVICE_MODE_DIRECT) {
Jeff Brown65fd2512011-08-18 11:20:58 -07003375 getContext()->fadePointer();
3376 }
3377
3378 // Initial downs on external touch devices should wake the device.
3379 // We don't do this for internal touch screens to prevent them from waking
3380 // up in your pocket.
3381 // TODO: Use the input device configuration to control this behavior more finely.
3382 if (getDevice()->isExternal()) {
3383 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
3384 }
3385 }
3386
3387 // Synthesize key down from raw buttons if needed.
3388 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
3389 policyFlags, mLastButtonState, mCurrentButtonState);
3390
3391 // Consume raw off-screen touches before cooking pointer data.
3392 // If touches are consumed, subsequent code will not receive any pointer data.
3393 if (consumeRawTouches(when, policyFlags)) {
3394 mCurrentRawPointerData.clear();
3395 }
3396
3397 // Cook pointer data. This call populates the mCurrentCookedPointerData structure
3398 // with cooked pointer data that has the same ids and indices as the raw data.
3399 // The following code can use either the raw or cooked data, as needed.
3400 cookPointerData();
3401
3402 // Dispatch the touches either directly or by translation through a pointer on screen.
Jeff Browndaf4a122011-08-26 17:14:14 -07003403 if (mDeviceMode == DEVICE_MODE_POINTER) {
Jeff Brown65fd2512011-08-18 11:20:58 -07003404 for (BitSet32 idBits(mCurrentRawPointerData.touchingIdBits); !idBits.isEmpty(); ) {
3405 uint32_t id = idBits.clearFirstMarkedBit();
3406 const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
3407 if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
3408 || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
3409 mCurrentStylusIdBits.markBit(id);
3410 } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
3411 || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
3412 mCurrentFingerIdBits.markBit(id);
3413 } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
3414 mCurrentMouseIdBits.markBit(id);
3415 }
3416 }
3417 for (BitSet32 idBits(mCurrentRawPointerData.hoveringIdBits); !idBits.isEmpty(); ) {
3418 uint32_t id = idBits.clearFirstMarkedBit();
3419 const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
3420 if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
3421 || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
3422 mCurrentStylusIdBits.markBit(id);
3423 }
3424 }
3425
3426 // Stylus takes precedence over all tools, then mouse, then finger.
3427 PointerUsage pointerUsage = mPointerUsage;
3428 if (!mCurrentStylusIdBits.isEmpty()) {
3429 mCurrentMouseIdBits.clear();
3430 mCurrentFingerIdBits.clear();
3431 pointerUsage = POINTER_USAGE_STYLUS;
3432 } else if (!mCurrentMouseIdBits.isEmpty()) {
3433 mCurrentFingerIdBits.clear();
3434 pointerUsage = POINTER_USAGE_MOUSE;
3435 } else if (!mCurrentFingerIdBits.isEmpty() || isPointerDown(mCurrentButtonState)) {
3436 pointerUsage = POINTER_USAGE_GESTURES;
Jeff Brown65fd2512011-08-18 11:20:58 -07003437 }
3438
3439 dispatchPointerUsage(when, policyFlags, pointerUsage);
3440 } else {
Jeff Browndaf4a122011-08-26 17:14:14 -07003441 if (mDeviceMode == DEVICE_MODE_DIRECT
3442 && mConfig.showTouches && mPointerController != NULL) {
3443 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
3444 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
3445
3446 mPointerController->setButtonState(mCurrentButtonState);
3447 mPointerController->setSpots(mCurrentCookedPointerData.pointerCoords,
3448 mCurrentCookedPointerData.idToIndex,
3449 mCurrentCookedPointerData.touchingIdBits);
3450 }
3451
Jeff Brown65fd2512011-08-18 11:20:58 -07003452 dispatchHoverExit(when, policyFlags);
3453 dispatchTouches(when, policyFlags);
3454 dispatchHoverEnterAndMove(when, policyFlags);
3455 }
3456
3457 // Synthesize key up from raw buttons if needed.
3458 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
3459 policyFlags, mLastButtonState, mCurrentButtonState);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003460 }
3461
Jeff Brown6328cdc2010-07-29 18:18:33 -07003462 // Copy current touch to last touch in preparation for the next cycle.
Jeff Brownbe1aa822011-07-27 16:04:54 -07003463 mLastRawPointerData.copyFrom(mCurrentRawPointerData);
3464 mLastCookedPointerData.copyFrom(mCurrentCookedPointerData);
3465 mLastButtonState = mCurrentButtonState;
Jeff Brown65fd2512011-08-18 11:20:58 -07003466 mLastFingerIdBits = mCurrentFingerIdBits;
3467 mLastStylusIdBits = mCurrentStylusIdBits;
3468 mLastMouseIdBits = mCurrentMouseIdBits;
3469
3470 // Clear some transient state.
3471 mCurrentRawVScroll = 0;
3472 mCurrentRawHScroll = 0;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003473}
3474
Jeff Brown79ac9692011-04-19 21:20:10 -07003475void TouchInputMapper::timeoutExpired(nsecs_t when) {
Jeff Browndaf4a122011-08-26 17:14:14 -07003476 if (mDeviceMode == DEVICE_MODE_POINTER) {
Jeff Brown65fd2512011-08-18 11:20:58 -07003477 if (mPointerUsage == POINTER_USAGE_GESTURES) {
3478 dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
3479 }
Jeff Brown79ac9692011-04-19 21:20:10 -07003480 }
3481}
3482
Jeff Brownbe1aa822011-07-27 16:04:54 -07003483bool TouchInputMapper::consumeRawTouches(nsecs_t when, uint32_t policyFlags) {
3484 // Check for release of a virtual key.
3485 if (mCurrentVirtualKey.down) {
3486 if (mCurrentRawPointerData.touchingIdBits.isEmpty()) {
3487 // Pointer went up while virtual key was down.
3488 mCurrentVirtualKey.down = false;
3489 if (!mCurrentVirtualKey.ignored) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003490#if DEBUG_VIRTUAL_KEYS
Steve Block5baa3a62011-12-20 16:23:08 +00003491 ALOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
Jeff Brownbe1aa822011-07-27 16:04:54 -07003492 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003493#endif
Jeff Brownbe1aa822011-07-27 16:04:54 -07003494 dispatchVirtualKey(when, policyFlags,
3495 AKEY_EVENT_ACTION_UP,
3496 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003497 }
Jeff Brownbe1aa822011-07-27 16:04:54 -07003498 return true;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003499 }
3500
Jeff Brownbe1aa822011-07-27 16:04:54 -07003501 if (mCurrentRawPointerData.touchingIdBits.count() == 1) {
3502 uint32_t id = mCurrentRawPointerData.touchingIdBits.firstMarkedBit();
3503 const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
3504 const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
3505 if (virtualKey && virtualKey->keyCode == mCurrentVirtualKey.keyCode) {
3506 // Pointer is still within the space of the virtual key.
3507 return true;
3508 }
3509 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003510
Jeff Brownbe1aa822011-07-27 16:04:54 -07003511 // Pointer left virtual key area or another pointer also went down.
3512 // Send key cancellation but do not consume the touch yet.
3513 // This is useful when the user swipes through from the virtual key area
3514 // into the main display surface.
3515 mCurrentVirtualKey.down = false;
3516 if (!mCurrentVirtualKey.ignored) {
3517#if DEBUG_VIRTUAL_KEYS
Steve Block5baa3a62011-12-20 16:23:08 +00003518 ALOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
Jeff Brownbe1aa822011-07-27 16:04:54 -07003519 mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
3520#endif
3521 dispatchVirtualKey(when, policyFlags,
3522 AKEY_EVENT_ACTION_UP,
3523 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
3524 | AKEY_EVENT_FLAG_CANCELED);
3525 }
3526 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003527
Jeff Brownbe1aa822011-07-27 16:04:54 -07003528 if (mLastRawPointerData.touchingIdBits.isEmpty()
3529 && !mCurrentRawPointerData.touchingIdBits.isEmpty()) {
3530 // Pointer just went down. Check for virtual key press or off-screen touches.
3531 uint32_t id = mCurrentRawPointerData.touchingIdBits.firstMarkedBit();
3532 const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
3533 if (!isPointInsideSurface(pointer.x, pointer.y)) {
3534 // If exactly one pointer went down, check for virtual key hit.
3535 // Otherwise we will drop the entire stroke.
3536 if (mCurrentRawPointerData.touchingIdBits.count() == 1) {
3537 const VirtualKey* virtualKey = findVirtualKeyHit(pointer.x, pointer.y);
3538 if (virtualKey) {
3539 mCurrentVirtualKey.down = true;
3540 mCurrentVirtualKey.downTime = when;
3541 mCurrentVirtualKey.keyCode = virtualKey->keyCode;
3542 mCurrentVirtualKey.scanCode = virtualKey->scanCode;
3543 mCurrentVirtualKey.ignored = mContext->shouldDropVirtualKey(
3544 when, getDevice(), virtualKey->keyCode, virtualKey->scanCode);
3545
3546 if (!mCurrentVirtualKey.ignored) {
3547#if DEBUG_VIRTUAL_KEYS
Steve Block5baa3a62011-12-20 16:23:08 +00003548 ALOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
Jeff Brownbe1aa822011-07-27 16:04:54 -07003549 mCurrentVirtualKey.keyCode,
3550 mCurrentVirtualKey.scanCode);
3551#endif
3552 dispatchVirtualKey(when, policyFlags,
3553 AKEY_EVENT_ACTION_DOWN,
3554 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
3555 }
3556 }
3557 }
3558 return true;
3559 }
3560 }
3561
Jeff Brownfe508922011-01-18 15:10:10 -08003562 // Disable all virtual key touches that happen within a short time interval of the
Jeff Brownbe1aa822011-07-27 16:04:54 -07003563 // most recent touch within the screen area. The idea is to filter out stray
3564 // virtual key presses when interacting with the touch screen.
Jeff Brownfe508922011-01-18 15:10:10 -08003565 //
3566 // Problems we're trying to solve:
3567 //
3568 // 1. While scrolling a list or dragging the window shade, the user swipes down into a
3569 // virtual key area that is implemented by a separate touch panel and accidentally
3570 // triggers a virtual key.
3571 //
3572 // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
3573 // area and accidentally triggers a virtual key. This often happens when virtual keys
3574 // are layed out below the screen near to where the on screen keyboard's space bar
3575 // is displayed.
Jeff Brownbe1aa822011-07-27 16:04:54 -07003576 if (mConfig.virtualKeyQuietTime > 0 && !mCurrentRawPointerData.touchingIdBits.isEmpty()) {
Jeff Brown474dcb52011-06-14 20:22:50 -07003577 mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime);
Jeff Brownfe508922011-01-18 15:10:10 -08003578 }
Jeff Brownbe1aa822011-07-27 16:04:54 -07003579 return false;
3580}
3581
3582void TouchInputMapper::dispatchVirtualKey(nsecs_t when, uint32_t policyFlags,
3583 int32_t keyEventAction, int32_t keyEventFlags) {
3584 int32_t keyCode = mCurrentVirtualKey.keyCode;
3585 int32_t scanCode = mCurrentVirtualKey.scanCode;
3586 nsecs_t downTime = mCurrentVirtualKey.downTime;
3587 int32_t metaState = mContext->getGlobalMetaState();
3588 policyFlags |= POLICY_FLAG_VIRTUAL;
3589
3590 NotifyKeyArgs args(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
3591 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
3592 getListener()->notifyKey(&args);
Jeff Brownfe508922011-01-18 15:10:10 -08003593}
3594
Jeff Brown6d0fec22010-07-23 21:28:06 -07003595void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07003596 BitSet32 currentIdBits = mCurrentCookedPointerData.touchingIdBits;
3597 BitSet32 lastIdBits = mLastCookedPointerData.touchingIdBits;
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003598 int32_t metaState = getContext()->getGlobalMetaState();
Jeff Brownbe1aa822011-07-27 16:04:54 -07003599 int32_t buttonState = mCurrentButtonState;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003600
3601 if (currentIdBits == lastIdBits) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07003602 if (!currentIdBits.isEmpty()) {
3603 // No pointer id changes so this is a move event.
3604 // The listener takes care of batching moves so we don't have to deal with that here.
Jeff Brown65fd2512011-08-18 11:20:58 -07003605 dispatchMotion(when, policyFlags, mSource,
Jeff Brownbe1aa822011-07-27 16:04:54 -07003606 AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState,
3607 AMOTION_EVENT_EDGE_FLAG_NONE,
3608 mCurrentCookedPointerData.pointerProperties,
3609 mCurrentCookedPointerData.pointerCoords,
3610 mCurrentCookedPointerData.idToIndex,
3611 currentIdBits, -1,
3612 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
3613 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003614 } else {
Jeff Brownc3db8582010-10-20 15:33:38 -07003615 // There may be pointers going up and pointers going down and pointers moving
3616 // all at the same time.
Jeff Brownace13b12011-03-09 17:39:48 -08003617 BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
3618 BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
Jeff Brownc3db8582010-10-20 15:33:38 -07003619 BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
Jeff Brownace13b12011-03-09 17:39:48 -08003620 BitSet32 dispatchedIdBits(lastIdBits.value);
Jeff Brownc3db8582010-10-20 15:33:38 -07003621
Jeff Brownace13b12011-03-09 17:39:48 -08003622 // Update last coordinates of pointers that have moved so that we observe the new
3623 // pointer positions at the same time as other pointers that have just gone up.
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003624 bool moveNeeded = updateMovedPointers(
Jeff Brownbe1aa822011-07-27 16:04:54 -07003625 mCurrentCookedPointerData.pointerProperties,
3626 mCurrentCookedPointerData.pointerCoords,
3627 mCurrentCookedPointerData.idToIndex,
3628 mLastCookedPointerData.pointerProperties,
3629 mLastCookedPointerData.pointerCoords,
3630 mLastCookedPointerData.idToIndex,
Jeff Brownace13b12011-03-09 17:39:48 -08003631 moveIdBits);
Jeff Brownbe1aa822011-07-27 16:04:54 -07003632 if (buttonState != mLastButtonState) {
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003633 moveNeeded = true;
3634 }
Jeff Brownc3db8582010-10-20 15:33:38 -07003635
Jeff Brownace13b12011-03-09 17:39:48 -08003636 // Dispatch pointer up events.
Jeff Brownc3db8582010-10-20 15:33:38 -07003637 while (!upIdBits.isEmpty()) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07003638 uint32_t upId = upIdBits.clearFirstMarkedBit();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003639
Jeff Brown65fd2512011-08-18 11:20:58 -07003640 dispatchMotion(when, policyFlags, mSource,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003641 AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, buttonState, 0,
Jeff Brownbe1aa822011-07-27 16:04:54 -07003642 mLastCookedPointerData.pointerProperties,
3643 mLastCookedPointerData.pointerCoords,
3644 mLastCookedPointerData.idToIndex,
3645 dispatchedIdBits, upId,
3646 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
Jeff Brownace13b12011-03-09 17:39:48 -08003647 dispatchedIdBits.clearBit(upId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003648 }
3649
Jeff Brownc3db8582010-10-20 15:33:38 -07003650 // Dispatch move events if any of the remaining pointers moved from their old locations.
3651 // Although applications receive new locations as part of individual pointer up
3652 // events, they do not generally handle them except when presented in a move event.
3653 if (moveNeeded) {
Steve Blockec193de2012-01-09 18:35:44 +00003654 ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
Jeff Brown65fd2512011-08-18 11:20:58 -07003655 dispatchMotion(when, policyFlags, mSource,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003656 AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0,
Jeff Brownbe1aa822011-07-27 16:04:54 -07003657 mCurrentCookedPointerData.pointerProperties,
3658 mCurrentCookedPointerData.pointerCoords,
3659 mCurrentCookedPointerData.idToIndex,
3660 dispatchedIdBits, -1,
3661 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
Jeff Brownc3db8582010-10-20 15:33:38 -07003662 }
3663
3664 // Dispatch pointer down events using the new pointer locations.
3665 while (!downIdBits.isEmpty()) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07003666 uint32_t downId = downIdBits.clearFirstMarkedBit();
Jeff Brownace13b12011-03-09 17:39:48 -08003667 dispatchedIdBits.markBit(downId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003668
Jeff Brownace13b12011-03-09 17:39:48 -08003669 if (dispatchedIdBits.count() == 1) {
3670 // First pointer is going down. Set down time.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003671 mDownTime = when;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003672 }
3673
Jeff Brown65fd2512011-08-18 11:20:58 -07003674 dispatchMotion(when, policyFlags, mSource,
Jeff Browna6111372011-07-14 21:48:23 -07003675 AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
Jeff Brownbe1aa822011-07-27 16:04:54 -07003676 mCurrentCookedPointerData.pointerProperties,
3677 mCurrentCookedPointerData.pointerCoords,
3678 mCurrentCookedPointerData.idToIndex,
3679 dispatchedIdBits, downId,
3680 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
Jeff Brownace13b12011-03-09 17:39:48 -08003681 }
3682 }
Jeff Brownace13b12011-03-09 17:39:48 -08003683}
3684
Jeff Brownbe1aa822011-07-27 16:04:54 -07003685void TouchInputMapper::dispatchHoverExit(nsecs_t when, uint32_t policyFlags) {
3686 if (mSentHoverEnter &&
3687 (mCurrentCookedPointerData.hoveringIdBits.isEmpty()
3688 || !mCurrentCookedPointerData.touchingIdBits.isEmpty())) {
3689 int32_t metaState = getContext()->getGlobalMetaState();
Jeff Brown65fd2512011-08-18 11:20:58 -07003690 dispatchMotion(when, policyFlags, mSource,
Jeff Brownbe1aa822011-07-27 16:04:54 -07003691 AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0,
3692 mLastCookedPointerData.pointerProperties,
3693 mLastCookedPointerData.pointerCoords,
3694 mLastCookedPointerData.idToIndex,
3695 mLastCookedPointerData.hoveringIdBits, -1,
3696 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
3697 mSentHoverEnter = false;
3698 }
3699}
Jeff Brownace13b12011-03-09 17:39:48 -08003700
Jeff Brownbe1aa822011-07-27 16:04:54 -07003701void TouchInputMapper::dispatchHoverEnterAndMove(nsecs_t when, uint32_t policyFlags) {
3702 if (mCurrentCookedPointerData.touchingIdBits.isEmpty()
3703 && !mCurrentCookedPointerData.hoveringIdBits.isEmpty()) {
3704 int32_t metaState = getContext()->getGlobalMetaState();
3705 if (!mSentHoverEnter) {
Jeff Brown65fd2512011-08-18 11:20:58 -07003706 dispatchMotion(when, policyFlags, mSource,
Jeff Brownbe1aa822011-07-27 16:04:54 -07003707 AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0,
3708 mCurrentCookedPointerData.pointerProperties,
3709 mCurrentCookedPointerData.pointerCoords,
3710 mCurrentCookedPointerData.idToIndex,
3711 mCurrentCookedPointerData.hoveringIdBits, -1,
3712 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
3713 mSentHoverEnter = true;
3714 }
Jeff Brownace13b12011-03-09 17:39:48 -08003715
Jeff Brown65fd2512011-08-18 11:20:58 -07003716 dispatchMotion(when, policyFlags, mSource,
Jeff Brownbe1aa822011-07-27 16:04:54 -07003717 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0,
3718 mCurrentCookedPointerData.pointerProperties,
3719 mCurrentCookedPointerData.pointerCoords,
3720 mCurrentCookedPointerData.idToIndex,
3721 mCurrentCookedPointerData.hoveringIdBits, -1,
3722 mOrientedXPrecision, mOrientedYPrecision, mDownTime);
3723 }
3724}
3725
3726void TouchInputMapper::cookPointerData() {
3727 uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount;
3728
3729 mCurrentCookedPointerData.clear();
3730 mCurrentCookedPointerData.pointerCount = currentPointerCount;
3731 mCurrentCookedPointerData.hoveringIdBits = mCurrentRawPointerData.hoveringIdBits;
3732 mCurrentCookedPointerData.touchingIdBits = mCurrentRawPointerData.touchingIdBits;
3733
3734 // Walk through the the active pointers and map device coordinates onto
3735 // surface coordinates and adjust for display orientation.
Jeff Brownace13b12011-03-09 17:39:48 -08003736 for (uint32_t i = 0; i < currentPointerCount; i++) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07003737 const RawPointerData::Pointer& in = mCurrentRawPointerData.pointers[i];
Jeff Brownace13b12011-03-09 17:39:48 -08003738
Jeff Browna1f89ce2011-08-11 00:05:01 -07003739 // Size
3740 float touchMajor, touchMinor, toolMajor, toolMinor, size;
3741 switch (mCalibration.sizeCalibration) {
3742 case Calibration::SIZE_CALIBRATION_GEOMETRIC:
3743 case Calibration::SIZE_CALIBRATION_DIAMETER:
3744 case Calibration::SIZE_CALIBRATION_AREA:
3745 if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
3746 touchMajor = in.touchMajor;
3747 touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
3748 toolMajor = in.toolMajor;
3749 toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
3750 size = mRawPointerAxes.touchMinor.valid
3751 ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
3752 } else if (mRawPointerAxes.touchMajor.valid) {
3753 toolMajor = touchMajor = in.touchMajor;
3754 toolMinor = touchMinor = mRawPointerAxes.touchMinor.valid
3755 ? in.touchMinor : in.touchMajor;
3756 size = mRawPointerAxes.touchMinor.valid
3757 ? avg(in.touchMajor, in.touchMinor) : in.touchMajor;
3758 } else if (mRawPointerAxes.toolMajor.valid) {
3759 touchMajor = toolMajor = in.toolMajor;
3760 touchMinor = toolMinor = mRawPointerAxes.toolMinor.valid
3761 ? in.toolMinor : in.toolMajor;
3762 size = mRawPointerAxes.toolMinor.valid
3763 ? avg(in.toolMajor, in.toolMinor) : in.toolMajor;
Jeff Brownace13b12011-03-09 17:39:48 -08003764 } else {
Steve Blockec193de2012-01-09 18:35:44 +00003765 ALOG_ASSERT(false, "No touch or tool axes. "
Jeff Browna1f89ce2011-08-11 00:05:01 -07003766 "Size calibration should have been resolved to NONE.");
3767 touchMajor = 0;
3768 touchMinor = 0;
Jeff Brownace13b12011-03-09 17:39:48 -08003769 toolMajor = 0;
Jeff Browna1f89ce2011-08-11 00:05:01 -07003770 toolMinor = 0;
3771 size = 0;
Jeff Brownace13b12011-03-09 17:39:48 -08003772 }
Jeff Brownace13b12011-03-09 17:39:48 -08003773
Jeff Browna1f89ce2011-08-11 00:05:01 -07003774 if (mCalibration.haveSizeIsSummed && mCalibration.sizeIsSummed) {
3775 uint32_t touchingCount = mCurrentRawPointerData.touchingIdBits.count();
3776 if (touchingCount > 1) {
3777 touchMajor /= touchingCount;
3778 touchMinor /= touchingCount;
3779 toolMajor /= touchingCount;
3780 toolMinor /= touchingCount;
3781 size /= touchingCount;
3782 }
3783 }
Jeff Brownace13b12011-03-09 17:39:48 -08003784
Jeff Browna1f89ce2011-08-11 00:05:01 -07003785 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_GEOMETRIC) {
3786 touchMajor *= mGeometricScale;
3787 touchMinor *= mGeometricScale;
3788 toolMajor *= mGeometricScale;
3789 toolMinor *= mGeometricScale;
3790 } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_AREA) {
3791 touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0;
Jeff Brownace13b12011-03-09 17:39:48 -08003792 touchMinor = touchMajor;
Jeff Browna1f89ce2011-08-11 00:05:01 -07003793 toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0;
3794 toolMinor = toolMajor;
3795 } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_DIAMETER) {
3796 touchMinor = touchMajor;
3797 toolMinor = toolMajor;
Jeff Brownace13b12011-03-09 17:39:48 -08003798 }
Jeff Browna1f89ce2011-08-11 00:05:01 -07003799
3800 mCalibration.applySizeScaleAndBias(&touchMajor);
3801 mCalibration.applySizeScaleAndBias(&touchMinor);
3802 mCalibration.applySizeScaleAndBias(&toolMajor);
3803 mCalibration.applySizeScaleAndBias(&toolMinor);
3804 size *= mSizeScale;
Jeff Brownace13b12011-03-09 17:39:48 -08003805 break;
3806 default:
3807 touchMajor = 0;
3808 touchMinor = 0;
Jeff Browna1f89ce2011-08-11 00:05:01 -07003809 toolMajor = 0;
3810 toolMinor = 0;
Jeff Brownace13b12011-03-09 17:39:48 -08003811 size = 0;
3812 break;
3813 }
3814
Jeff Browna1f89ce2011-08-11 00:05:01 -07003815 // Pressure
3816 float pressure;
3817 switch (mCalibration.pressureCalibration) {
3818 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
3819 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
3820 pressure = in.pressure * mPressureScale;
3821 break;
3822 default:
3823 pressure = in.isHovering ? 0 : 1;
3824 break;
3825 }
3826
Jeff Brown65fd2512011-08-18 11:20:58 -07003827 // Tilt and Orientation
3828 float tilt;
Jeff Brownace13b12011-03-09 17:39:48 -08003829 float orientation;
Jeff Brown65fd2512011-08-18 11:20:58 -07003830 if (mHaveTilt) {
3831 float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale;
3832 float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale;
3833 orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
3834 tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
3835 } else {
3836 tilt = 0;
3837
3838 switch (mCalibration.orientationCalibration) {
3839 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
3840 orientation = (in.orientation - mOrientationCenter) * mOrientationScale;
3841 break;
3842 case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
3843 int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
3844 int32_t c2 = signExtendNybble(in.orientation & 0x0f);
3845 if (c1 != 0 || c2 != 0) {
3846 orientation = atan2f(c1, c2) * 0.5f;
3847 float confidence = hypotf(c1, c2);
3848 float scale = 1.0f + confidence / 16.0f;
3849 touchMajor *= scale;
3850 touchMinor /= scale;
3851 toolMajor *= scale;
3852 toolMinor /= scale;
3853 } else {
3854 orientation = 0;
3855 }
3856 break;
3857 }
3858 default:
Jeff Brownace13b12011-03-09 17:39:48 -08003859 orientation = 0;
3860 }
Jeff Brownace13b12011-03-09 17:39:48 -08003861 }
3862
Jeff Brown80fd47c2011-05-24 01:07:44 -07003863 // Distance
3864 float distance;
3865 switch (mCalibration.distanceCalibration) {
3866 case Calibration::DISTANCE_CALIBRATION_SCALED:
Jeff Brownbe1aa822011-07-27 16:04:54 -07003867 distance = in.distance * mDistanceScale;
Jeff Brown80fd47c2011-05-24 01:07:44 -07003868 break;
3869 default:
3870 distance = 0;
3871 }
3872
Jeff Brownace13b12011-03-09 17:39:48 -08003873 // X and Y
3874 // Adjust coords for surface orientation.
3875 float x, y;
Jeff Brownbe1aa822011-07-27 16:04:54 -07003876 switch (mSurfaceOrientation) {
Jeff Brownace13b12011-03-09 17:39:48 -08003877 case DISPLAY_ORIENTATION_90:
Jeff Brownbe1aa822011-07-27 16:04:54 -07003878 x = float(in.y - mRawPointerAxes.y.minValue) * mYScale;
3879 y = float(mRawPointerAxes.x.maxValue - in.x) * mXScale;
Jeff Brownace13b12011-03-09 17:39:48 -08003880 orientation -= M_PI_2;
3881 if (orientation < - M_PI_2) {
3882 orientation += M_PI;
3883 }
3884 break;
3885 case DISPLAY_ORIENTATION_180:
Jeff Brownbe1aa822011-07-27 16:04:54 -07003886 x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale;
3887 y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale;
Jeff Brownace13b12011-03-09 17:39:48 -08003888 break;
3889 case DISPLAY_ORIENTATION_270:
Jeff Brownbe1aa822011-07-27 16:04:54 -07003890 x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale;
3891 y = float(in.x - mRawPointerAxes.x.minValue) * mXScale;
Jeff Brownace13b12011-03-09 17:39:48 -08003892 orientation += M_PI_2;
3893 if (orientation > M_PI_2) {
3894 orientation -= M_PI;
3895 }
3896 break;
3897 default:
Jeff Brownbe1aa822011-07-27 16:04:54 -07003898 x = float(in.x - mRawPointerAxes.x.minValue) * mXScale;
3899 y = float(in.y - mRawPointerAxes.y.minValue) * mYScale;
Jeff Brownace13b12011-03-09 17:39:48 -08003900 break;
3901 }
3902
3903 // Write output coords.
Jeff Brownbe1aa822011-07-27 16:04:54 -07003904 PointerCoords& out = mCurrentCookedPointerData.pointerCoords[i];
Jeff Brownace13b12011-03-09 17:39:48 -08003905 out.clear();
3906 out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
3907 out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
3908 out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
3909 out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
3910 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
3911 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
3912 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
3913 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
3914 out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
Jeff Brown65fd2512011-08-18 11:20:58 -07003915 out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
Jeff Brownbe1aa822011-07-27 16:04:54 -07003916 out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003917
3918 // Write output properties.
Jeff Brownbe1aa822011-07-27 16:04:54 -07003919 PointerProperties& properties = mCurrentCookedPointerData.pointerProperties[i];
3920 uint32_t id = in.id;
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003921 properties.clear();
Jeff Brownbe1aa822011-07-27 16:04:54 -07003922 properties.id = id;
3923 properties.toolType = in.toolType;
Jeff Brownace13b12011-03-09 17:39:48 -08003924
Jeff Brownbe1aa822011-07-27 16:04:54 -07003925 // Write id index.
3926 mCurrentCookedPointerData.idToIndex[id] = i;
3927 }
Jeff Brownace13b12011-03-09 17:39:48 -08003928}
3929
Jeff Brown65fd2512011-08-18 11:20:58 -07003930void TouchInputMapper::dispatchPointerUsage(nsecs_t when, uint32_t policyFlags,
3931 PointerUsage pointerUsage) {
3932 if (pointerUsage != mPointerUsage) {
3933 abortPointerUsage(when, policyFlags);
3934 mPointerUsage = pointerUsage;
3935 }
3936
3937 switch (mPointerUsage) {
3938 case POINTER_USAGE_GESTURES:
3939 dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
3940 break;
3941 case POINTER_USAGE_STYLUS:
3942 dispatchPointerStylus(when, policyFlags);
3943 break;
3944 case POINTER_USAGE_MOUSE:
3945 dispatchPointerMouse(when, policyFlags);
3946 break;
3947 default:
3948 break;
3949 }
3950}
3951
3952void TouchInputMapper::abortPointerUsage(nsecs_t when, uint32_t policyFlags) {
3953 switch (mPointerUsage) {
3954 case POINTER_USAGE_GESTURES:
3955 abortPointerGestures(when, policyFlags);
3956 break;
3957 case POINTER_USAGE_STYLUS:
3958 abortPointerStylus(when, policyFlags);
3959 break;
3960 case POINTER_USAGE_MOUSE:
3961 abortPointerMouse(when, policyFlags);
3962 break;
3963 default:
3964 break;
3965 }
3966
3967 mPointerUsage = POINTER_USAGE_NONE;
3968}
3969
Jeff Brown79ac9692011-04-19 21:20:10 -07003970void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
3971 bool isTimeout) {
Jeff Brownace13b12011-03-09 17:39:48 -08003972 // Update current gesture coordinates.
3973 bool cancelPreviousGesture, finishPreviousGesture;
Jeff Brown79ac9692011-04-19 21:20:10 -07003974 bool sendEvents = preparePointerGestures(when,
3975 &cancelPreviousGesture, &finishPreviousGesture, isTimeout);
3976 if (!sendEvents) {
3977 return;
3978 }
Jeff Brown19c97d462011-06-01 12:33:19 -07003979 if (finishPreviousGesture) {
3980 cancelPreviousGesture = false;
3981 }
Jeff Brownace13b12011-03-09 17:39:48 -08003982
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003983 // Update the pointer presentation and spots.
3984 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3985 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
3986 if (finishPreviousGesture || cancelPreviousGesture) {
3987 mPointerController->clearSpots();
3988 }
Jeff Browncb5ffcf2011-06-06 20:03:18 -07003989 mPointerController->setSpots(mPointerGesture.currentGestureCoords,
3990 mPointerGesture.currentGestureIdToIndex,
3991 mPointerGesture.currentGestureIdBits);
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003992 } else {
3993 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
3994 }
Jeff Brown214eaf42011-05-26 19:17:02 -07003995
Jeff Brown538881e2011-05-25 18:23:38 -07003996 // Show or hide the pointer if needed.
3997 switch (mPointerGesture.currentGestureMode) {
3998 case PointerGesture::NEUTRAL:
3999 case PointerGesture::QUIET:
4000 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
4001 && (mPointerGesture.lastGestureMode == PointerGesture::SWIPE
4002 || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)) {
4003 // Remind the user of where the pointer is after finishing a gesture with spots.
4004 mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
4005 }
4006 break;
4007 case PointerGesture::TAP:
4008 case PointerGesture::TAP_DRAG:
4009 case PointerGesture::BUTTON_CLICK_OR_DRAG:
4010 case PointerGesture::HOVER:
4011 case PointerGesture::PRESS:
4012 // Unfade the pointer when the current gesture manipulates the
4013 // area directly under the pointer.
4014 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
4015 break;
4016 case PointerGesture::SWIPE:
4017 case PointerGesture::FREEFORM:
4018 // Fade the pointer when the current gesture manipulates a different
4019 // area and there are spots to guide the user experience.
4020 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
4021 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
4022 } else {
4023 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
4024 }
4025 break;
Jeff Brown2352b972011-04-12 22:39:53 -07004026 }
4027
Jeff Brownace13b12011-03-09 17:39:48 -08004028 // Send events!
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004029 int32_t metaState = getContext()->getGlobalMetaState();
Jeff Brownbe1aa822011-07-27 16:04:54 -07004030 int32_t buttonState = mCurrentButtonState;
Jeff Brownace13b12011-03-09 17:39:48 -08004031
4032 // Update last coordinates of pointers that have moved so that we observe the new
4033 // pointer positions at the same time as other pointers that have just gone up.
Jeff Brown79ac9692011-04-19 21:20:10 -07004034 bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP
4035 || mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG
4036 || mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
Jeff Brown2352b972011-04-12 22:39:53 -07004037 || mPointerGesture.currentGestureMode == PointerGesture::PRESS
Jeff Brownace13b12011-03-09 17:39:48 -08004038 || mPointerGesture.currentGestureMode == PointerGesture::SWIPE
4039 || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
4040 bool moveNeeded = false;
4041 if (down && !cancelPreviousGesture && !finishPreviousGesture
Jeff Brown2352b972011-04-12 22:39:53 -07004042 && !mPointerGesture.lastGestureIdBits.isEmpty()
4043 && !mPointerGesture.currentGestureIdBits.isEmpty()) {
Jeff Brownace13b12011-03-09 17:39:48 -08004044 BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value
4045 & mPointerGesture.lastGestureIdBits.value);
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004046 moveNeeded = updateMovedPointers(mPointerGesture.currentGestureProperties,
Jeff Brownace13b12011-03-09 17:39:48 -08004047 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004048 mPointerGesture.lastGestureProperties,
Jeff Brownace13b12011-03-09 17:39:48 -08004049 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
4050 movedGestureIdBits);
Jeff Brownbe1aa822011-07-27 16:04:54 -07004051 if (buttonState != mLastButtonState) {
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004052 moveNeeded = true;
4053 }
Jeff Brownace13b12011-03-09 17:39:48 -08004054 }
4055
4056 // Send motion events for all pointers that went up or were canceled.
4057 BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
4058 if (!dispatchedGestureIdBits.isEmpty()) {
4059 if (cancelPreviousGesture) {
Jeff Brown65fd2512011-08-18 11:20:58 -07004060 dispatchMotion(when, policyFlags, mSource,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004061 AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
4062 AMOTION_EVENT_EDGE_FLAG_NONE,
4063 mPointerGesture.lastGestureProperties,
Jeff Brownace13b12011-03-09 17:39:48 -08004064 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
4065 dispatchedGestureIdBits, -1,
4066 0, 0, mPointerGesture.downTime);
4067
4068 dispatchedGestureIdBits.clear();
4069 } else {
4070 BitSet32 upGestureIdBits;
4071 if (finishPreviousGesture) {
4072 upGestureIdBits = dispatchedGestureIdBits;
4073 } else {
4074 upGestureIdBits.value = dispatchedGestureIdBits.value
4075 & ~mPointerGesture.currentGestureIdBits.value;
4076 }
4077 while (!upGestureIdBits.isEmpty()) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07004078 uint32_t id = upGestureIdBits.clearFirstMarkedBit();
Jeff Brownace13b12011-03-09 17:39:48 -08004079
Jeff Brown65fd2512011-08-18 11:20:58 -07004080 dispatchMotion(when, policyFlags, mSource,
Jeff Brownace13b12011-03-09 17:39:48 -08004081 AMOTION_EVENT_ACTION_POINTER_UP, 0,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004082 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
4083 mPointerGesture.lastGestureProperties,
Jeff Brownace13b12011-03-09 17:39:48 -08004084 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
4085 dispatchedGestureIdBits, id,
4086 0, 0, mPointerGesture.downTime);
4087
4088 dispatchedGestureIdBits.clearBit(id);
4089 }
4090 }
4091 }
4092
4093 // Send motion events for all pointers that moved.
4094 if (moveNeeded) {
Jeff Brown65fd2512011-08-18 11:20:58 -07004095 dispatchMotion(when, policyFlags, mSource,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004096 AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
4097 mPointerGesture.currentGestureProperties,
Jeff Brownace13b12011-03-09 17:39:48 -08004098 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
4099 dispatchedGestureIdBits, -1,
4100 0, 0, mPointerGesture.downTime);
4101 }
4102
4103 // Send motion events for all pointers that went down.
4104 if (down) {
4105 BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value
4106 & ~dispatchedGestureIdBits.value);
4107 while (!downGestureIdBits.isEmpty()) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07004108 uint32_t id = downGestureIdBits.clearFirstMarkedBit();
Jeff Brownace13b12011-03-09 17:39:48 -08004109 dispatchedGestureIdBits.markBit(id);
4110
Jeff Brownace13b12011-03-09 17:39:48 -08004111 if (dispatchedGestureIdBits.count() == 1) {
Jeff Brownace13b12011-03-09 17:39:48 -08004112 mPointerGesture.downTime = when;
4113 }
4114
Jeff Brown65fd2512011-08-18 11:20:58 -07004115 dispatchMotion(when, policyFlags, mSource,
Jeff Browna6111372011-07-14 21:48:23 -07004116 AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004117 mPointerGesture.currentGestureProperties,
Jeff Brownace13b12011-03-09 17:39:48 -08004118 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
4119 dispatchedGestureIdBits, id,
4120 0, 0, mPointerGesture.downTime);
4121 }
4122 }
4123
Jeff Brownace13b12011-03-09 17:39:48 -08004124 // Send motion events for hover.
4125 if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
Jeff Brown65fd2512011-08-18 11:20:58 -07004126 dispatchMotion(when, policyFlags, mSource,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004127 AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
4128 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
4129 mPointerGesture.currentGestureProperties,
Jeff Brownace13b12011-03-09 17:39:48 -08004130 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
4131 mPointerGesture.currentGestureIdBits, -1,
4132 0, 0, mPointerGesture.downTime);
Jeff Brown81346812011-06-28 20:08:48 -07004133 } else if (dispatchedGestureIdBits.isEmpty()
4134 && !mPointerGesture.lastGestureIdBits.isEmpty()) {
4135 // Synthesize a hover move event after all pointers go up to indicate that
4136 // the pointer is hovering again even if the user is not currently touching
4137 // the touch pad. This ensures that a view will receive a fresh hover enter
4138 // event after a tap.
4139 float x, y;
4140 mPointerController->getPosition(&x, &y);
4141
4142 PointerProperties pointerProperties;
4143 pointerProperties.clear();
4144 pointerProperties.id = 0;
Jeff Brown49754db2011-07-01 17:37:58 -07004145 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jeff Brown81346812011-06-28 20:08:48 -07004146
4147 PointerCoords pointerCoords;
4148 pointerCoords.clear();
4149 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
4150 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
4151
Jeff Brown65fd2512011-08-18 11:20:58 -07004152 NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
Jeff Brown81346812011-06-28 20:08:48 -07004153 AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
4154 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
4155 1, &pointerProperties, &pointerCoords, 0, 0, mPointerGesture.downTime);
Jeff Brownbe1aa822011-07-27 16:04:54 -07004156 getListener()->notifyMotion(&args);
Jeff Brownace13b12011-03-09 17:39:48 -08004157 }
4158
4159 // Update state.
4160 mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode;
4161 if (!down) {
Jeff Brownace13b12011-03-09 17:39:48 -08004162 mPointerGesture.lastGestureIdBits.clear();
4163 } else {
Jeff Brownace13b12011-03-09 17:39:48 -08004164 mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits;
4165 for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07004166 uint32_t id = idBits.clearFirstMarkedBit();
Jeff Brownace13b12011-03-09 17:39:48 -08004167 uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004168 mPointerGesture.lastGestureProperties[index].copyFrom(
4169 mPointerGesture.currentGestureProperties[index]);
Jeff Brownace13b12011-03-09 17:39:48 -08004170 mPointerGesture.lastGestureCoords[index].copyFrom(
4171 mPointerGesture.currentGestureCoords[index]);
4172 mPointerGesture.lastGestureIdToIndex[id] = index;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004173 }
4174 }
4175}
4176
Jeff Brown65fd2512011-08-18 11:20:58 -07004177void TouchInputMapper::abortPointerGestures(nsecs_t when, uint32_t policyFlags) {
4178 // Cancel previously dispatches pointers.
4179 if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
4180 int32_t metaState = getContext()->getGlobalMetaState();
4181 int32_t buttonState = mCurrentButtonState;
4182 dispatchMotion(when, policyFlags, mSource,
4183 AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
4184 AMOTION_EVENT_EDGE_FLAG_NONE,
4185 mPointerGesture.lastGestureProperties,
4186 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
4187 mPointerGesture.lastGestureIdBits, -1,
4188 0, 0, mPointerGesture.downTime);
4189 }
4190
4191 // Reset the current pointer gesture.
4192 mPointerGesture.reset();
4193 mPointerVelocityControl.reset();
4194
4195 // Remove any current spots.
4196 if (mPointerController != NULL) {
4197 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
4198 mPointerController->clearSpots();
4199 }
4200}
4201
Jeff Brown79ac9692011-04-19 21:20:10 -07004202bool TouchInputMapper::preparePointerGestures(nsecs_t when,
4203 bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) {
Jeff Brownace13b12011-03-09 17:39:48 -08004204 *outCancelPreviousGesture = false;
4205 *outFinishPreviousGesture = false;
Jeff Brown6328cdc2010-07-29 18:18:33 -07004206
Jeff Brown79ac9692011-04-19 21:20:10 -07004207 // Handle TAP timeout.
4208 if (isTimeout) {
4209#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004210 ALOGD("Gestures: Processing timeout");
Jeff Brown79ac9692011-04-19 21:20:10 -07004211#endif
4212
4213 if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
Jeff Brown474dcb52011-06-14 20:22:50 -07004214 if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
Jeff Brown79ac9692011-04-19 21:20:10 -07004215 // The tap/drag timeout has not yet expired.
Jeff Brown214eaf42011-05-26 19:17:02 -07004216 getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime
Jeff Brown474dcb52011-06-14 20:22:50 -07004217 + mConfig.pointerGestureTapDragInterval);
Jeff Brown79ac9692011-04-19 21:20:10 -07004218 } else {
4219 // The tap is finished.
4220#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004221 ALOGD("Gestures: TAP finished");
Jeff Brown79ac9692011-04-19 21:20:10 -07004222#endif
4223 *outFinishPreviousGesture = true;
4224
4225 mPointerGesture.activeGestureId = -1;
4226 mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
4227 mPointerGesture.currentGestureIdBits.clear();
4228
Jeff Brown65fd2512011-08-18 11:20:58 -07004229 mPointerVelocityControl.reset();
Jeff Brown79ac9692011-04-19 21:20:10 -07004230 return true;
4231 }
4232 }
4233
4234 // We did not handle this timeout.
4235 return false;
4236 }
4237
Jeff Brown65fd2512011-08-18 11:20:58 -07004238 const uint32_t currentFingerCount = mCurrentFingerIdBits.count();
4239 const uint32_t lastFingerCount = mLastFingerIdBits.count();
4240
Jeff Brownace13b12011-03-09 17:39:48 -08004241 // Update the velocity tracker.
4242 {
4243 VelocityTracker::Position positions[MAX_POINTERS];
4244 uint32_t count = 0;
Jeff Brown65fd2512011-08-18 11:20:58 -07004245 for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); count++) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07004246 uint32_t id = idBits.clearFirstMarkedBit();
4247 const RawPointerData::Pointer& pointer = mCurrentRawPointerData.pointerForId(id);
Jeff Brown65fd2512011-08-18 11:20:58 -07004248 positions[count].x = pointer.x * mPointerXMovementScale;
4249 positions[count].y = pointer.y * mPointerYMovementScale;
Jeff Brownace13b12011-03-09 17:39:48 -08004250 }
Jeff Brownbe1aa822011-07-27 16:04:54 -07004251 mPointerGesture.velocityTracker.addMovement(when,
Jeff Brown65fd2512011-08-18 11:20:58 -07004252 mCurrentFingerIdBits, positions);
Jeff Brownace13b12011-03-09 17:39:48 -08004253 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07004254
Jeff Brownace13b12011-03-09 17:39:48 -08004255 // Pick a new active touch id if needed.
4256 // Choose an arbitrary pointer that just went down, if there is one.
4257 // Otherwise choose an arbitrary remaining pointer.
4258 // This guarantees we always have an active touch id when there is at least one pointer.
Jeff Brown2352b972011-04-12 22:39:53 -07004259 // We keep the same active touch id for as long as possible.
4260 bool activeTouchChanged = false;
4261 int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
4262 int32_t activeTouchId = lastActiveTouchId;
4263 if (activeTouchId < 0) {
Jeff Brown65fd2512011-08-18 11:20:58 -07004264 if (!mCurrentFingerIdBits.isEmpty()) {
Jeff Brown2352b972011-04-12 22:39:53 -07004265 activeTouchChanged = true;
Jeff Brownbe1aa822011-07-27 16:04:54 -07004266 activeTouchId = mPointerGesture.activeTouchId =
Jeff Brown65fd2512011-08-18 11:20:58 -07004267 mCurrentFingerIdBits.firstMarkedBit();
Jeff Brown2352b972011-04-12 22:39:53 -07004268 mPointerGesture.firstTouchTime = when;
Jeff Brownace13b12011-03-09 17:39:48 -08004269 }
Jeff Brown65fd2512011-08-18 11:20:58 -07004270 } else if (!mCurrentFingerIdBits.hasBit(activeTouchId)) {
Jeff Brown2352b972011-04-12 22:39:53 -07004271 activeTouchChanged = true;
Jeff Brown65fd2512011-08-18 11:20:58 -07004272 if (!mCurrentFingerIdBits.isEmpty()) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07004273 activeTouchId = mPointerGesture.activeTouchId =
Jeff Brown65fd2512011-08-18 11:20:58 -07004274 mCurrentFingerIdBits.firstMarkedBit();
Jeff Brown2352b972011-04-12 22:39:53 -07004275 } else {
4276 activeTouchId = mPointerGesture.activeTouchId = -1;
Jeff Brownace13b12011-03-09 17:39:48 -08004277 }
4278 }
4279
4280 // Determine whether we are in quiet time.
Jeff Brown2352b972011-04-12 22:39:53 -07004281 bool isQuietTime = false;
4282 if (activeTouchId < 0) {
4283 mPointerGesture.resetQuietTime();
4284 } else {
Jeff Brown474dcb52011-06-14 20:22:50 -07004285 isQuietTime = when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval;
Jeff Brown2352b972011-04-12 22:39:53 -07004286 if (!isQuietTime) {
4287 if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
4288 || mPointerGesture.lastGestureMode == PointerGesture::SWIPE
4289 || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)
Jeff Brown65fd2512011-08-18 11:20:58 -07004290 && currentFingerCount < 2) {
Jeff Brown2352b972011-04-12 22:39:53 -07004291 // Enter quiet time when exiting swipe or freeform state.
4292 // This is to prevent accidentally entering the hover state and flinging the
4293 // pointer when finishing a swipe and there is still one pointer left onscreen.
4294 isQuietTime = true;
Jeff Brown79ac9692011-04-19 21:20:10 -07004295 } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
Jeff Brown65fd2512011-08-18 11:20:58 -07004296 && currentFingerCount >= 2
Jeff Brownbe1aa822011-07-27 16:04:54 -07004297 && !isPointerDown(mCurrentButtonState)) {
Jeff Brown2352b972011-04-12 22:39:53 -07004298 // Enter quiet time when releasing the button and there are still two or more
4299 // fingers down. This may indicate that one finger was used to press the button
4300 // but it has not gone up yet.
4301 isQuietTime = true;
4302 }
4303 if (isQuietTime) {
4304 mPointerGesture.quietTime = when;
4305 }
Jeff Brownace13b12011-03-09 17:39:48 -08004306 }
4307 }
4308
4309 // Switch states based on button and pointer state.
4310 if (isQuietTime) {
4311 // Case 1: Quiet time. (QUIET)
4312#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004313 ALOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime
Jeff Brown474dcb52011-06-14 20:22:50 -07004314 + mConfig.pointerGestureQuietInterval - when) * 0.000001f);
Jeff Brownace13b12011-03-09 17:39:48 -08004315#endif
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004316 if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) {
4317 *outFinishPreviousGesture = true;
4318 }
Jeff Brownace13b12011-03-09 17:39:48 -08004319
4320 mPointerGesture.activeGestureId = -1;
4321 mPointerGesture.currentGestureMode = PointerGesture::QUIET;
Jeff Brownace13b12011-03-09 17:39:48 -08004322 mPointerGesture.currentGestureIdBits.clear();
Jeff Brown2352b972011-04-12 22:39:53 -07004323
Jeff Brown65fd2512011-08-18 11:20:58 -07004324 mPointerVelocityControl.reset();
Jeff Brownbe1aa822011-07-27 16:04:54 -07004325 } else if (isPointerDown(mCurrentButtonState)) {
Jeff Brown79ac9692011-04-19 21:20:10 -07004326 // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
Jeff Brownace13b12011-03-09 17:39:48 -08004327 // The pointer follows the active touch point.
4328 // Emit DOWN, MOVE, UP events at the pointer location.
4329 //
4330 // Only the active touch matters; other fingers are ignored. This policy helps
4331 // to handle the case where the user places a second finger on the touch pad
4332 // to apply the necessary force to depress an integrated button below the surface.
4333 // We don't want the second finger to be delivered to applications.
4334 //
4335 // For this to work well, we need to make sure to track the pointer that is really
4336 // active. If the user first puts one finger down to click then adds another
4337 // finger to drag then the active pointer should switch to the finger that is
4338 // being dragged.
4339#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004340 ALOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
Jeff Brown65fd2512011-08-18 11:20:58 -07004341 "currentFingerCount=%d", activeTouchId, currentFingerCount);
Jeff Brownace13b12011-03-09 17:39:48 -08004342#endif
4343 // Reset state when just starting.
Jeff Brown79ac9692011-04-19 21:20:10 -07004344 if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
Jeff Brownace13b12011-03-09 17:39:48 -08004345 *outFinishPreviousGesture = true;
4346 mPointerGesture.activeGestureId = 0;
4347 }
4348
4349 // Switch pointers if needed.
4350 // Find the fastest pointer and follow it.
Jeff Brown65fd2512011-08-18 11:20:58 -07004351 if (activeTouchId >= 0 && currentFingerCount > 1) {
Jeff Brown19c97d462011-06-01 12:33:19 -07004352 int32_t bestId = -1;
Jeff Brown474dcb52011-06-14 20:22:50 -07004353 float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed;
Jeff Brown65fd2512011-08-18 11:20:58 -07004354 for (BitSet32 idBits(mCurrentFingerIdBits); !idBits.isEmpty(); ) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07004355 uint32_t id = idBits.clearFirstMarkedBit();
Jeff Brown19c97d462011-06-01 12:33:19 -07004356 float vx, vy;
4357 if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
4358 float speed = hypotf(vx, vy);
4359 if (speed > bestSpeed) {
4360 bestId = id;
4361 bestSpeed = speed;
Jeff Brownace13b12011-03-09 17:39:48 -08004362 }
Jeff Brown8d608662010-08-30 03:02:23 -07004363 }
Jeff Brown19c97d462011-06-01 12:33:19 -07004364 }
4365 if (bestId >= 0 && bestId != activeTouchId) {
4366 mPointerGesture.activeTouchId = activeTouchId = bestId;
4367 activeTouchChanged = true;
Jeff Brownace13b12011-03-09 17:39:48 -08004368#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004369 ALOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
Jeff Brown19c97d462011-06-01 12:33:19 -07004370 "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
Jeff Brownace13b12011-03-09 17:39:48 -08004371#endif
Jeff Brown6328cdc2010-07-29 18:18:33 -07004372 }
Jeff Brown19c97d462011-06-01 12:33:19 -07004373 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07004374
Jeff Brown65fd2512011-08-18 11:20:58 -07004375 if (activeTouchId >= 0 && mLastFingerIdBits.hasBit(activeTouchId)) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07004376 const RawPointerData::Pointer& currentPointer =
4377 mCurrentRawPointerData.pointerForId(activeTouchId);
4378 const RawPointerData::Pointer& lastPointer =
4379 mLastRawPointerData.pointerForId(activeTouchId);
Jeff Brown65fd2512011-08-18 11:20:58 -07004380 float deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
4381 float deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
Jeff Brown2352b972011-04-12 22:39:53 -07004382
Jeff Brownbe1aa822011-07-27 16:04:54 -07004383 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
Jeff Brown65fd2512011-08-18 11:20:58 -07004384 mPointerVelocityControl.move(when, &deltaX, &deltaY);
Jeff Brown19c97d462011-06-01 12:33:19 -07004385
4386 // Move the pointer using a relative motion.
4387 // When using spots, the click will occur at the position of the anchor
4388 // spot and all other spots will move there.
4389 mPointerController->move(deltaX, deltaY);
4390 } else {
Jeff Brown65fd2512011-08-18 11:20:58 -07004391 mPointerVelocityControl.reset();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004392 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07004393
Jeff Brownace13b12011-03-09 17:39:48 -08004394 float x, y;
4395 mPointerController->getPosition(&x, &y);
Jeff Brown91c69ab2011-02-14 17:03:18 -08004396
Jeff Brown79ac9692011-04-19 21:20:10 -07004397 mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
Jeff Brownace13b12011-03-09 17:39:48 -08004398 mPointerGesture.currentGestureIdBits.clear();
4399 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
4400 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004401 mPointerGesture.currentGestureProperties[0].clear();
4402 mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
Jeff Brown49754db2011-07-01 17:37:58 -07004403 mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jeff Brownace13b12011-03-09 17:39:48 -08004404 mPointerGesture.currentGestureCoords[0].clear();
4405 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
4406 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
4407 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
Jeff Brown65fd2512011-08-18 11:20:58 -07004408 } else if (currentFingerCount == 0) {
Jeff Brownace13b12011-03-09 17:39:48 -08004409 // Case 3. No fingers down and button is not pressed. (NEUTRAL)
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004410 if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
4411 *outFinishPreviousGesture = true;
4412 }
Jeff Brownace13b12011-03-09 17:39:48 -08004413
Jeff Brown79ac9692011-04-19 21:20:10 -07004414 // Watch for taps coming out of HOVER or TAP_DRAG mode.
Jeff Brown214eaf42011-05-26 19:17:02 -07004415 // Checking for taps after TAP_DRAG allows us to detect double-taps.
Jeff Brownace13b12011-03-09 17:39:48 -08004416 bool tapped = false;
Jeff Brown79ac9692011-04-19 21:20:10 -07004417 if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
4418 || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
Jeff Brown65fd2512011-08-18 11:20:58 -07004419 && lastFingerCount == 1) {
Jeff Brown474dcb52011-06-14 20:22:50 -07004420 if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) {
Jeff Brownace13b12011-03-09 17:39:48 -08004421 float x, y;
4422 mPointerController->getPosition(&x, &y);
Jeff Brown474dcb52011-06-14 20:22:50 -07004423 if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
4424 && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
Jeff Brownace13b12011-03-09 17:39:48 -08004425#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004426 ALOGD("Gestures: TAP");
Jeff Brownace13b12011-03-09 17:39:48 -08004427#endif
Jeff Brown79ac9692011-04-19 21:20:10 -07004428
4429 mPointerGesture.tapUpTime = when;
Jeff Brown214eaf42011-05-26 19:17:02 -07004430 getContext()->requestTimeoutAtTime(when
Jeff Brown474dcb52011-06-14 20:22:50 -07004431 + mConfig.pointerGestureTapDragInterval);
Jeff Brown79ac9692011-04-19 21:20:10 -07004432
Jeff Brownace13b12011-03-09 17:39:48 -08004433 mPointerGesture.activeGestureId = 0;
4434 mPointerGesture.currentGestureMode = PointerGesture::TAP;
Jeff Brownace13b12011-03-09 17:39:48 -08004435 mPointerGesture.currentGestureIdBits.clear();
4436 mPointerGesture.currentGestureIdBits.markBit(
4437 mPointerGesture.activeGestureId);
4438 mPointerGesture.currentGestureIdToIndex[
4439 mPointerGesture.activeGestureId] = 0;
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004440 mPointerGesture.currentGestureProperties[0].clear();
4441 mPointerGesture.currentGestureProperties[0].id =
4442 mPointerGesture.activeGestureId;
4443 mPointerGesture.currentGestureProperties[0].toolType =
Jeff Brown49754db2011-07-01 17:37:58 -07004444 AMOTION_EVENT_TOOL_TYPE_FINGER;
Jeff Brownace13b12011-03-09 17:39:48 -08004445 mPointerGesture.currentGestureCoords[0].clear();
4446 mPointerGesture.currentGestureCoords[0].setAxisValue(
Jeff Brown2352b972011-04-12 22:39:53 -07004447 AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
Jeff Brownace13b12011-03-09 17:39:48 -08004448 mPointerGesture.currentGestureCoords[0].setAxisValue(
Jeff Brown2352b972011-04-12 22:39:53 -07004449 AMOTION_EVENT_AXIS_Y, mPointerGesture.tapY);
Jeff Brownace13b12011-03-09 17:39:48 -08004450 mPointerGesture.currentGestureCoords[0].setAxisValue(
4451 AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
Jeff Brown2352b972011-04-12 22:39:53 -07004452
Jeff Brownace13b12011-03-09 17:39:48 -08004453 tapped = true;
4454 } else {
4455#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004456 ALOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f",
Jeff Brown2352b972011-04-12 22:39:53 -07004457 x - mPointerGesture.tapX,
4458 y - mPointerGesture.tapY);
Jeff Brownace13b12011-03-09 17:39:48 -08004459#endif
4460 }
4461 } else {
4462#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004463 ALOGD("Gestures: Not a TAP, %0.3fms since down",
Jeff Brown79ac9692011-04-19 21:20:10 -07004464 (when - mPointerGesture.tapDownTime) * 0.000001f);
Jeff Brownace13b12011-03-09 17:39:48 -08004465#endif
Jeff Brown6328cdc2010-07-29 18:18:33 -07004466 }
Jeff Brownace13b12011-03-09 17:39:48 -08004467 }
Jeff Brown2352b972011-04-12 22:39:53 -07004468
Jeff Brown65fd2512011-08-18 11:20:58 -07004469 mPointerVelocityControl.reset();
Jeff Brown19c97d462011-06-01 12:33:19 -07004470
Jeff Brownace13b12011-03-09 17:39:48 -08004471 if (!tapped) {
4472#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004473 ALOGD("Gestures: NEUTRAL");
Jeff Brownace13b12011-03-09 17:39:48 -08004474#endif
4475 mPointerGesture.activeGestureId = -1;
4476 mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
Jeff Brownace13b12011-03-09 17:39:48 -08004477 mPointerGesture.currentGestureIdBits.clear();
4478 }
Jeff Brown65fd2512011-08-18 11:20:58 -07004479 } else if (currentFingerCount == 1) {
Jeff Brown79ac9692011-04-19 21:20:10 -07004480 // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
Jeff Brownace13b12011-03-09 17:39:48 -08004481 // The pointer follows the active touch point.
Jeff Brown79ac9692011-04-19 21:20:10 -07004482 // When in HOVER, emit HOVER_MOVE events at the pointer location.
4483 // When in TAP_DRAG, emit MOVE events at the pointer location.
Steve Blockec193de2012-01-09 18:35:44 +00004484 ALOG_ASSERT(activeTouchId >= 0);
Jeff Brownace13b12011-03-09 17:39:48 -08004485
Jeff Brown79ac9692011-04-19 21:20:10 -07004486 mPointerGesture.currentGestureMode = PointerGesture::HOVER;
4487 if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
Jeff Brown474dcb52011-06-14 20:22:50 -07004488 if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
Jeff Brown79ac9692011-04-19 21:20:10 -07004489 float x, y;
4490 mPointerController->getPosition(&x, &y);
Jeff Brown474dcb52011-06-14 20:22:50 -07004491 if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
4492 && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
Jeff Brown79ac9692011-04-19 21:20:10 -07004493 mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
4494 } else {
Jeff Brownace13b12011-03-09 17:39:48 -08004495#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004496 ALOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
Jeff Brown79ac9692011-04-19 21:20:10 -07004497 x - mPointerGesture.tapX,
4498 y - mPointerGesture.tapY);
Jeff Brownace13b12011-03-09 17:39:48 -08004499#endif
Jeff Brown79ac9692011-04-19 21:20:10 -07004500 }
4501 } else {
4502#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004503 ALOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
Jeff Brown79ac9692011-04-19 21:20:10 -07004504 (when - mPointerGesture.tapUpTime) * 0.000001f);
4505#endif
4506 }
4507 } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
4508 mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
4509 }
Jeff Brownace13b12011-03-09 17:39:48 -08004510
Jeff Brown65fd2512011-08-18 11:20:58 -07004511 if (mLastFingerIdBits.hasBit(activeTouchId)) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07004512 const RawPointerData::Pointer& currentPointer =
4513 mCurrentRawPointerData.pointerForId(activeTouchId);
4514 const RawPointerData::Pointer& lastPointer =
4515 mLastRawPointerData.pointerForId(activeTouchId);
Jeff Brownace13b12011-03-09 17:39:48 -08004516 float deltaX = (currentPointer.x - lastPointer.x)
Jeff Brown65fd2512011-08-18 11:20:58 -07004517 * mPointerXMovementScale;
Jeff Brownace13b12011-03-09 17:39:48 -08004518 float deltaY = (currentPointer.y - lastPointer.y)
Jeff Brown65fd2512011-08-18 11:20:58 -07004519 * mPointerYMovementScale;
Jeff Brown2352b972011-04-12 22:39:53 -07004520
Jeff Brownbe1aa822011-07-27 16:04:54 -07004521 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
Jeff Brown65fd2512011-08-18 11:20:58 -07004522 mPointerVelocityControl.move(when, &deltaX, &deltaY);
Jeff Brown19c97d462011-06-01 12:33:19 -07004523
Jeff Brown2352b972011-04-12 22:39:53 -07004524 // Move the pointer using a relative motion.
Jeff Brown79ac9692011-04-19 21:20:10 -07004525 // When using spots, the hover or drag will occur at the position of the anchor spot.
Jeff Brownace13b12011-03-09 17:39:48 -08004526 mPointerController->move(deltaX, deltaY);
Jeff Brown19c97d462011-06-01 12:33:19 -07004527 } else {
Jeff Brown65fd2512011-08-18 11:20:58 -07004528 mPointerVelocityControl.reset();
Jeff Brownace13b12011-03-09 17:39:48 -08004529 }
4530
Jeff Brown79ac9692011-04-19 21:20:10 -07004531 bool down;
4532 if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
4533#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004534 ALOGD("Gestures: TAP_DRAG");
Jeff Brown79ac9692011-04-19 21:20:10 -07004535#endif
4536 down = true;
4537 } else {
4538#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004539 ALOGD("Gestures: HOVER");
Jeff Brown79ac9692011-04-19 21:20:10 -07004540#endif
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004541 if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) {
4542 *outFinishPreviousGesture = true;
4543 }
Jeff Brown79ac9692011-04-19 21:20:10 -07004544 mPointerGesture.activeGestureId = 0;
4545 down = false;
4546 }
Jeff Brownace13b12011-03-09 17:39:48 -08004547
4548 float x, y;
4549 mPointerController->getPosition(&x, &y);
4550
Jeff Brownace13b12011-03-09 17:39:48 -08004551 mPointerGesture.currentGestureIdBits.clear();
4552 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
4553 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004554 mPointerGesture.currentGestureProperties[0].clear();
4555 mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
4556 mPointerGesture.currentGestureProperties[0].toolType =
Jeff Brown49754db2011-07-01 17:37:58 -07004557 AMOTION_EVENT_TOOL_TYPE_FINGER;
Jeff Brownace13b12011-03-09 17:39:48 -08004558 mPointerGesture.currentGestureCoords[0].clear();
4559 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
4560 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Jeff Brown79ac9692011-04-19 21:20:10 -07004561 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
4562 down ? 1.0f : 0.0f);
4563
Jeff Brown65fd2512011-08-18 11:20:58 -07004564 if (lastFingerCount == 0 && currentFingerCount != 0) {
Jeff Brown79ac9692011-04-19 21:20:10 -07004565 mPointerGesture.resetTap();
4566 mPointerGesture.tapDownTime = when;
Jeff Brown2352b972011-04-12 22:39:53 -07004567 mPointerGesture.tapX = x;
4568 mPointerGesture.tapY = y;
4569 }
Jeff Brownace13b12011-03-09 17:39:48 -08004570 } else {
Jeff Brown2352b972011-04-12 22:39:53 -07004571 // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
4572 // We need to provide feedback for each finger that goes down so we cannot wait
4573 // for the fingers to move before deciding what to do.
Jeff Brownace13b12011-03-09 17:39:48 -08004574 //
Jeff Brown2352b972011-04-12 22:39:53 -07004575 // The ambiguous case is deciding what to do when there are two fingers down but they
4576 // have not moved enough to determine whether they are part of a drag or part of a
4577 // freeform gesture, or just a press or long-press at the pointer location.
4578 //
4579 // When there are two fingers we start with the PRESS hypothesis and we generate a
4580 // down at the pointer location.
4581 //
4582 // When the two fingers move enough or when additional fingers are added, we make
4583 // a decision to transition into SWIPE or FREEFORM mode accordingly.
Steve Blockec193de2012-01-09 18:35:44 +00004584 ALOG_ASSERT(activeTouchId >= 0);
Jeff Brownace13b12011-03-09 17:39:48 -08004585
Jeff Brown214eaf42011-05-26 19:17:02 -07004586 bool settled = when >= mPointerGesture.firstTouchTime
Jeff Brown474dcb52011-06-14 20:22:50 -07004587 + mConfig.pointerGestureMultitouchSettleInterval;
Jeff Brown2352b972011-04-12 22:39:53 -07004588 if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
Jeff Brownace13b12011-03-09 17:39:48 -08004589 && mPointerGesture.lastGestureMode != PointerGesture::SWIPE
4590 && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
Jeff Brownace13b12011-03-09 17:39:48 -08004591 *outFinishPreviousGesture = true;
Jeff Brown65fd2512011-08-18 11:20:58 -07004592 } else if (!settled && currentFingerCount > lastFingerCount) {
Jeff Brown19c97d462011-06-01 12:33:19 -07004593 // Additional pointers have gone down but not yet settled.
4594 // Reset the gesture.
4595#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004596 ALOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004597 "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
Jeff Brown474dcb52011-06-14 20:22:50 -07004598 + mConfig.pointerGestureMultitouchSettleInterval - when)
Jeff Brown19c97d462011-06-01 12:33:19 -07004599 * 0.000001f);
4600#endif
4601 *outCancelPreviousGesture = true;
4602 } else {
4603 // Continue previous gesture.
4604 mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
4605 }
4606
4607 if (*outFinishPreviousGesture || *outCancelPreviousGesture) {
Jeff Brown2352b972011-04-12 22:39:53 -07004608 mPointerGesture.currentGestureMode = PointerGesture::PRESS;
4609 mPointerGesture.activeGestureId = 0;
Jeff Brown538881e2011-05-25 18:23:38 -07004610 mPointerGesture.referenceIdBits.clear();
Jeff Brown65fd2512011-08-18 11:20:58 -07004611 mPointerVelocityControl.reset();
Jeff Brownace13b12011-03-09 17:39:48 -08004612
Jeff Browncb5ffcf2011-06-06 20:03:18 -07004613 // Use the centroid and pointer location as the reference points for the gesture.
Jeff Brown2352b972011-04-12 22:39:53 -07004614#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004615 ALOGD("Gestures: Using centroid as reference for MULTITOUCH, "
Jeff Browncb5ffcf2011-06-06 20:03:18 -07004616 "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
Jeff Brown474dcb52011-06-14 20:22:50 -07004617 + mConfig.pointerGestureMultitouchSettleInterval - when)
Jeff Browncb5ffcf2011-06-06 20:03:18 -07004618 * 0.000001f);
Jeff Brown2352b972011-04-12 22:39:53 -07004619#endif
Jeff Brownbe1aa822011-07-27 16:04:54 -07004620 mCurrentRawPointerData.getCentroidOfTouchingPointers(
4621 &mPointerGesture.referenceTouchX,
Jeff Browncb5ffcf2011-06-06 20:03:18 -07004622 &mPointerGesture.referenceTouchY);
4623 mPointerController->getPosition(&mPointerGesture.referenceGestureX,
4624 &mPointerGesture.referenceGestureY);
Jeff Brown2352b972011-04-12 22:39:53 -07004625 }
Jeff Brownace13b12011-03-09 17:39:48 -08004626
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004627 // Clear the reference deltas for fingers not yet included in the reference calculation.
Jeff Brown65fd2512011-08-18 11:20:58 -07004628 for (BitSet32 idBits(mCurrentFingerIdBits.value
Jeff Brownbe1aa822011-07-27 16:04:54 -07004629 & ~mPointerGesture.referenceIdBits.value); !idBits.isEmpty(); ) {
4630 uint32_t id = idBits.clearFirstMarkedBit();
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004631 mPointerGesture.referenceDeltas[id].dx = 0;
4632 mPointerGesture.referenceDeltas[id].dy = 0;
4633 }
Jeff Brown65fd2512011-08-18 11:20:58 -07004634 mPointerGesture.referenceIdBits = mCurrentFingerIdBits;
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004635
4636 // Add delta for all fingers and calculate a common movement delta.
4637 float commonDeltaX = 0, commonDeltaY = 0;
Jeff Brown65fd2512011-08-18 11:20:58 -07004638 BitSet32 commonIdBits(mLastFingerIdBits.value
4639 & mCurrentFingerIdBits.value);
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004640 for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
4641 bool first = (idBits == commonIdBits);
Jeff Brownbe1aa822011-07-27 16:04:54 -07004642 uint32_t id = idBits.clearFirstMarkedBit();
4643 const RawPointerData::Pointer& cpd = mCurrentRawPointerData.pointerForId(id);
4644 const RawPointerData::Pointer& lpd = mLastRawPointerData.pointerForId(id);
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004645 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
4646 delta.dx += cpd.x - lpd.x;
4647 delta.dy += cpd.y - lpd.y;
4648
4649 if (first) {
4650 commonDeltaX = delta.dx;
4651 commonDeltaY = delta.dy;
Jeff Brown2352b972011-04-12 22:39:53 -07004652 } else {
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004653 commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
4654 commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
4655 }
4656 }
Jeff Brownace13b12011-03-09 17:39:48 -08004657
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004658 // Consider transitions from PRESS to SWIPE or MULTITOUCH.
4659 if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
4660 float dist[MAX_POINTER_ID + 1];
4661 int32_t distOverThreshold = 0;
4662 for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07004663 uint32_t id = idBits.clearFirstMarkedBit();
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004664 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
Jeff Brown65fd2512011-08-18 11:20:58 -07004665 dist[id] = hypotf(delta.dx * mPointerXZoomScale,
4666 delta.dy * mPointerYZoomScale);
Jeff Brown474dcb52011-06-14 20:22:50 -07004667 if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) {
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004668 distOverThreshold += 1;
4669 }
4670 }
4671
4672 // Only transition when at least two pointers have moved further than
4673 // the minimum distance threshold.
4674 if (distOverThreshold >= 2) {
Jeff Brown65fd2512011-08-18 11:20:58 -07004675 if (currentFingerCount > 2) {
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004676 // There are more than two pointers, switch to FREEFORM.
Jeff Brown2352b972011-04-12 22:39:53 -07004677#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004678 ALOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
Jeff Brown65fd2512011-08-18 11:20:58 -07004679 currentFingerCount);
Jeff Brown2352b972011-04-12 22:39:53 -07004680#endif
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004681 *outCancelPreviousGesture = true;
4682 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
4683 } else {
Jeff Brownbe1aa822011-07-27 16:04:54 -07004684 // There are exactly two pointers.
Jeff Brown65fd2512011-08-18 11:20:58 -07004685 BitSet32 idBits(mCurrentFingerIdBits);
Jeff Brownbe1aa822011-07-27 16:04:54 -07004686 uint32_t id1 = idBits.clearFirstMarkedBit();
4687 uint32_t id2 = idBits.firstMarkedBit();
4688 const RawPointerData::Pointer& p1 = mCurrentRawPointerData.pointerForId(id1);
4689 const RawPointerData::Pointer& p2 = mCurrentRawPointerData.pointerForId(id2);
4690 float mutualDistance = distance(p1.x, p1.y, p2.x, p2.y);
4691 if (mutualDistance > mPointerGestureMaxSwipeWidth) {
4692 // There are two pointers but they are too far apart for a SWIPE,
4693 // switch to FREEFORM.
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004694#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004695 ALOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
Jeff Brownbe1aa822011-07-27 16:04:54 -07004696 mutualDistance, mPointerGestureMaxSwipeWidth);
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004697#endif
Jeff Brownbe1aa822011-07-27 16:04:54 -07004698 *outCancelPreviousGesture = true;
4699 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
4700 } else {
4701 // There are two pointers. Wait for both pointers to start moving
4702 // before deciding whether this is a SWIPE or FREEFORM gesture.
4703 float dist1 = dist[id1];
4704 float dist2 = dist[id2];
4705 if (dist1 >= mConfig.pointerGestureMultitouchMinDistance
4706 && dist2 >= mConfig.pointerGestureMultitouchMinDistance) {
4707 // Calculate the dot product of the displacement vectors.
4708 // When the vectors are oriented in approximately the same direction,
4709 // the angle betweeen them is near zero and the cosine of the angle
4710 // approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
4711 PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1];
4712 PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2];
Jeff Brown65fd2512011-08-18 11:20:58 -07004713 float dx1 = delta1.dx * mPointerXZoomScale;
4714 float dy1 = delta1.dy * mPointerYZoomScale;
4715 float dx2 = delta2.dx * mPointerXZoomScale;
4716 float dy2 = delta2.dy * mPointerYZoomScale;
Jeff Brownbe1aa822011-07-27 16:04:54 -07004717 float dot = dx1 * dx2 + dy1 * dy2;
4718 float cosine = dot / (dist1 * dist2); // denominator always > 0
4719 if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) {
4720 // Pointers are moving in the same direction. Switch to SWIPE.
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004721#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004722 ALOGD("Gestures: PRESS transitioned to SWIPE, "
Jeff Brownbe1aa822011-07-27 16:04:54 -07004723 "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
4724 "cosine %0.3f >= %0.3f",
4725 dist1, mConfig.pointerGestureMultitouchMinDistance,
4726 dist2, mConfig.pointerGestureMultitouchMinDistance,
4727 cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004728#endif
Jeff Brownbe1aa822011-07-27 16:04:54 -07004729 mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
4730 } else {
4731 // Pointers are moving in different directions. Switch to FREEFORM.
4732#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004733 ALOGD("Gestures: PRESS transitioned to FREEFORM, "
Jeff Brownbe1aa822011-07-27 16:04:54 -07004734 "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
4735 "cosine %0.3f < %0.3f",
4736 dist1, mConfig.pointerGestureMultitouchMinDistance,
4737 dist2, mConfig.pointerGestureMultitouchMinDistance,
4738 cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
4739#endif
4740 *outCancelPreviousGesture = true;
4741 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
4742 }
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004743 }
Jeff Brownace13b12011-03-09 17:39:48 -08004744 }
4745 }
Jeff Brownace13b12011-03-09 17:39:48 -08004746 }
4747 } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
Jeff Brown2352b972011-04-12 22:39:53 -07004748 // Switch from SWIPE to FREEFORM if additional pointers go down.
4749 // Cancel previous gesture.
Jeff Brown65fd2512011-08-18 11:20:58 -07004750 if (currentFingerCount > 2) {
Jeff Brown2352b972011-04-12 22:39:53 -07004751#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004752 ALOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
Jeff Brown65fd2512011-08-18 11:20:58 -07004753 currentFingerCount);
Jeff Brown2352b972011-04-12 22:39:53 -07004754#endif
Jeff Brownace13b12011-03-09 17:39:48 -08004755 *outCancelPreviousGesture = true;
4756 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
Jeff Brown6328cdc2010-07-29 18:18:33 -07004757 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004758 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07004759
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004760 // Move the reference points based on the overall group motion of the fingers
4761 // except in PRESS mode while waiting for a transition to occur.
4762 if (mPointerGesture.currentGestureMode != PointerGesture::PRESS
4763 && (commonDeltaX || commonDeltaY)) {
4764 for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07004765 uint32_t id = idBits.clearFirstMarkedBit();
Jeff Brown538881e2011-05-25 18:23:38 -07004766 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004767 delta.dx = 0;
4768 delta.dy = 0;
Jeff Brown2352b972011-04-12 22:39:53 -07004769 }
4770
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004771 mPointerGesture.referenceTouchX += commonDeltaX;
4772 mPointerGesture.referenceTouchY += commonDeltaY;
Jeff Brown538881e2011-05-25 18:23:38 -07004773
Jeff Brown65fd2512011-08-18 11:20:58 -07004774 commonDeltaX *= mPointerXMovementScale;
4775 commonDeltaY *= mPointerYMovementScale;
Jeff Brown612891e2011-07-15 20:44:17 -07004776
Jeff Brownbe1aa822011-07-27 16:04:54 -07004777 rotateDelta(mSurfaceOrientation, &commonDeltaX, &commonDeltaY);
Jeff Brown65fd2512011-08-18 11:20:58 -07004778 mPointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
Jeff Brown538881e2011-05-25 18:23:38 -07004779
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004780 mPointerGesture.referenceGestureX += commonDeltaX;
4781 mPointerGesture.referenceGestureY += commonDeltaY;
Jeff Brown2352b972011-04-12 22:39:53 -07004782 }
4783
4784 // Report gestures.
Jeff Brown612891e2011-07-15 20:44:17 -07004785 if (mPointerGesture.currentGestureMode == PointerGesture::PRESS
4786 || mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
4787 // PRESS or SWIPE mode.
Jeff Brownace13b12011-03-09 17:39:48 -08004788#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004789 ALOGD("Gestures: PRESS or SWIPE activeTouchId=%d,"
Jeff Brown2352b972011-04-12 22:39:53 -07004790 "activeGestureId=%d, currentTouchPointerCount=%d",
Jeff Brown65fd2512011-08-18 11:20:58 -07004791 activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
Jeff Brown2352b972011-04-12 22:39:53 -07004792#endif
Steve Blockec193de2012-01-09 18:35:44 +00004793 ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
Jeff Brown2352b972011-04-12 22:39:53 -07004794
4795 mPointerGesture.currentGestureIdBits.clear();
4796 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
4797 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004798 mPointerGesture.currentGestureProperties[0].clear();
4799 mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
4800 mPointerGesture.currentGestureProperties[0].toolType =
Jeff Brown49754db2011-07-01 17:37:58 -07004801 AMOTION_EVENT_TOOL_TYPE_FINGER;
Jeff Brown2352b972011-04-12 22:39:53 -07004802 mPointerGesture.currentGestureCoords[0].clear();
4803 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
4804 mPointerGesture.referenceGestureX);
4805 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
4806 mPointerGesture.referenceGestureY);
4807 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
Jeff Brownace13b12011-03-09 17:39:48 -08004808 } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
4809 // FREEFORM mode.
4810#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004811 ALOGD("Gestures: FREEFORM activeTouchId=%d,"
Jeff Brownace13b12011-03-09 17:39:48 -08004812 "activeGestureId=%d, currentTouchPointerCount=%d",
Jeff Brown65fd2512011-08-18 11:20:58 -07004813 activeTouchId, mPointerGesture.activeGestureId, currentFingerCount);
Jeff Brownace13b12011-03-09 17:39:48 -08004814#endif
Steve Blockec193de2012-01-09 18:35:44 +00004815 ALOG_ASSERT(mPointerGesture.activeGestureId >= 0);
Jeff Brownace13b12011-03-09 17:39:48 -08004816
Jeff Brownace13b12011-03-09 17:39:48 -08004817 mPointerGesture.currentGestureIdBits.clear();
4818
4819 BitSet32 mappedTouchIdBits;
4820 BitSet32 usedGestureIdBits;
4821 if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
4822 // Initially, assign the active gesture id to the active touch point
4823 // if there is one. No other touch id bits are mapped yet.
4824 if (!*outCancelPreviousGesture) {
4825 mappedTouchIdBits.markBit(activeTouchId);
4826 usedGestureIdBits.markBit(mPointerGesture.activeGestureId);
4827 mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] =
4828 mPointerGesture.activeGestureId;
4829 } else {
4830 mPointerGesture.activeGestureId = -1;
4831 }
4832 } else {
4833 // Otherwise, assume we mapped all touches from the previous frame.
4834 // Reuse all mappings that are still applicable.
Jeff Brown65fd2512011-08-18 11:20:58 -07004835 mappedTouchIdBits.value = mLastFingerIdBits.value
4836 & mCurrentFingerIdBits.value;
Jeff Brownace13b12011-03-09 17:39:48 -08004837 usedGestureIdBits = mPointerGesture.lastGestureIdBits;
4838
4839 // Check whether we need to choose a new active gesture id because the
4840 // current went went up.
Jeff Brown65fd2512011-08-18 11:20:58 -07004841 for (BitSet32 upTouchIdBits(mLastFingerIdBits.value
4842 & ~mCurrentFingerIdBits.value);
Jeff Brownace13b12011-03-09 17:39:48 -08004843 !upTouchIdBits.isEmpty(); ) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07004844 uint32_t upTouchId = upTouchIdBits.clearFirstMarkedBit();
Jeff Brownace13b12011-03-09 17:39:48 -08004845 uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
4846 if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) {
4847 mPointerGesture.activeGestureId = -1;
4848 break;
4849 }
4850 }
4851 }
4852
4853#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004854 ALOGD("Gestures: FREEFORM follow up "
Jeff Brownace13b12011-03-09 17:39:48 -08004855 "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
4856 "activeGestureId=%d",
4857 mappedTouchIdBits.value, usedGestureIdBits.value,
4858 mPointerGesture.activeGestureId);
4859#endif
4860
Jeff Brown65fd2512011-08-18 11:20:58 -07004861 BitSet32 idBits(mCurrentFingerIdBits);
4862 for (uint32_t i = 0; i < currentFingerCount; i++) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07004863 uint32_t touchId = idBits.clearFirstMarkedBit();
Jeff Brownace13b12011-03-09 17:39:48 -08004864 uint32_t gestureId;
4865 if (!mappedTouchIdBits.hasBit(touchId)) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07004866 gestureId = usedGestureIdBits.markFirstUnmarkedBit();
Jeff Brownace13b12011-03-09 17:39:48 -08004867 mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
4868#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004869 ALOGD("Gestures: FREEFORM "
Jeff Brownace13b12011-03-09 17:39:48 -08004870 "new mapping for touch id %d -> gesture id %d",
4871 touchId, gestureId);
4872#endif
4873 } else {
4874 gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
4875#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004876 ALOGD("Gestures: FREEFORM "
Jeff Brownace13b12011-03-09 17:39:48 -08004877 "existing mapping for touch id %d -> gesture id %d",
4878 touchId, gestureId);
4879#endif
4880 }
4881 mPointerGesture.currentGestureIdBits.markBit(gestureId);
4882 mPointerGesture.currentGestureIdToIndex[gestureId] = i;
4883
Jeff Brownbe1aa822011-07-27 16:04:54 -07004884 const RawPointerData::Pointer& pointer =
4885 mCurrentRawPointerData.pointerForId(touchId);
4886 float deltaX = (pointer.x - mPointerGesture.referenceTouchX)
Jeff Brown65fd2512011-08-18 11:20:58 -07004887 * mPointerXZoomScale;
Jeff Brownbe1aa822011-07-27 16:04:54 -07004888 float deltaY = (pointer.y - mPointerGesture.referenceTouchY)
Jeff Brown65fd2512011-08-18 11:20:58 -07004889 * mPointerYZoomScale;
Jeff Brownbe1aa822011-07-27 16:04:54 -07004890 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
Jeff Brownace13b12011-03-09 17:39:48 -08004891
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004892 mPointerGesture.currentGestureProperties[i].clear();
4893 mPointerGesture.currentGestureProperties[i].id = gestureId;
4894 mPointerGesture.currentGestureProperties[i].toolType =
Jeff Brown49754db2011-07-01 17:37:58 -07004895 AMOTION_EVENT_TOOL_TYPE_FINGER;
Jeff Brownace13b12011-03-09 17:39:48 -08004896 mPointerGesture.currentGestureCoords[i].clear();
4897 mPointerGesture.currentGestureCoords[i].setAxisValue(
Jeff Brown612891e2011-07-15 20:44:17 -07004898 AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX + deltaX);
Jeff Brownace13b12011-03-09 17:39:48 -08004899 mPointerGesture.currentGestureCoords[i].setAxisValue(
Jeff Brown612891e2011-07-15 20:44:17 -07004900 AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY + deltaY);
Jeff Brownace13b12011-03-09 17:39:48 -08004901 mPointerGesture.currentGestureCoords[i].setAxisValue(
4902 AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4903 }
4904
4905 if (mPointerGesture.activeGestureId < 0) {
4906 mPointerGesture.activeGestureId =
4907 mPointerGesture.currentGestureIdBits.firstMarkedBit();
4908#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004909 ALOGD("Gestures: FREEFORM new "
Jeff Brownace13b12011-03-09 17:39:48 -08004910 "activeGestureId=%d", mPointerGesture.activeGestureId);
4911#endif
4912 }
Jeff Brown2352b972011-04-12 22:39:53 -07004913 }
Jeff Brownace13b12011-03-09 17:39:48 -08004914 }
4915
Jeff Brownbe1aa822011-07-27 16:04:54 -07004916 mPointerController->setButtonState(mCurrentButtonState);
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004917
Jeff Brownace13b12011-03-09 17:39:48 -08004918#if DEBUG_GESTURES
Steve Block5baa3a62011-12-20 16:23:08 +00004919 ALOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
Jeff Brown2352b972011-04-12 22:39:53 -07004920 "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
4921 "lastGestureMode=%d, lastGestureIdBits=0x%08x",
Jeff Brownace13b12011-03-09 17:39:48 -08004922 toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
Jeff Brown2352b972011-04-12 22:39:53 -07004923 mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
4924 mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
Jeff Brownace13b12011-03-09 17:39:48 -08004925 for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty(); ) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07004926 uint32_t id = idBits.clearFirstMarkedBit();
Jeff Brownace13b12011-03-09 17:39:48 -08004927 uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004928 const PointerProperties& properties = mPointerGesture.currentGestureProperties[index];
Jeff Brownace13b12011-03-09 17:39:48 -08004929 const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
Steve Block5baa3a62011-12-20 16:23:08 +00004930 ALOGD(" currentGesture[%d]: index=%d, toolType=%d, "
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004931 "x=%0.3f, y=%0.3f, pressure=%0.3f",
4932 id, index, properties.toolType,
4933 coords.getAxisValue(AMOTION_EVENT_AXIS_X),
Jeff Brownace13b12011-03-09 17:39:48 -08004934 coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
4935 coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
4936 }
4937 for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty(); ) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07004938 uint32_t id = idBits.clearFirstMarkedBit();
Jeff Brownace13b12011-03-09 17:39:48 -08004939 uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004940 const PointerProperties& properties = mPointerGesture.lastGestureProperties[index];
Jeff Brownace13b12011-03-09 17:39:48 -08004941 const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
Steve Block5baa3a62011-12-20 16:23:08 +00004942 ALOGD(" lastGesture[%d]: index=%d, toolType=%d, "
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004943 "x=%0.3f, y=%0.3f, pressure=%0.3f",
4944 id, index, properties.toolType,
4945 coords.getAxisValue(AMOTION_EVENT_AXIS_X),
Jeff Brownace13b12011-03-09 17:39:48 -08004946 coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
4947 coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
4948 }
4949#endif
Jeff Brown79ac9692011-04-19 21:20:10 -07004950 return true;
Jeff Brownace13b12011-03-09 17:39:48 -08004951}
4952
Jeff Brown65fd2512011-08-18 11:20:58 -07004953void TouchInputMapper::dispatchPointerStylus(nsecs_t when, uint32_t policyFlags) {
4954 mPointerSimple.currentCoords.clear();
4955 mPointerSimple.currentProperties.clear();
4956
4957 bool down, hovering;
4958 if (!mCurrentStylusIdBits.isEmpty()) {
4959 uint32_t id = mCurrentStylusIdBits.firstMarkedBit();
4960 uint32_t index = mCurrentCookedPointerData.idToIndex[id];
4961 float x = mCurrentCookedPointerData.pointerCoords[index].getX();
4962 float y = mCurrentCookedPointerData.pointerCoords[index].getY();
4963 mPointerController->setPosition(x, y);
4964
4965 hovering = mCurrentCookedPointerData.hoveringIdBits.hasBit(id);
4966 down = !hovering;
4967
4968 mPointerController->getPosition(&x, &y);
4969 mPointerSimple.currentCoords.copyFrom(mCurrentCookedPointerData.pointerCoords[index]);
4970 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
4971 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
4972 mPointerSimple.currentProperties.id = 0;
4973 mPointerSimple.currentProperties.toolType =
4974 mCurrentCookedPointerData.pointerProperties[index].toolType;
4975 } else {
4976 down = false;
4977 hovering = false;
4978 }
4979
4980 dispatchPointerSimple(when, policyFlags, down, hovering);
4981}
4982
4983void TouchInputMapper::abortPointerStylus(nsecs_t when, uint32_t policyFlags) {
4984 abortPointerSimple(when, policyFlags);
4985}
4986
4987void TouchInputMapper::dispatchPointerMouse(nsecs_t when, uint32_t policyFlags) {
4988 mPointerSimple.currentCoords.clear();
4989 mPointerSimple.currentProperties.clear();
4990
4991 bool down, hovering;
4992 if (!mCurrentMouseIdBits.isEmpty()) {
4993 uint32_t id = mCurrentMouseIdBits.firstMarkedBit();
4994 uint32_t currentIndex = mCurrentRawPointerData.idToIndex[id];
4995 if (mLastMouseIdBits.hasBit(id)) {
4996 uint32_t lastIndex = mCurrentRawPointerData.idToIndex[id];
4997 float deltaX = (mCurrentRawPointerData.pointers[currentIndex].x
4998 - mLastRawPointerData.pointers[lastIndex].x)
4999 * mPointerXMovementScale;
5000 float deltaY = (mCurrentRawPointerData.pointers[currentIndex].y
5001 - mLastRawPointerData.pointers[lastIndex].y)
5002 * mPointerYMovementScale;
5003
5004 rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
5005 mPointerVelocityControl.move(when, &deltaX, &deltaY);
5006
5007 mPointerController->move(deltaX, deltaY);
5008 } else {
5009 mPointerVelocityControl.reset();
5010 }
5011
5012 down = isPointerDown(mCurrentButtonState);
5013 hovering = !down;
5014
5015 float x, y;
5016 mPointerController->getPosition(&x, &y);
5017 mPointerSimple.currentCoords.copyFrom(
5018 mCurrentCookedPointerData.pointerCoords[currentIndex]);
5019 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
5020 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
5021 mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
5022 hovering ? 0.0f : 1.0f);
5023 mPointerSimple.currentProperties.id = 0;
5024 mPointerSimple.currentProperties.toolType =
5025 mCurrentCookedPointerData.pointerProperties[currentIndex].toolType;
5026 } else {
5027 mPointerVelocityControl.reset();
5028
5029 down = false;
5030 hovering = false;
5031 }
5032
5033 dispatchPointerSimple(when, policyFlags, down, hovering);
5034}
5035
5036void TouchInputMapper::abortPointerMouse(nsecs_t when, uint32_t policyFlags) {
5037 abortPointerSimple(when, policyFlags);
5038
5039 mPointerVelocityControl.reset();
5040}
5041
5042void TouchInputMapper::dispatchPointerSimple(nsecs_t when, uint32_t policyFlags,
5043 bool down, bool hovering) {
5044 int32_t metaState = getContext()->getGlobalMetaState();
5045
5046 if (mPointerController != NULL) {
5047 if (down || hovering) {
5048 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
5049 mPointerController->clearSpots();
5050 mPointerController->setButtonState(mCurrentButtonState);
5051 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
5052 } else if (!down && !hovering && (mPointerSimple.down || mPointerSimple.hovering)) {
5053 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
5054 }
5055 }
5056
5057 if (mPointerSimple.down && !down) {
5058 mPointerSimple.down = false;
5059
5060 // Send up.
5061 NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5062 AMOTION_EVENT_ACTION_UP, 0, metaState, mLastButtonState, 0,
5063 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
5064 mOrientedXPrecision, mOrientedYPrecision,
5065 mPointerSimple.downTime);
5066 getListener()->notifyMotion(&args);
5067 }
5068
5069 if (mPointerSimple.hovering && !hovering) {
5070 mPointerSimple.hovering = false;
5071
5072 // Send hover exit.
5073 NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5074 AMOTION_EVENT_ACTION_HOVER_EXIT, 0, metaState, mLastButtonState, 0,
5075 1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
5076 mOrientedXPrecision, mOrientedYPrecision,
5077 mPointerSimple.downTime);
5078 getListener()->notifyMotion(&args);
5079 }
5080
5081 if (down) {
5082 if (!mPointerSimple.down) {
5083 mPointerSimple.down = true;
5084 mPointerSimple.downTime = when;
5085
5086 // Send down.
5087 NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5088 AMOTION_EVENT_ACTION_DOWN, 0, metaState, mCurrentButtonState, 0,
5089 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
5090 mOrientedXPrecision, mOrientedYPrecision,
5091 mPointerSimple.downTime);
5092 getListener()->notifyMotion(&args);
5093 }
5094
5095 // Send move.
5096 NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5097 AMOTION_EVENT_ACTION_MOVE, 0, metaState, mCurrentButtonState, 0,
5098 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
5099 mOrientedXPrecision, mOrientedYPrecision,
5100 mPointerSimple.downTime);
5101 getListener()->notifyMotion(&args);
5102 }
5103
5104 if (hovering) {
5105 if (!mPointerSimple.hovering) {
5106 mPointerSimple.hovering = true;
5107
5108 // Send hover enter.
5109 NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5110 AMOTION_EVENT_ACTION_HOVER_ENTER, 0, metaState, mCurrentButtonState, 0,
5111 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
5112 mOrientedXPrecision, mOrientedYPrecision,
5113 mPointerSimple.downTime);
5114 getListener()->notifyMotion(&args);
5115 }
5116
5117 // Send hover move.
5118 NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5119 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, mCurrentButtonState, 0,
5120 1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
5121 mOrientedXPrecision, mOrientedYPrecision,
5122 mPointerSimple.downTime);
5123 getListener()->notifyMotion(&args);
5124 }
5125
5126 if (mCurrentRawVScroll || mCurrentRawHScroll) {
5127 float vscroll = mCurrentRawVScroll;
5128 float hscroll = mCurrentRawHScroll;
5129 mWheelYVelocityControl.move(when, NULL, &vscroll);
5130 mWheelXVelocityControl.move(when, &hscroll, NULL);
5131
5132 // Send scroll.
5133 PointerCoords pointerCoords;
5134 pointerCoords.copyFrom(mPointerSimple.currentCoords);
5135 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
5136 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
5137
5138 NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
5139 AMOTION_EVENT_ACTION_SCROLL, 0, metaState, mCurrentButtonState, 0,
5140 1, &mPointerSimple.currentProperties, &pointerCoords,
5141 mOrientedXPrecision, mOrientedYPrecision,
5142 mPointerSimple.downTime);
5143 getListener()->notifyMotion(&args);
5144 }
5145
5146 // Save state.
5147 if (down || hovering) {
5148 mPointerSimple.lastCoords.copyFrom(mPointerSimple.currentCoords);
5149 mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties);
5150 } else {
5151 mPointerSimple.reset();
5152 }
5153}
5154
5155void TouchInputMapper::abortPointerSimple(nsecs_t when, uint32_t policyFlags) {
5156 mPointerSimple.currentCoords.clear();
5157 mPointerSimple.currentProperties.clear();
5158
5159 dispatchPointerSimple(when, policyFlags, false, false);
5160}
5161
Jeff Brownace13b12011-03-09 17:39:48 -08005162void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07005163 int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
5164 const PointerProperties* properties, const PointerCoords* coords,
5165 const uint32_t* idToIndex, BitSet32 idBits,
Jeff Brownace13b12011-03-09 17:39:48 -08005166 int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) {
5167 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07005168 PointerProperties pointerProperties[MAX_POINTERS];
Jeff Brownace13b12011-03-09 17:39:48 -08005169 uint32_t pointerCount = 0;
5170 while (!idBits.isEmpty()) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07005171 uint32_t id = idBits.clearFirstMarkedBit();
Jeff Brownace13b12011-03-09 17:39:48 -08005172 uint32_t index = idToIndex[id];
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07005173 pointerProperties[pointerCount].copyFrom(properties[index]);
Jeff Brownace13b12011-03-09 17:39:48 -08005174 pointerCoords[pointerCount].copyFrom(coords[index]);
5175
5176 if (changedId >= 0 && id == uint32_t(changedId)) {
5177 action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
5178 }
5179
5180 pointerCount += 1;
5181 }
5182
Steve Blockec193de2012-01-09 18:35:44 +00005183 ALOG_ASSERT(pointerCount != 0);
Jeff Brownace13b12011-03-09 17:39:48 -08005184
5185 if (changedId >= 0 && pointerCount == 1) {
5186 // Replace initial down and final up action.
5187 // We can compare the action without masking off the changed pointer index
5188 // because we know the index is 0.
5189 if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
5190 action = AMOTION_EVENT_ACTION_DOWN;
5191 } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
5192 action = AMOTION_EVENT_ACTION_UP;
5193 } else {
5194 // Can't happen.
Steve Blockec193de2012-01-09 18:35:44 +00005195 ALOG_ASSERT(false);
Jeff Brownace13b12011-03-09 17:39:48 -08005196 }
5197 }
5198
Jeff Brownbe1aa822011-07-27 16:04:54 -07005199 NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07005200 action, flags, metaState, buttonState, edgeFlags,
5201 pointerCount, pointerProperties, pointerCoords, xPrecision, yPrecision, downTime);
Jeff Brownbe1aa822011-07-27 16:04:54 -07005202 getListener()->notifyMotion(&args);
Jeff Brownace13b12011-03-09 17:39:48 -08005203}
5204
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07005205bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties,
Jeff Brownace13b12011-03-09 17:39:48 -08005206 const PointerCoords* inCoords, const uint32_t* inIdToIndex,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07005207 PointerProperties* outProperties, PointerCoords* outCoords, const uint32_t* outIdToIndex,
5208 BitSet32 idBits) const {
Jeff Brownace13b12011-03-09 17:39:48 -08005209 bool changed = false;
5210 while (!idBits.isEmpty()) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07005211 uint32_t id = idBits.clearFirstMarkedBit();
Jeff Brownace13b12011-03-09 17:39:48 -08005212 uint32_t inIndex = inIdToIndex[id];
5213 uint32_t outIndex = outIdToIndex[id];
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07005214
5215 const PointerProperties& curInProperties = inProperties[inIndex];
Jeff Brownace13b12011-03-09 17:39:48 -08005216 const PointerCoords& curInCoords = inCoords[inIndex];
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07005217 PointerProperties& curOutProperties = outProperties[outIndex];
Jeff Brownace13b12011-03-09 17:39:48 -08005218 PointerCoords& curOutCoords = outCoords[outIndex];
5219
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07005220 if (curInProperties != curOutProperties) {
5221 curOutProperties.copyFrom(curInProperties);
5222 changed = true;
5223 }
5224
Jeff Brownace13b12011-03-09 17:39:48 -08005225 if (curInCoords != curOutCoords) {
5226 curOutCoords.copyFrom(curInCoords);
5227 changed = true;
5228 }
5229 }
5230 return changed;
5231}
5232
5233void TouchInputMapper::fadePointer() {
Jeff Brownbe1aa822011-07-27 16:04:54 -07005234 if (mPointerController != NULL) {
5235 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
5236 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005237}
5238
Jeff Brownbe1aa822011-07-27 16:04:54 -07005239bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
5240 return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue
5241 && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07005242}
5243
Jeff Brownbe1aa822011-07-27 16:04:54 -07005244const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(
Jeff Brown6328cdc2010-07-29 18:18:33 -07005245 int32_t x, int32_t y) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07005246 size_t numVirtualKeys = mVirtualKeys.size();
Jeff Brown6328cdc2010-07-29 18:18:33 -07005247 for (size_t i = 0; i < numVirtualKeys; i++) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07005248 const VirtualKey& virtualKey = mVirtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07005249
5250#if DEBUG_VIRTUAL_KEYS
Steve Block5baa3a62011-12-20 16:23:08 +00005251 ALOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
Jeff Brown6d0fec22010-07-23 21:28:06 -07005252 "left=%d, top=%d, right=%d, bottom=%d",
5253 x, y,
5254 virtualKey.keyCode, virtualKey.scanCode,
5255 virtualKey.hitLeft, virtualKey.hitTop,
5256 virtualKey.hitRight, virtualKey.hitBottom);
5257#endif
5258
5259 if (virtualKey.isHit(x, y)) {
5260 return & virtualKey;
5261 }
5262 }
5263
5264 return NULL;
5265}
5266
Jeff Brownbe1aa822011-07-27 16:04:54 -07005267void TouchInputMapper::assignPointerIds() {
5268 uint32_t currentPointerCount = mCurrentRawPointerData.pointerCount;
5269 uint32_t lastPointerCount = mLastRawPointerData.pointerCount;
5270
5271 mCurrentRawPointerData.clearIdBits();
Jeff Brown6d0fec22010-07-23 21:28:06 -07005272
5273 if (currentPointerCount == 0) {
5274 // No pointers to assign.
Jeff Brownbe1aa822011-07-27 16:04:54 -07005275 return;
5276 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07005277
Jeff Brownbe1aa822011-07-27 16:04:54 -07005278 if (lastPointerCount == 0) {
5279 // All pointers are new.
5280 for (uint32_t i = 0; i < currentPointerCount; i++) {
5281 uint32_t id = i;
5282 mCurrentRawPointerData.pointers[i].id = id;
5283 mCurrentRawPointerData.idToIndex[id] = i;
5284 mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(i));
5285 }
5286 return;
5287 }
5288
5289 if (currentPointerCount == 1 && lastPointerCount == 1
5290 && mCurrentRawPointerData.pointers[0].toolType
5291 == mLastRawPointerData.pointers[0].toolType) {
5292 // Only one pointer and no change in count so it must have the same id as before.
5293 uint32_t id = mLastRawPointerData.pointers[0].id;
5294 mCurrentRawPointerData.pointers[0].id = id;
5295 mCurrentRawPointerData.idToIndex[id] = 0;
5296 mCurrentRawPointerData.markIdBit(id, mCurrentRawPointerData.isHovering(0));
5297 return;
5298 }
5299
5300 // General case.
5301 // We build a heap of squared euclidean distances between current and last pointers
5302 // associated with the current and last pointer indices. Then, we find the best
5303 // match (by distance) for each current pointer.
5304 // The pointers must have the same tool type but it is possible for them to
5305 // transition from hovering to touching or vice-versa while retaining the same id.
5306 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
5307
5308 uint32_t heapSize = 0;
5309 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
5310 currentPointerIndex++) {
5311 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
5312 lastPointerIndex++) {
5313 const RawPointerData::Pointer& currentPointer =
5314 mCurrentRawPointerData.pointers[currentPointerIndex];
5315 const RawPointerData::Pointer& lastPointer =
5316 mLastRawPointerData.pointers[lastPointerIndex];
5317 if (currentPointer.toolType == lastPointer.toolType) {
5318 int64_t deltaX = currentPointer.x - lastPointer.x;
5319 int64_t deltaY = currentPointer.y - lastPointer.y;
Jeff Brown6d0fec22010-07-23 21:28:06 -07005320
5321 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
5322
5323 // Insert new element into the heap (sift up).
5324 heap[heapSize].currentPointerIndex = currentPointerIndex;
5325 heap[heapSize].lastPointerIndex = lastPointerIndex;
5326 heap[heapSize].distance = distance;
5327 heapSize += 1;
5328 }
5329 }
Jeff Brownbe1aa822011-07-27 16:04:54 -07005330 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07005331
Jeff Brownbe1aa822011-07-27 16:04:54 -07005332 // Heapify
5333 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
5334 startIndex -= 1;
5335 for (uint32_t parentIndex = startIndex; ;) {
5336 uint32_t childIndex = parentIndex * 2 + 1;
5337 if (childIndex >= heapSize) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07005338 break;
5339 }
Jeff Brownbe1aa822011-07-27 16:04:54 -07005340
5341 if (childIndex + 1 < heapSize
5342 && heap[childIndex + 1].distance < heap[childIndex].distance) {
5343 childIndex += 1;
5344 }
5345
5346 if (heap[parentIndex].distance <= heap[childIndex].distance) {
5347 break;
5348 }
5349
5350 swap(heap[parentIndex], heap[childIndex]);
5351 parentIndex = childIndex;
Jeff Brown6d0fec22010-07-23 21:28:06 -07005352 }
Jeff Brownbe1aa822011-07-27 16:04:54 -07005353 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07005354
5355#if DEBUG_POINTER_ASSIGNMENT
Steve Block5baa3a62011-12-20 16:23:08 +00005356 ALOGD("assignPointerIds - initial distance min-heap: size=%d", heapSize);
Jeff Brownbe1aa822011-07-27 16:04:54 -07005357 for (size_t i = 0; i < heapSize; i++) {
Steve Block5baa3a62011-12-20 16:23:08 +00005358 ALOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
Jeff Brownbe1aa822011-07-27 16:04:54 -07005359 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
5360 heap[i].distance);
5361 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07005362#endif
5363
Jeff Brownbe1aa822011-07-27 16:04:54 -07005364 // Pull matches out by increasing order of distance.
5365 // To avoid reassigning pointers that have already been matched, the loop keeps track
5366 // of which last and current pointers have been matched using the matchedXXXBits variables.
5367 // It also tracks the used pointer id bits.
5368 BitSet32 matchedLastBits(0);
5369 BitSet32 matchedCurrentBits(0);
5370 BitSet32 usedIdBits(0);
5371 bool first = true;
5372 for (uint32_t i = min(currentPointerCount, lastPointerCount); heapSize > 0 && i > 0; i--) {
5373 while (heapSize > 0) {
5374 if (first) {
5375 // The first time through the loop, we just consume the root element of
5376 // the heap (the one with smallest distance).
5377 first = false;
5378 } else {
5379 // Previous iterations consumed the root element of the heap.
5380 // Pop root element off of the heap (sift down).
5381 heap[0] = heap[heapSize];
5382 for (uint32_t parentIndex = 0; ;) {
5383 uint32_t childIndex = parentIndex * 2 + 1;
5384 if (childIndex >= heapSize) {
5385 break;
5386 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07005387
Jeff Brownbe1aa822011-07-27 16:04:54 -07005388 if (childIndex + 1 < heapSize
5389 && heap[childIndex + 1].distance < heap[childIndex].distance) {
5390 childIndex += 1;
5391 }
5392
5393 if (heap[parentIndex].distance <= heap[childIndex].distance) {
5394 break;
5395 }
5396
5397 swap(heap[parentIndex], heap[childIndex]);
5398 parentIndex = childIndex;
5399 }
5400
5401#if DEBUG_POINTER_ASSIGNMENT
Steve Block5baa3a62011-12-20 16:23:08 +00005402 ALOGD("assignPointerIds - reduced distance min-heap: size=%d", heapSize);
Jeff Brownbe1aa822011-07-27 16:04:54 -07005403 for (size_t i = 0; i < heapSize; i++) {
Steve Block5baa3a62011-12-20 16:23:08 +00005404 ALOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
Jeff Brownbe1aa822011-07-27 16:04:54 -07005405 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
5406 heap[i].distance);
5407 }
5408#endif
5409 }
5410
5411 heapSize -= 1;
5412
5413 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
5414 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
5415
5416 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
5417 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
5418
5419 matchedCurrentBits.markBit(currentPointerIndex);
5420 matchedLastBits.markBit(lastPointerIndex);
5421
5422 uint32_t id = mLastRawPointerData.pointers[lastPointerIndex].id;
5423 mCurrentRawPointerData.pointers[currentPointerIndex].id = id;
5424 mCurrentRawPointerData.idToIndex[id] = currentPointerIndex;
5425 mCurrentRawPointerData.markIdBit(id,
5426 mCurrentRawPointerData.isHovering(currentPointerIndex));
5427 usedIdBits.markBit(id);
5428
5429#if DEBUG_POINTER_ASSIGNMENT
Steve Block5baa3a62011-12-20 16:23:08 +00005430 ALOGD("assignPointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
Jeff Brownbe1aa822011-07-27 16:04:54 -07005431 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
5432#endif
5433 break;
5434 }
5435 }
5436
5437 // Assign fresh ids to pointers that were not matched in the process.
5438 for (uint32_t i = currentPointerCount - matchedCurrentBits.count(); i != 0; i--) {
5439 uint32_t currentPointerIndex = matchedCurrentBits.markFirstUnmarkedBit();
5440 uint32_t id = usedIdBits.markFirstUnmarkedBit();
5441
5442 mCurrentRawPointerData.pointers[currentPointerIndex].id = id;
5443 mCurrentRawPointerData.idToIndex[id] = currentPointerIndex;
5444 mCurrentRawPointerData.markIdBit(id,
5445 mCurrentRawPointerData.isHovering(currentPointerIndex));
5446
5447#if DEBUG_POINTER_ASSIGNMENT
Steve Block5baa3a62011-12-20 16:23:08 +00005448 ALOGD("assignPointerIds - assigned: cur=%d, id=%d",
Jeff Brownbe1aa822011-07-27 16:04:54 -07005449 currentPointerIndex, id);
5450#endif
Jeff Brown6d0fec22010-07-23 21:28:06 -07005451 }
5452}
5453
Jeff Brown6d0fec22010-07-23 21:28:06 -07005454int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07005455 if (mCurrentVirtualKey.down && mCurrentVirtualKey.keyCode == keyCode) {
5456 return AKEY_STATE_VIRTUAL;
5457 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07005458
Jeff Brownbe1aa822011-07-27 16:04:54 -07005459 size_t numVirtualKeys = mVirtualKeys.size();
5460 for (size_t i = 0; i < numVirtualKeys; i++) {
5461 const VirtualKey& virtualKey = mVirtualKeys[i];
5462 if (virtualKey.keyCode == keyCode) {
5463 return AKEY_STATE_UP;
Jeff Brown6d0fec22010-07-23 21:28:06 -07005464 }
Jeff Brownbe1aa822011-07-27 16:04:54 -07005465 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07005466
5467 return AKEY_STATE_UNKNOWN;
5468}
5469
5470int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07005471 if (mCurrentVirtualKey.down && mCurrentVirtualKey.scanCode == scanCode) {
5472 return AKEY_STATE_VIRTUAL;
5473 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07005474
Jeff Brownbe1aa822011-07-27 16:04:54 -07005475 size_t numVirtualKeys = mVirtualKeys.size();
5476 for (size_t i = 0; i < numVirtualKeys; i++) {
5477 const VirtualKey& virtualKey = mVirtualKeys[i];
5478 if (virtualKey.scanCode == scanCode) {
5479 return AKEY_STATE_UP;
Jeff Brown6d0fec22010-07-23 21:28:06 -07005480 }
Jeff Brownbe1aa822011-07-27 16:04:54 -07005481 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07005482
5483 return AKEY_STATE_UNKNOWN;
5484}
5485
5486bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
5487 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07005488 size_t numVirtualKeys = mVirtualKeys.size();
5489 for (size_t i = 0; i < numVirtualKeys; i++) {
5490 const VirtualKey& virtualKey = mVirtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07005491
Jeff Brownbe1aa822011-07-27 16:04:54 -07005492 for (size_t i = 0; i < numCodes; i++) {
5493 if (virtualKey.keyCode == keyCodes[i]) {
5494 outFlags[i] = 1;
Jeff Brown6d0fec22010-07-23 21:28:06 -07005495 }
5496 }
Jeff Brownbe1aa822011-07-27 16:04:54 -07005497 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07005498
5499 return true;
5500}
5501
5502
5503// --- SingleTouchInputMapper ---
5504
Jeff Brown47e6b1b2010-11-29 17:37:49 -08005505SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
5506 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07005507}
5508
5509SingleTouchInputMapper::~SingleTouchInputMapper() {
5510}
5511
Jeff Brown65fd2512011-08-18 11:20:58 -07005512void SingleTouchInputMapper::reset(nsecs_t when) {
5513 mSingleTouchMotionAccumulator.reset(getDevice());
5514
5515 TouchInputMapper::reset(when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07005516}
5517
Jeff Brown6d0fec22010-07-23 21:28:06 -07005518void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
Jeff Brown65fd2512011-08-18 11:20:58 -07005519 TouchInputMapper::process(rawEvent);
Jeff Brown6d0fec22010-07-23 21:28:06 -07005520
Jeff Brown65fd2512011-08-18 11:20:58 -07005521 mSingleTouchMotionAccumulator.process(rawEvent);
Jeff Brown6d0fec22010-07-23 21:28:06 -07005522}
5523
Jeff Brown65fd2512011-08-18 11:20:58 -07005524void SingleTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) {
Jeff Brownd87c6d52011-08-10 14:55:59 -07005525 if (mTouchButtonAccumulator.isToolActive()) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07005526 mCurrentRawPointerData.pointerCount = 1;
5527 mCurrentRawPointerData.idToIndex[0] = 0;
Jeff Brown49754db2011-07-01 17:37:58 -07005528
Jeff Brown65fd2512011-08-18 11:20:58 -07005529 bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
5530 && (mTouchButtonAccumulator.isHovering()
5531 || (mRawPointerAxes.pressure.valid
5532 && mSingleTouchMotionAccumulator.getAbsolutePressure() <= 0));
Jeff Brownbe1aa822011-07-27 16:04:54 -07005533 mCurrentRawPointerData.markIdBit(0, isHovering);
Jeff Brown49754db2011-07-01 17:37:58 -07005534
Jeff Brownbe1aa822011-07-27 16:04:54 -07005535 RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[0];
Jeff Brown49754db2011-07-01 17:37:58 -07005536 outPointer.id = 0;
5537 outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX();
5538 outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY();
5539 outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
5540 outPointer.touchMajor = 0;
5541 outPointer.touchMinor = 0;
5542 outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
5543 outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
5544 outPointer.orientation = 0;
5545 outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance();
Jeff Brown65fd2512011-08-18 11:20:58 -07005546 outPointer.tiltX = mSingleTouchMotionAccumulator.getAbsoluteTiltX();
5547 outPointer.tiltY = mSingleTouchMotionAccumulator.getAbsoluteTiltY();
Jeff Brown49754db2011-07-01 17:37:58 -07005548 outPointer.toolType = mTouchButtonAccumulator.getToolType();
5549 if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
5550 outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
5551 }
5552 outPointer.isHovering = isHovering;
Jeff Brown6d0fec22010-07-23 21:28:06 -07005553 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07005554}
5555
Jeff Brownbe1aa822011-07-27 16:04:54 -07005556void SingleTouchInputMapper::configureRawPointerAxes() {
5557 TouchInputMapper::configureRawPointerAxes();
Jeff Brown6d0fec22010-07-23 21:28:06 -07005558
Jeff Brownbe1aa822011-07-27 16:04:54 -07005559 getAbsoluteAxisInfo(ABS_X, &mRawPointerAxes.x);
5560 getAbsoluteAxisInfo(ABS_Y, &mRawPointerAxes.y);
5561 getAbsoluteAxisInfo(ABS_PRESSURE, &mRawPointerAxes.pressure);
5562 getAbsoluteAxisInfo(ABS_TOOL_WIDTH, &mRawPointerAxes.toolMajor);
5563 getAbsoluteAxisInfo(ABS_DISTANCE, &mRawPointerAxes.distance);
Jeff Brown65fd2512011-08-18 11:20:58 -07005564 getAbsoluteAxisInfo(ABS_TILT_X, &mRawPointerAxes.tiltX);
5565 getAbsoluteAxisInfo(ABS_TILT_Y, &mRawPointerAxes.tiltY);
Jeff Brown6d0fec22010-07-23 21:28:06 -07005566}
5567
5568
5569// --- MultiTouchInputMapper ---
5570
Jeff Brown47e6b1b2010-11-29 17:37:49 -08005571MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
Jeff Brown49754db2011-07-01 17:37:58 -07005572 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07005573}
5574
5575MultiTouchInputMapper::~MultiTouchInputMapper() {
5576}
5577
Jeff Brown65fd2512011-08-18 11:20:58 -07005578void MultiTouchInputMapper::reset(nsecs_t when) {
5579 mMultiTouchMotionAccumulator.reset(getDevice());
5580
Jeff Brown6894a292011-07-01 17:59:27 -07005581 mPointerIdBits.clear();
Jeff Brown2717eff2011-06-30 23:53:07 -07005582
Jeff Brown65fd2512011-08-18 11:20:58 -07005583 TouchInputMapper::reset(when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07005584}
5585
5586void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
Jeff Brown65fd2512011-08-18 11:20:58 -07005587 TouchInputMapper::process(rawEvent);
Jeff Brownace13b12011-03-09 17:39:48 -08005588
Jeff Brown65fd2512011-08-18 11:20:58 -07005589 mMultiTouchMotionAccumulator.process(rawEvent);
Jeff Brown6d0fec22010-07-23 21:28:06 -07005590}
5591
Jeff Brown65fd2512011-08-18 11:20:58 -07005592void MultiTouchInputMapper::syncTouch(nsecs_t when, bool* outHavePointerIds) {
Jeff Brown49754db2011-07-01 17:37:58 -07005593 size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
Jeff Brown80fd47c2011-05-24 01:07:44 -07005594 size_t outCount = 0;
Jeff Brownbe1aa822011-07-27 16:04:54 -07005595 BitSet32 newPointerIdBits;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005596
Jeff Brown80fd47c2011-05-24 01:07:44 -07005597 for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brown49754db2011-07-01 17:37:58 -07005598 const MultiTouchMotionAccumulator::Slot* inSlot =
5599 mMultiTouchMotionAccumulator.getSlot(inIndex);
5600 if (!inSlot->isInUse()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005601 continue;
5602 }
5603
Jeff Brown80fd47c2011-05-24 01:07:44 -07005604 if (outCount >= MAX_POINTERS) {
5605#if DEBUG_POINTERS
Steve Block5baa3a62011-12-20 16:23:08 +00005606 ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
Jeff Brown80fd47c2011-05-24 01:07:44 -07005607 "ignoring the rest.",
5608 getDeviceName().string(), MAX_POINTERS);
5609#endif
5610 break; // too many fingers!
5611 }
5612
Jeff Brownbe1aa822011-07-27 16:04:54 -07005613 RawPointerData::Pointer& outPointer = mCurrentRawPointerData.pointers[outCount];
Jeff Brown49754db2011-07-01 17:37:58 -07005614 outPointer.x = inSlot->getX();
5615 outPointer.y = inSlot->getY();
5616 outPointer.pressure = inSlot->getPressure();
5617 outPointer.touchMajor = inSlot->getTouchMajor();
5618 outPointer.touchMinor = inSlot->getTouchMinor();
5619 outPointer.toolMajor = inSlot->getToolMajor();
5620 outPointer.toolMinor = inSlot->getToolMinor();
5621 outPointer.orientation = inSlot->getOrientation();
5622 outPointer.distance = inSlot->getDistance();
Jeff Brown65fd2512011-08-18 11:20:58 -07005623 outPointer.tiltX = 0;
5624 outPointer.tiltY = 0;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005625
Jeff Brown49754db2011-07-01 17:37:58 -07005626 outPointer.toolType = inSlot->getToolType();
5627 if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
5628 outPointer.toolType = mTouchButtonAccumulator.getToolType();
5629 if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
5630 outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
5631 }
Jeff Brown8d608662010-08-30 03:02:23 -07005632 }
5633
Jeff Brown65fd2512011-08-18 11:20:58 -07005634 bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE
5635 && (mTouchButtonAccumulator.isHovering()
5636 || (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));
Jeff Brownbe1aa822011-07-27 16:04:54 -07005637 outPointer.isHovering = isHovering;
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07005638
Jeff Brown8d608662010-08-30 03:02:23 -07005639 // Assign pointer id using tracking id if available.
Jeff Brown65fd2512011-08-18 11:20:58 -07005640 if (*outHavePointerIds) {
Jeff Brown49754db2011-07-01 17:37:58 -07005641 int32_t trackingId = inSlot->getTrackingId();
Jeff Brown6894a292011-07-01 17:59:27 -07005642 int32_t id = -1;
Jeff Brown49754db2011-07-01 17:37:58 -07005643 if (trackingId >= 0) {
Jeff Brown6894a292011-07-01 17:59:27 -07005644 for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07005645 uint32_t n = idBits.clearFirstMarkedBit();
Jeff Brown6894a292011-07-01 17:59:27 -07005646 if (mPointerTrackingIdMap[n] == trackingId) {
5647 id = n;
5648 }
5649 }
5650
5651 if (id < 0 && !mPointerIdBits.isFull()) {
Jeff Brownbe1aa822011-07-27 16:04:54 -07005652 id = mPointerIdBits.markFirstUnmarkedBit();
Jeff Brown6894a292011-07-01 17:59:27 -07005653 mPointerTrackingIdMap[id] = trackingId;
5654 }
5655 }
5656 if (id < 0) {
Jeff Brown65fd2512011-08-18 11:20:58 -07005657 *outHavePointerIds = false;
Jeff Brownbe1aa822011-07-27 16:04:54 -07005658 mCurrentRawPointerData.clearIdBits();
5659 newPointerIdBits.clear();
Jeff Brown6894a292011-07-01 17:59:27 -07005660 } else {
Jeff Brown80fd47c2011-05-24 01:07:44 -07005661 outPointer.id = id;
Jeff Brownbe1aa822011-07-27 16:04:54 -07005662 mCurrentRawPointerData.idToIndex[id] = outCount;
5663 mCurrentRawPointerData.markIdBit(id, isHovering);
5664 newPointerIdBits.markBit(id);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005665 }
5666 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005667
Jeff Brown6d0fec22010-07-23 21:28:06 -07005668 outCount += 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005669 }
5670
Jeff Brownbe1aa822011-07-27 16:04:54 -07005671 mCurrentRawPointerData.pointerCount = outCount;
Jeff Brownbe1aa822011-07-27 16:04:54 -07005672 mPointerIdBits = newPointerIdBits;
Jeff Brown6894a292011-07-01 17:59:27 -07005673
Jeff Brown65fd2512011-08-18 11:20:58 -07005674 mMultiTouchMotionAccumulator.finishSync();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005675}
5676
Jeff Brownbe1aa822011-07-27 16:04:54 -07005677void MultiTouchInputMapper::configureRawPointerAxes() {
5678 TouchInputMapper::configureRawPointerAxes();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005679
Jeff Brownbe1aa822011-07-27 16:04:54 -07005680 getAbsoluteAxisInfo(ABS_MT_POSITION_X, &mRawPointerAxes.x);
5681 getAbsoluteAxisInfo(ABS_MT_POSITION_Y, &mRawPointerAxes.y);
5682 getAbsoluteAxisInfo(ABS_MT_TOUCH_MAJOR, &mRawPointerAxes.touchMajor);
5683 getAbsoluteAxisInfo(ABS_MT_TOUCH_MINOR, &mRawPointerAxes.touchMinor);
5684 getAbsoluteAxisInfo(ABS_MT_WIDTH_MAJOR, &mRawPointerAxes.toolMajor);
5685 getAbsoluteAxisInfo(ABS_MT_WIDTH_MINOR, &mRawPointerAxes.toolMinor);
5686 getAbsoluteAxisInfo(ABS_MT_ORIENTATION, &mRawPointerAxes.orientation);
5687 getAbsoluteAxisInfo(ABS_MT_PRESSURE, &mRawPointerAxes.pressure);
5688 getAbsoluteAxisInfo(ABS_MT_DISTANCE, &mRawPointerAxes.distance);
5689 getAbsoluteAxisInfo(ABS_MT_TRACKING_ID, &mRawPointerAxes.trackingId);
5690 getAbsoluteAxisInfo(ABS_MT_SLOT, &mRawPointerAxes.slot);
Jeff Brown80fd47c2011-05-24 01:07:44 -07005691
Jeff Brownbe1aa822011-07-27 16:04:54 -07005692 if (mRawPointerAxes.trackingId.valid
5693 && mRawPointerAxes.slot.valid
5694 && mRawPointerAxes.slot.minValue == 0 && mRawPointerAxes.slot.maxValue > 0) {
5695 size_t slotCount = mRawPointerAxes.slot.maxValue + 1;
Jeff Brown49754db2011-07-01 17:37:58 -07005696 if (slotCount > MAX_SLOTS) {
Steve Block8564c8d2012-01-05 23:22:43 +00005697 ALOGW("MultiTouch Device %s reported %d slots but the framework "
Jeff Brown80fd47c2011-05-24 01:07:44 -07005698 "only supports a maximum of %d slots at this time.",
Jeff Brown49754db2011-07-01 17:37:58 -07005699 getDeviceName().string(), slotCount, MAX_SLOTS);
5700 slotCount = MAX_SLOTS;
Jeff Brown80fd47c2011-05-24 01:07:44 -07005701 }
Jeff Brown49754db2011-07-01 17:37:58 -07005702 mMultiTouchMotionAccumulator.configure(slotCount, true /*usingSlotsProtocol*/);
Jeff Brown80fd47c2011-05-24 01:07:44 -07005703 } else {
Jeff Brown49754db2011-07-01 17:37:58 -07005704 mMultiTouchMotionAccumulator.configure(MAX_POINTERS, false /*usingSlotsProtocol*/);
Jeff Brown80fd47c2011-05-24 01:07:44 -07005705 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07005706}
5707
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005708
Jeff Browncb1404e2011-01-15 18:14:15 -08005709// --- JoystickInputMapper ---
5710
5711JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
5712 InputMapper(device) {
Jeff Browncb1404e2011-01-15 18:14:15 -08005713}
5714
5715JoystickInputMapper::~JoystickInputMapper() {
5716}
5717
5718uint32_t JoystickInputMapper::getSources() {
5719 return AINPUT_SOURCE_JOYSTICK;
5720}
5721
5722void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
5723 InputMapper::populateDeviceInfo(info);
5724
Jeff Brown6f2fba42011-02-19 01:08:02 -08005725 for (size_t i = 0; i < mAxes.size(); i++) {
5726 const Axis& axis = mAxes.valueAt(i);
Jeff Brownefd32662011-03-08 15:13:06 -08005727 info->addMotionRange(axis.axisInfo.axis, AINPUT_SOURCE_JOYSTICK,
5728 axis.min, axis.max, axis.flat, axis.fuzz);
Jeff Brown85297452011-03-04 13:07:49 -08005729 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
Jeff Brownefd32662011-03-08 15:13:06 -08005730 info->addMotionRange(axis.axisInfo.highAxis, AINPUT_SOURCE_JOYSTICK,
5731 axis.min, axis.max, axis.flat, axis.fuzz);
Jeff Brown85297452011-03-04 13:07:49 -08005732 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005733 }
5734}
5735
5736void JoystickInputMapper::dump(String8& dump) {
5737 dump.append(INDENT2 "Joystick Input Mapper:\n");
5738
Jeff Brown6f2fba42011-02-19 01:08:02 -08005739 dump.append(INDENT3 "Axes:\n");
5740 size_t numAxes = mAxes.size();
5741 for (size_t i = 0; i < numAxes; i++) {
5742 const Axis& axis = mAxes.valueAt(i);
Jeff Brown85297452011-03-04 13:07:49 -08005743 const char* label = getAxisLabel(axis.axisInfo.axis);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005744 if (label) {
Jeff Brown85297452011-03-04 13:07:49 -08005745 dump.appendFormat(INDENT4 "%s", label);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005746 } else {
Jeff Brown85297452011-03-04 13:07:49 -08005747 dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005748 }
Jeff Brown85297452011-03-04 13:07:49 -08005749 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5750 label = getAxisLabel(axis.axisInfo.highAxis);
5751 if (label) {
5752 dump.appendFormat(" / %s (split at %d)", label, axis.axisInfo.splitValue);
5753 } else {
5754 dump.appendFormat(" / %d (split at %d)", axis.axisInfo.highAxis,
5755 axis.axisInfo.splitValue);
5756 }
5757 } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
5758 dump.append(" (invert)");
5759 }
5760
5761 dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f\n",
5762 axis.min, axis.max, axis.flat, axis.fuzz);
5763 dump.appendFormat(INDENT4 " scale=%0.5f, offset=%0.5f, "
5764 "highScale=%0.5f, highOffset=%0.5f\n",
5765 axis.scale, axis.offset, axis.highScale, axis.highOffset);
Jeff Brownb3a2d132011-06-12 18:14:50 -07005766 dump.appendFormat(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, "
5767 "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n",
Jeff Brown6f2fba42011-02-19 01:08:02 -08005768 mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
Jeff Brownb3a2d132011-06-12 18:14:50 -07005769 axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz, axis.rawAxisInfo.resolution);
Jeff Browncb1404e2011-01-15 18:14:15 -08005770 }
5771}
5772
Jeff Brown65fd2512011-08-18 11:20:58 -07005773void JoystickInputMapper::configure(nsecs_t when,
5774 const InputReaderConfiguration* config, uint32_t changes) {
5775 InputMapper::configure(when, config, changes);
Jeff Browncb1404e2011-01-15 18:14:15 -08005776
Jeff Brown474dcb52011-06-14 20:22:50 -07005777 if (!changes) { // first time only
5778 // Collect all axes.
5779 for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
Jeff Brown9ee285af2011-08-31 12:56:34 -07005780 if (!(getAbsAxisUsage(abs, getDevice()->getClasses())
5781 & INPUT_DEVICE_CLASS_JOYSTICK)) {
5782 continue; // axis must be claimed by a different device
5783 }
5784
Jeff Brown474dcb52011-06-14 20:22:50 -07005785 RawAbsoluteAxisInfo rawAxisInfo;
Jeff Brownbe1aa822011-07-27 16:04:54 -07005786 getAbsoluteAxisInfo(abs, &rawAxisInfo);
Jeff Brown474dcb52011-06-14 20:22:50 -07005787 if (rawAxisInfo.valid) {
5788 // Map axis.
5789 AxisInfo axisInfo;
5790 bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
5791 if (!explicitlyMapped) {
5792 // Axis is not explicitly mapped, will choose a generic axis later.
5793 axisInfo.mode = AxisInfo::MODE_NORMAL;
5794 axisInfo.axis = -1;
5795 }
5796
5797 // Apply flat override.
5798 int32_t rawFlat = axisInfo.flatOverride < 0
5799 ? rawAxisInfo.flat : axisInfo.flatOverride;
5800
5801 // Calculate scaling factors and limits.
5802 Axis axis;
5803 if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
5804 float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
5805 float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
5806 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5807 scale, 0.0f, highScale, 0.0f,
5808 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
5809 } else if (isCenteredAxis(axisInfo.axis)) {
5810 float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
5811 float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
5812 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5813 scale, offset, scale, offset,
5814 -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
5815 } else {
5816 float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
5817 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5818 scale, 0.0f, scale, 0.0f,
5819 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
5820 }
5821
5822 // To eliminate noise while the joystick is at rest, filter out small variations
5823 // in axis values up front.
5824 axis.filter = axis.flat * 0.25f;
5825
5826 mAxes.add(abs, axis);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005827 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08005828 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08005829
Jeff Brown474dcb52011-06-14 20:22:50 -07005830 // If there are too many axes, start dropping them.
5831 // Prefer to keep explicitly mapped axes.
5832 if (mAxes.size() > PointerCoords::MAX_AXES) {
Steve Block6215d3f2012-01-04 20:05:49 +00005833 ALOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
Jeff Brown474dcb52011-06-14 20:22:50 -07005834 getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
5835 pruneAxes(true);
5836 pruneAxes(false);
5837 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08005838
Jeff Brown474dcb52011-06-14 20:22:50 -07005839 // Assign generic axis ids to remaining axes.
5840 int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
5841 size_t numAxes = mAxes.size();
5842 for (size_t i = 0; i < numAxes; i++) {
5843 Axis& axis = mAxes.editValueAt(i);
5844 if (axis.axisInfo.axis < 0) {
5845 while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
5846 && haveAxis(nextGenericAxisId)) {
5847 nextGenericAxisId += 1;
5848 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08005849
Jeff Brown474dcb52011-06-14 20:22:50 -07005850 if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
5851 axis.axisInfo.axis = nextGenericAxisId;
5852 nextGenericAxisId += 1;
5853 } else {
Steve Block6215d3f2012-01-04 20:05:49 +00005854 ALOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
Jeff Brown474dcb52011-06-14 20:22:50 -07005855 "have already been assigned to other axes.",
5856 getDeviceName().string(), mAxes.keyAt(i));
5857 mAxes.removeItemsAt(i--);
5858 numAxes -= 1;
5859 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08005860 }
5861 }
5862 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005863}
5864
Jeff Brown85297452011-03-04 13:07:49 -08005865bool JoystickInputMapper::haveAxis(int32_t axisId) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005866 size_t numAxes = mAxes.size();
5867 for (size_t i = 0; i < numAxes; i++) {
Jeff Brown85297452011-03-04 13:07:49 -08005868 const Axis& axis = mAxes.valueAt(i);
5869 if (axis.axisInfo.axis == axisId
5870 || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
5871 && axis.axisInfo.highAxis == axisId)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005872 return true;
5873 }
5874 }
5875 return false;
5876}
Jeff Browncb1404e2011-01-15 18:14:15 -08005877
Jeff Brown6f2fba42011-02-19 01:08:02 -08005878void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
5879 size_t i = mAxes.size();
5880 while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
5881 if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
5882 continue;
5883 }
Steve Block6215d3f2012-01-04 20:05:49 +00005884 ALOGI("Discarding joystick '%s' axis %d because there are too many axes.",
Jeff Brown6f2fba42011-02-19 01:08:02 -08005885 getDeviceName().string(), mAxes.keyAt(i));
5886 mAxes.removeItemsAt(i);
5887 }
5888}
5889
5890bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
5891 switch (axis) {
5892 case AMOTION_EVENT_AXIS_X:
5893 case AMOTION_EVENT_AXIS_Y:
5894 case AMOTION_EVENT_AXIS_Z:
5895 case AMOTION_EVENT_AXIS_RX:
5896 case AMOTION_EVENT_AXIS_RY:
5897 case AMOTION_EVENT_AXIS_RZ:
5898 case AMOTION_EVENT_AXIS_HAT_X:
5899 case AMOTION_EVENT_AXIS_HAT_Y:
5900 case AMOTION_EVENT_AXIS_ORIENTATION:
Jeff Brown85297452011-03-04 13:07:49 -08005901 case AMOTION_EVENT_AXIS_RUDDER:
5902 case AMOTION_EVENT_AXIS_WHEEL:
Jeff Brown6f2fba42011-02-19 01:08:02 -08005903 return true;
5904 default:
5905 return false;
5906 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005907}
5908
Jeff Brown65fd2512011-08-18 11:20:58 -07005909void JoystickInputMapper::reset(nsecs_t when) {
Jeff Browncb1404e2011-01-15 18:14:15 -08005910 // Recenter all axes.
Jeff Brown6f2fba42011-02-19 01:08:02 -08005911 size_t numAxes = mAxes.size();
5912 for (size_t i = 0; i < numAxes; i++) {
5913 Axis& axis = mAxes.editValueAt(i);
Jeff Brown85297452011-03-04 13:07:49 -08005914 axis.resetValue();
Jeff Brown6f2fba42011-02-19 01:08:02 -08005915 }
5916
Jeff Brown65fd2512011-08-18 11:20:58 -07005917 InputMapper::reset(when);
Jeff Browncb1404e2011-01-15 18:14:15 -08005918}
5919
5920void JoystickInputMapper::process(const RawEvent* rawEvent) {
5921 switch (rawEvent->type) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005922 case EV_ABS: {
5923 ssize_t index = mAxes.indexOfKey(rawEvent->scanCode);
5924 if (index >= 0) {
5925 Axis& axis = mAxes.editValueAt(index);
Jeff Brown85297452011-03-04 13:07:49 -08005926 float newValue, highNewValue;
5927 switch (axis.axisInfo.mode) {
5928 case AxisInfo::MODE_INVERT:
5929 newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
5930 * axis.scale + axis.offset;
5931 highNewValue = 0.0f;
5932 break;
5933 case AxisInfo::MODE_SPLIT:
5934 if (rawEvent->value < axis.axisInfo.splitValue) {
5935 newValue = (axis.axisInfo.splitValue - rawEvent->value)
5936 * axis.scale + axis.offset;
5937 highNewValue = 0.0f;
5938 } else if (rawEvent->value > axis.axisInfo.splitValue) {
5939 newValue = 0.0f;
5940 highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
5941 * axis.highScale + axis.highOffset;
5942 } else {
5943 newValue = 0.0f;
5944 highNewValue = 0.0f;
5945 }
5946 break;
5947 default:
5948 newValue = rawEvent->value * axis.scale + axis.offset;
5949 highNewValue = 0.0f;
5950 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08005951 }
Jeff Brown85297452011-03-04 13:07:49 -08005952 axis.newValue = newValue;
5953 axis.highNewValue = highNewValue;
Jeff Browncb1404e2011-01-15 18:14:15 -08005954 }
5955 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08005956 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005957
5958 case EV_SYN:
5959 switch (rawEvent->scanCode) {
5960 case SYN_REPORT:
Jeff Brown6f2fba42011-02-19 01:08:02 -08005961 sync(rawEvent->when, false /*force*/);
Jeff Browncb1404e2011-01-15 18:14:15 -08005962 break;
5963 }
5964 break;
5965 }
5966}
5967
Jeff Brown6f2fba42011-02-19 01:08:02 -08005968void JoystickInputMapper::sync(nsecs_t when, bool force) {
Jeff Brown85297452011-03-04 13:07:49 -08005969 if (!filterAxes(force)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005970 return;
Jeff Browncb1404e2011-01-15 18:14:15 -08005971 }
5972
5973 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07005974 int32_t buttonState = 0;
5975
5976 PointerProperties pointerProperties;
5977 pointerProperties.clear();
5978 pointerProperties.id = 0;
5979 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
Jeff Browncb1404e2011-01-15 18:14:15 -08005980
Jeff Brown6f2fba42011-02-19 01:08:02 -08005981 PointerCoords pointerCoords;
5982 pointerCoords.clear();
5983
5984 size_t numAxes = mAxes.size();
5985 for (size_t i = 0; i < numAxes; i++) {
Jeff Brown85297452011-03-04 13:07:49 -08005986 const Axis& axis = mAxes.valueAt(i);
5987 pointerCoords.setAxisValue(axis.axisInfo.axis, axis.currentValue);
5988 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5989 pointerCoords.setAxisValue(axis.axisInfo.highAxis, axis.highCurrentValue);
5990 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005991 }
5992
Jeff Brown56194eb2011-03-02 19:23:13 -08005993 // Moving a joystick axis should not wake the devide because joysticks can
5994 // be fairly noisy even when not in use. On the other hand, pushing a gamepad
5995 // button will likely wake the device.
5996 // TODO: Use the input device configuration to control this behavior more finely.
5997 uint32_t policyFlags = 0;
5998
Jeff Brownbe1aa822011-07-27 16:04:54 -07005999 NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07006000 AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
6001 1, &pointerProperties, &pointerCoords, 0, 0, 0);
Jeff Brownbe1aa822011-07-27 16:04:54 -07006002 getListener()->notifyMotion(&args);
Jeff Browncb1404e2011-01-15 18:14:15 -08006003}
6004
Jeff Brown85297452011-03-04 13:07:49 -08006005bool JoystickInputMapper::filterAxes(bool force) {
6006 bool atLeastOneSignificantChange = force;
Jeff Brown6f2fba42011-02-19 01:08:02 -08006007 size_t numAxes = mAxes.size();
6008 for (size_t i = 0; i < numAxes; i++) {
Jeff Brown85297452011-03-04 13:07:49 -08006009 Axis& axis = mAxes.editValueAt(i);
6010 if (force || hasValueChangedSignificantly(axis.filter,
6011 axis.newValue, axis.currentValue, axis.min, axis.max)) {
6012 axis.currentValue = axis.newValue;
6013 atLeastOneSignificantChange = true;
6014 }
6015 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
6016 if (force || hasValueChangedSignificantly(axis.filter,
6017 axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
6018 axis.highCurrentValue = axis.highNewValue;
6019 atLeastOneSignificantChange = true;
6020 }
6021 }
6022 }
6023 return atLeastOneSignificantChange;
6024}
6025
6026bool JoystickInputMapper::hasValueChangedSignificantly(
6027 float filter, float newValue, float currentValue, float min, float max) {
6028 if (newValue != currentValue) {
6029 // Filter out small changes in value unless the value is converging on the axis
6030 // bounds or center point. This is intended to reduce the amount of information
6031 // sent to applications by particularly noisy joysticks (such as PS3).
6032 if (fabs(newValue - currentValue) > filter
6033 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
6034 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
6035 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
6036 return true;
6037 }
6038 }
6039 return false;
6040}
6041
6042bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
6043 float filter, float newValue, float currentValue, float thresholdValue) {
6044 float newDistance = fabs(newValue - thresholdValue);
6045 if (newDistance < filter) {
6046 float oldDistance = fabs(currentValue - thresholdValue);
6047 if (newDistance < oldDistance) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08006048 return true;
6049 }
Jeff Browncb1404e2011-01-15 18:14:15 -08006050 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08006051 return false;
Jeff Browncb1404e2011-01-15 18:14:15 -08006052}
6053
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07006054} // namespace android