google推出的carboard、daydream是没有usb接口的,调节全靠手机自身的sensor。而想gear vr这类VR眼镜是有USB接口的,眼镜内部是有sensor用户调节眼镜的,而且有触屏、返回键和音量调节键。是不是很像一个鼠标。
add device 1: /dev/input/event19
name: "XXXX VR, Inc. x HID"
could not get driver version for /dev/input/mouse1, Not a typewriter
shell状态下输入getevent -l,/dev/input/mouse1确实是一个鼠标,证明了我们的猜想。
下面我们从设备输入的源头InputReader.cpp进行分析。
InputManager::InputManager(
const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
mDispatcher = new InputDispatcher(dispatcherPolicy);
mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
initialize();
}
void InputManager::initialize() {
mReaderThread = new InputReaderThread(mReader);
mDispatcherThread = new InputDispatcherThread(mDispatcher);
}
status_t InputManager::start() {
status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
if (result) {
ALOGE("Could not start InputDispatcher thread due to error %d.", result);
return result;
}
result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
if (result) {
ALOGE("Could not start InputReader thread due to error %d.", result);
mDispatcherThread->requestExit();
return result;
}
return OK;
}
InputReader是由InputManager生成,同时还生成了两个线程,一个用于取InputDevice输入的信息,一个负责分发事件
void CursorInputMapper::process(const RawEvent* rawEvent) {
mCursorButtonAccumulator.process(rawEvent);
mCursorMotionAccumulator.process(rawEvent);
mCursorScrollAccumulator.process(rawEvent);
if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
sync(rawEvent->when);
}
}
void CursorInputMapper::sync(nsecs_t when) {
......
// Synthesize key down from buttons if needed.
synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
policyFlags, lastButtonState, currentButtonState);
// Send motion event.
if (downChanged || moved || scrolled || buttonsChanged) {
int32_t metaState = mContext->getGlobalMetaState();
int32_t buttonState = lastButtonState;
int32_t motionEventAction;
if (downChanged) {
motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
} else if (down || mPointerController == NULL) {
motionEventAction = AMOTION_EVENT_ACTION_MOVE;
} else {
motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
}
if (buttonsReleased) {
BitSet32 released(buttonsReleased);
while (!released.isEmpty()) {
int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit());
buttonState &= ~actionButton;
NotifyMotionArgs releaseArgs(when, getDeviceId(), mSource, policyFlags,
AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
displayId, 1, &pointerProperties, &pointerCoords,
mXPrecision, mYPrecision, downTime);
getListener()->notifyMotion(&releaseArgs);
}
}
NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
motionEventAction, 0, 0, metaState, currentButtonState,
AMOTION_EVENT_EDGE_FLAG_NONE,
displayId, 1, &pointerProperties, &pointerCoords,
mXPrecision, mYPrecision, downTime);
getListener()->notifyMotion(&args);
......
// Synthesize key up from buttons if needed.
synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
policyFlags, lastButtonState, currentButtonState);
mCursorMotionAccumulator.finishSync();
mCursorScrollAccumulator.finishSync();
}
InputReader管理着所有的InputDevice,针对不同的输入设备类型,对应不同的InputMapper类,鼠标类型是CursorInputMapper类,Cursor取事件的方法是process,在sync方法中进行处理。
static void synthesizeButtonKey(InputReaderContext* context, int32_t action,
nsecs_t when, int32_t deviceId, uint32_t source,
uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState,
int32_t buttonState, int32_t keyCode) {
if (
(action == AKEY_EVENT_ACTION_DOWN
&& !(lastButtonState & buttonState)
&& (currentButtonState & buttonState))
|| (action == AKEY_EVENT_ACTION_UP
&& (lastButtonState & buttonState)
&& !(currentButtonState & buttonState))) {
NotifyKeyArgs args(when, deviceId, source, policyFlags,
action, 0, keyCode, 0, context->getGlobalMetaState(), when);
context->getListener()->notifyKey(&args);
}
}
static void synthesizeButtonKeys(InputReaderContext* context, int32_t action,
nsecs_t when, int32_t deviceId, uint32_t source,
uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState) {
synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
lastButtonState, currentButtonState,
AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK);
synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
lastButtonState, currentButtonState,
AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD);
}
synthesizeButtonKeys对key进行合成,我们看到了熟悉的BACK键,context->getListener()->notifyKey(&key)
InputManager::InputManager(
const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
mDispatcher = new InputDispatcher(dispatcherPolicy);
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
......
int32_t keyCode = args->keyCode;
if (metaState & AMETA_META_ON && args->action == AKEY_EVENT_ACTION_DOWN) {
int32_t newKeyCode = AKEYCODE_UNKNOWN;
if (keyCode == AKEYCODE_DEL) {
newKeyCode = AKEYCODE_BACK;
} else if (keyCode == AKEYCODE_ENTER) {
newKeyCode = AKEYCODE_HOME;
}
if (newKeyCode != AKEYCODE_UNKNOWN) {
AutoMutex _l(mLock);
struct Ke