在frameworks/base/services/jni/com_android_server_KeyInputQueue.cpp文 件中,向 JAVA提供了函数android_server_KeyInputQueue_readEvent,用于读 取输入设备事件。
C代码
static jboolean android_server_KeyInputQueue_readEvent(JNIEnv* env, jobject clazz, jobject event) { gLock.lock(); sp hub = gHub; if (hub == NULL) { hub = new EventHub; gHub = hub; } gLock.unlock(); int32_t deviceId; int32_t type; int32_t scancode, keycode; uint32_t flags; int32_t value; nsecs_t when; bool res = hub->getEvent(&deviceId, &type, &scancode, &keycode, &flags, &value, &when); env->SetIntField(event, gInputOffsets.mDeviceId, (jint)deviceId); env->SetIntField(event, gInputOffsets.mType, (jint)type); env->SetIntField(event, gInputOffsets.mScancode, (jint)scancode); env->SetIntField(event, gInputOffsets.mKeycode, (jint)keycode); env->SetIntField(event, gInputOffsets.mFlags, (jint)flags); env->SetIntField(event, gInputOffsets.mValue, value); env->SetLongField(event, gInputOffsets.mWhen, (jlong)(nanoseconds_to_milliseconds(when))); return res; }readEvent调用hub->getEvent读了取事件,然后转换成JAVA的结构。
Thread mThread = new Thread("InputDeviceReader") { public void run() { android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY); try { RawInputEvent ev = new RawInputEvent(); while (true) { InputDevice di; readEvent(ev); send = preprocessEvent(di, ev); addLocked(di, curTime, ev.flags, ..., me); } } };
mQueue.getEvent dispatchKey/dispatchPointer/dispatchTrackball
Thread mThread = new Thread("InputDeviceReader") { public void run() { 在循环中调用:readEvent(ev); ... send = preprocessEvent(di, ev); 实际调用的是 KeyQ 类的 preprocessEvent 函数 ... int keycode = rotateKeyCodeLocked(ev.keycode); int[] map = mKeyRotationMap; for (int i=0; i<N; i+=2) { if (map[i] == keyCode) return map[i+1]; } // addLocked(di, curTime, ev.flags,RawInputEvent.CLASS_KEYBOARD,newKeyEvent(di, di.mDownTime, curTime, down,keycode, 0, scancode,...)); QueuedEvent ev = obtainLocked(device, when, flags, classType, event); } }
static jboolean android_server_KeyInputQueue_readEvent(JNIEnv* env, jobject clazz,jobject event) bool res = hub->getEvent(&deviceId, &type, &scancode, &keycode,&flags, &value, &when);
bool EventHub::getEvent(int32_t* outDeviceId, int32_t* outType, int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags, int32_t* outValue, nsecs_t* outWhen)
res = read(mFDs[i].fd, &iev, sizeof(iev));
mInputThread = new InputDispatcherThread(); ... mInputThread.start();来启动一个线程 InputDispatcherThread
run() process(); QueuedEvent ev = mQueue.getEvent(...)
switch (ev.classType) case RawInputEvent.CLASS_KEYBOARD: ... dispatchKey((KeyEvent)ev.event, 0, 0); mQueue.recycleEvent(ev); break; case RawInputEvent.CLASS_TOUCHSCREEN: //Log.i(TAG, "Read next event " + ev); dispatchPointer(ev, (MotionEvent)ev.event, 0, 0); break;
static jboolean android_server_KeyInputQueue_readEvent(JNIEnv* env, jobject clazz, jobject event)android_server_KeyInputQueue_readEvent中有:
hub = new EventHub; bool res = hub->getEvent(&deviceId, &type, &scancode, &keycode, &flags, &value, &when);
bool EventHub::getEvent(int32_t* outDeviceId, int32_t* outType, int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags, int32_t* outValue, nsecs_t* outWhen)读取按键。
class RefBase::weakref_impl : public RefBase::weakref_type
static const char *device_path = "/dev/input"; bool EventHub::openPlatformInput(void) res = scan_dir(device_path);
int EventHub::open_device(const char *deviceName) { ... fd = open(deviceName, O_RDWR); ... mFDs[mFDCount].fd = fd; mFDs[mFDCount].events = POLLIN; ... ioctl(mFDs[mFDCount].fd, EVIOCGNAME(sizeof(devname)-1), devname); ... const char* root = getenv("ANDROID_ROOT"); snprintf(keylayoutFilename, sizeof(keylayoutFilename), "%s/usr/keylayout/%s.kl", root, tmpfn); ... device->layoutMap->load(keylayoutFilename); ... }
enum { CLASS_KEYBOARD = 0x00000001, //键盘 CLASS_ALPHAKEY = 0x00000002, // CLASS_TOUCHSCREEN = 0x00000004, //触摸屏 CLASS_TRACKBALL = 0x00000008 //轨迹球 };
static struct platform_driver pxa27x_keypad_driver = { .probe = pxa27x_keypad_probe, .remove = __devexit_p(pxa27x_keypad_remove), .suspend = pxa27x_keypad_suspend, .resume = pxa27x_keypad_resume, .driver = { .name = "pxa27x-keypad", .owner = THIS_MODULE, }, };
# NUMERIC KEYS 3x4 key 2 1 key 3 2 key 4 3 key 5 4 key 6 5 key 7 6 key 8 7 key 9 8 key 10 9 key 11 0 key 83 POUND key 55 STAR # FUNCTIONAL KEYS key 231 MENU WAKE_DROPPED key 192 BACK WAKE_DROPPED key 193 HOME WAKE key 107 DEL WAKE key 102 CALL WAKE_DROPPED key 158 ENDCALL WAKE_DROPPED key 28 DPAD_CENTER WAKE key 115 VOLUME_UP key 114 VOLUME_DOWN
status_t KeyLayoutMap::map(int32_t scancode, int32_t *keycode, uint32_t *flags)由映射关系 KeyedVector<int32_t,Key> m_keys 把扫描码转换成andorid上层可以识别的按键。