For button events, call mdevices [I]-> layoutmap-> map for ing. The Keying is actually completed by keylayoutmap: map. The configuration file Qwerty. KL is read in the keylayoutmap class, and the key-value ing relationship is determined by the configuration file Qwerty. KL. You can modify the key-value ing relationship by modifying./development/emulator/keymaps/Qwerty. KL.
JNI Functions
In the frameworks/base/services/JNI/com_android_server_keyinputqueue.cpp file, the android_server_keyinputqueue_readevent function is provided to Java for reading input device events.
C code
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 calls hub-> getevent to read the get event and convert it to the Java structure.
Event transfer thread
Create a thread in frameworks/base/services/Java/COM/Android/Server/keyinputqueue. Java to read events cyclically and put the events into the event queue.
Java code
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); } } };
Input event distribution thread
An input event distribution thread is created in frameworks/base/services/Java/COM/Android/Server/windowmanagerservice. Java to distribute events to corresponding windows.
Java code
mQueue.getEvent dispatchKey/dispatchPointer/dispatchTrackball
Button touch screen process analysis:
Constructor of the windowmanagerservice class
Windowmanagerservice ()
Mqueue = new keyq ();
Because windowmanagerservice. Java (frameworks \ base \ Services \ Java \ com \ Android \ Server) contains:
Private class keyq extends keyinputqueue
Keyq is the implementation of the abstract class keyinputqueue, so when the new keyq class is actually created in the keyinputqueue class
One thread, inputdevicereader, is used to read key events from devices. The Code is as follows:
Thread mthread = new thread ("inputdevicereader") {public void run () {called in a loop: readevent (EV );... send = preprocessevent (Di, Ev); actually, the preprocessevent function of the keyq class is called... 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 );}}
Readevent () actually calls:
static jboolean android_server_KeyInputQueue_readEvent(JNIEnv* env, jobject clazz,jobject event) bool res = hub->getEvent(&deviceId, &type, &scancode, &keycode,&flags, &value, &when);
In eventhub. cpp (frameworks \ base \ libs \ UI:
bool EventHub::getEvent(int32_t* outDeviceId, int32_t* outType, int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags, int32_t* outValue, nsecs_t* outWhen)
The Read Device operation is called in the function:
res = read(mFDs[i].fd, &iev, sizeof(iev));
After the constructor windowmanagerservice () calls New keyq (), it calls:
mInputThread = new InputDispatcherThread(); ... mInputThread.start();
To start a thread, inputdispatcherthread.
run() process(); QueuedEvent ev = mQueue.getEvent(...)
Because in the windowmanagerservice class: Final keyq mqueue;
Therefore, the inputdispatcherthread actually reads the key event from the keyq event queue.
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;
========================================================== ======================================
Keyinputqueue. Java (frameworks \ base \ Services \ Java \ com \ Android \ Server ):
Thread thread mthread = new thread ("inputdevicereader") Local call:
Readevent (EV); read key. Readevent calls a file:
Functions in com_android_server_keyinputqueue.cpp (frameworks \ base \ Services \ JNI:
static jboolean android_server_KeyInputQueue_readEvent(JNIEnv* env, jobject clazz, jobject event)
Android_server_keyinputqueue_readevent contains:
hub = new EventHub; bool res = hub->getEvent(&deviceId, &type, &scancode, &keycode, &flags, &value, &when);
Hub-> getevent is called
Functions in the eventhub. cpp (frameworks \ base \ libs \ UI) file:
bool EventHub::getEvent(int32_t* outDeviceId, int32_t* outType, int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags, int32_t* outValue, nsecs_t* outWhen)
Read button.
class RefBase::weakref_impl : public RefBase::weakref_type
After the system is started, Android
static const char *device_path = "/dev/input"; bool EventHub::openPlatformInput(void) res = scan_dir(device_path);
Use the following function to open the device.
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); ... }
When the device is turned on, if the value of device-> classes & class_keyboard is not 0, the keyboard is used.
Commonly used input devices are defined as follows:
Enum {class_keyboard = 0x00000001, // keyboard class_alphakey = 0x00000002, // class_touchscreen = 0x00000004, // touch screen class_trackball = 0x00000008 // trackball };
When you open a keyboard device, obtain the device name through IOCTL. The command eviocgname is defined in the file:
In kernel/include/Linux/input. h.
# Define eviocgname (LEN) _ IOC (_ ioc_read, 'E', 0x06, Len)/* Get device name */
The device name: pxa27x-keypad is defined in the kernel keyboard driver file Drivers/input/keyboard/pxa27x_keypad.c
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, }, };
Android_root is the environment variable. In Android command mode, you can use printenv to know that it is: System
So keylayoutfilename is:/system/usr/keylayout/pxa27x-keypad.kl
The pxa27x-keypad.kl defines the key ing, as follows:
# 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
If no keyboard ing file is defined, the/system/usr/keylayout/Qwerty. KL file of the system is used by default.
You can modify the/system/usr/keylayout/Qwerty. KL file to change the key ing of Android.
Device-> layoutmap-> load (keylayoutfilename) calls the file:
Functions in keylayoutmap. cpp (frameworks \ base \ libs \ UI:
Status_t keylayoutmap: load (const char * filename) by parsing pxa27x-keypad.kl
Save the key ing relationships in: keyedvector <int32_t, key> m_keys.
Called after obtaining the key event:
status_t KeyLayoutMap::map(int32_t scancode, int32_t *keycode, uint32_t *flags)
The scan code is converted into a recognizable button at the top of the andorid by the ing relationship keyedvector <int32_t, key> m_keys.