Skip to content

Commit 4a3862f

Browse files
author
Jeff Brown
committed
Add Dvorak keyboard layout.
Added support for mapping both scan codes and HID usages to KeyLayoutMap and KeyCharacterMap. Keyboard overlays can now influence how key events are mapped to key codes. Bug: 6110399 Change-Id: I6619fd2d3e1337c55928f89869dbc45b535c7ccf
1 parent 6ec6f79 commit 4a3862f

File tree

6 files changed

+186
-26
lines changed

6 files changed

+186
-26
lines changed

include/androidfw/KeyCharacterMap.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ class KeyCharacterMap : public RefBase {
120120
bool getEvents(int32_t deviceId, const char16_t* chars, size_t numChars,
121121
Vector<KeyEvent>& outEvents) const;
122122

123+
/* Maps a scan code and usage code to a key code, in case this key map overrides
124+
* the mapping in some way. */
125+
status_t mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const;
126+
123127
#if HAVE_ANDROID_OS
124128
/* Reads a key map from a parcel. */
125129
static sp<KeyCharacterMap> readFromParcel(Parcel* parcel);
@@ -198,6 +202,8 @@ class KeyCharacterMap : public RefBase {
198202

199203
private:
200204
status_t parseType();
205+
status_t parseMap();
206+
status_t parseMapKey();
201207
status_t parseKey();
202208
status_t parseKeyProperty();
203209
status_t parseModifier(const String8& token, int32_t* outMetaState);
@@ -209,6 +215,9 @@ class KeyCharacterMap : public RefBase {
209215
KeyedVector<int32_t, Key*> mKeys;
210216
int mType;
211217

218+
KeyedVector<int32_t, int32_t> mKeysByScanCode;
219+
KeyedVector<int32_t, int32_t> mKeysByUsageCode;
220+
212221
KeyCharacterMap();
213222
KeyCharacterMap(const KeyCharacterMap& other);
214223

libs/androidfw/KeyCharacterMap.cpp

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ KeyCharacterMap::KeyCharacterMap() :
9090
}
9191

9292
KeyCharacterMap::KeyCharacterMap(const KeyCharacterMap& other) :
93-
RefBase(), mType(other.mType) {
93+
RefBase(), mType(other.mType), mKeysByScanCode(other.mKeysByScanCode),
94+
mKeysByUsageCode(other.mKeysByUsageCode) {
9495
for (size_t i = 0; i < other.mKeys.size(); i++) {
9596
mKeys.add(other.mKeys.keyAt(i), new Key(*other.mKeys.valueAt(i)));
9697
}
@@ -180,6 +181,16 @@ sp<KeyCharacterMap> KeyCharacterMap::combine(const sp<KeyCharacterMap>& base,
180181
map->mKeys.add(keyCode, new Key(*key));
181182
}
182183
}
184+
185+
for (size_t i = 0; i < overlay->mKeysByScanCode.size(); i++) {
186+
map->mKeysByScanCode.replaceValueFor(overlay->mKeysByScanCode.keyAt(i),
187+
overlay->mKeysByScanCode.valueAt(i));
188+
}
189+
190+
for (size_t i = 0; i < overlay->mKeysByUsageCode.size(); i++) {
191+
map->mKeysByUsageCode.replaceValueFor(overlay->mKeysByUsageCode.keyAt(i),
192+
overlay->mKeysByUsageCode.valueAt(i));
193+
}
183194
return map;
184195
}
185196

@@ -315,6 +326,37 @@ bool KeyCharacterMap::getEvents(int32_t deviceId, const char16_t* chars, size_t
315326
return true;
316327
}
317328

329+
status_t KeyCharacterMap::mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const {
330+
if (usageCode) {
331+
ssize_t index = mKeysByUsageCode.indexOfKey(usageCode);
332+
if (index >= 0) {
333+
#if DEBUG_MAPPING
334+
ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.",
335+
scanCode, usageCode, *outKeyCode);
336+
#endif
337+
*outKeyCode = mKeysByUsageCode.valueAt(index);
338+
return OK;
339+
}
340+
}
341+
if (scanCode) {
342+
ssize_t index = mKeysByScanCode.indexOfKey(scanCode);
343+
if (index >= 0) {
344+
#if DEBUG_MAPPING
345+
ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.",
346+
scanCode, usageCode, *outKeyCode);
347+
#endif
348+
*outKeyCode = mKeysByScanCode.valueAt(index);
349+
return OK;
350+
}
351+
}
352+
353+
#if DEBUG_MAPPING
354+
ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Failed.", scanCode, usageCode);
355+
#endif
356+
*outKeyCode = AKEYCODE_UNKNOWN;
357+
return NAME_NOT_FOUND;
358+
}
359+
318360
bool KeyCharacterMap::getKey(int32_t keyCode, const Key** outKey) const {
319361
ssize_t index = mKeys.indexOfKey(keyCode);
320362
if (index >= 0) {
@@ -616,6 +658,10 @@ status_t KeyCharacterMap::Parser::parse() {
616658
mTokenizer->skipDelimiters(WHITESPACE);
617659
status_t status = parseType();
618660
if (status) return status;
661+
} else if (keywordToken == "map") {
662+
mTokenizer->skipDelimiters(WHITESPACE);
663+
status_t status = parseMap();
664+
if (status) return status;
619665
} else if (keywordToken == "key") {
620666
mTokenizer->skipDelimiters(WHITESPACE);
621667
status_t status = parseKey();
@@ -710,6 +756,58 @@ status_t KeyCharacterMap::Parser::parseType() {
710756
return NO_ERROR;
711757
}
712758

759+
status_t KeyCharacterMap::Parser::parseMap() {
760+
String8 keywordToken = mTokenizer->nextToken(WHITESPACE);
761+
if (keywordToken == "key") {
762+
mTokenizer->skipDelimiters(WHITESPACE);
763+
return parseMapKey();
764+
}
765+
ALOGE("%s: Expected keyword after 'map', got '%s'.", mTokenizer->getLocation().string(),
766+
keywordToken.string());
767+
return BAD_VALUE;
768+
}
769+
770+
status_t KeyCharacterMap::Parser::parseMapKey() {
771+
String8 codeToken = mTokenizer->nextToken(WHITESPACE);
772+
bool mapUsage = false;
773+
if (codeToken == "usage") {
774+
mapUsage = true;
775+
mTokenizer->skipDelimiters(WHITESPACE);
776+
codeToken = mTokenizer->nextToken(WHITESPACE);
777+
}
778+
779+
char* end;
780+
int32_t code = int32_t(strtol(codeToken.string(), &end, 0));
781+
if (*end) {
782+
ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(),
783+
mapUsage ? "usage" : "scan code", codeToken.string());
784+
return BAD_VALUE;
785+
}
786+
KeyedVector<int32_t, int32_t>& map =
787+
mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode;
788+
if (map.indexOfKey(code) >= 0) {
789+
ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(),
790+
mapUsage ? "usage" : "scan code", codeToken.string());
791+
return BAD_VALUE;
792+
}
793+
794+
mTokenizer->skipDelimiters(WHITESPACE);
795+
String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
796+
int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string());
797+
if (!keyCode) {
798+
ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(),
799+
keyCodeToken.string());
800+
return BAD_VALUE;
801+
}
802+
803+
#if DEBUG_PARSER
804+
ALOGD("Parsed map key %s: code=%d, keyCode=%d.",
805+
mapUsage ? "usage" : "scan code", code, keyCode);
806+
#endif
807+
map.add(code, keyCode);
808+
return NO_ERROR;
809+
}
810+
713811
status_t KeyCharacterMap::Parser::parseKey() {
714812
String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
715813
int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string());

libs/androidfw/KeyLayoutMap.cpp

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -199,17 +199,26 @@ status_t KeyLayoutMap::Parser::parse() {
199199
}
200200

201201
status_t KeyLayoutMap::Parser::parseKey() {
202-
String8 scanCodeToken = mTokenizer->nextToken(WHITESPACE);
202+
String8 codeToken = mTokenizer->nextToken(WHITESPACE);
203+
bool mapUsage = false;
204+
if (codeToken == "usage") {
205+
mapUsage = true;
206+
mTokenizer->skipDelimiters(WHITESPACE);
207+
codeToken = mTokenizer->nextToken(WHITESPACE);
208+
}
209+
203210
char* end;
204-
int32_t scanCode = int32_t(strtol(scanCodeToken.string(), &end, 0));
211+
int32_t code = int32_t(strtol(codeToken.string(), &end, 0));
205212
if (*end) {
206-
ALOGE("%s: Expected key scan code number, got '%s'.", mTokenizer->getLocation().string(),
207-
scanCodeToken.string());
213+
ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(),
214+
mapUsage ? "usage" : "scan code", codeToken.string());
208215
return BAD_VALUE;
209216
}
210-
if (mMap->mKeysByScanCode.indexOfKey(scanCode) >= 0) {
211-
ALOGE("%s: Duplicate entry for key scan code '%s'.", mTokenizer->getLocation().string(),
212-
scanCodeToken.string());
217+
KeyedVector<int32_t, Key>& map =
218+
mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode;
219+
if (map.indexOfKey(code) >= 0) {
220+
ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(),
221+
mapUsage ? "usage" : "scan code", codeToken.string());
213222
return BAD_VALUE;
214223
}
215224

@@ -243,12 +252,13 @@ status_t KeyLayoutMap::Parser::parseKey() {
243252
}
244253

245254
#if DEBUG_PARSER
246-
ALOGD("Parsed key: scanCode=%d, keyCode=%d, flags=0x%08x.", scanCode, keyCode, flags);
255+
ALOGD("Parsed key %s: code=%d, keyCode=%d, flags=0x%08x.",
256+
mapUsage ? "usage" : "scan code", code, keyCode, flags);
247257
#endif
248258
Key key;
249259
key.keyCode = keyCode;
250260
key.flags = flags;
251-
mMap->mKeysByScanCode.add(scanCode, key);
261+
map.add(code, key);
252262
return NO_ERROR;
253263
}
254264

packages/InputDevices/res/raw/keyboard_layout_english_us_dvorak.kcm

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,38 @@
1919

2020
type OVERLAY
2121

22-
# Test
23-
key A {
24-
label: 'X'
25-
base: 'x'
26-
shift, capslock: 'X'
27-
ctrl, alt, meta: none
28-
}
22+
map key 12 LEFT_BRACKET
23+
map key 13 RIGHT_BRACKET
24+
map key 16 APOSTROPHE
25+
map key 17 COMMA
26+
map key 18 PERIOD
27+
map key 19 P
28+
map key 20 Y
29+
map key 21 F
30+
map key 22 G
31+
map key 23 C
32+
map key 24 R
33+
map key 25 L
34+
map key 26 SLASH
35+
map key 27 EQUALS
36+
map key 30 A
37+
map key 31 O
38+
map key 32 E
39+
map key 33 U
40+
map key 34 I
41+
map key 35 D
42+
map key 36 H
43+
map key 37 T
44+
map key 38 N
45+
map key 39 S
46+
map key 40 MINUS
47+
map key 44 SEMICOLON
48+
map key 45 Q
49+
map key 46 J
50+
map key 47 K
51+
map key 48 X
52+
map key 49 B
53+
map key 50 M
54+
map key 51 W
55+
map key 52 V
56+
map key 53 Z

services/input/EventHub.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -443,11 +443,22 @@ status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
443443
AutoMutex _l(mLock);
444444
Device* device = getDeviceLocked(deviceId);
445445

446-
if (device && device->keyMap.haveKeyLayout()) {
447-
status_t err = device->keyMap.keyLayoutMap->mapKey(
448-
scanCode, usageCode, outKeycode, outFlags);
449-
if (err == NO_ERROR) {
450-
return NO_ERROR;
446+
if (device) {
447+
// Check the key character map first.
448+
sp<KeyCharacterMap> kcm = device->getKeyCharacterMap();
449+
if (kcm != NULL) {
450+
if (!kcm->mapKey(scanCode, usageCode, outKeycode)) {
451+
*outFlags = 0;
452+
return NO_ERROR;
453+
}
454+
}
455+
456+
// Check the key layout next.
457+
if (device->keyMap.haveKeyLayout()) {
458+
if (!device->keyMap.keyLayoutMap->mapKey(
459+
scanCode, usageCode, outKeycode, outFlags)) {
460+
return NO_ERROR;
461+
}
451462
}
452463
}
453464

@@ -531,10 +542,7 @@ sp<KeyCharacterMap> EventHub::getKeyCharacterMap(int32_t deviceId) const {
531542
AutoMutex _l(mLock);
532543
Device* device = getDeviceLocked(deviceId);
533544
if (device) {
534-
if (device->combinedKeyMap != NULL) {
535-
return device->combinedKeyMap;
536-
}
537-
return device->keyMap.keyCharacterMap;
545+
return device->getKeyCharacterMap();
538546
}
539547
return NULL;
540548
}

services/input/EventHub.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,13 @@ class EventHub : public EventHubInterface
335335
void close();
336336

337337
inline bool isVirtual() const { return fd < 0; }
338+
339+
const sp<KeyCharacterMap>& getKeyCharacterMap() const {
340+
if (combinedKeyMap != NULL) {
341+
return combinedKeyMap;
342+
}
343+
return keyMap.keyCharacterMap;
344+
}
338345
};
339346

340347
status_t openDeviceLocked(const char *devicePath);

0 commit comments

Comments
 (0)