diff options
-rw-r--r-- | include/ui/EventHub.h | 23 | ||||
-rw-r--r-- | include/ui/Input.h | 3 | ||||
-rw-r--r-- | include/ui/InputReader.h | 13 | ||||
-rwxr-xr-x | include/ui/KeycodeLabels.h | 56 | ||||
-rw-r--r-- | include/utils/String8.h | 8 | ||||
-rw-r--r-- | libs/ui/EventHub.cpp | 210 | ||||
-rw-r--r-- | libs/ui/InputReader.cpp | 113 | ||||
-rw-r--r-- | libs/ui/KeyCharacterMap.cpp | 42 | ||||
-rw-r--r-- | libs/utils/String8.cpp | 5 |
9 files changed, 387 insertions, 86 deletions
diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h index d78e35fbfa..1431964865 100644 --- a/include/ui/EventHub.h +++ b/include/ui/EventHub.h @@ -187,6 +187,9 @@ public: virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const = 0; + virtual bool hasLed(int32_t deviceId, int32_t led) const = 0; + virtual void setLedState(int32_t deviceId, int32_t led, bool on) = 0; + virtual void dump(String8& dump) = 0; }; @@ -198,9 +201,9 @@ public: status_t errorCheck() const; virtual uint32_t getDeviceClasses(int32_t deviceId) const; - + virtual String8 getDeviceName(int32_t deviceId) const; - + virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis, RawAbsoluteAxisInfo* outAxisInfo) const; @@ -218,6 +221,9 @@ public: virtual bool getEvent(RawEvent* outEvent); + virtual bool hasLed(int32_t deviceId, int32_t led) const; + virtual void setLedState(int32_t deviceId, int32_t led, bool on); + virtual void dump(String8& dump); protected: @@ -240,7 +246,10 @@ private: uint32_t classes; uint8_t* keyBitmask; KeyLayoutMap* layoutMap; - String8 keylayoutFilename; + String8 keyMapName; + bool defaultKeyMap; + String8 keyLayoutFilename; + String8 keyCharacterMapFilename; int fd; device_t* next; @@ -250,13 +259,19 @@ private: device_t* getDeviceLocked(int32_t deviceId) const; bool hasKeycodeLocked(device_t* device, int keycode) const; - + int32_t getScanCodeStateLocked(device_t* device, int32_t scanCode) const; int32_t getKeyCodeStateLocked(device_t* device, int32_t keyCode) const; int32_t getSwitchStateLocked(device_t* device, int32_t sw) const; bool markSupportedKeyCodesLocked(device_t* device, size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const; + void configureKeyMap(device_t* device); + bool probeKeyMap(device_t* device, const String8& keyMapName, bool defaultKeyMap); + void selectKeyMap(device_t* device, const String8& keyMapName, bool defaultKeyMap); + void setKeyboardProperties(device_t* device, bool firstKeyboard); + void clearKeyboardProperties(device_t* device, bool firstKeyboard); + // Protect all internal state. mutable Mutex mLock; diff --git a/include/ui/Input.h b/include/ui/Input.h index 8c6018bfee..1355bab31c 100644 --- a/include/ui/Input.h +++ b/include/ui/Input.h @@ -76,7 +76,7 @@ namespace android { */ enum { /* These flags originate in RawEvents and are generally set in the key map. - * See also labels for policy flags in KeycodeLabels.h. */ + * NOTE: If you edit these flags, also edit labels in KeycodeLabels.h. */ POLICY_FLAG_WAKE = 0x00000001, POLICY_FLAG_WAKE_DROPPED = 0x00000002, @@ -87,6 +87,7 @@ enum { POLICY_FLAG_MENU = 0x00000040, POLICY_FLAG_LAUNCHER = 0x00000080, POLICY_FLAG_VIRTUAL = 0x00000100, + POLICY_FLAG_FUNCTION = 0x00000200, POLICY_FLAG_RAW_MASK = 0x0000ffff, diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h index c15e3825ed..a1b59e620f 100644 --- a/include/ui/InputReader.h +++ b/include/ui/InputReader.h @@ -419,9 +419,18 @@ private: Vector<KeyDown> keyDowns; // keys that are down int32_t metaState; nsecs_t downTime; // time of most recent key down + + struct LedState { + bool avail; // led is available + bool on; // we think the led is currently on + }; + LedState capsLockLedState; + LedState numLockLedState; + LedState scrollLockLedState; } mLocked; void initializeLocked(); + void initializeLedStateLocked(LockedState::LedState& ledState, int32_t led); bool isKeyboardOrGamepadKey(int32_t scanCode); @@ -429,6 +438,10 @@ private: uint32_t policyFlags); ssize_t findKeyDownLocked(int32_t scanCode); + + void updateLedStateLocked(bool reset); + void updateLedStateForModifierLocked(LockedState::LedState& ledState, int32_t led, + int32_t modifier, bool reset); }; diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h index f71d9cdf4d..ef2b6b33d3 100755 --- a/include/ui/KeycodeLabels.h +++ b/include/ui/KeycodeLabels.h @@ -135,6 +135,59 @@ static const KeycodeLabel KEYCODES[] = { { "BUTTON_START", 108 }, { "BUTTON_SELECT", 109 }, { "BUTTON_MODE", 110 }, + { "ESCAPE", 111 }, + { "FORWARD_DEL", 112 }, + { "CTRL_LEFT", 113 }, + { "CTRL_RIGHT", 114 }, + { "CAPS_LOCK", 115 }, + { "SCROLL_LOCK", 116 }, + { "META_LEFT", 117 }, + { "META_RIGHT", 118 }, + { "FUNCTION", 119 }, + { "SYSRQ", 120 }, + { "BREAK", 121 }, + { "MOVE_HOME", 122 }, + { "MOVE_END", 123 }, + { "INSERT", 124 }, + { "FORWARD", 125 }, + { "MEDIA_PLAY", 126 }, + { "MEDIA_PAUSE", 127 }, + { "MEDIA_CLOSE", 128 }, + { "MEDIA_EJECT", 129 }, + { "MEDIA_RECORD", 130 }, + { "F1", 131 }, + { "F2", 132 }, + { "F3", 133 }, + { "F4", 134 }, + { "F5", 135 }, + { "F6", 136 }, + { "F7", 137 }, + { "F8", 138 }, + { "F9", 139 }, + { "F10", 140 }, + { "F11", 141 }, + { "F12", 142 }, + { "NUM_LOCK", 143 }, + { "NUMPAD_0", 144 }, + { "NUMPAD_1", 145 }, + { "NUMPAD_2", 146 }, + { "NUMPAD_3", 147 }, + { "NUMPAD_4", 148 }, + { "NUMPAD_5", 149 }, + { "NUMPAD_6", 150 }, + { "NUMPAD_7", 151 }, + { "NUMPAD_8", 152 }, + { "NUMPAD_9", 153 }, + { "NUMPAD_DIVIDE", 154 }, + { "NUMPAD_MULTIPLY", 155 }, + { "NUMPAD_SUBTRACT", 156 }, + { "NUMPAD_ADD", 157 }, + { "NUMPAD_DOT", 158 }, + { "NUMPAD_COMMA", 159 }, + { "NUMPAD_ENTER", 160 }, + { "NUMPAD_EQUALS", 161 }, + { "NUMPAD_LEFT_PAREN", 162 }, + { "NUMPAD_RIGHT_PAREN", 163 }, // NOTE: If you add a new keycode here you must also add it to several other files. // Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list. @@ -142,7 +195,7 @@ static const KeycodeLabel KEYCODES[] = { { NULL, 0 } }; -// See also policy flags in Input.h. +// NOTE: If you edit these flags, also edit policy flags in Input.h. static const KeycodeLabel FLAGS[] = { { "WAKE", 0x00000001 }, { "WAKE_DROPPED", 0x00000002 }, @@ -153,6 +206,7 @@ static const KeycodeLabel FLAGS[] = { { "MENU", 0x00000040 }, { "LAUNCHER", 0x00000080 }, { "VIRTUAL", 0x00000100 }, + { "FUNCTION", 0x00000200 }, { NULL, 0 } }; diff --git a/include/utils/String8.h b/include/utils/String8.h index ef0b51a443..cef8ecab96 100644 --- a/include/utils/String8.h +++ b/include/utils/String8.h @@ -157,9 +157,12 @@ public: inline size_t size() const; inline size_t length() const; inline size_t bytes() const; + inline bool isEmpty() const; inline const SharedBuffer* sharedBuffer() const; + void clear(); + void setTo(const String8& other); status_t setTo(const char* other); status_t setTo(const char* other, size_t numChars); @@ -345,6 +348,11 @@ inline size_t String8::size() const return length(); } +inline bool String8::isEmpty() const +{ + return length() == 0; +} + inline size_t String8::bytes() const { return SharedBuffer::sizeFromData(mString)-1; diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp index 944731dba6..97a7528904 100644 --- a/libs/ui/EventHub.cpp +++ b/libs/ui/EventHub.cpp @@ -94,7 +94,7 @@ static inline const char* toString(bool value) { EventHub::device_t::device_t(int32_t _id, const char* _path, const char* name) : id(_id), path(_path), name(name), classes(0) - , keyBitmask(NULL), layoutMap(new KeyLayoutMap()), fd(-1), next(NULL) { + , keyBitmask(NULL), layoutMap(new KeyLayoutMap()), defaultKeyMap(false), fd(-1), next(NULL) { } EventHub::device_t::~device_t() { @@ -103,7 +103,7 @@ EventHub::device_t::~device_t() { } EventHub::EventHub(void) - : mError(NO_INIT), mHaveFirstKeyboard(false), mFirstKeyboardId(0) + : mError(NO_INIT), mHaveFirstKeyboard(false), mFirstKeyboardId(-1) , mDevicesById(0), mNumDevicesById(0) , mOpeningDevices(0), mClosingDevices(0) , mDevices(0), mFDs(0), mFDCount(0), mOpened(false), mNeedToSendFinishedDeviceScan(false) @@ -325,6 +325,39 @@ void EventHub::addExcludedDevice(const char* deviceName) mExcludedDevices.push_back(name); } +bool EventHub::hasLed(int32_t deviceId, int32_t led) const { + AutoMutex _l(mLock); + device_t* device = getDeviceLocked(deviceId); + if (device) { + uint8_t bitmask[sizeof_bit_array(LED_MAX + 1)]; + memset(bitmask, 0, sizeof(bitmask)); + if (ioctl(device->fd, EVIOCGBIT(EV_LED, sizeof(bitmask)), bitmask) >= 0) { + if (test_bit(led, bitmask)) { + return true; + } + } + } + return false; +} + +void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) { + AutoMutex _l(mLock); + device_t* device = getDeviceLocked(deviceId); + if (device) { + struct input_event ev; + ev.time.tv_sec = 0; + ev.time.tv_usec = 0; + ev.type = EV_LED; + ev.code = led; + ev.value = on ? 1 : 0; + + ssize_t nWrite; + do { + nWrite = write(device->fd, &ev, sizeof(struct input_event)); + } while (nWrite == -1 && errno == EINTR); + } +} + EventHub::device_t* EventHub::getDeviceLocked(int32_t deviceId) const { if (deviceId == 0) deviceId = mFirstKeyboardId; @@ -760,54 +793,42 @@ int EventHub::openDevice(const char *deviceName) { #endif if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) { - char tmpfn[sizeof(name)]; - char keylayoutFilename[300]; - // a more descriptive name device->name = name; - // replace all the spaces with underscores - strcpy(tmpfn, name); - for (char *p = strchr(tmpfn, ' '); p && *p; p = strchr(tmpfn, ' ')) - *p = '_'; - - // find the .kl file we need for this device - const char* root = getenv("ANDROID_ROOT"); - snprintf(keylayoutFilename, sizeof(keylayoutFilename), - "%s/usr/keylayout/%s.kl", root, tmpfn); - bool defaultKeymap = false; - if (access(keylayoutFilename, R_OK)) { - snprintf(keylayoutFilename, sizeof(keylayoutFilename), - "%s/usr/keylayout/%s", root, "qwerty.kl"); - defaultKeymap = true; - } - status_t status = device->layoutMap->load(keylayoutFilename); - if (status) { - LOGE("Error %d loading key layout.", status); - } + // Configure the keymap for the device. + configureKeyMap(device); - // tell the world about the devname (the descriptive name) - if (!mHaveFirstKeyboard && !defaultKeymap && strstr(name, "-keypad")) { + // Tell the world about the devname (the descriptive name) + if (!mHaveFirstKeyboard && !device->defaultKeyMap && strstr(name, "-keypad")) { // the built-in keyboard has a well-known device ID of 0, // this device better not go away. mHaveFirstKeyboard = true; mFirstKeyboardId = device->id; - property_set("hw.keyboards.0.devname", name); + setKeyboardProperties(device, true); } else { // ensure mFirstKeyboardId is set to -something-. - if (mFirstKeyboardId == 0) { + if (mFirstKeyboardId == -1) { mFirstKeyboardId = device->id; + setKeyboardProperties(device, true); + } + } + setKeyboardProperties(device, false); + + // Load the keylayout. + if (!device->keyLayoutFilename.isEmpty()) { + status_t status = device->layoutMap->load(device->keyLayoutFilename); + if (status) { + LOGE("Error %d loading key layout file '%s'.", status, + device->keyLayoutFilename.string()); } } - char propName[100]; - sprintf(propName, "hw.keyboards.%u.devname", device->id); - property_set(propName, name); // 'Q' key support = cheap test of whether this is an alpha-capable kbd if (hasKeycodeLocked(device, AKEYCODE_Q)) { device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY; } - + // See if this device has a DPAD. if (hasKeycodeLocked(device, AKEYCODE_DPAD_UP) && hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) && @@ -816,7 +837,7 @@ int EventHub::openDevice(const char *deviceName) { hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) { device->classes |= INPUT_DEVICE_CLASS_DPAD; } - + // See if this device has a gamepad. for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES); i++) { if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) { @@ -825,8 +846,9 @@ int EventHub::openDevice(const char *deviceName) { } } - LOGI("New keyboard: device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n", - device->id, name, propName, keylayoutFilename); + LOGI("New keyboard: device->id=0x%x devname='%s' keylayout='%s' keycharactermap='%s'\n", + device->id, name, + device->keyLayoutFilename.string(), device->keyCharacterMapFilename.string()); } // If the device isn't recognized as something we handle, don't monitor it. @@ -852,6 +874,109 @@ int EventHub::openDevice(const char *deviceName) { return 0; } +void EventHub::configureKeyMap(device_t* device) { + // As an initial key map name, try using the device name. + String8 keyMapName(device->name); + char* p = keyMapName.lockBuffer(keyMapName.size()); + while (*p) { + if (*p == ' ') *p = '_'; + p++; + } + keyMapName.unlockBuffer(); + + if (probeKeyMap(device, keyMapName, false)) return; + + // TODO Consider allowing the user to configure a specific key map somehow. + + // Try the Generic key map. + // TODO Apply some additional heuristics here to figure out what kind of + // generic key map to use (US English, etc.). + keyMapName.setTo("Generic"); + if (probeKeyMap(device, keyMapName, true)) return; + + // Fall back on the old style catchall qwerty key map. + keyMapName.setTo("qwerty"); + if (probeKeyMap(device, keyMapName, true)) return; + + // Give up! + keyMapName.setTo("unknown"); + selectKeyMap(device, keyMapName, true); + LOGE("Could not determine key map for device '%s'.", device->name.string()); +} + +bool EventHub::probeKeyMap(device_t* device, const String8& keyMapName, bool defaultKeyMap) { + const char* root = getenv("ANDROID_ROOT"); + + // TODO Consider also looking somewhere in a writeable partition like /data for a + // custom keymap supplied by the user for this device. + bool haveKeyLayout = !device->keyLayoutFilename.isEmpty(); + if (!haveKeyLayout) { + device->keyLayoutFilename.setTo(root); + device->keyLayoutFilename.append("/usr/keylayout/"); + device->keyLayoutFilename.append(keyMapName); + device->keyLayoutFilename.append(".kl"); + if (access(device->keyLayoutFilename.string(), R_OK)) { + device->keyLayoutFilename.clear(); + } else { + haveKeyLayout = true; + } + } + + bool haveKeyCharacterMap = !device->keyCharacterMapFilename.isEmpty(); + if (!haveKeyCharacterMap) { + device->keyCharacterMapFilename.setTo(root); + device->keyCharacterMapFilename.append("/usr/keychars/"); + device->keyCharacterMapFilename.append(keyMapName); + device->keyCharacterMapFilename.append(".kcm.bin"); + if (access(device->keyCharacterMapFilename.string(), R_OK)) { + device->keyCharacterMapFilename.clear(); + } else { + haveKeyCharacterMap = true; + } + } + + if (haveKeyLayout || haveKeyCharacterMap) { + selectKeyMap(device, keyMapName, defaultKeyMap); + } + return haveKeyLayout && haveKeyCharacterMap; +} + +void EventHub::selectKeyMap(device_t* device, + const String8& keyMapName, bool defaultKeyMap) { + if (device->keyMapName.isEmpty()) { + device->keyMapName.setTo(keyMapName); + device->defaultKeyMap = defaultKeyMap; + } +} + +void EventHub::setKeyboardProperties(device_t* device, bool firstKeyboard) { + int32_t id = firstKeyboard ? 0 : device->id; + + char propName[100]; + sprintf(propName, "hw.keyboards.%u.devname", id); + property_set(propName, device->name.string()); + sprintf(propName, "hw.keyboards.%u.keymap", id); + property_set(propName, device->keyMapName.string()); + sprintf(propName, "hw.keyboards.%u.klfile", id); + property_set(propName, device->keyLayoutFilename.string()); + sprintf(propName, "hw.keyboards.%u.kcmfile", id); + property_set(propName, device->keyCharacterMapFilename.string()); +} + +void EventHub::clearKeyboardProperties(device_t* device, bool firstKeyboard) { + int32_t id = firstKeyboard ? 0 : device->id; + + char propName[100]; + sprintf(propName, "hw.keyboards.%u.devname", id); + property_set(propName, ""); + sprintf(propName, "hw.keyboards.%u.keymap", id); + property_set(propName, ""); + sprintf(propName, "hw.keyboards.%u.klfile", id); + property_set(propName, ""); + sprintf(propName, "hw.keyboards.%u.kcmfile", id); + property_set(propName, ""); +} + bool EventHub::hasKeycodeLocked(device_t* device, int keycode) const { if (device->keyBitmask == NULL || device->layoutMap == NULL) { @@ -909,13 +1034,10 @@ int EventHub::closeDevice(const char *deviceName) { if (device->id == mFirstKeyboardId) { LOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this", device->path.string(), mFirstKeyboardId); - mFirstKeyboardId = 0; - property_set("hw.keyboards.0.devname", NULL); + mFirstKeyboardId = -1; + clearKeyboardProperties(device, true); } - // clear the property - char propName[100]; - sprintf(propName, "hw.keyboards.%u.devname", device->id); - property_set(propName, NULL); + clearKeyboardProperties(device, false); return 0; } } @@ -1014,7 +1136,11 @@ void EventHub::dump(String8& dump) { } dump.appendFormat(INDENT3 "Classes: 0x%08x\n", device->classes); dump.appendFormat(INDENT3 "Path: %s\n", device->path.string()); - dump.appendFormat(INDENT3 "KeyLayoutFile: %s\n", device->keylayoutFilename.string()); + dump.appendFormat(INDENT3 "KeyMapName: %s\n", device->keyMapName.string()); + dump.appendFormat(INDENT3 "KeyLayoutFilename: %s\n", + device->keyLayoutFilename.string()); + dump.appendFormat(INDENT3 "KeyCharacterMapFilename: %s\n", + device->keyCharacterMapFilename.string()); } } } // release lock diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp index 0560bb89fb..62251217c3 100644 --- a/libs/ui/InputReader.cpp +++ b/libs/ui/InputReader.cpp @@ -70,41 +70,73 @@ static inline const char* toString(bool value) { return value ? "true" : "false"; } +int32_t setEphemeralMetaState(int32_t mask, bool down, int32_t oldMetaState) { + int32_t newMetaState; + if (down) { + newMetaState = oldMetaState | mask; + } else { + newMetaState = oldMetaState & + ~(mask | AMETA_ALT_ON | AMETA_SHIFT_ON | AMETA_CTRL_ON | AMETA_META_ON); + } + + if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) { + newMetaState |= AMETA_ALT_ON; + } + + if (newMetaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) { + newMetaState |= AMETA_SHIFT_ON; + } + + if (newMetaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) { + newMetaState |= AMETA_CTRL_ON; + } + + if (newMetaState & (AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON)) { + newMetaState |= AMETA_META_ON; + } + return newMetaState; +} + +int32_t toggleLockedMetaState(int32_t mask, bool down, int32_t oldMetaState) { + if (down) { + return oldMetaState; + } else { + return oldMetaState ^ mask; + } +} int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) { int32_t mask; switch (keyCode) { case AKEYCODE_ALT_LEFT: - mask = AMETA_ALT_LEFT_ON; - break; + return setEphemeralMetaState(AMETA_ALT_LEFT_ON, down, oldMetaState); case AKEYCODE_ALT_RIGHT: - mask = AMETA_ALT_RIGHT_ON; - break; + return setEphemeralMetaState(AMETA_ALT_RIGHT_ON, down, oldMetaState); case AKEYCODE_SHIFT_LEFT: - mask = AMETA_SHIFT_LEFT_ON; - break; + return setEphemeralMetaState(AMETA_SHIFT_LEFT_ON, down, oldMetaState); case AKEYCODE_SHIFT_RIGHT: - mask = AMETA_SHIFT_RIGHT_ON; - break; + return setEphemeralMetaState(AMETA_SHIFT_RIGHT_ON, down, oldMetaState); case AKEYCODE_SYM: - mask = AMETA_SYM_ON; - break; + return setEphemeralMetaState(AMETA_SYM_ON, down, oldMetaState); + case AKEYCODE_FUNCTION: + return setEphemeralMetaState(AMETA_FUNCTION_ON, down, oldMetaState); + case AKEYCODE_CTRL_LEFT: + return setEphemeralMetaState(AMETA_CTRL_LEFT_ON, down, oldMetaState); + case AKEYCODE_CTRL_RIGHT: + return setEphemeralMetaState(AMETA_CTRL_RIGHT_ON, down, oldMetaState); + case AKEYCODE_META_LEFT: + return setEphemeralMetaState(AMETA_META_LEFT_ON, down, oldMetaState); + case AKEYCODE_META_RIGHT: + return setEphemeralMetaState(AMETA_META_RIGHT_ON, down, oldMetaState); + case AKEYCODE_CAPS_LOCK: + return toggleLockedMetaState(AMETA_CAPS_LOCK_LATCHED, down, oldMetaState); + case AKEYCODE_NUM_LOCK: + return toggleLockedMetaState(AMETA_NUM_LOCK_LATCHED, down, oldMetaState); + case AKEYCODE_SCROLL_LOCK: + return toggleLockedMetaState(AMETA_SCROLL_LOCK_LATCHED, down, oldMetaState); default: return oldMetaState; } - - int32_t newMetaState = down ? oldMetaState | mask : oldMetaState & ~ mask - & ~ (AMETA_ALT_ON | AMETA_SHIFT_ON); - - if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) { - newMetaState |= AMETA_ALT_ON; - } - - if (newMetaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) { - newMetaState |= AMETA_SHIFT_ON; - } - - return newMetaState; } static const int32_t keyCodeRotationMap[][4] = { @@ -842,6 +874,17 @@ KeyboardInputMapper::~KeyboardInputMapper() { void KeyboardInputMapper::initializeLocked() { mLocked.metaState = AMETA_NONE; mLocked.downTime = 0; + + initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL); + initializeLedStateLocked(mLocked.numLockLedState, LED_NUML); + initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL); + + updateLedStateLocked(true); +} + +void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) { + ledState.avail = getEventHub()->hasLed(getDeviceId(), led); + ledState.on = false; } uint32_t KeyboardInputMapper::getSources() { @@ -966,6 +1009,7 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode, if (oldMetaState != newMetaState) { mLocked.metaState = newMetaState; metaStateChanged = true; + updateLedStateLocked(false); } downTime = mLocked.downTime; @@ -975,6 +1019,9 @@ void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode, getContext()->updateGlobalMetaState(); } + if (policyFlags & POLICY_FLAG_FUNCTION) { + newMetaState |= AMETA_FUNCTION_ON; + } getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime); @@ -1010,6 +1057,26 @@ int32_t KeyboardInputMapper::getMetaState() { } // release lock } +void KeyboardInputMapper::updateLedStateLocked(bool reset) { + updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL, + AMETA_CAPS_LOCK_LATCHED, reset); + updateLedStateForModifierLocked(mLocked.numLockLedState, LED_NUML, + AMETA_NUM_LOCK_LATCHED, reset); + updateLedStateForModifierLocked(mLocked.scrollLockLedState, LED_SCROLLL, + AMETA_SCROLL_LOCK_LATCHED, reset); +} + +void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& ledState, + int32_t led, int32_t modifier, bool reset) { + if (ledState.avail) { + bool desiredState = (mLocked.metaState & modifier) != 0; + if (ledState.on != desiredState) { + getEventHub()->setLedState(getDeviceId(), led, desiredState); + ledState.on = desiredState; + } + } +} + // --- TrackballInputMapper --- diff --git a/libs/ui/KeyCharacterMap.cpp b/libs/ui/KeyCharacterMap.cpp index e891181c82..870a45c169 100644 --- a/libs/ui/KeyCharacterMap.cpp +++ b/libs/ui/KeyCharacterMap.cpp @@ -156,26 +156,38 @@ KeyCharacterMap::find_key(int keycode) KeyCharacterMap* KeyCharacterMap::load(int id) { - KeyCharacterMap* rv = NULL; + KeyCharacterMap* map; char path[PATH_MAX]; char propName[100]; char dev[PROPERTY_VALUE_MAX]; - char tmpfn[PROPERTY_VALUE_MAX]; + char fn[PROPERTY_VALUE_MAX]; int err; + + // Check whether the EventHub has set a key character map filename for us already. + sprintf(propName, "hw.keyboards.%u.kcmfile", id); + err = property_get(propName, fn, ""); + if (err > 0) { + map = try_file(fn); + if (map) { + return map; + } + LOGW("Error loading keycharmap file '%s'. %s='%s'", path, propName, fn); + } + + // Try using the device name. const char* root = getenv("ANDROID_ROOT"); sprintf(propName, "hw.keyboards.%u.devname", id); err = property_get(propName, dev, ""); if (err > 0) { // replace all the spaces with underscores - strcpy(tmpfn, dev); - for (char *p = strchr(tmpfn, ' '); p && *p; p = strchr(tmpfn, ' ')) + strcpy(fn, dev); + for (char *p = strchr(fn, ' '); p && *p; p = strchr(p + 1, ' ')) *p = '_'; - snprintf(path, sizeof(path), "%s/usr/keychars/%s.kcm.bin", root, tmpfn); - //LOGD("load: dev='%s' path='%s'\n", dev, path); - rv = try_file(path); - if (rv != NULL) { - return rv; + snprintf(path, sizeof(path), "%s/usr/keychars/%s.kcm.bin", root, fn); + map = try_file(path); + if (map) { + return map; } LOGW("Error loading keycharmap file '%s'. %s='%s'", path, propName, dev); } else { @@ -183,14 +195,14 @@ KeyCharacterMap::load(int id) } snprintf(path, sizeof(path), "%s/usr/keychars/qwerty.kcm.bin", root); - rv = try_file(path); - if (rv == NULL) { - LOGE("Can't find any keycharmaps (also tried %s)", path); - return NULL; + map = try_file(path); + if (map) { + LOGW("Using default keymap: %s", path); + return map; } - LOGW("Using default keymap: %s", path); - return rv; + LOGE("Can't find any keycharmaps (also tried %s)", path); + return NULL; } KeyCharacterMap* diff --git a/libs/utils/String8.cpp b/libs/utils/String8.cpp index 1c4f80c1f8..6358fc4243 100644 --- a/libs/utils/String8.cpp +++ b/libs/utils/String8.cpp @@ -292,6 +292,11 @@ String8::~String8() SharedBuffer::bufferFromData(mString)->release(); } +void String8::clear() { + SharedBuffer::bufferFromData(mString)->release(); + mString = getEmptyString(); +} + void String8::setTo(const String8& other) { SharedBuffer::bufferFromData(other.mString)->acquire(); |