blob: 7ac8a2e02c1451dd493fbbddaf8ac55fa2cfcade [file] [log] [blame]
Jeff Brown5912f952013-07-01 19:10:31 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "KeyCharacterMap"
18
19#include <stdlib.h>
20#include <string.h>
21
Elliott Hughes6071da72015-08-12 15:27:47 -070022#ifdef __ANDROID__
Jeff Brown5912f952013-07-01 19:10:31 -070023#include <binder/Parcel.h>
24#endif
25
26#include <android/keycodes.h>
chaviw09c8d2d2020-08-24 15:48:26 -070027#include <attestation/HmacKeyManager.h>
Michael Wright872db4f2014-04-22 15:03:51 -070028#include <input/InputEventLabels.h>
Jeff Brown5912f952013-07-01 19:10:31 -070029#include <input/KeyCharacterMap.h>
chaviw09c8d2d2020-08-24 15:48:26 -070030#include <input/Keyboard.h>
Jeff Brown5912f952013-07-01 19:10:31 -070031
32#include <utils/Log.h>
33#include <utils/Errors.h>
34#include <utils/Tokenizer.h>
35#include <utils/Timers.h>
36
37// Enables debug output for the parser.
38#define DEBUG_PARSER 0
39
40// Enables debug output for parser performance.
41#define DEBUG_PARSER_PERFORMANCE 0
42
43// Enables debug output for mapping.
44#define DEBUG_MAPPING 0
45
46
47namespace android {
48
49static const char* WHITESPACE = " \t\r";
50static const char* WHITESPACE_OR_PROPERTY_DELIMITER = " \t\r,:";
51
52struct Modifier {
53 const char* label;
54 int32_t metaState;
55};
56static const Modifier modifiers[] = {
57 { "shift", AMETA_SHIFT_ON },
58 { "lshift", AMETA_SHIFT_LEFT_ON },
59 { "rshift", AMETA_SHIFT_RIGHT_ON },
60 { "alt", AMETA_ALT_ON },
61 { "lalt", AMETA_ALT_LEFT_ON },
62 { "ralt", AMETA_ALT_RIGHT_ON },
63 { "ctrl", AMETA_CTRL_ON },
64 { "lctrl", AMETA_CTRL_LEFT_ON },
65 { "rctrl", AMETA_CTRL_RIGHT_ON },
66 { "meta", AMETA_META_ON },
67 { "lmeta", AMETA_META_LEFT_ON },
68 { "rmeta", AMETA_META_RIGHT_ON },
69 { "sym", AMETA_SYM_ON },
70 { "fn", AMETA_FUNCTION_ON },
71 { "capslock", AMETA_CAPS_LOCK_ON },
72 { "numlock", AMETA_NUM_LOCK_ON },
73 { "scrolllock", AMETA_SCROLL_LOCK_ON },
74};
75
76#if DEBUG_MAPPING
77static String8 toString(const char16_t* chars, size_t numChars) {
78 String8 result;
79 for (size_t i = 0; i < numChars; i++) {
80 result.appendFormat(i == 0 ? "%d" : ", %d", chars[i]);
81 }
82 return result;
83}
84#endif
85
86
87// --- KeyCharacterMap ---
88
Jeff Brown5912f952013-07-01 19:10:31 -070089KeyCharacterMap::KeyCharacterMap() :
90 mType(KEYBOARD_TYPE_UNKNOWN) {
91}
92
Chris Ye3a1e4462020-08-12 10:13:15 -070093KeyCharacterMap::KeyCharacterMap(const KeyCharacterMap& other)
94 : mType(other.mType),
95 mKeysByScanCode(other.mKeysByScanCode),
96 mKeysByUsageCode(other.mKeysByUsageCode) {
Jeff Brown5912f952013-07-01 19:10:31 -070097 for (size_t i = 0; i < other.mKeys.size(); i++) {
98 mKeys.add(other.mKeys.keyAt(i), new Key(*other.mKeys.valueAt(i)));
99 }
100}
101
102KeyCharacterMap::~KeyCharacterMap() {
103 for (size_t i = 0; i < mKeys.size(); i++) {
104 Key* key = mKeys.editValueAt(i);
105 delete key;
106 }
107}
108
Chris Ye3a1e4462020-08-12 10:13:15 -0700109base::Result<std::shared_ptr<KeyCharacterMap>> KeyCharacterMap::load(const std::string& filename,
110 Format format) {
Jeff Brown5912f952013-07-01 19:10:31 -0700111 Tokenizer* tokenizer;
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100112 status_t status = Tokenizer::open(String8(filename.c_str()), &tokenizer);
Jeff Brown5912f952013-07-01 19:10:31 -0700113 if (status) {
Chris Ye3a1e4462020-08-12 10:13:15 -0700114 return Errorf("Error {} opening key character map file {}.", status, filename.c_str());
Jeff Brown5912f952013-07-01 19:10:31 -0700115 }
Chris Ye3a1e4462020-08-12 10:13:15 -0700116 std::unique_ptr<Tokenizer> t(tokenizer);
117 auto ret = load(t.get(), format);
118 if (ret) {
119 (*ret)->mLoadFileName = filename;
120 }
121 return ret;
Jeff Brown5912f952013-07-01 19:10:31 -0700122}
123
Chris Ye3a1e4462020-08-12 10:13:15 -0700124base::Result<std::shared_ptr<KeyCharacterMap>> KeyCharacterMap::loadContents(
125 const std::string& filename, const char* contents, Format format) {
Jeff Brown5912f952013-07-01 19:10:31 -0700126 Tokenizer* tokenizer;
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100127 status_t status = Tokenizer::fromContents(String8(filename.c_str()), contents, &tokenizer);
Jeff Brown5912f952013-07-01 19:10:31 -0700128 if (status) {
129 ALOGE("Error %d opening key character map.", status);
Chris Ye3a1e4462020-08-12 10:13:15 -0700130 return Errorf("Error {} opening key character map.", status);
Jeff Brown5912f952013-07-01 19:10:31 -0700131 }
Chris Ye3a1e4462020-08-12 10:13:15 -0700132 std::unique_ptr<Tokenizer> t(tokenizer);
133 auto ret = load(t.get(), format);
134 if (ret) {
135 (*ret)->mLoadFileName = filename;
136 }
137 return ret;
Jeff Brown5912f952013-07-01 19:10:31 -0700138}
139
Chris Ye3a1e4462020-08-12 10:13:15 -0700140base::Result<std::shared_ptr<KeyCharacterMap>> KeyCharacterMap::load(Tokenizer* tokenizer,
141 Format format) {
Jeff Brown5912f952013-07-01 19:10:31 -0700142 status_t status = OK;
Chris Ye3a1e4462020-08-12 10:13:15 -0700143 std::shared_ptr<KeyCharacterMap> map = std::shared_ptr<KeyCharacterMap>(new KeyCharacterMap());
Jeff Brown5912f952013-07-01 19:10:31 -0700144 if (!map.get()) {
145 ALOGE("Error allocating key character map.");
Chris Ye3a1e4462020-08-12 10:13:15 -0700146 return Errorf("Error allocating key character map.");
Jeff Brown5912f952013-07-01 19:10:31 -0700147 }
Chris Ye3a1e4462020-08-12 10:13:15 -0700148#if DEBUG_PARSER_PERFORMANCE
149 nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC);
150#endif
151 Parser parser(map.get(), tokenizer, format);
152 status = parser.parse();
153#if DEBUG_PARSER_PERFORMANCE
154 nsecs_t elapsedTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
155 ALOGD("Parsed key character map file '%s' %d lines in %0.3fms.",
156 tokenizer->getFilename().string(), tokenizer->getLineNumber(), elapsedTime / 1000000.0);
157#endif
158 if (status == OK) {
159 return map;
160 }
161
162 return Errorf("Load KeyCharacterMap failed {}.", status);
Jeff Brown5912f952013-07-01 19:10:31 -0700163}
164
Chris Ye3a1e4462020-08-12 10:13:15 -0700165void KeyCharacterMap::combine(const KeyCharacterMap& overlay) {
166 for (size_t i = 0; i < overlay.mKeys.size(); i++) {
167 int32_t keyCode = overlay.mKeys.keyAt(i);
168 Key* key = overlay.mKeys.valueAt(i);
169 ssize_t oldIndex = mKeys.indexOfKey(keyCode);
Jeff Brown5912f952013-07-01 19:10:31 -0700170 if (oldIndex >= 0) {
Chris Ye3a1e4462020-08-12 10:13:15 -0700171 delete mKeys.valueAt(oldIndex);
172 mKeys.editValueAt(oldIndex) = new Key(*key);
Jeff Brown5912f952013-07-01 19:10:31 -0700173 } else {
Chris Ye3a1e4462020-08-12 10:13:15 -0700174 mKeys.add(keyCode, new Key(*key));
Jeff Brown5912f952013-07-01 19:10:31 -0700175 }
176 }
177
Chris Ye3a1e4462020-08-12 10:13:15 -0700178 for (size_t i = 0; i < overlay.mKeysByScanCode.size(); i++) {
179 mKeysByScanCode.replaceValueFor(overlay.mKeysByScanCode.keyAt(i),
180 overlay.mKeysByScanCode.valueAt(i));
Jeff Brown5912f952013-07-01 19:10:31 -0700181 }
182
Chris Ye3a1e4462020-08-12 10:13:15 -0700183 for (size_t i = 0; i < overlay.mKeysByUsageCode.size(); i++) {
184 mKeysByUsageCode.replaceValueFor(overlay.mKeysByUsageCode.keyAt(i),
185 overlay.mKeysByUsageCode.valueAt(i));
Jeff Brown5912f952013-07-01 19:10:31 -0700186 }
Chris Ye3a1e4462020-08-12 10:13:15 -0700187 mLoadFileName = overlay.mLoadFileName;
Jeff Brown5912f952013-07-01 19:10:31 -0700188}
189
190int32_t KeyCharacterMap::getKeyboardType() const {
191 return mType;
192}
193
Chris Ye3a1e4462020-08-12 10:13:15 -0700194const std::string KeyCharacterMap::getLoadFileName() const {
195 return mLoadFileName;
196}
197
Jeff Brown5912f952013-07-01 19:10:31 -0700198char16_t KeyCharacterMap::getDisplayLabel(int32_t keyCode) const {
199 char16_t result = 0;
200 const Key* key;
201 if (getKey(keyCode, &key)) {
202 result = key->label;
203 }
204#if DEBUG_MAPPING
205 ALOGD("getDisplayLabel: keyCode=%d ~ Result %d.", keyCode, result);
206#endif
207 return result;
208}
209
210char16_t KeyCharacterMap::getNumber(int32_t keyCode) const {
211 char16_t result = 0;
212 const Key* key;
213 if (getKey(keyCode, &key)) {
214 result = key->number;
215 }
216#if DEBUG_MAPPING
217 ALOGD("getNumber: keyCode=%d ~ Result %d.", keyCode, result);
218#endif
219 return result;
220}
221
222char16_t KeyCharacterMap::getCharacter(int32_t keyCode, int32_t metaState) const {
223 char16_t result = 0;
224 const Key* key;
225 const Behavior* behavior;
226 if (getKeyBehavior(keyCode, metaState, &key, &behavior)) {
227 result = behavior->character;
228 }
229#if DEBUG_MAPPING
230 ALOGD("getCharacter: keyCode=%d, metaState=0x%08x ~ Result %d.", keyCode, metaState, result);
231#endif
232 return result;
233}
234
235bool KeyCharacterMap::getFallbackAction(int32_t keyCode, int32_t metaState,
236 FallbackAction* outFallbackAction) const {
237 outFallbackAction->keyCode = 0;
238 outFallbackAction->metaState = 0;
239
240 bool result = false;
241 const Key* key;
242 const Behavior* behavior;
243 if (getKeyBehavior(keyCode, metaState, &key, &behavior)) {
244 if (behavior->fallbackKeyCode) {
245 outFallbackAction->keyCode = behavior->fallbackKeyCode;
246 outFallbackAction->metaState = metaState & ~behavior->metaState;
247 result = true;
248 }
249 }
250#if DEBUG_MAPPING
251 ALOGD("getFallbackKeyCode: keyCode=%d, metaState=0x%08x ~ Result %s, "
252 "fallback keyCode=%d, fallback metaState=0x%08x.",
253 keyCode, metaState, result ? "true" : "false",
254 outFallbackAction->keyCode, outFallbackAction->metaState);
255#endif
256 return result;
257}
258
259char16_t KeyCharacterMap::getMatch(int32_t keyCode, const char16_t* chars, size_t numChars,
260 int32_t metaState) const {
261 char16_t result = 0;
262 const Key* key;
263 if (getKey(keyCode, &key)) {
264 // Try to find the most general behavior that maps to this character.
265 // For example, the base key behavior will usually be last in the list.
266 // However, if we find a perfect meta state match for one behavior then use that one.
267 for (const Behavior* behavior = key->firstBehavior; behavior; behavior = behavior->next) {
268 if (behavior->character) {
269 for (size_t i = 0; i < numChars; i++) {
270 if (behavior->character == chars[i]) {
271 result = behavior->character;
272 if ((behavior->metaState & metaState) == behavior->metaState) {
273 goto ExactMatch;
274 }
275 break;
276 }
277 }
278 }
279 }
280 ExactMatch: ;
281 }
282#if DEBUG_MAPPING
283 ALOGD("getMatch: keyCode=%d, chars=[%s], metaState=0x%08x ~ Result %d.",
284 keyCode, toString(chars, numChars).string(), metaState, result);
285#endif
286 return result;
287}
288
289bool KeyCharacterMap::getEvents(int32_t deviceId, const char16_t* chars, size_t numChars,
290 Vector<KeyEvent>& outEvents) const {
291 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
292
293 for (size_t i = 0; i < numChars; i++) {
294 int32_t keyCode, metaState;
295 char16_t ch = chars[i];
296 if (!findKey(ch, &keyCode, &metaState)) {
297#if DEBUG_MAPPING
298 ALOGD("getEvents: deviceId=%d, chars=[%s] ~ Failed to find mapping for character %d.",
299 deviceId, toString(chars, numChars).string(), ch);
300#endif
301 return false;
302 }
303
304 int32_t currentMetaState = 0;
305 addMetaKeys(outEvents, deviceId, metaState, true, now, &currentMetaState);
306 addKey(outEvents, deviceId, keyCode, currentMetaState, true, now);
307 addKey(outEvents, deviceId, keyCode, currentMetaState, false, now);
308 addMetaKeys(outEvents, deviceId, metaState, false, now, &currentMetaState);
309 }
310#if DEBUG_MAPPING
311 ALOGD("getEvents: deviceId=%d, chars=[%s] ~ Generated %d events.",
312 deviceId, toString(chars, numChars).string(), int32_t(outEvents.size()));
313 for (size_t i = 0; i < outEvents.size(); i++) {
314 ALOGD(" Key: keyCode=%d, metaState=0x%08x, %s.",
315 outEvents[i].getKeyCode(), outEvents[i].getMetaState(),
316 outEvents[i].getAction() == AKEY_EVENT_ACTION_DOWN ? "down" : "up");
317 }
318#endif
319 return true;
320}
321
322status_t KeyCharacterMap::mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const {
323 if (usageCode) {
324 ssize_t index = mKeysByUsageCode.indexOfKey(usageCode);
325 if (index >= 0) {
Jeff Brown5912f952013-07-01 19:10:31 -0700326 *outKeyCode = mKeysByUsageCode.valueAt(index);
Dmitry Torokhov115f93e2015-09-17 18:04:50 -0700327#if DEBUG_MAPPING
328 ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.",
329 scanCode, usageCode, *outKeyCode);
330#endif
Jeff Brown5912f952013-07-01 19:10:31 -0700331 return OK;
332 }
333 }
334 if (scanCode) {
335 ssize_t index = mKeysByScanCode.indexOfKey(scanCode);
336 if (index >= 0) {
Jeff Brown5912f952013-07-01 19:10:31 -0700337 *outKeyCode = mKeysByScanCode.valueAt(index);
Dmitry Torokhov115f93e2015-09-17 18:04:50 -0700338#if DEBUG_MAPPING
339 ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.",
340 scanCode, usageCode, *outKeyCode);
341#endif
Jeff Brown5912f952013-07-01 19:10:31 -0700342 return OK;
343 }
344 }
345
346#if DEBUG_MAPPING
Dmitry Torokhov115f93e2015-09-17 18:04:50 -0700347 ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Failed.", scanCode, usageCode);
Jeff Brown5912f952013-07-01 19:10:31 -0700348#endif
349 *outKeyCode = AKEYCODE_UNKNOWN;
350 return NAME_NOT_FOUND;
351}
352
Dmitry Torokhov115f93e2015-09-17 18:04:50 -0700353void KeyCharacterMap::tryRemapKey(int32_t keyCode, int32_t metaState,
354 int32_t *outKeyCode, int32_t *outMetaState) const {
355 *outKeyCode = keyCode;
356 *outMetaState = metaState;
357
358 const Key* key;
359 const Behavior* behavior;
360 if (getKeyBehavior(keyCode, metaState, &key, &behavior)) {
361 if (behavior->replacementKeyCode) {
362 *outKeyCode = behavior->replacementKeyCode;
363 int32_t newMetaState = metaState & ~behavior->metaState;
364 // Reset dependent meta states.
365 if (behavior->metaState & AMETA_ALT_ON) {
366 newMetaState &= ~(AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON);
367 }
368 if (behavior->metaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
369 newMetaState &= ~AMETA_ALT_ON;
370 }
371 if (behavior->metaState & AMETA_CTRL_ON) {
372 newMetaState &= ~(AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON);
373 }
374 if (behavior->metaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) {
375 newMetaState &= ~AMETA_CTRL_ON;
376 }
377 if (behavior->metaState & AMETA_SHIFT_ON) {
378 newMetaState &= ~(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON);
379 }
380 if (behavior->metaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
381 newMetaState &= ~AMETA_SHIFT_ON;
382 }
383 // ... and put universal bits back if needed
384 *outMetaState = normalizeMetaState(newMetaState);
385 }
386 }
387
388#if DEBUG_MAPPING
389 ALOGD("tryRemapKey: keyCode=%d, metaState=0x%08x ~ "
390 "replacement keyCode=%d, replacement metaState=0x%08x.",
391 keyCode, metaState, *outKeyCode, *outMetaState);
392#endif
393}
394
Jeff Brown5912f952013-07-01 19:10:31 -0700395bool KeyCharacterMap::getKey(int32_t keyCode, const Key** outKey) const {
396 ssize_t index = mKeys.indexOfKey(keyCode);
397 if (index >= 0) {
398 *outKey = mKeys.valueAt(index);
399 return true;
400 }
401 return false;
402}
403
404bool KeyCharacterMap::getKeyBehavior(int32_t keyCode, int32_t metaState,
405 const Key** outKey, const Behavior** outBehavior) const {
406 const Key* key;
407 if (getKey(keyCode, &key)) {
408 const Behavior* behavior = key->firstBehavior;
409 while (behavior) {
410 if (matchesMetaState(metaState, behavior->metaState)) {
411 *outKey = key;
412 *outBehavior = behavior;
413 return true;
414 }
415 behavior = behavior->next;
416 }
417 }
418 return false;
419}
420
421bool KeyCharacterMap::matchesMetaState(int32_t eventMetaState, int32_t behaviorMetaState) {
422 // Behavior must have at least the set of meta states specified.
423 // And if the key event has CTRL, ALT or META then the behavior must exactly
424 // match those, taking into account that a behavior can specify that it handles
425 // one, both or either of a left/right modifier pair.
426 if ((eventMetaState & behaviorMetaState) == behaviorMetaState) {
427 const int32_t EXACT_META_STATES =
428 AMETA_CTRL_ON | AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON
429 | AMETA_ALT_ON | AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON
430 | AMETA_META_ON | AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON;
431 int32_t unmatchedMetaState = eventMetaState & ~behaviorMetaState & EXACT_META_STATES;
432 if (behaviorMetaState & AMETA_CTRL_ON) {
433 unmatchedMetaState &= ~(AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON);
434 } else if (behaviorMetaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) {
435 unmatchedMetaState &= ~AMETA_CTRL_ON;
436 }
437 if (behaviorMetaState & AMETA_ALT_ON) {
438 unmatchedMetaState &= ~(AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON);
439 } else if (behaviorMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
440 unmatchedMetaState &= ~AMETA_ALT_ON;
441 }
442 if (behaviorMetaState & AMETA_META_ON) {
443 unmatchedMetaState &= ~(AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON);
444 } else if (behaviorMetaState & (AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON)) {
445 unmatchedMetaState &= ~AMETA_META_ON;
446 }
447 return !unmatchedMetaState;
448 }
449 return false;
450}
451
452bool KeyCharacterMap::findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const {
453 if (!ch) {
454 return false;
455 }
456
457 for (size_t i = 0; i < mKeys.size(); i++) {
458 const Key* key = mKeys.valueAt(i);
459
460 // Try to find the most general behavior that maps to this character.
461 // For example, the base key behavior will usually be last in the list.
Yi Kong5bed83b2018-07-17 12:53:47 -0700462 const Behavior* found = nullptr;
Jeff Brown5912f952013-07-01 19:10:31 -0700463 for (const Behavior* behavior = key->firstBehavior; behavior; behavior = behavior->next) {
464 if (behavior->character == ch) {
465 found = behavior;
466 }
467 }
468 if (found) {
469 *outKeyCode = mKeys.keyAt(i);
470 *outMetaState = found->metaState;
471 return true;
472 }
473 }
474 return false;
475}
476
477void KeyCharacterMap::addKey(Vector<KeyEvent>& outEvents,
478 int32_t deviceId, int32_t keyCode, int32_t metaState, bool down, nsecs_t time) {
479 outEvents.push();
480 KeyEvent& event = outEvents.editTop();
Garfield Tan4cc839f2020-01-24 11:26:14 -0800481 event.initialize(InputEvent::nextId(), deviceId, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
482 INVALID_HMAC, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, 0, keyCode,
483 0, metaState, 0, time, time);
Jeff Brown5912f952013-07-01 19:10:31 -0700484}
485
486void KeyCharacterMap::addMetaKeys(Vector<KeyEvent>& outEvents,
487 int32_t deviceId, int32_t metaState, bool down, nsecs_t time,
488 int32_t* currentMetaState) {
489 // Add and remove meta keys symmetrically.
490 if (down) {
491 addLockedMetaKey(outEvents, deviceId, metaState, time,
492 AKEYCODE_CAPS_LOCK, AMETA_CAPS_LOCK_ON, currentMetaState);
493 addLockedMetaKey(outEvents, deviceId, metaState, time,
494 AKEYCODE_NUM_LOCK, AMETA_NUM_LOCK_ON, currentMetaState);
495 addLockedMetaKey(outEvents, deviceId, metaState, time,
496 AKEYCODE_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, currentMetaState);
497
498 addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time,
499 AKEYCODE_SHIFT_LEFT, AMETA_SHIFT_LEFT_ON,
500 AKEYCODE_SHIFT_RIGHT, AMETA_SHIFT_RIGHT_ON,
501 AMETA_SHIFT_ON, currentMetaState);
502 addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time,
503 AKEYCODE_ALT_LEFT, AMETA_ALT_LEFT_ON,
504 AKEYCODE_ALT_RIGHT, AMETA_ALT_RIGHT_ON,
505 AMETA_ALT_ON, currentMetaState);
506 addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time,
507 AKEYCODE_CTRL_LEFT, AMETA_CTRL_LEFT_ON,
508 AKEYCODE_CTRL_RIGHT, AMETA_CTRL_RIGHT_ON,
509 AMETA_CTRL_ON, currentMetaState);
510 addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, true, time,
511 AKEYCODE_META_LEFT, AMETA_META_LEFT_ON,
512 AKEYCODE_META_RIGHT, AMETA_META_RIGHT_ON,
513 AMETA_META_ON, currentMetaState);
514
515 addSingleEphemeralMetaKey(outEvents, deviceId, metaState, true, time,
516 AKEYCODE_SYM, AMETA_SYM_ON, currentMetaState);
517 addSingleEphemeralMetaKey(outEvents, deviceId, metaState, true, time,
518 AKEYCODE_FUNCTION, AMETA_FUNCTION_ON, currentMetaState);
519 } else {
520 addSingleEphemeralMetaKey(outEvents, deviceId, metaState, false, time,
521 AKEYCODE_FUNCTION, AMETA_FUNCTION_ON, currentMetaState);
522 addSingleEphemeralMetaKey(outEvents, deviceId, metaState, false, time,
523 AKEYCODE_SYM, AMETA_SYM_ON, currentMetaState);
524
525 addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time,
526 AKEYCODE_META_LEFT, AMETA_META_LEFT_ON,
527 AKEYCODE_META_RIGHT, AMETA_META_RIGHT_ON,
528 AMETA_META_ON, currentMetaState);
529 addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time,
530 AKEYCODE_CTRL_LEFT, AMETA_CTRL_LEFT_ON,
531 AKEYCODE_CTRL_RIGHT, AMETA_CTRL_RIGHT_ON,
532 AMETA_CTRL_ON, currentMetaState);
533 addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time,
534 AKEYCODE_ALT_LEFT, AMETA_ALT_LEFT_ON,
535 AKEYCODE_ALT_RIGHT, AMETA_ALT_RIGHT_ON,
536 AMETA_ALT_ON, currentMetaState);
537 addDoubleEphemeralMetaKey(outEvents, deviceId, metaState, false, time,
538 AKEYCODE_SHIFT_LEFT, AMETA_SHIFT_LEFT_ON,
539 AKEYCODE_SHIFT_RIGHT, AMETA_SHIFT_RIGHT_ON,
540 AMETA_SHIFT_ON, currentMetaState);
541
542 addLockedMetaKey(outEvents, deviceId, metaState, time,
543 AKEYCODE_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, currentMetaState);
544 addLockedMetaKey(outEvents, deviceId, metaState, time,
545 AKEYCODE_NUM_LOCK, AMETA_NUM_LOCK_ON, currentMetaState);
546 addLockedMetaKey(outEvents, deviceId, metaState, time,
547 AKEYCODE_CAPS_LOCK, AMETA_CAPS_LOCK_ON, currentMetaState);
548 }
549}
550
551bool KeyCharacterMap::addSingleEphemeralMetaKey(Vector<KeyEvent>& outEvents,
552 int32_t deviceId, int32_t metaState, bool down, nsecs_t time,
553 int32_t keyCode, int32_t keyMetaState,
554 int32_t* currentMetaState) {
555 if ((metaState & keyMetaState) == keyMetaState) {
556 *currentMetaState = updateMetaState(keyCode, down, *currentMetaState);
557 addKey(outEvents, deviceId, keyCode, *currentMetaState, down, time);
558 return true;
559 }
560 return false;
561}
562
563void KeyCharacterMap::addDoubleEphemeralMetaKey(Vector<KeyEvent>& outEvents,
564 int32_t deviceId, int32_t metaState, bool down, nsecs_t time,
565 int32_t leftKeyCode, int32_t leftKeyMetaState,
566 int32_t rightKeyCode, int32_t rightKeyMetaState,
567 int32_t eitherKeyMetaState,
568 int32_t* currentMetaState) {
569 bool specific = false;
570 specific |= addSingleEphemeralMetaKey(outEvents, deviceId, metaState, down, time,
571 leftKeyCode, leftKeyMetaState, currentMetaState);
572 specific |= addSingleEphemeralMetaKey(outEvents, deviceId, metaState, down, time,
573 rightKeyCode, rightKeyMetaState, currentMetaState);
574
575 if (!specific) {
576 addSingleEphemeralMetaKey(outEvents, deviceId, metaState, down, time,
577 leftKeyCode, eitherKeyMetaState, currentMetaState);
578 }
579}
580
581void KeyCharacterMap::addLockedMetaKey(Vector<KeyEvent>& outEvents,
582 int32_t deviceId, int32_t metaState, nsecs_t time,
583 int32_t keyCode, int32_t keyMetaState,
584 int32_t* currentMetaState) {
585 if ((metaState & keyMetaState) == keyMetaState) {
586 *currentMetaState = updateMetaState(keyCode, true, *currentMetaState);
587 addKey(outEvents, deviceId, keyCode, *currentMetaState, true, time);
588 *currentMetaState = updateMetaState(keyCode, false, *currentMetaState);
589 addKey(outEvents, deviceId, keyCode, *currentMetaState, false, time);
590 }
591}
592
Elliott Hughes6071da72015-08-12 15:27:47 -0700593#ifdef __ANDROID__
Chris Ye3a1e4462020-08-12 10:13:15 -0700594std::shared_ptr<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) {
595 if (parcel == nullptr) {
596 ALOGE("%s: Null parcel", __func__);
597 return nullptr;
598 }
599 std::shared_ptr<KeyCharacterMap> map = std::shared_ptr<KeyCharacterMap>(new KeyCharacterMap());
Jeff Brown5912f952013-07-01 19:10:31 -0700600 map->mType = parcel->readInt32();
601 size_t numKeys = parcel->readInt32();
602 if (parcel->errorCheck()) {
Yi Kong5bed83b2018-07-17 12:53:47 -0700603 return nullptr;
Jeff Brown5912f952013-07-01 19:10:31 -0700604 }
Michael Wright4c971c02015-10-21 14:38:03 +0100605 if (numKeys > MAX_KEYS) {
Ian Pedowitzd57d9b92016-02-19 08:34:43 +0000606 ALOGE("Too many keys in KeyCharacterMap (%zu > %d)", numKeys, MAX_KEYS);
Yi Kong5bed83b2018-07-17 12:53:47 -0700607 return nullptr;
Michael Wright4c971c02015-10-21 14:38:03 +0100608 }
Jeff Brown5912f952013-07-01 19:10:31 -0700609
610 for (size_t i = 0; i < numKeys; i++) {
611 int32_t keyCode = parcel->readInt32();
612 char16_t label = parcel->readInt32();
613 char16_t number = parcel->readInt32();
614 if (parcel->errorCheck()) {
Yi Kong5bed83b2018-07-17 12:53:47 -0700615 return nullptr;
Jeff Brown5912f952013-07-01 19:10:31 -0700616 }
617
618 Key* key = new Key();
619 key->label = label;
620 key->number = number;
621 map->mKeys.add(keyCode, key);
622
Yi Kong5bed83b2018-07-17 12:53:47 -0700623 Behavior* lastBehavior = nullptr;
Jeff Brown5912f952013-07-01 19:10:31 -0700624 while (parcel->readInt32()) {
625 int32_t metaState = parcel->readInt32();
626 char16_t character = parcel->readInt32();
627 int32_t fallbackKeyCode = parcel->readInt32();
Dmitry Torokhov115f93e2015-09-17 18:04:50 -0700628 int32_t replacementKeyCode = parcel->readInt32();
Jeff Brown5912f952013-07-01 19:10:31 -0700629 if (parcel->errorCheck()) {
Yi Kong5bed83b2018-07-17 12:53:47 -0700630 return nullptr;
Jeff Brown5912f952013-07-01 19:10:31 -0700631 }
632
633 Behavior* behavior = new Behavior();
634 behavior->metaState = metaState;
635 behavior->character = character;
636 behavior->fallbackKeyCode = fallbackKeyCode;
Dmitry Torokhov115f93e2015-09-17 18:04:50 -0700637 behavior->replacementKeyCode = replacementKeyCode;
Jeff Brown5912f952013-07-01 19:10:31 -0700638 if (lastBehavior) {
639 lastBehavior->next = behavior;
640 } else {
641 key->firstBehavior = behavior;
642 }
643 lastBehavior = behavior;
644 }
645
646 if (parcel->errorCheck()) {
Yi Kong5bed83b2018-07-17 12:53:47 -0700647 return nullptr;
Jeff Brown5912f952013-07-01 19:10:31 -0700648 }
649 }
650 return map;
651}
652
653void KeyCharacterMap::writeToParcel(Parcel* parcel) const {
Chris Ye3a1e4462020-08-12 10:13:15 -0700654 if (parcel == nullptr) {
655 ALOGE("%s: Null parcel", __func__);
656 return;
657 }
Jeff Brown5912f952013-07-01 19:10:31 -0700658 parcel->writeInt32(mType);
659
660 size_t numKeys = mKeys.size();
661 parcel->writeInt32(numKeys);
662 for (size_t i = 0; i < numKeys; i++) {
663 int32_t keyCode = mKeys.keyAt(i);
664 const Key* key = mKeys.valueAt(i);
665 parcel->writeInt32(keyCode);
666 parcel->writeInt32(key->label);
667 parcel->writeInt32(key->number);
Yi Kong5bed83b2018-07-17 12:53:47 -0700668 for (const Behavior* behavior = key->firstBehavior; behavior != nullptr;
Jeff Brown5912f952013-07-01 19:10:31 -0700669 behavior = behavior->next) {
670 parcel->writeInt32(1);
671 parcel->writeInt32(behavior->metaState);
672 parcel->writeInt32(behavior->character);
673 parcel->writeInt32(behavior->fallbackKeyCode);
Dmitry Torokhov115f93e2015-09-17 18:04:50 -0700674 parcel->writeInt32(behavior->replacementKeyCode);
Jeff Brown5912f952013-07-01 19:10:31 -0700675 }
676 parcel->writeInt32(0);
677 }
678}
679#endif
680
681
682// --- KeyCharacterMap::Key ---
683
684KeyCharacterMap::Key::Key() :
Yi Kong5bed83b2018-07-17 12:53:47 -0700685 label(0), number(0), firstBehavior(nullptr) {
Jeff Brown5912f952013-07-01 19:10:31 -0700686}
687
688KeyCharacterMap::Key::Key(const Key& other) :
689 label(other.label), number(other.number),
Yi Kong5bed83b2018-07-17 12:53:47 -0700690 firstBehavior(other.firstBehavior ? new Behavior(*other.firstBehavior) : nullptr) {
Jeff Brown5912f952013-07-01 19:10:31 -0700691}
692
693KeyCharacterMap::Key::~Key() {
694 Behavior* behavior = firstBehavior;
695 while (behavior) {
696 Behavior* next = behavior->next;
697 delete behavior;
698 behavior = next;
699 }
700}
701
702
703// --- KeyCharacterMap::Behavior ---
704
705KeyCharacterMap::Behavior::Behavior() :
Yi Kong5bed83b2018-07-17 12:53:47 -0700706 next(nullptr), metaState(0), character(0), fallbackKeyCode(0), replacementKeyCode(0) {
Jeff Brown5912f952013-07-01 19:10:31 -0700707}
708
709KeyCharacterMap::Behavior::Behavior(const Behavior& other) :
Yi Kong5bed83b2018-07-17 12:53:47 -0700710 next(other.next ? new Behavior(*other.next) : nullptr),
Jeff Brown5912f952013-07-01 19:10:31 -0700711 metaState(other.metaState), character(other.character),
Dmitry Torokhov115f93e2015-09-17 18:04:50 -0700712 fallbackKeyCode(other.fallbackKeyCode),
713 replacementKeyCode(other.replacementKeyCode) {
Jeff Brown5912f952013-07-01 19:10:31 -0700714}
715
716
717// --- KeyCharacterMap::Parser ---
718
719KeyCharacterMap::Parser::Parser(KeyCharacterMap* map, Tokenizer* tokenizer, Format format) :
720 mMap(map), mTokenizer(tokenizer), mFormat(format), mState(STATE_TOP) {
721}
722
723KeyCharacterMap::Parser::~Parser() {
724}
725
726status_t KeyCharacterMap::Parser::parse() {
727 while (!mTokenizer->isEof()) {
728#if DEBUG_PARSER
729 ALOGD("Parsing %s: '%s'.", mTokenizer->getLocation().string(),
730 mTokenizer->peekRemainderOfLine().string());
731#endif
732
733 mTokenizer->skipDelimiters(WHITESPACE);
734
735 if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
736 switch (mState) {
737 case STATE_TOP: {
738 String8 keywordToken = mTokenizer->nextToken(WHITESPACE);
739 if (keywordToken == "type") {
740 mTokenizer->skipDelimiters(WHITESPACE);
741 status_t status = parseType();
742 if (status) return status;
743 } else if (keywordToken == "map") {
744 mTokenizer->skipDelimiters(WHITESPACE);
745 status_t status = parseMap();
746 if (status) return status;
747 } else if (keywordToken == "key") {
748 mTokenizer->skipDelimiters(WHITESPACE);
749 status_t status = parseKey();
750 if (status) return status;
751 } else {
752 ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(),
753 keywordToken.string());
754 return BAD_VALUE;
755 }
756 break;
757 }
758
759 case STATE_KEY: {
760 status_t status = parseKeyProperty();
761 if (status) return status;
762 break;
763 }
764 }
765
766 mTokenizer->skipDelimiters(WHITESPACE);
767 if (!mTokenizer->isEol() && mTokenizer->peekChar() != '#') {
768 ALOGE("%s: Expected end of line or trailing comment, got '%s'.",
769 mTokenizer->getLocation().string(),
770 mTokenizer->peekRemainderOfLine().string());
771 return BAD_VALUE;
772 }
773 }
774
775 mTokenizer->nextLine();
776 }
777
778 if (mState != STATE_TOP) {
779 ALOGE("%s: Unterminated key description at end of file.",
780 mTokenizer->getLocation().string());
781 return BAD_VALUE;
782 }
783
784 if (mMap->mType == KEYBOARD_TYPE_UNKNOWN) {
785 ALOGE("%s: Keyboard layout missing required keyboard 'type' declaration.",
786 mTokenizer->getLocation().string());
787 return BAD_VALUE;
788 }
789
790 if (mFormat == FORMAT_BASE) {
791 if (mMap->mType == KEYBOARD_TYPE_OVERLAY) {
792 ALOGE("%s: Base keyboard layout must specify a keyboard 'type' other than 'OVERLAY'.",
793 mTokenizer->getLocation().string());
794 return BAD_VALUE;
795 }
796 } else if (mFormat == FORMAT_OVERLAY) {
797 if (mMap->mType != KEYBOARD_TYPE_OVERLAY) {
798 ALOGE("%s: Overlay keyboard layout missing required keyboard "
799 "'type OVERLAY' declaration.",
800 mTokenizer->getLocation().string());
801 return BAD_VALUE;
802 }
803 }
804
805 return NO_ERROR;
806}
807
808status_t KeyCharacterMap::Parser::parseType() {
809 if (mMap->mType != KEYBOARD_TYPE_UNKNOWN) {
810 ALOGE("%s: Duplicate keyboard 'type' declaration.",
811 mTokenizer->getLocation().string());
812 return BAD_VALUE;
813 }
814
815 KeyboardType type;
816 String8 typeToken = mTokenizer->nextToken(WHITESPACE);
817 if (typeToken == "NUMERIC") {
818 type = KEYBOARD_TYPE_NUMERIC;
819 } else if (typeToken == "PREDICTIVE") {
820 type = KEYBOARD_TYPE_PREDICTIVE;
821 } else if (typeToken == "ALPHA") {
822 type = KEYBOARD_TYPE_ALPHA;
823 } else if (typeToken == "FULL") {
824 type = KEYBOARD_TYPE_FULL;
825 } else if (typeToken == "SPECIAL_FUNCTION") {
Siarhei Vishniakou61da25a2018-02-15 21:04:49 -0600826 ALOGW("The SPECIAL_FUNCTION type is now declared in the device's IDC file, please set "
827 "the property 'keyboard.specialFunction' to '1' there instead.");
828 // TODO: return BAD_VALUE here in Q
Jeff Brown5912f952013-07-01 19:10:31 -0700829 type = KEYBOARD_TYPE_SPECIAL_FUNCTION;
830 } else if (typeToken == "OVERLAY") {
831 type = KEYBOARD_TYPE_OVERLAY;
832 } else {
833 ALOGE("%s: Expected keyboard type label, got '%s'.", mTokenizer->getLocation().string(),
834 typeToken.string());
835 return BAD_VALUE;
836 }
837
838#if DEBUG_PARSER
839 ALOGD("Parsed type: type=%d.", type);
840#endif
841 mMap->mType = type;
842 return NO_ERROR;
843}
844
845status_t KeyCharacterMap::Parser::parseMap() {
846 String8 keywordToken = mTokenizer->nextToken(WHITESPACE);
847 if (keywordToken == "key") {
848 mTokenizer->skipDelimiters(WHITESPACE);
849 return parseMapKey();
850 }
851 ALOGE("%s: Expected keyword after 'map', got '%s'.", mTokenizer->getLocation().string(),
852 keywordToken.string());
853 return BAD_VALUE;
854}
855
856status_t KeyCharacterMap::Parser::parseMapKey() {
857 String8 codeToken = mTokenizer->nextToken(WHITESPACE);
858 bool mapUsage = false;
859 if (codeToken == "usage") {
860 mapUsage = true;
861 mTokenizer->skipDelimiters(WHITESPACE);
862 codeToken = mTokenizer->nextToken(WHITESPACE);
863 }
864
865 char* end;
866 int32_t code = int32_t(strtol(codeToken.string(), &end, 0));
867 if (*end) {
868 ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(),
869 mapUsage ? "usage" : "scan code", codeToken.string());
870 return BAD_VALUE;
871 }
872 KeyedVector<int32_t, int32_t>& map =
873 mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode;
874 if (map.indexOfKey(code) >= 0) {
875 ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(),
876 mapUsage ? "usage" : "scan code", codeToken.string());
877 return BAD_VALUE;
878 }
879
880 mTokenizer->skipDelimiters(WHITESPACE);
881 String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
Chris Ye4958d062020-08-20 13:21:10 -0700882 int32_t keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.string());
Jeff Brown5912f952013-07-01 19:10:31 -0700883 if (!keyCode) {
884 ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(),
885 keyCodeToken.string());
886 return BAD_VALUE;
887 }
888
889#if DEBUG_PARSER
890 ALOGD("Parsed map key %s: code=%d, keyCode=%d.",
891 mapUsage ? "usage" : "scan code", code, keyCode);
892#endif
893 map.add(code, keyCode);
894 return NO_ERROR;
895}
896
897status_t KeyCharacterMap::Parser::parseKey() {
898 String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
Chris Ye4958d062020-08-20 13:21:10 -0700899 int32_t keyCode = InputEventLookup::getKeyCodeByLabel(keyCodeToken.string());
Jeff Brown5912f952013-07-01 19:10:31 -0700900 if (!keyCode) {
901 ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(),
902 keyCodeToken.string());
903 return BAD_VALUE;
904 }
905 if (mMap->mKeys.indexOfKey(keyCode) >= 0) {
906 ALOGE("%s: Duplicate entry for key code '%s'.", mTokenizer->getLocation().string(),
907 keyCodeToken.string());
908 return BAD_VALUE;
909 }
910
911 mTokenizer->skipDelimiters(WHITESPACE);
912 String8 openBraceToken = mTokenizer->nextToken(WHITESPACE);
913 if (openBraceToken != "{") {
914 ALOGE("%s: Expected '{' after key code label, got '%s'.",
915 mTokenizer->getLocation().string(), openBraceToken.string());
916 return BAD_VALUE;
917 }
918
919#if DEBUG_PARSER
920 ALOGD("Parsed beginning of key: keyCode=%d.", keyCode);
921#endif
922 mKeyCode = keyCode;
923 mMap->mKeys.add(keyCode, new Key());
924 mState = STATE_KEY;
925 return NO_ERROR;
926}
927
928status_t KeyCharacterMap::Parser::parseKeyProperty() {
929 Key* key = mMap->mKeys.valueFor(mKeyCode);
930 String8 token = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER);
931 if (token == "}") {
932 mState = STATE_TOP;
933 return finishKey(key);
934 }
935
936 Vector<Property> properties;
937
938 // Parse all comma-delimited property names up to the first colon.
939 for (;;) {
940 if (token == "label") {
941 properties.add(Property(PROPERTY_LABEL));
942 } else if (token == "number") {
943 properties.add(Property(PROPERTY_NUMBER));
944 } else {
945 int32_t metaState;
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +0100946 status_t status = parseModifier(token.string(), &metaState);
Jeff Brown5912f952013-07-01 19:10:31 -0700947 if (status) {
948 ALOGE("%s: Expected a property name or modifier, got '%s'.",
949 mTokenizer->getLocation().string(), token.string());
950 return status;
951 }
952 properties.add(Property(PROPERTY_META, metaState));
953 }
954
955 mTokenizer->skipDelimiters(WHITESPACE);
956 if (!mTokenizer->isEol()) {
957 char ch = mTokenizer->nextChar();
958 if (ch == ':') {
959 break;
960 } else if (ch == ',') {
961 mTokenizer->skipDelimiters(WHITESPACE);
962 token = mTokenizer->nextToken(WHITESPACE_OR_PROPERTY_DELIMITER);
963 continue;
964 }
965 }
966
967 ALOGE("%s: Expected ',' or ':' after property name.",
968 mTokenizer->getLocation().string());
969 return BAD_VALUE;
970 }
971
972 // Parse behavior after the colon.
973 mTokenizer->skipDelimiters(WHITESPACE);
974
975 Behavior behavior;
976 bool haveCharacter = false;
977 bool haveFallback = false;
Dmitry Torokhov115f93e2015-09-17 18:04:50 -0700978 bool haveReplacement = false;
Jeff Brown5912f952013-07-01 19:10:31 -0700979
980 do {
981 char ch = mTokenizer->peekChar();
982 if (ch == '\'') {
983 char16_t character;
984 status_t status = parseCharacterLiteral(&character);
985 if (status || !character) {
986 ALOGE("%s: Invalid character literal for key.",
987 mTokenizer->getLocation().string());
988 return BAD_VALUE;
989 }
990 if (haveCharacter) {
991 ALOGE("%s: Cannot combine multiple character literals or 'none'.",
992 mTokenizer->getLocation().string());
993 return BAD_VALUE;
994 }
Dmitry Torokhov115f93e2015-09-17 18:04:50 -0700995 if (haveReplacement) {
996 ALOGE("%s: Cannot combine character literal with replace action.",
997 mTokenizer->getLocation().string());
998 return BAD_VALUE;
999 }
Jeff Brown5912f952013-07-01 19:10:31 -07001000 behavior.character = character;
1001 haveCharacter = true;
1002 } else {
1003 token = mTokenizer->nextToken(WHITESPACE);
1004 if (token == "none") {
1005 if (haveCharacter) {
1006 ALOGE("%s: Cannot combine multiple character literals or 'none'.",
1007 mTokenizer->getLocation().string());
1008 return BAD_VALUE;
1009 }
Dmitry Torokhov115f93e2015-09-17 18:04:50 -07001010 if (haveReplacement) {
1011 ALOGE("%s: Cannot combine 'none' with replace action.",
1012 mTokenizer->getLocation().string());
1013 return BAD_VALUE;
1014 }
Jeff Brown5912f952013-07-01 19:10:31 -07001015 haveCharacter = true;
1016 } else if (token == "fallback") {
1017 mTokenizer->skipDelimiters(WHITESPACE);
1018 token = mTokenizer->nextToken(WHITESPACE);
Chris Ye4958d062020-08-20 13:21:10 -07001019 int32_t keyCode = InputEventLookup::getKeyCodeByLabel(token.string());
Jeff Brown5912f952013-07-01 19:10:31 -07001020 if (!keyCode) {
1021 ALOGE("%s: Invalid key code label for fallback behavior, got '%s'.",
1022 mTokenizer->getLocation().string(),
1023 token.string());
1024 return BAD_VALUE;
1025 }
Dmitry Torokhov115f93e2015-09-17 18:04:50 -07001026 if (haveFallback || haveReplacement) {
1027 ALOGE("%s: Cannot combine multiple fallback/replacement key codes.",
Jeff Brown5912f952013-07-01 19:10:31 -07001028 mTokenizer->getLocation().string());
1029 return BAD_VALUE;
1030 }
1031 behavior.fallbackKeyCode = keyCode;
1032 haveFallback = true;
Dmitry Torokhov115f93e2015-09-17 18:04:50 -07001033 } else if (token == "replace") {
1034 mTokenizer->skipDelimiters(WHITESPACE);
1035 token = mTokenizer->nextToken(WHITESPACE);
Chris Ye4958d062020-08-20 13:21:10 -07001036 int32_t keyCode = InputEventLookup::getKeyCodeByLabel(token.string());
Dmitry Torokhov115f93e2015-09-17 18:04:50 -07001037 if (!keyCode) {
1038 ALOGE("%s: Invalid key code label for replace, got '%s'.",
1039 mTokenizer->getLocation().string(),
1040 token.string());
1041 return BAD_VALUE;
1042 }
1043 if (haveCharacter) {
1044 ALOGE("%s: Cannot combine character literal with replace action.",
1045 mTokenizer->getLocation().string());
1046 return BAD_VALUE;
1047 }
1048 if (haveFallback || haveReplacement) {
1049 ALOGE("%s: Cannot combine multiple fallback/replacement key codes.",
1050 mTokenizer->getLocation().string());
1051 return BAD_VALUE;
1052 }
1053 behavior.replacementKeyCode = keyCode;
1054 haveReplacement = true;
1055
Jeff Brown5912f952013-07-01 19:10:31 -07001056 } else {
1057 ALOGE("%s: Expected a key behavior after ':'.",
1058 mTokenizer->getLocation().string());
1059 return BAD_VALUE;
1060 }
1061 }
1062
1063 mTokenizer->skipDelimiters(WHITESPACE);
1064 } while (!mTokenizer->isEol() && mTokenizer->peekChar() != '#');
1065
1066 // Add the behavior.
1067 for (size_t i = 0; i < properties.size(); i++) {
1068 const Property& property = properties.itemAt(i);
1069 switch (property.property) {
1070 case PROPERTY_LABEL:
1071 if (key->label) {
1072 ALOGE("%s: Duplicate label for key.",
1073 mTokenizer->getLocation().string());
1074 return BAD_VALUE;
1075 }
1076 key->label = behavior.character;
1077#if DEBUG_PARSER
1078 ALOGD("Parsed key label: keyCode=%d, label=%d.", mKeyCode, key->label);
1079#endif
1080 break;
1081 case PROPERTY_NUMBER:
1082 if (key->number) {
1083 ALOGE("%s: Duplicate number for key.",
1084 mTokenizer->getLocation().string());
1085 return BAD_VALUE;
1086 }
1087 key->number = behavior.character;
1088#if DEBUG_PARSER
1089 ALOGD("Parsed key number: keyCode=%d, number=%d.", mKeyCode, key->number);
1090#endif
1091 break;
1092 case PROPERTY_META: {
1093 for (Behavior* b = key->firstBehavior; b; b = b->next) {
1094 if (b->metaState == property.metaState) {
1095 ALOGE("%s: Duplicate key behavior for modifier.",
1096 mTokenizer->getLocation().string());
1097 return BAD_VALUE;
1098 }
1099 }
1100 Behavior* newBehavior = new Behavior(behavior);
1101 newBehavior->metaState = property.metaState;
1102 newBehavior->next = key->firstBehavior;
1103 key->firstBehavior = newBehavior;
1104#if DEBUG_PARSER
Dmitry Torokhov115f93e2015-09-17 18:04:50 -07001105 ALOGD("Parsed key meta: keyCode=%d, meta=0x%x, char=%d, fallback=%d replace=%d.",
1106 mKeyCode,
1107 newBehavior->metaState, newBehavior->character,
1108 newBehavior->fallbackKeyCode, newBehavior->replacementKeyCode);
Jeff Brown5912f952013-07-01 19:10:31 -07001109#endif
1110 break;
1111 }
1112 }
1113 }
1114 return NO_ERROR;
1115}
1116
1117status_t KeyCharacterMap::Parser::finishKey(Key* key) {
1118 // Fill in default number property.
1119 if (!key->number) {
1120 char16_t digit = 0;
1121 char16_t symbol = 0;
1122 for (Behavior* b = key->firstBehavior; b; b = b->next) {
1123 char16_t ch = b->character;
1124 if (ch) {
1125 if (ch >= '0' && ch <= '9') {
1126 digit = ch;
1127 } else if (ch == '(' || ch == ')' || ch == '#' || ch == '*'
1128 || ch == '-' || ch == '+' || ch == ',' || ch == '.'
1129 || ch == '\'' || ch == ':' || ch == ';' || ch == '/') {
1130 symbol = ch;
1131 }
1132 }
1133 }
1134 key->number = digit ? digit : symbol;
1135 }
1136 return NO_ERROR;
1137}
1138
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01001139status_t KeyCharacterMap::Parser::parseModifier(const std::string& token, int32_t* outMetaState) {
Jeff Brown5912f952013-07-01 19:10:31 -07001140 if (token == "base") {
1141 *outMetaState = 0;
1142 return NO_ERROR;
1143 }
1144
1145 int32_t combinedMeta = 0;
1146
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01001147 const char* str = token.c_str();
Jeff Brown5912f952013-07-01 19:10:31 -07001148 const char* start = str;
1149 for (const char* cur = str; ; cur++) {
1150 char ch = *cur;
1151 if (ch == '+' || ch == '\0') {
1152 size_t len = cur - start;
1153 int32_t metaState = 0;
1154 for (size_t i = 0; i < sizeof(modifiers) / sizeof(Modifier); i++) {
1155 if (strlen(modifiers[i].label) == len
1156 && strncmp(modifiers[i].label, start, len) == 0) {
1157 metaState = modifiers[i].metaState;
1158 break;
1159 }
1160 }
1161 if (!metaState) {
1162 return BAD_VALUE;
1163 }
1164 if (combinedMeta & metaState) {
1165 ALOGE("%s: Duplicate modifier combination '%s'.",
Siarhei Vishniakouec8f7252018-07-06 11:19:32 +01001166 mTokenizer->getLocation().string(), token.c_str());
Jeff Brown5912f952013-07-01 19:10:31 -07001167 return BAD_VALUE;
1168 }
1169
1170 combinedMeta |= metaState;
1171 start = cur + 1;
1172
1173 if (ch == '\0') {
1174 break;
1175 }
1176 }
1177 }
1178 *outMetaState = combinedMeta;
1179 return NO_ERROR;
1180}
1181
1182status_t KeyCharacterMap::Parser::parseCharacterLiteral(char16_t* outCharacter) {
1183 char ch = mTokenizer->nextChar();
1184 if (ch != '\'') {
1185 goto Error;
1186 }
1187
1188 ch = mTokenizer->nextChar();
1189 if (ch == '\\') {
1190 // Escape sequence.
1191 ch = mTokenizer->nextChar();
1192 if (ch == 'n') {
1193 *outCharacter = '\n';
1194 } else if (ch == 't') {
1195 *outCharacter = '\t';
1196 } else if (ch == '\\') {
1197 *outCharacter = '\\';
1198 } else if (ch == '\'') {
1199 *outCharacter = '\'';
1200 } else if (ch == '"') {
1201 *outCharacter = '"';
1202 } else if (ch == 'u') {
1203 *outCharacter = 0;
1204 for (int i = 0; i < 4; i++) {
1205 ch = mTokenizer->nextChar();
1206 int digit;
1207 if (ch >= '0' && ch <= '9') {
1208 digit = ch - '0';
1209 } else if (ch >= 'A' && ch <= 'F') {
1210 digit = ch - 'A' + 10;
1211 } else if (ch >= 'a' && ch <= 'f') {
1212 digit = ch - 'a' + 10;
1213 } else {
1214 goto Error;
1215 }
1216 *outCharacter = (*outCharacter << 4) | digit;
1217 }
1218 } else {
1219 goto Error;
1220 }
1221 } else if (ch >= 32 && ch <= 126 && ch != '\'') {
1222 // ASCII literal character.
1223 *outCharacter = ch;
1224 } else {
1225 goto Error;
1226 }
1227
1228 ch = mTokenizer->nextChar();
1229 if (ch != '\'') {
1230 goto Error;
1231 }
1232
1233 // Ensure that we consumed the entire token.
1234 if (mTokenizer->nextToken(WHITESPACE).isEmpty()) {
1235 return NO_ERROR;
1236 }
1237
1238Error:
1239 ALOGE("%s: Malformed character literal.", mTokenizer->getLocation().string());
1240 return BAD_VALUE;
1241}
1242
1243} // namespace android