Merge "Close System.out and System.err streams when they are made unreachable."
diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h
index d78e35f..1431964 100644
--- a/include/ui/EventHub.h
+++ b/include/ui/EventHub.h
@@ -187,6 +187,9 @@
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 @@
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 @@
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 @@
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 @@
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 8c6018b..1355bab 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -76,7 +76,7 @@
*/
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 @@
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 c15e382..a1b59e6 100644
--- a/include/ui/InputReader.h
+++ b/include/ui/InputReader.h
@@ -419,9 +419,18 @@
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 @@
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 f71d9cd..ef2b6b3 100755
--- a/include/ui/KeycodeLabels.h
+++ b/include/ui/KeycodeLabels.h
@@ -135,6 +135,59 @@
{ "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 @@
{ 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 @@
{ "MENU", 0x00000040 },
{ "LAUNCHER", 0x00000080 },
{ "VIRTUAL", 0x00000100 },
+ { "FUNCTION", 0x00000200 },
{ NULL, 0 }
};
diff --git a/include/utils/String8.h b/include/utils/String8.h
index ef0b51a..cef8eca 100644
--- a/include/utils/String8.h
+++ b/include/utils/String8.h
@@ -157,9 +157,12 @@
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 @@
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 944731d..97a7528 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -94,7 +94,7 @@
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::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 @@
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 @@
#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 = '_';
+ // Configure the keymap for the device.
+ configureKeyMap(device);
- // 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);
- }
-
- // 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);
}
}
- char propName[100];
- sprintf(propName, "hw.keyboards.%u.devname", device->id);
- property_set(propName, name);
+ 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());
+ }
+ }
// '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 @@
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 @@
}
}
- 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 @@
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 @@
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 @@
}
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 0560bb8..6225121 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -70,32 +70,15 @@
return value ? "true" : "false";
}
-
-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;
- case AKEYCODE_ALT_RIGHT:
- mask = AMETA_ALT_RIGHT_ON;
- break;
- case AKEYCODE_SHIFT_LEFT:
- mask = AMETA_SHIFT_LEFT_ON;
- break;
- case AKEYCODE_SHIFT_RIGHT:
- mask = AMETA_SHIFT_RIGHT_ON;
- break;
- case AKEYCODE_SYM:
- mask = AMETA_SYM_ON;
- break;
- default:
- return oldMetaState;
+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);
}
- 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;
}
@@ -104,9 +87,58 @@
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:
+ return setEphemeralMetaState(AMETA_ALT_LEFT_ON, down, oldMetaState);
+ case AKEYCODE_ALT_RIGHT:
+ return setEphemeralMetaState(AMETA_ALT_RIGHT_ON, down, oldMetaState);
+ case AKEYCODE_SHIFT_LEFT:
+ return setEphemeralMetaState(AMETA_SHIFT_LEFT_ON, down, oldMetaState);
+ case AKEYCODE_SHIFT_RIGHT:
+ return setEphemeralMetaState(AMETA_SHIFT_RIGHT_ON, down, oldMetaState);
+ case AKEYCODE_SYM:
+ 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;
+ }
+}
+
static const int32_t keyCodeRotationMap[][4] = {
// key codes enumerated counter-clockwise with the original (unrotated) key first
// no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
@@ -842,6 +874,17 @@
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 @@
if (oldMetaState != newMetaState) {
mLocked.metaState = newMetaState;
metaStateChanged = true;
+ updateLedStateLocked(false);
}
downTime = mLocked.downTime;
@@ -975,6 +1019,9 @@
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 @@
} // 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 e891181..870a45c 100644
--- a/libs/ui/KeyCharacterMap.cpp
+++ b/libs/ui/KeyCharacterMap.cpp
@@ -156,26 +156,38 @@
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 @@
}
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 1c4f80c..6358fc4 100644
--- a/libs/utils/String8.cpp
+++ b/libs/utils/String8.cpp
@@ -292,6 +292,11 @@
SharedBuffer::bufferFromData(mString)->release();
}
+void String8::clear() {
+ SharedBuffer::bufferFromData(mString)->release();
+ mString = getEmptyString();
+}
+
void String8::setTo(const String8& other)
{
SharedBuffer::bufferFromData(other.mString)->acquire();