The driver is loaded during system startup.ProgramInitialize the hardware device and enter the bool eventhub: openplatforminput (void) function. The main function of this function is to scan the/dev/input directory to obtain the input device. How to obtain it? Use the Linux API res = scan_dir (device_path); this function is called
While (DE = readdir (DIR ))){
Strcpy (filename, de-> d_name );
Open_device (devname );
}
Constantly read the directory file and open the device through open_device. The specific function to open the device is FD = open (devicename, o_rdwr). To open the function in read/write mode, this function calls the implementation function in file_operations in the driver.
All input devices are enabled.
When the windowmanagerservice service class is running, the internal class keyq object will be created in the constructor. The keyinputqueue class inherited by this class. Of course, you must enter the constructor of this class. In the constructor of the keyinputqueue class, the anonymous internal class thread ("inputdevicereader") is started. The thread reads the driver event and places it in the message queue. The specific implementation is:
Thread mthread = new thread ("inputdevicereader "){
Public void run (){
Rawinputevent EV = new rawinputevent ();
While (true ){
Inputdevice di;
Readevent (EV );
}
}
This thread continues to run and runs cyclically through readevent (); this function is a native method. The specific implementation is
Static jboolean
Android_server_keyinputqueue_readevent (jnienv * ENV, jobject clazz,
Jobject event)
{
Glock. Lock ();
Sp <eventhub> 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 );
}
The above steps obtain the event queuedevent.
After obtaining the event, pass
Private void addlocked (inputdevice device, long when, int flags,
Int classtype, object event ){
Boolean poke = mfirst. Next = mlast;
Queuedevent EV = obtainlocked (device, when, flags, classtype, event );
Queuedevent P = mlast. Prev;
While (P! = Mfirst & eV. When <p. When ){
P = P. Prev;
}
Ev. Next = P. Next;
Ev. Prev = P;
P. Next = EV;
Ev. Next. Prev = EV;
Ev. inqueue = true;
}
This function is added to the Message Queue. The message queue is a two-way connection table with the final queuedevent mfirst header and tail respectively;
Final queuedevent mlast; this function inserts a new message before the end.
The message queue is available. You also need to read the queue. An internal thread is opened in the windowmanagerservice. Java class at the same time.
Minputthread = new inputdispatcherthread ();
Minputthread. Start ();
This thread is parallel to the write queue thread. After the thread gets up
Public void run (){
While (true ){
Try {
Process ();
} Catch (exception e ){
Log. E (TAG, "exception in input dispatcher", e );
}
}
}
This process () function reads messages. The specific implementation is
Private void process (){
Android. OS. process. setthreadpriority (
Android. OS. process. thread_priority_urgent_display );
While (true ){
Queuedevent EV = mqueue. getevent (
(INT )((! Configchanged & curtime <nextkeytime)
? (Nextkeytime-curtime): 0 ));
}
The specific implementation of the getevent () function is
Queuedevent getevent (long timeoutms ){
Long begin = systemclock. uptimemillis ();
Final long end = begin + timeoutms;
Long Now = begin;
Synchronized (mfirst ){
While (mfirst. Next = mlast & End> now ){
Queuedevent P = mfirst. Next;
Mfirst. Next = P. Next;
Mfirst. Next. Prev = mfirst;
P. inqueue = false;
Return P;
}
}
Messages are read continuously. If there is no message, the messages are blocked. If there is a message, the messages are read and referenced. Then, the message is deleted from the two-way connection table. After a message is obtained, the message is sent to a specific AP Based on the device type of the message input. For example
Switch (EV. classtype ){
Case rawinputevent. class_keyboard:
Dispatchkey (keyevent) eV. event, 0, 0 );
Mqueue. recycleevent (EV );
Break;
Case rawinputevent. class_touchscreen:
Dispatchpointer (EV, (motionevent) eV. event, 0, 0 );
Break;
Case rawinputevent. class_trackball:
Dispatchtrackball (EV, (motionevent) eV. event, 0, 0 );
Break;
Case rawinputevent. class_configuration_changed:
Configchanged = true;
Break;
Default:
Mqueue. recycleevent (EV );
Break;
}
Of course, this involves a lot of details. If you are interested, please take a look. At the same time, the mutex mechanism of read/write queues is also worth learning.