summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/androidfw/KeyCharacterMap.h9
-rw-r--r--libs/androidfw/KeyCharacterMap.cpp100
-rw-r--r--libs/androidfw/KeyLayoutMap.cpp28
-rw-r--r--packages/InputDevices/res/raw/keyboard_layout_english_us_dvorak.kcm42
-rw-r--r--services/input/EventHub.cpp26
-rw-r--r--services/input/EventHub.h7
6 files changed, 186 insertions, 26 deletions
diff --git a/include/androidfw/KeyCharacterMap.h b/include/androidfw/KeyCharacterMap.h
index e0e6ffa73e82..8db578129707 100644
--- a/include/androidfw/KeyCharacterMap.h
+++ b/include/androidfw/KeyCharacterMap.h
@@ -120,6 +120,10 @@ public:
bool getEvents(int32_t deviceId, const char16_t* chars, size_t numChars,
Vector<KeyEvent>& outEvents) const;
+ /* Maps a scan code and usage code to a key code, in case this key map overrides
+ * the mapping in some way. */
+ status_t mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const;
+
#if HAVE_ANDROID_OS
/* Reads a key map from a parcel. */
static sp<KeyCharacterMap> readFromParcel(Parcel* parcel);
@@ -198,6 +202,8 @@ private:
private:
status_t parseType();
+ status_t parseMap();
+ status_t parseMapKey();
status_t parseKey();
status_t parseKeyProperty();
status_t parseModifier(const String8& token, int32_t* outMetaState);
@@ -209,6 +215,9 @@ private:
KeyedVector<int32_t, Key*> mKeys;
int mType;
+ KeyedVector<int32_t, int32_t> mKeysByScanCode;
+ KeyedVector<int32_t, int32_t> mKeysByUsageCode;
+
KeyCharacterMap();
KeyCharacterMap(const KeyCharacterMap& other);
diff --git a/libs/androidfw/KeyCharacterMap.cpp b/libs/androidfw/KeyCharacterMap.cpp
index 66fdfd7828ec..c8f94390e4bf 100644
--- a/libs/androidfw/KeyCharacterMap.cpp
+++ b/libs/androidfw/KeyCharacterMap.cpp
@@ -90,7 +90,8 @@ KeyCharacterMap::KeyCharacterMap() :
}
KeyCharacterMap::KeyCharacterMap(const KeyCharacterMap& other) :
- RefBase(), mType(other.mType) {
+ RefBase(), mType(other.mType), mKeysByScanCode(other.mKeysByScanCode),
+ mKeysByUsageCode(other.mKeysByUsageCode) {
for (size_t i = 0; i < other.mKeys.size(); i++) {
mKeys.add(other.mKeys.keyAt(i), new Key(*other.mKeys.valueAt(i)));
}
@@ -180,6 +181,16 @@ sp<KeyCharacterMap> KeyCharacterMap::combine(const sp<KeyCharacterMap>& base,
map->mKeys.add(keyCode, new Key(*key));
}
}
+
+ for (size_t i = 0; i < overlay->mKeysByScanCode.size(); i++) {
+ map->mKeysByScanCode.replaceValueFor(overlay->mKeysByScanCode.keyAt(i),
+ overlay->mKeysByScanCode.valueAt(i));
+ }
+
+ for (size_t i = 0; i < overlay->mKeysByUsageCode.size(); i++) {
+ map->mKeysByUsageCode.replaceValueFor(overlay->mKeysByUsageCode.keyAt(i),
+ overlay->mKeysByUsageCode.valueAt(i));
+ }
return map;
}
@@ -315,6 +326,37 @@ bool KeyCharacterMap::getEvents(int32_t deviceId, const char16_t* chars, size_t
return true;
}
+status_t KeyCharacterMap::mapKey(int32_t scanCode, int32_t usageCode, int32_t* outKeyCode) const {
+ if (usageCode) {
+ ssize_t index = mKeysByUsageCode.indexOfKey(usageCode);
+ if (index >= 0) {
+#if DEBUG_MAPPING
+ ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.",
+ scanCode, usageCode, *outKeyCode);
+#endif
+ *outKeyCode = mKeysByUsageCode.valueAt(index);
+ return OK;
+ }
+ }
+ if (scanCode) {
+ ssize_t index = mKeysByScanCode.indexOfKey(scanCode);
+ if (index >= 0) {
+#if DEBUG_MAPPING
+ ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Result keyCode=%d.",
+ scanCode, usageCode, *outKeyCode);
+#endif
+ *outKeyCode = mKeysByScanCode.valueAt(index);
+ return OK;
+ }
+ }
+
+#if DEBUG_MAPPING
+ ALOGD("mapKey: scanCode=%d, usageCode=0x%08x ~ Failed.", scanCode, usageCode);
+#endif
+ *outKeyCode = AKEYCODE_UNKNOWN;
+ return NAME_NOT_FOUND;
+}
+
bool KeyCharacterMap::getKey(int32_t keyCode, const Key** outKey) const {
ssize_t index = mKeys.indexOfKey(keyCode);
if (index >= 0) {
@@ -616,6 +658,10 @@ status_t KeyCharacterMap::Parser::parse() {
mTokenizer->skipDelimiters(WHITESPACE);
status_t status = parseType();
if (status) return status;
+ } else if (keywordToken == "map") {
+ mTokenizer->skipDelimiters(WHITESPACE);
+ status_t status = parseMap();
+ if (status) return status;
} else if (keywordToken == "key") {
mTokenizer->skipDelimiters(WHITESPACE);
status_t status = parseKey();
@@ -710,6 +756,58 @@ status_t KeyCharacterMap::Parser::parseType() {
return NO_ERROR;
}
+status_t KeyCharacterMap::Parser::parseMap() {
+ String8 keywordToken = mTokenizer->nextToken(WHITESPACE);
+ if (keywordToken == "key") {
+ mTokenizer->skipDelimiters(WHITESPACE);
+ return parseMapKey();
+ }
+ ALOGE("%s: Expected keyword after 'map', got '%s'.", mTokenizer->getLocation().string(),
+ keywordToken.string());
+ return BAD_VALUE;
+}
+
+status_t KeyCharacterMap::Parser::parseMapKey() {
+ String8 codeToken = mTokenizer->nextToken(WHITESPACE);
+ bool mapUsage = false;
+ if (codeToken == "usage") {
+ mapUsage = true;
+ mTokenizer->skipDelimiters(WHITESPACE);
+ codeToken = mTokenizer->nextToken(WHITESPACE);
+ }
+
+ char* end;
+ int32_t code = int32_t(strtol(codeToken.string(), &end, 0));
+ if (*end) {
+ ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(),
+ mapUsage ? "usage" : "scan code", codeToken.string());
+ return BAD_VALUE;
+ }
+ KeyedVector<int32_t, int32_t>& map =
+ mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode;
+ if (map.indexOfKey(code) >= 0) {
+ ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(),
+ mapUsage ? "usage" : "scan code", codeToken.string());
+ return BAD_VALUE;
+ }
+
+ mTokenizer->skipDelimiters(WHITESPACE);
+ String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
+ int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string());
+ if (!keyCode) {
+ ALOGE("%s: Expected key code label, got '%s'.", mTokenizer->getLocation().string(),
+ keyCodeToken.string());
+ return BAD_VALUE;
+ }
+
+#if DEBUG_PARSER
+ ALOGD("Parsed map key %s: code=%d, keyCode=%d.",
+ mapUsage ? "usage" : "scan code", code, keyCode);
+#endif
+ map.add(code, keyCode);
+ return NO_ERROR;
+}
+
status_t KeyCharacterMap::Parser::parseKey() {
String8 keyCodeToken = mTokenizer->nextToken(WHITESPACE);
int32_t keyCode = getKeyCodeByLabel(keyCodeToken.string());
diff --git a/libs/androidfw/KeyLayoutMap.cpp b/libs/androidfw/KeyLayoutMap.cpp
index a7c219965262..2db19c5ff72f 100644
--- a/libs/androidfw/KeyLayoutMap.cpp
+++ b/libs/androidfw/KeyLayoutMap.cpp
@@ -199,17 +199,26 @@ status_t KeyLayoutMap::Parser::parse() {
}
status_t KeyLayoutMap::Parser::parseKey() {
- String8 scanCodeToken = mTokenizer->nextToken(WHITESPACE);
+ String8 codeToken = mTokenizer->nextToken(WHITESPACE);
+ bool mapUsage = false;
+ if (codeToken == "usage") {
+ mapUsage = true;
+ mTokenizer->skipDelimiters(WHITESPACE);
+ codeToken = mTokenizer->nextToken(WHITESPACE);
+ }
+
char* end;
- int32_t scanCode = int32_t(strtol(scanCodeToken.string(), &end, 0));
+ int32_t code = int32_t(strtol(codeToken.string(), &end, 0));
if (*end) {
- ALOGE("%s: Expected key scan code number, got '%s'.", mTokenizer->getLocation().string(),
- scanCodeToken.string());
+ ALOGE("%s: Expected key %s number, got '%s'.", mTokenizer->getLocation().string(),
+ mapUsage ? "usage" : "scan code", codeToken.string());
return BAD_VALUE;
}
- if (mMap->mKeysByScanCode.indexOfKey(scanCode) >= 0) {
- ALOGE("%s: Duplicate entry for key scan code '%s'.", mTokenizer->getLocation().string(),
- scanCodeToken.string());
+ KeyedVector<int32_t, Key>& map =
+ mapUsage ? mMap->mKeysByUsageCode : mMap->mKeysByScanCode;
+ if (map.indexOfKey(code) >= 0) {
+ ALOGE("%s: Duplicate entry for key %s '%s'.", mTokenizer->getLocation().string(),
+ mapUsage ? "usage" : "scan code", codeToken.string());
return BAD_VALUE;
}
@@ -243,12 +252,13 @@ status_t KeyLayoutMap::Parser::parseKey() {
}
#if DEBUG_PARSER
- ALOGD("Parsed key: scanCode=%d, keyCode=%d, flags=0x%08x.", scanCode, keyCode, flags);
+ ALOGD("Parsed key %s: code=%d, keyCode=%d, flags=0x%08x.",
+ mapUsage ? "usage" : "scan code", code, keyCode, flags);
#endif
Key key;
key.keyCode = keyCode;
key.flags = flags;
- mMap->mKeysByScanCode.add(scanCode, key);
+ map.add(code, key);
return NO_ERROR;
}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_english_us_dvorak.kcm b/packages/InputDevices/res/raw/keyboard_layout_english_us_dvorak.kcm
index b5bf2ef44eb4..a2d110ea1eae 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_english_us_dvorak.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_english_us_dvorak.kcm
@@ -19,10 +19,38 @@
type OVERLAY
-# Test
-key A {
- label: 'X'
- base: 'x'
- shift, capslock: 'X'
- ctrl, alt, meta: none
-}
+map key 12 LEFT_BRACKET
+map key 13 RIGHT_BRACKET
+map key 16 APOSTROPHE
+map key 17 COMMA
+map key 18 PERIOD
+map key 19 P
+map key 20 Y
+map key 21 F
+map key 22 G
+map key 23 C
+map key 24 R
+map key 25 L
+map key 26 SLASH
+map key 27 EQUALS
+map key 30 A
+map key 31 O
+map key 32 E
+map key 33 U
+map key 34 I
+map key 35 D
+map key 36 H
+map key 37 T
+map key 38 N
+map key 39 S
+map key 40 MINUS
+map key 44 SEMICOLON
+map key 45 Q
+map key 46 J
+map key 47 K
+map key 48 X
+map key 49 B
+map key 50 M
+map key 51 W
+map key 52 V
+map key 53 Z
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index b788e16f1f5e..326dc3267e26 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -443,11 +443,22 @@ status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
- if (device && device->keyMap.haveKeyLayout()) {
- status_t err = device->keyMap.keyLayoutMap->mapKey(
- scanCode, usageCode, outKeycode, outFlags);
- if (err == NO_ERROR) {
- return NO_ERROR;
+ if (device) {
+ // Check the key character map first.
+ sp<KeyCharacterMap> kcm = device->getKeyCharacterMap();
+ if (kcm != NULL) {
+ if (!kcm->mapKey(scanCode, usageCode, outKeycode)) {
+ *outFlags = 0;
+ return NO_ERROR;
+ }
+ }
+
+ // Check the key layout next.
+ if (device->keyMap.haveKeyLayout()) {
+ if (!device->keyMap.keyLayoutMap->mapKey(
+ scanCode, usageCode, outKeycode, outFlags)) {
+ return NO_ERROR;
+ }
}
}
@@ -531,10 +542,7 @@ sp<KeyCharacterMap> EventHub::getKeyCharacterMap(int32_t deviceId) const {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
if (device) {
- if (device->combinedKeyMap != NULL) {
- return device->combinedKeyMap;
- }
- return device->keyMap.keyCharacterMap;
+ return device->getKeyCharacterMap();
}
return NULL;
}
diff --git a/services/input/EventHub.h b/services/input/EventHub.h
index f885f4da7e00..afc12ef1aa45 100644
--- a/services/input/EventHub.h
+++ b/services/input/EventHub.h
@@ -335,6 +335,13 @@ private:
void close();
inline bool isVirtual() const { return fd < 0; }
+
+ const sp<KeyCharacterMap>& getKeyCharacterMap() const {
+ if (combinedKeyMap != NULL) {
+ return combinedKeyMap;
+ }
+ return keyMap.keyCharacterMap;
+ }
};
status_t openDeviceLocked(const char *devicePath);