Add support for fallback keycodes.
This change enables the framework to synthesize key events to implement default behavior when an application does not handle a key. For example, this change enables numeric keypad keys to perform their associated special function when numlock is off. The application is informed that it is processing a fallback keypress so it can choose to ignore it. Added a new keycode for switching applications. Added ALT key deadkeys. New default key mappings: - ESC -> BACK - Meta+ESC -> HOME - Alt+ESC -> MENU - Meta+Space -> SEARCH - Meta+Tab -> APP_SWITCH Fixed some comments. Fixed some tests. Change-Id: Id7f3b6645f3a350275e624547822f72652f3defe
This commit is contained in:
parent
b5a00fcb71
commit
02d85b5021
@ -306,9 +306,10 @@ public:
|
|||||||
virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
|
virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
|
||||||
const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
|
const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
|
||||||
|
|
||||||
/* Allows the policy a chance to perform default processing for an unhandled key. */
|
/* Allows the policy a chance to perform default processing for an unhandled key.
|
||||||
|
* Returns an alternate keycode to redispatch as a fallback, or 0 to give up. */
|
||||||
virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
|
virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
|
||||||
const KeyEvent* keyEvent, uint32_t policyFlags) = 0;
|
const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) = 0;
|
||||||
|
|
||||||
/* Notifies the policy about switch events.
|
/* Notifies the policy about switch events.
|
||||||
*/
|
*/
|
||||||
@ -735,6 +736,7 @@ private:
|
|||||||
CANCEL_ALL_EVENTS = 0,
|
CANCEL_ALL_EVENTS = 0,
|
||||||
CANCEL_POINTER_EVENTS = 1,
|
CANCEL_POINTER_EVENTS = 1,
|
||||||
CANCEL_NON_POINTER_EVENTS = 2,
|
CANCEL_NON_POINTER_EVENTS = 2,
|
||||||
|
CANCEL_FALLBACK_EVENTS = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
InputState();
|
InputState();
|
||||||
@ -771,6 +773,7 @@ private:
|
|||||||
int32_t source;
|
int32_t source;
|
||||||
int32_t keyCode;
|
int32_t keyCode;
|
||||||
int32_t scanCode;
|
int32_t scanCode;
|
||||||
|
int32_t flags;
|
||||||
nsecs_t downTime;
|
nsecs_t downTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -790,7 +793,10 @@ private:
|
|||||||
Vector<KeyMemento> mKeyMementos;
|
Vector<KeyMemento> mKeyMementos;
|
||||||
Vector<MotionMemento> mMotionMementos;
|
Vector<MotionMemento> mMotionMementos;
|
||||||
|
|
||||||
static bool shouldCancelEvent(int32_t eventSource, CancelationOptions options);
|
static bool shouldCancelKey(const KeyMemento& memento,
|
||||||
|
CancelationOptions options);
|
||||||
|
static bool shouldCancelMotion(const MotionMemento& memento,
|
||||||
|
CancelationOptions options);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Manages the dispatch state associated with a single input channel. */
|
/* Manages the dispatch state associated with a single input channel. */
|
||||||
|
@ -402,7 +402,6 @@ private:
|
|||||||
} mLocked;
|
} mLocked;
|
||||||
|
|
||||||
void initializeLocked();
|
void initializeLocked();
|
||||||
void initializeLedStateLocked(LockedState::LedState& ledState, int32_t led);
|
|
||||||
|
|
||||||
void configureParameters();
|
void configureParameters();
|
||||||
void dumpParameters(String8& dump);
|
void dumpParameters(String8& dump);
|
||||||
@ -414,6 +413,8 @@ private:
|
|||||||
|
|
||||||
ssize_t findKeyDownLocked(int32_t scanCode);
|
ssize_t findKeyDownLocked(int32_t scanCode);
|
||||||
|
|
||||||
|
void resetLedStateLocked();
|
||||||
|
void initializeLedStateLocked(LockedState::LedState& ledState, int32_t led);
|
||||||
void updateLedStateLocked(bool reset);
|
void updateLedStateLocked(bool reset);
|
||||||
void updateLedStateForModifierLocked(LockedState::LedState& ledState, int32_t led,
|
void updateLedStateForModifierLocked(LockedState::LedState& ledState, int32_t led,
|
||||||
int32_t modifier, bool reset);
|
int32_t modifier, bool reset);
|
||||||
|
@ -256,7 +256,7 @@ public:
|
|||||||
* Returns WOULD_BLOCK if there is no signal present.
|
* Returns WOULD_BLOCK if there is no signal present.
|
||||||
* Other errors probably indicate that the channel is broken.
|
* Other errors probably indicate that the channel is broken.
|
||||||
*/
|
*/
|
||||||
status_t receiveFinishedSignal(bool& outHandled);
|
status_t receiveFinishedSignal(bool* outHandled);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sp<InputChannel> mChannel;
|
sp<InputChannel> mChannel;
|
||||||
|
@ -44,6 +44,12 @@ public:
|
|||||||
KEYBOARD_TYPE_SPECIAL_FUNCTION = 5,
|
KEYBOARD_TYPE_SPECIAL_FUNCTION = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Substitute key code and meta state for fallback action.
|
||||||
|
struct FallbackAction {
|
||||||
|
int32_t keyCode;
|
||||||
|
int32_t metaState;
|
||||||
|
};
|
||||||
|
|
||||||
~KeyCharacterMap();
|
~KeyCharacterMap();
|
||||||
|
|
||||||
static status_t load(const String8& filename, KeyCharacterMap** outMap);
|
static status_t load(const String8& filename, KeyCharacterMap** outMap);
|
||||||
@ -67,6 +73,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
char16_t getCharacter(int32_t keyCode, int32_t metaState) const;
|
char16_t getCharacter(int32_t keyCode, int32_t metaState) const;
|
||||||
|
|
||||||
|
/* Gets the fallback action to use by default if the application does not
|
||||||
|
* handle the specified key.
|
||||||
|
* Returns true if an action was available, false if none.
|
||||||
|
*/
|
||||||
|
bool getFallbackAction(int32_t keyCode, int32_t metaState,
|
||||||
|
FallbackAction* outFallbackAction) const;
|
||||||
|
|
||||||
/* Gets the first matching Unicode character that can be generated by the key,
|
/* Gets the first matching Unicode character that can be generated by the key,
|
||||||
* preferring the one with the specified meta key modifiers.
|
* preferring the one with the specified meta key modifiers.
|
||||||
* Returns 0 if no matching character is generated.
|
* Returns 0 if no matching character is generated.
|
||||||
@ -155,6 +168,10 @@ private:
|
|||||||
|
|
||||||
KeyCharacterMap();
|
KeyCharacterMap();
|
||||||
|
|
||||||
|
bool getKey(int32_t keyCode, const Key** outKey) const;
|
||||||
|
bool getKeyBehavior(int32_t keyCode, int32_t metaState,
|
||||||
|
const Key** outKey, const Behavior** outBehavior) const;
|
||||||
|
|
||||||
bool findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const;
|
bool findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const;
|
||||||
|
|
||||||
static void addKey(Vector<KeyEvent>& outEvents,
|
static void addKey(Vector<KeyEvent>& outEvents,
|
||||||
|
@ -211,6 +211,7 @@ static const KeycodeLabel KEYCODES[] = {
|
|||||||
{ "PROG_GREEN", 184 },
|
{ "PROG_GREEN", 184 },
|
||||||
{ "PROG_YELLOW", 185 },
|
{ "PROG_YELLOW", 185 },
|
||||||
{ "PROG_BLUE", 186 },
|
{ "PROG_BLUE", 186 },
|
||||||
|
{ "APP_SWITCH", 187 },
|
||||||
|
|
||||||
// NOTE: If you add a new keycode here you must also add it to several other files.
|
// 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.
|
// Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
|
||||||
|
@ -1884,7 +1884,7 @@ int InputDispatcher::handleReceiveCallback(int receiveFd, int events, void* data
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
status_t status = connection->inputPublisher.receiveFinishedSignal(handled);
|
status_t status = connection->inputPublisher.receiveFinishedSignal(&handled);
|
||||||
if (status) {
|
if (status) {
|
||||||
LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
|
LOGE("channel '%s' ~ Failed to receive finished signal. status=%d",
|
||||||
connection->getInputChannelName(), status);
|
connection->getInputChannelName(), status);
|
||||||
@ -3039,21 +3039,57 @@ void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(
|
|||||||
sp<Connection> connection = commandEntry->connection;
|
sp<Connection> connection = commandEntry->connection;
|
||||||
bool handled = commandEntry->handled;
|
bool handled = commandEntry->handled;
|
||||||
|
|
||||||
if (!handled && !connection->outboundQueue.isEmpty()) {
|
if (!connection->outboundQueue.isEmpty()) {
|
||||||
DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
|
DispatchEntry* dispatchEntry = connection->outboundQueue.headSentinel.next;
|
||||||
if (dispatchEntry->inProgress
|
if (dispatchEntry->inProgress
|
||||||
&& dispatchEntry->hasForegroundTarget()
|
&& dispatchEntry->hasForegroundTarget()
|
||||||
&& dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
|
&& dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
|
||||||
KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
|
KeyEntry* keyEntry = static_cast<KeyEntry*>(dispatchEntry->eventEntry);
|
||||||
KeyEvent event;
|
if (!(keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK)) {
|
||||||
initializeKeyEvent(&event, keyEntry);
|
if (handled) {
|
||||||
|
// If the application handled a non-fallback key, then immediately
|
||||||
|
// cancel all fallback keys previously dispatched to the application.
|
||||||
|
// This behavior will prevent chording with fallback keys (so they cannot
|
||||||
|
// be used as modifiers) but it will ensure that fallback keys do not
|
||||||
|
// get stuck. This takes care of the case where the application does not handle
|
||||||
|
// the original DOWN so we generate a fallback DOWN but it does handle
|
||||||
|
// the original UP in which case we would not generate the fallback UP.
|
||||||
|
synthesizeCancelationEventsForConnectionLocked(connection,
|
||||||
|
InputState::CANCEL_FALLBACK_EVENTS,
|
||||||
|
"Application handled a non-fallback event.");
|
||||||
|
} else {
|
||||||
|
// If the application did not handle a non-fallback key, then ask
|
||||||
|
// the policy what to do with it. We might generate a fallback key
|
||||||
|
// event here.
|
||||||
|
KeyEvent event;
|
||||||
|
initializeKeyEvent(&event, keyEntry);
|
||||||
|
|
||||||
mLock.unlock();
|
mLock.unlock();
|
||||||
|
|
||||||
mPolicy->dispatchUnhandledKey(connection->inputChannel,
|
bool fallback = mPolicy->dispatchUnhandledKey(connection->inputChannel,
|
||||||
&event, keyEntry->policyFlags);
|
&event, keyEntry->policyFlags, &event);
|
||||||
|
|
||||||
mLock.lock();
|
mLock.lock();
|
||||||
|
|
||||||
|
if (fallback) {
|
||||||
|
// Restart the dispatch cycle using the fallback key.
|
||||||
|
keyEntry->eventTime = event.getEventTime();
|
||||||
|
keyEntry->deviceId = event.getDeviceId();
|
||||||
|
keyEntry->source = event.getSource();
|
||||||
|
keyEntry->flags = event.getFlags() | AKEY_EVENT_FLAG_FALLBACK;
|
||||||
|
keyEntry->keyCode = event.getKeyCode();
|
||||||
|
keyEntry->scanCode = event.getScanCode();
|
||||||
|
keyEntry->metaState = event.getMetaState();
|
||||||
|
keyEntry->repeatCount = event.getRepeatCount();
|
||||||
|
keyEntry->downTime = event.getDownTime();
|
||||||
|
keyEntry->syntheticRepeat = false;
|
||||||
|
|
||||||
|
dispatchEntry->inProgress = false;
|
||||||
|
startDispatchCycleLocked(now(), connection);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3371,6 +3407,7 @@ InputDispatcher::InputState::Consistency InputDispatcher::InputState::trackKey(
|
|||||||
memento.source = entry->source;
|
memento.source = entry->source;
|
||||||
memento.keyCode = entry->keyCode;
|
memento.keyCode = entry->keyCode;
|
||||||
memento.scanCode = entry->scanCode;
|
memento.scanCode = entry->scanCode;
|
||||||
|
memento.flags = entry->flags;
|
||||||
memento.downTime = entry->downTime;
|
memento.downTime = entry->downTime;
|
||||||
return CONSISTENT;
|
return CONSISTENT;
|
||||||
}
|
}
|
||||||
@ -3453,10 +3490,10 @@ void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTim
|
|||||||
CancelationOptions options) {
|
CancelationOptions options) {
|
||||||
for (size_t i = 0; i < mKeyMementos.size(); ) {
|
for (size_t i = 0; i < mKeyMementos.size(); ) {
|
||||||
const KeyMemento& memento = mKeyMementos.itemAt(i);
|
const KeyMemento& memento = mKeyMementos.itemAt(i);
|
||||||
if (shouldCancelEvent(memento.source, options)) {
|
if (shouldCancelKey(memento, options)) {
|
||||||
outEvents.push(allocator->obtainKeyEntry(currentTime,
|
outEvents.push(allocator->obtainKeyEntry(currentTime,
|
||||||
memento.deviceId, memento.source, 0,
|
memento.deviceId, memento.source, 0,
|
||||||
AKEY_EVENT_ACTION_UP, AKEY_EVENT_FLAG_CANCELED,
|
AKEY_EVENT_ACTION_UP, memento.flags | AKEY_EVENT_FLAG_CANCELED,
|
||||||
memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
|
memento.keyCode, memento.scanCode, 0, 0, memento.downTime));
|
||||||
mKeyMementos.removeAt(i);
|
mKeyMementos.removeAt(i);
|
||||||
} else {
|
} else {
|
||||||
@ -3466,7 +3503,7 @@ void InputDispatcher::InputState::synthesizeCancelationEvents(nsecs_t currentTim
|
|||||||
|
|
||||||
for (size_t i = 0; i < mMotionMementos.size(); ) {
|
for (size_t i = 0; i < mMotionMementos.size(); ) {
|
||||||
const MotionMemento& memento = mMotionMementos.itemAt(i);
|
const MotionMemento& memento = mMotionMementos.itemAt(i);
|
||||||
if (shouldCancelEvent(memento.source, options)) {
|
if (shouldCancelMotion(memento, options)) {
|
||||||
outEvents.push(allocator->obtainMotionEntry(currentTime,
|
outEvents.push(allocator->obtainMotionEntry(currentTime,
|
||||||
memento.deviceId, memento.source, 0,
|
memento.deviceId, memento.source, 0,
|
||||||
AMOTION_EVENT_ACTION_CANCEL, 0, 0, 0,
|
AMOTION_EVENT_ACTION_CANCEL, 0, 0, 0,
|
||||||
@ -3502,15 +3539,30 @@ void InputDispatcher::InputState::copyPointerStateTo(InputState& other) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputDispatcher::InputState::shouldCancelEvent(int32_t eventSource,
|
bool InputDispatcher::InputState::shouldCancelKey(const KeyMemento& memento,
|
||||||
CancelationOptions options) {
|
CancelationOptions options) {
|
||||||
switch (options) {
|
switch (options) {
|
||||||
case CANCEL_POINTER_EVENTS:
|
case CANCEL_ALL_EVENTS:
|
||||||
return eventSource & AINPUT_SOURCE_CLASS_POINTER;
|
|
||||||
case CANCEL_NON_POINTER_EVENTS:
|
case CANCEL_NON_POINTER_EVENTS:
|
||||||
return !(eventSource & AINPUT_SOURCE_CLASS_POINTER);
|
|
||||||
default:
|
|
||||||
return true;
|
return true;
|
||||||
|
case CANCEL_FALLBACK_EVENTS:
|
||||||
|
return memento.flags & AKEY_EVENT_FLAG_FALLBACK;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InputDispatcher::InputState::shouldCancelMotion(const MotionMemento& memento,
|
||||||
|
CancelationOptions options) {
|
||||||
|
switch (options) {
|
||||||
|
case CANCEL_ALL_EVENTS:
|
||||||
|
return true;
|
||||||
|
case CANCEL_POINTER_EVENTS:
|
||||||
|
return memento.source & AINPUT_SOURCE_CLASS_POINTER;
|
||||||
|
case CANCEL_NON_POINTER_EVENTS:
|
||||||
|
return !(memento.source & AINPUT_SOURCE_CLASS_POINTER);
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -745,17 +745,6 @@ KeyboardInputMapper::~KeyboardInputMapper() {
|
|||||||
void KeyboardInputMapper::initializeLocked() {
|
void KeyboardInputMapper::initializeLocked() {
|
||||||
mLocked.metaState = AMETA_NONE;
|
mLocked.metaState = AMETA_NONE;
|
||||||
mLocked.downTime = 0;
|
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() {
|
uint32_t KeyboardInputMapper::getSources() {
|
||||||
@ -786,6 +775,12 @@ void KeyboardInputMapper::configure() {
|
|||||||
|
|
||||||
// Configure basic parameters.
|
// Configure basic parameters.
|
||||||
configureParameters();
|
configureParameters();
|
||||||
|
|
||||||
|
// Reset LEDs.
|
||||||
|
{
|
||||||
|
AutoMutex _l(mLock);
|
||||||
|
resetLedStateLocked();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyboardInputMapper::configureParameters() {
|
void KeyboardInputMapper::configureParameters() {
|
||||||
@ -813,6 +808,7 @@ void KeyboardInputMapper::reset() {
|
|||||||
// Synthesize key up event on reset if keys are currently down.
|
// Synthesize key up event on reset if keys are currently down.
|
||||||
if (mLocked.keyDowns.isEmpty()) {
|
if (mLocked.keyDowns.isEmpty()) {
|
||||||
initializeLocked();
|
initializeLocked();
|
||||||
|
resetLedStateLocked();
|
||||||
break; // done
|
break; // done
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -953,6 +949,19 @@ int32_t KeyboardInputMapper::getMetaState() {
|
|||||||
} // release lock
|
} // release lock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KeyboardInputMapper::resetLedStateLocked() {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
void KeyboardInputMapper::updateLedStateLocked(bool reset) {
|
void KeyboardInputMapper::updateLedStateLocked(bool reset) {
|
||||||
updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
|
updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
|
||||||
AMETA_CAPS_LOCK_ON, reset);
|
AMETA_CAPS_LOCK_ON, reset);
|
||||||
@ -966,7 +975,7 @@ void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState&
|
|||||||
int32_t led, int32_t modifier, bool reset) {
|
int32_t led, int32_t modifier, bool reset) {
|
||||||
if (ledState.avail) {
|
if (ledState.avail) {
|
||||||
bool desiredState = (mLocked.metaState & modifier) != 0;
|
bool desiredState = (mLocked.metaState & modifier) != 0;
|
||||||
if (ledState.on != desiredState) {
|
if (reset || ledState.on != desiredState) {
|
||||||
getEventHub()->setLedState(getDeviceId(), led, desiredState);
|
getEventHub()->setLedState(getDeviceId(), led, desiredState);
|
||||||
ledState.on = desiredState;
|
ledState.on = desiredState;
|
||||||
}
|
}
|
||||||
|
@ -501,7 +501,7 @@ status_t InputPublisher::sendDispatchSignal() {
|
|||||||
return mChannel->sendSignal(INPUT_SIGNAL_DISPATCH);
|
return mChannel->sendSignal(INPUT_SIGNAL_DISPATCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t InputPublisher::receiveFinishedSignal(bool& outHandled) {
|
status_t InputPublisher::receiveFinishedSignal(bool* outHandled) {
|
||||||
#if DEBUG_TRANSPORT_ACTIONS
|
#if DEBUG_TRANSPORT_ACTIONS
|
||||||
LOGD("channel '%s' publisher ~ receiveFinishedSignal",
|
LOGD("channel '%s' publisher ~ receiveFinishedSignal",
|
||||||
mChannel->getName().string());
|
mChannel->getName().string());
|
||||||
@ -510,13 +510,13 @@ status_t InputPublisher::receiveFinishedSignal(bool& outHandled) {
|
|||||||
char signal;
|
char signal;
|
||||||
status_t result = mChannel->receiveSignal(& signal);
|
status_t result = mChannel->receiveSignal(& signal);
|
||||||
if (result) {
|
if (result) {
|
||||||
outHandled = false;
|
*outHandled = false;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (signal == INPUT_SIGNAL_FINISHED_HANDLED) {
|
if (signal == INPUT_SIGNAL_FINISHED_HANDLED) {
|
||||||
outHandled = true;
|
*outHandled = true;
|
||||||
} else if (signal == INPUT_SIGNAL_FINISHED_UNHANDLED) {
|
} else if (signal == INPUT_SIGNAL_FINISHED_UNHANDLED) {
|
||||||
outHandled = false;
|
*outHandled = false;
|
||||||
} else {
|
} else {
|
||||||
LOGE("channel '%s' publisher ~ Received unexpected signal '%c' from consumer",
|
LOGE("channel '%s' publisher ~ Received unexpected signal '%c' from consumer",
|
||||||
mChannel->getName().string(), signal);
|
mChannel->getName().string(), signal);
|
||||||
|
@ -141,9 +141,8 @@ int32_t KeyCharacterMap::getKeyboardType() const {
|
|||||||
|
|
||||||
char16_t KeyCharacterMap::getDisplayLabel(int32_t keyCode) const {
|
char16_t KeyCharacterMap::getDisplayLabel(int32_t keyCode) const {
|
||||||
char16_t result = 0;
|
char16_t result = 0;
|
||||||
ssize_t index = mKeys.indexOfKey(keyCode);
|
const Key* key;
|
||||||
if (index >= 0) {
|
if (getKey(keyCode, &key)) {
|
||||||
const Key* key = mKeys.valueAt(index);
|
|
||||||
result = key->label;
|
result = key->label;
|
||||||
}
|
}
|
||||||
#if DEBUG_MAPPING
|
#if DEBUG_MAPPING
|
||||||
@ -154,9 +153,8 @@ char16_t KeyCharacterMap::getDisplayLabel(int32_t keyCode) const {
|
|||||||
|
|
||||||
char16_t KeyCharacterMap::getNumber(int32_t keyCode) const {
|
char16_t KeyCharacterMap::getNumber(int32_t keyCode) const {
|
||||||
char16_t result = 0;
|
char16_t result = 0;
|
||||||
ssize_t index = mKeys.indexOfKey(keyCode);
|
const Key* key;
|
||||||
if (index >= 0) {
|
if (getKey(keyCode, &key)) {
|
||||||
const Key* key = mKeys.valueAt(index);
|
|
||||||
result = key->number;
|
result = key->number;
|
||||||
}
|
}
|
||||||
#if DEBUG_MAPPING
|
#if DEBUG_MAPPING
|
||||||
@ -167,15 +165,10 @@ char16_t KeyCharacterMap::getNumber(int32_t keyCode) const {
|
|||||||
|
|
||||||
char16_t KeyCharacterMap::getCharacter(int32_t keyCode, int32_t metaState) const {
|
char16_t KeyCharacterMap::getCharacter(int32_t keyCode, int32_t metaState) const {
|
||||||
char16_t result = 0;
|
char16_t result = 0;
|
||||||
ssize_t index = mKeys.indexOfKey(keyCode);
|
const Key* key;
|
||||||
if (index >= 0) {
|
const Behavior* behavior;
|
||||||
const Key* key = mKeys.valueAt(index);
|
if (getKeyBehavior(keyCode, metaState, &key, &behavior)) {
|
||||||
for (const Behavior* behavior = key->firstBehavior; behavior; behavior = behavior->next) {
|
result = behavior->character;
|
||||||
if ((behavior->metaState & metaState) == behavior->metaState) {
|
|
||||||
result = behavior->character;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#if DEBUG_MAPPING
|
#if DEBUG_MAPPING
|
||||||
LOGD("getCharacter: keyCode=%d, metaState=0x%08x ~ Result %d.", keyCode, metaState, result);
|
LOGD("getCharacter: keyCode=%d, metaState=0x%08x ~ Result %d.", keyCode, metaState, result);
|
||||||
@ -183,13 +176,33 @@ char16_t KeyCharacterMap::getCharacter(int32_t keyCode, int32_t metaState) const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool KeyCharacterMap::getFallbackAction(int32_t keyCode, int32_t metaState,
|
||||||
|
FallbackAction* outFallbackAction) const {
|
||||||
|
outFallbackAction->keyCode = 0;
|
||||||
|
outFallbackAction->metaState = 0;
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
const Key* key;
|
||||||
|
const Behavior* behavior;
|
||||||
|
if (getKeyBehavior(keyCode, metaState, &key, &behavior)) {
|
||||||
|
outFallbackAction->keyCode = behavior->fallbackKeyCode;
|
||||||
|
outFallbackAction->metaState = metaState & ~behavior->metaState;
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
#if DEBUG_MAPPING
|
||||||
|
LOGD("getFallbackKeyCode: keyCode=%d, metaState=0x%08x ~ Result %s, "
|
||||||
|
"fallback keyCode=%d, fallback metaState=0x%08x.",
|
||||||
|
keyCode, metaState, result ? "true" : "false",
|
||||||
|
outFallbackAction->keyCode, outFallbackAction->metaState);
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
char16_t KeyCharacterMap::getMatch(int32_t keyCode, const char16_t* chars, size_t numChars,
|
char16_t KeyCharacterMap::getMatch(int32_t keyCode, const char16_t* chars, size_t numChars,
|
||||||
int32_t metaState) const {
|
int32_t metaState) const {
|
||||||
char16_t result = 0;
|
char16_t result = 0;
|
||||||
ssize_t index = mKeys.indexOfKey(keyCode);
|
const Key* key;
|
||||||
if (index >= 0) {
|
if (getKey(keyCode, &key)) {
|
||||||
const Key* key = mKeys.valueAt(index);
|
|
||||||
|
|
||||||
// Try to find the most general behavior that maps to this character.
|
// Try to find the most general behavior that maps to this character.
|
||||||
// For example, the base key behavior will usually be last in the list.
|
// For example, the base key behavior will usually be last in the list.
|
||||||
// However, if we find a perfect meta state match for one behavior then use that one.
|
// However, if we find a perfect meta state match for one behavior then use that one.
|
||||||
@ -238,7 +251,7 @@ bool KeyCharacterMap::getEvents(int32_t deviceId, const char16_t* chars, size_t
|
|||||||
}
|
}
|
||||||
#if DEBUG_MAPPING
|
#if DEBUG_MAPPING
|
||||||
LOGD("getEvents: deviceId=%d, chars=[%s] ~ Generated %d events.",
|
LOGD("getEvents: deviceId=%d, chars=[%s] ~ Generated %d events.",
|
||||||
deviceId, toString(chars, numChars).string(), outEvents.size());
|
deviceId, toString(chars, numChars).string(), int32_t(outEvents.size()));
|
||||||
for (size_t i = 0; i < outEvents.size(); i++) {
|
for (size_t i = 0; i < outEvents.size(); i++) {
|
||||||
LOGD(" Key: keyCode=%d, metaState=0x%08x, %s.",
|
LOGD(" Key: keyCode=%d, metaState=0x%08x, %s.",
|
||||||
outEvents[i].getKeyCode(), outEvents[i].getMetaState(),
|
outEvents[i].getKeyCode(), outEvents[i].getMetaState(),
|
||||||
@ -248,6 +261,32 @@ bool KeyCharacterMap::getEvents(int32_t deviceId, const char16_t* chars, size_t
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool KeyCharacterMap::getKey(int32_t keyCode, const Key** outKey) const {
|
||||||
|
ssize_t index = mKeys.indexOfKey(keyCode);
|
||||||
|
if (index >= 0) {
|
||||||
|
*outKey = mKeys.valueAt(index);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KeyCharacterMap::getKeyBehavior(int32_t keyCode, int32_t metaState,
|
||||||
|
const Key** outKey, const Behavior** outBehavior) const {
|
||||||
|
const Key* key;
|
||||||
|
if (getKey(keyCode, &key)) {
|
||||||
|
const Behavior* behavior = key->firstBehavior;
|
||||||
|
while (behavior) {
|
||||||
|
if ((behavior->metaState & metaState) == behavior->metaState) {
|
||||||
|
*outKey = key;
|
||||||
|
*outBehavior = behavior;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
behavior = behavior->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool KeyCharacterMap::findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const {
|
bool KeyCharacterMap::findKey(char16_t ch, int32_t* outKeyCode, int32_t* outMetaState) const {
|
||||||
if (!ch) {
|
if (!ch) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -66,7 +66,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
|
virtual bool dispatchUnhandledKey(const sp<InputChannel>& inputChannel,
|
||||||
const KeyEvent* keyEvent, uint32_t policyFlags) {
|
const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeKeyEvent() {
|
|||||||
<< "consumer sendFinishedSignal should return OK";
|
<< "consumer sendFinishedSignal should return OK";
|
||||||
|
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
status = mPublisher->receiveFinishedSignal(handled);
|
status = mPublisher->receiveFinishedSignal(&handled);
|
||||||
ASSERT_EQ(OK, status)
|
ASSERT_EQ(OK, status)
|
||||||
<< "publisher receiveFinishedSignal should return OK";
|
<< "publisher receiveFinishedSignal should return OK";
|
||||||
ASSERT_TRUE(handled)
|
ASSERT_TRUE(handled)
|
||||||
@ -287,7 +287,7 @@ void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent(
|
|||||||
<< "consumer sendFinishedSignal should return OK";
|
<< "consumer sendFinishedSignal should return OK";
|
||||||
|
|
||||||
bool handled = true;
|
bool handled = true;
|
||||||
status = mPublisher->receiveFinishedSignal(handled);
|
status = mPublisher->receiveFinishedSignal(&handled);
|
||||||
ASSERT_EQ(OK, status)
|
ASSERT_EQ(OK, status)
|
||||||
<< "publisher receiveFinishedSignal should return OK";
|
<< "publisher receiveFinishedSignal should return OK";
|
||||||
ASSERT_FALSE(handled)
|
ASSERT_FALSE(handled)
|
||||||
|
@ -1137,6 +1137,7 @@ protected:
|
|||||||
mFakeDispatcher = new FakeInputDispatcher();
|
mFakeDispatcher = new FakeInputDispatcher();
|
||||||
mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeDispatcher);
|
mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeDispatcher);
|
||||||
|
|
||||||
|
mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
|
||||||
mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME));
|
mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1753,7 +1754,7 @@ TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds)
|
|||||||
process(mapper, ARBITRARY_TIME, DEVICE_ID,
|
process(mapper, ARBITRARY_TIME, DEVICE_ID,
|
||||||
EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 1, 0);
|
EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 1, 0);
|
||||||
process(mapper, ARBITRARY_TIME, DEVICE_ID,
|
process(mapper, ARBITRARY_TIME, DEVICE_ID,
|
||||||
EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 1, 0);
|
EV_KEY, KEY_CAPSLOCK, AKEYCODE_CAPS_LOCK, 0, 0);
|
||||||
ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
|
ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
|
||||||
ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
|
ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
|
||||||
ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
|
ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
|
||||||
@ -2225,19 +2226,19 @@ void SingleTouchInputMapperTest::processSync(SingleTouchInputMapper* mapper) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST_F(SingleTouchInputMapperTest, GetSources_WhenDisplayTypeIsTouchPad_ReturnsTouchPad) {
|
TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchPad_ReturnsTouchPad) {
|
||||||
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
|
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
|
||||||
prepareAxes(POSITION);
|
prepareAxes(POSITION);
|
||||||
addConfigurationProperty("touch.displayType", "touchPad");
|
addConfigurationProperty("touch.deviceType", "touchPad");
|
||||||
addMapperAndConfigure(mapper);
|
addMapperAndConfigure(mapper);
|
||||||
|
|
||||||
ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper->getSources());
|
ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper->getSources());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SingleTouchInputMapperTest, GetSources_WhenDisplayTypeIsTouchScreen_ReturnsTouchScreen) {
|
TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsTouchScreen_ReturnsTouchScreen) {
|
||||||
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
|
SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice);
|
||||||
prepareAxes(POSITION);
|
prepareAxes(POSITION);
|
||||||
addConfigurationProperty("touch.displayType", "touchScreen");
|
addConfigurationProperty("touch.deviceType", "touchScreen");
|
||||||
addMapperAndConfigure(mapper);
|
addMapperAndConfigure(mapper);
|
||||||
|
|
||||||
ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper->getSources());
|
ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper->getSources());
|
||||||
|
Loading…
Reference in New Issue
Block a user