blob: b8d59e68e6c5b31ad85908d5c276a1af5b15f96d [file] [log] [blame]
Jeff Brown46b9ac02010-04-22 18:58:52 -07001//
2// Copyright 2010 The Android Open Source Project
3//
4// Provides a pipe-based transport for native events in the NDK.
5//
6#define LOG_TAG "Input"
7
8//#define LOG_NDEBUG 0
9
Jeff Brown47e6b1b2010-11-29 17:37:49 -080010#define DEBUG_PROBE 0
11
12#include <stdlib.h>
13#include <unistd.h>
Jeff Brown90655042010-12-02 13:50:46 -080014#include <ctype.h>
Jeff Brown47e6b1b2010-11-29 17:37:49 -080015
Jeff Brown46b9ac02010-04-22 18:58:52 -070016#include <ui/Input.h>
17
18namespace android {
19
Jeff Brown47e6b1b2010-11-29 17:37:49 -080020static const char* CONFIGURATION_FILE_DIR[] = {
21 "idc/",
22 "keylayout/",
23 "keychars/",
24};
25
26static const char* CONFIGURATION_FILE_EXTENSION[] = {
27 ".idc",
28 ".kl",
29 ".kcm",
30};
31
Jeff Brown90655042010-12-02 13:50:46 -080032static bool isValidNameChar(char ch) {
33 return isascii(ch) && (isdigit(ch) || isalpha(ch) || ch == '-' || ch == '_');
34}
35
Jeff Brown47e6b1b2010-11-29 17:37:49 -080036static void appendInputDeviceConfigurationFileRelativePath(String8& path,
37 const String8& name, InputDeviceConfigurationFileType type) {
38 path.append(CONFIGURATION_FILE_DIR[type]);
39 for (size_t i = 0; i < name.length(); i++) {
40 char ch = name[i];
Jeff Brown90655042010-12-02 13:50:46 -080041 if (!isValidNameChar(ch)) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -080042 ch = '_';
43 }
44 path.append(&ch, 1);
45 }
46 path.append(CONFIGURATION_FILE_EXTENSION[type]);
47}
48
Jeff Brown90655042010-12-02 13:50:46 -080049String8 getInputDeviceConfigurationFilePathByDeviceIdentifier(
50 const InputDeviceIdentifier& deviceIdentifier,
51 InputDeviceConfigurationFileType type) {
52 if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {
53 if (deviceIdentifier.version != 0) {
54 // Try vendor product version.
55 String8 versionPath(getInputDeviceConfigurationFilePathByName(
56 String8::format("Vendor_%04x_Product_%04x_Version_%04x",
57 deviceIdentifier.vendor, deviceIdentifier.product,
58 deviceIdentifier.version),
59 type));
60 if (!versionPath.isEmpty()) {
61 return versionPath;
62 }
63 }
64
65 // Try vendor product.
66 String8 productPath(getInputDeviceConfigurationFilePathByName(
67 String8::format("Vendor_%04x_Product_%04x",
68 deviceIdentifier.vendor, deviceIdentifier.product),
69 type));
70 if (!productPath.isEmpty()) {
71 return productPath;
72 }
73 }
74
75 // Try device name.
76 return getInputDeviceConfigurationFilePathByName(deviceIdentifier.name, type);
77}
78
79String8 getInputDeviceConfigurationFilePathByName(
Jeff Brown47e6b1b2010-11-29 17:37:49 -080080 const String8& name, InputDeviceConfigurationFileType type) {
81 // Search system repository.
82 String8 path;
83 path.setTo(getenv("ANDROID_ROOT"));
84 path.append("/usr/");
85 appendInputDeviceConfigurationFileRelativePath(path, name, type);
86#if DEBUG_PROBE
87 LOGD("Probing for system provided input device configuration file: path='%s'", path.string());
88#endif
89 if (!access(path.string(), R_OK)) {
90#if DEBUG_PROBE
91 LOGD("Found");
92#endif
93 return path;
94 }
95
96 // Search user repository.
97 // TODO Should only look here if not in safe mode.
98 path.setTo(getenv("ANDROID_DATA"));
99 path.append("/system/devices/");
100 appendInputDeviceConfigurationFileRelativePath(path, name, type);
101#if DEBUG_PROBE
102 LOGD("Probing for system user input device configuration file: path='%s'", path.string());
103#endif
104 if (!access(path.string(), R_OK)) {
105#if DEBUG_PROBE
106 LOGD("Found");
107#endif
108 return path;
109 }
110
111 // Not found.
112#if DEBUG_PROBE
113 LOGD("Probe failed to find input device configuration file: name='%s', type=%d",
114 name.string(), type);
115#endif
116 return String8();
117}
118
119
120// --- InputEvent ---
Jeff Brown46b9ac02010-04-22 18:58:52 -0700121
Jeff Brownc5ed5912010-07-14 18:48:53 -0700122void InputEvent::initialize(int32_t deviceId, int32_t source) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700123 mDeviceId = deviceId;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700124 mSource = source;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700125}
126
Dianne Hackborn2c6081c2010-07-15 17:44:53 -0700127void InputEvent::initialize(const InputEvent& from) {
128 mDeviceId = from.mDeviceId;
129 mSource = from.mSource;
130}
131
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800132// --- KeyEvent ---
Jeff Brown46b9ac02010-04-22 18:58:52 -0700133
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700134bool KeyEvent::hasDefaultAction(int32_t keyCode) {
135 switch (keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -0700136 case AKEYCODE_HOME:
137 case AKEYCODE_BACK:
138 case AKEYCODE_CALL:
139 case AKEYCODE_ENDCALL:
140 case AKEYCODE_VOLUME_UP:
141 case AKEYCODE_VOLUME_DOWN:
Jeff Brownb0418da2010-11-01 15:24:01 -0700142 case AKEYCODE_VOLUME_MUTE:
Jeff Brownfd035822010-06-30 16:10:35 -0700143 case AKEYCODE_POWER:
144 case AKEYCODE_CAMERA:
145 case AKEYCODE_HEADSETHOOK:
146 case AKEYCODE_MENU:
147 case AKEYCODE_NOTIFICATION:
148 case AKEYCODE_FOCUS:
149 case AKEYCODE_SEARCH:
Jeff Brownb0418da2010-11-01 15:24:01 -0700150 case AKEYCODE_MEDIA_PLAY:
151 case AKEYCODE_MEDIA_PAUSE:
Jeff Brownfd035822010-06-30 16:10:35 -0700152 case AKEYCODE_MEDIA_PLAY_PAUSE:
153 case AKEYCODE_MEDIA_STOP:
154 case AKEYCODE_MEDIA_NEXT:
155 case AKEYCODE_MEDIA_PREVIOUS:
156 case AKEYCODE_MEDIA_REWIND:
Jeff Brownb0418da2010-11-01 15:24:01 -0700157 case AKEYCODE_MEDIA_RECORD:
Jeff Brownfd035822010-06-30 16:10:35 -0700158 case AKEYCODE_MEDIA_FAST_FORWARD:
159 case AKEYCODE_MUTE:
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700160 return true;
161 }
162
163 return false;
164}
165
166bool KeyEvent::hasDefaultAction() const {
167 return hasDefaultAction(getKeyCode());
168}
169
170bool KeyEvent::isSystemKey(int32_t keyCode) {
171 switch (keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -0700172 case AKEYCODE_MENU:
173 case AKEYCODE_SOFT_RIGHT:
174 case AKEYCODE_HOME:
175 case AKEYCODE_BACK:
176 case AKEYCODE_CALL:
177 case AKEYCODE_ENDCALL:
178 case AKEYCODE_VOLUME_UP:
179 case AKEYCODE_VOLUME_DOWN:
Jeff Brownb0418da2010-11-01 15:24:01 -0700180 case AKEYCODE_VOLUME_MUTE:
Jeff Brownfd035822010-06-30 16:10:35 -0700181 case AKEYCODE_MUTE:
182 case AKEYCODE_POWER:
183 case AKEYCODE_HEADSETHOOK:
Jeff Brownb0418da2010-11-01 15:24:01 -0700184 case AKEYCODE_MEDIA_PLAY:
185 case AKEYCODE_MEDIA_PAUSE:
Jeff Brownfd035822010-06-30 16:10:35 -0700186 case AKEYCODE_MEDIA_PLAY_PAUSE:
187 case AKEYCODE_MEDIA_STOP:
188 case AKEYCODE_MEDIA_NEXT:
189 case AKEYCODE_MEDIA_PREVIOUS:
190 case AKEYCODE_MEDIA_REWIND:
Jeff Brownb0418da2010-11-01 15:24:01 -0700191 case AKEYCODE_MEDIA_RECORD:
Jeff Brownfd035822010-06-30 16:10:35 -0700192 case AKEYCODE_MEDIA_FAST_FORWARD:
193 case AKEYCODE_CAMERA:
194 case AKEYCODE_FOCUS:
195 case AKEYCODE_SEARCH:
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700196 return true;
197 }
198
199 return false;
200}
201
202bool KeyEvent::isSystemKey() const {
203 return isSystemKey(getKeyCode());
204}
205
Jeff Brown46b9ac02010-04-22 18:58:52 -0700206void KeyEvent::initialize(
207 int32_t deviceId,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700208 int32_t source,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700209 int32_t action,
210 int32_t flags,
211 int32_t keyCode,
212 int32_t scanCode,
213 int32_t metaState,
214 int32_t repeatCount,
215 nsecs_t downTime,
216 nsecs_t eventTime) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700217 InputEvent::initialize(deviceId, source);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700218 mAction = action;
219 mFlags = flags;
220 mKeyCode = keyCode;
221 mScanCode = scanCode;
222 mMetaState = metaState;
223 mRepeatCount = repeatCount;
224 mDownTime = downTime;
225 mEventTime = eventTime;
226}
227
Dianne Hackborn2c6081c2010-07-15 17:44:53 -0700228void KeyEvent::initialize(const KeyEvent& from) {
229 InputEvent::initialize(from);
230 mAction = from.mAction;
231 mFlags = from.mFlags;
232 mKeyCode = from.mKeyCode;
233 mScanCode = from.mScanCode;
234 mMetaState = from.mMetaState;
235 mRepeatCount = from.mRepeatCount;
236 mDownTime = from.mDownTime;
237 mEventTime = from.mEventTime;
238}
239
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800240// --- MotionEvent ---
Jeff Brown46b9ac02010-04-22 18:58:52 -0700241
242void MotionEvent::initialize(
243 int32_t deviceId,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700244 int32_t source,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700245 int32_t action,
Jeff Brown85a31762010-09-01 17:01:00 -0700246 int32_t flags,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700247 int32_t edgeFlags,
248 int32_t metaState,
Jeff Brown5c225b12010-06-16 01:53:36 -0700249 float xOffset,
250 float yOffset,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700251 float xPrecision,
252 float yPrecision,
253 nsecs_t downTime,
254 nsecs_t eventTime,
255 size_t pointerCount,
256 const int32_t* pointerIds,
257 const PointerCoords* pointerCoords) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700258 InputEvent::initialize(deviceId, source);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700259 mAction = action;
Jeff Brown85a31762010-09-01 17:01:00 -0700260 mFlags = flags;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700261 mEdgeFlags = edgeFlags;
262 mMetaState = metaState;
Jeff Brown5c225b12010-06-16 01:53:36 -0700263 mXOffset = xOffset;
264 mYOffset = yOffset;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700265 mXPrecision = xPrecision;
266 mYPrecision = yPrecision;
267 mDownTime = downTime;
268 mPointerIds.clear();
269 mPointerIds.appendArray(pointerIds, pointerCount);
270 mSampleEventTimes.clear();
271 mSamplePointerCoords.clear();
272 addSample(eventTime, pointerCoords);
273}
274
275void MotionEvent::addSample(
276 int64_t eventTime,
277 const PointerCoords* pointerCoords) {
278 mSampleEventTimes.push(eventTime);
279 mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
280}
281
282void MotionEvent::offsetLocation(float xOffset, float yOffset) {
Jeff Brown5c225b12010-06-16 01:53:36 -0700283 mXOffset += xOffset;
284 mYOffset += yOffset;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700285}
286
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800287// --- InputDeviceInfo ---
Jeff Brown6d0fec22010-07-23 21:28:06 -0700288
289InputDeviceInfo::InputDeviceInfo() {
290 initialize(-1, String8("uninitialized device info"));
291}
292
293InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) :
294 mId(other.mId), mName(other.mName), mSources(other.mSources),
295 mKeyboardType(other.mKeyboardType),
296 mMotionRanges(other.mMotionRanges) {
297}
298
299InputDeviceInfo::~InputDeviceInfo() {
300}
301
302void InputDeviceInfo::initialize(int32_t id, const String8& name) {
303 mId = id;
304 mName = name;
305 mSources = 0;
306 mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
307 mMotionRanges.clear();
308}
309
310const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange(int32_t rangeType) const {
311 ssize_t index = mMotionRanges.indexOfKey(rangeType);
312 return index >= 0 ? & mMotionRanges.valueAt(index) : NULL;
313}
314
315void InputDeviceInfo::addSource(uint32_t source) {
316 mSources |= source;
317}
318
319void InputDeviceInfo::addMotionRange(int32_t rangeType, float min, float max,
320 float flat, float fuzz) {
321 MotionRange range = { min, max, flat, fuzz };
322 addMotionRange(rangeType, range);
323}
324
325void InputDeviceInfo::addMotionRange(int32_t rangeType, const MotionRange& range) {
326 mMotionRanges.add(rangeType, range);
327}
328
Jeff Brown46b9ac02010-04-22 18:58:52 -0700329} // namespace android