Android Keyboard System

Source: Internet
Author: User

AndroidKeyboard System

The life cycle of the keyboard system in Android starts from the startup of the system to the shutdown of the system, during the entire process, we hope that any button that is pressed will have an event. The investigation shows that the android keyboard system runs through the kernel (driver) at the bottom of the android framework to the upper Java architecture layer systemserver.

Several files closely related to the android keyboard system are listed from the lower layer to the upper layer: goldfish_event.c (in the Linux kernel) and eventhub. CPP (Hardware Abstraction Layer), com_android_server_keyinputqueue.cpp (JNI local method) keyinputqueue. java, windowmanagerservice. java (Java framework layer ). I found a very interesting problem. Android didn't build a pure keyboard system, but put the implementation of the keyboard system in the event processing module. We can see from the file names of these key files.

 

CallProcessAnalysis:

Window Management is started in windowmanagerservice. java. One of the statements is as follows:

Mqueue = new keyq ();

Tracking keyq:

Private class keyq extends keyinputqueue

(Note: In the following description, the parent class refers to keyinputqueue, And the subclass refers to keyq)

Continue tracking keyinputqueue

We will find that this is a very large class, And a thread is created in this class:

Thread mthread = new thread ("inputdevicereader ")


Constructor:

Public thread (string threadname ){

If (threadname = NULL ){

Throw new nullpointerexception ();

}

Create (null, null, threadname, 0 );

}


We can know that thread mthread = new thread ("inputdevicereader") creates a thread named inputdevicereader.

But how is this thread created? As we can see, the thread object is new in the parent class. From the source code of the parent class, we can see that there is a constructor. In this constructor, the method of the mthread. Start () object is called ();

Let's take a look at the code of this constructor:

Keyinputqueue (context, hapticfeedbackcallback ){

If (measure_latency ){

Lt = new latencytimer (100,100 0 );

}


Bad_touch_hack = context. getresources (). getboolean (

Com. Android. Internal. R. bool. config_filtertouchevents );

 

Mhapticfeedbackcallback = hapticfeedbackcallback;

 

Readexcludeddevices ();

 

Powermanager PM = (powermanager) Context. getsystemservice (

Context. power_service );

Mwakelock = PM. newwakelock (powermanager. partial_wake_lock,

"Keyinputqueue ");

Mwakelock. setreferencecounted (false );


Mfirst = new queuedevent ();

Mlast = new queuedevent ();

Mfirst. Next = mlast;

Mlast. Prev = mfirst;


Mthread. Start ();

}



In the keyq constructor of the subclass, this constructor of the parent class is called:

Private class keyq extends keyinputqueue

Implements keyinputqueue. filtercallback {

Powermanager. wakelock mholdingscreen;

// The following is the construction method of the subclass keyq

Keyq (){

Super (mcontext, windowmanagerservice. This );

Powermanager PM =

(Powermanager) mcontext. getsystemservice (context. power_service );

Mholdingscreen =

PM. newwakelock (powermanager. screen_bright_wake_lock,

"Keep_screen_on_flag ");

Mholdingscreen. setreferencecounted (false );

}

Naturally, a thread mthread in the parent class is created. Therefore, when a new subclass object is created:

Mqueue = new keyq (); the thread in the parent class is called.

 








In this thread, the local method readevent is called;

Thread mthread = new thread ("inputdevicereader "){

Public void run (){

.......................


 

Rawinputevent EV = new rawinputevent ();

While (true ){

Try {

Inputdevice di;

// This is a local method

Readevent (EV );

.......................


}

}

Because we track the JNI call: com_android_server_keyinputqueue.cpp

In this native method readevent, eeventhub. cpp is called.

.......................

Sp <eventhub> hub = ghub; // SP is a class with the smartpointer function.

.......................

Bool res = hub-> getevent (& DeviceID, & type, & scancode, & keycode, & flags, & Value, & When );

.......................


So we can go to eeventhub. cpp to view the method: getevevt


Bool eventhub: getevent (int32_t * outdeviceid, int32_t * outtype,

Int32_t * outscancode, int32_t * outkeycode, uint32_t * outflags,

Int32_t * outvalue, nsecs_t * outwhen)

Next, openplatforminput () is called in getevt, scan_dir () is called in openplatforminput (), and open_device is called in scan_dir.

We noticed that the function call and access to eeventhub. cpp belongs to the hardware abstraction layer, which can directly call the Linux kernel driver.



Let's go back to the thread mthread.

Mqueue = new keyq ();

Then, call

Send = preprocessevent (Di, Ev );

Here, we actually call the preprocessevent in the mqueue.

This is because when keyq inherits keyinputqueue, The preprocessevent method is rewritten.

@ Override

Boolean preprocessevent (inputdevice device, rawinputevent event)

{

.......................


}

The following code is related to the key:

// Is it a key event?

If (type = rawinputevent. ev_key &&

(Classes & rawinputevent. class_keyboard )! = 0 &&

(Scancode <rawinputevent. btn_first |

Scancode> rawinputevent. btn_last )){

Boolean down;

If (EV. value! = 0 ){

Down = true;

Di. mkeydowntime = curtime;

} Else {

Down = false;

}

Int keycode = rotatekeycodelocked (EV. keycode );

Addlocked (Di, curtimenano, Ev. flags,

Rawinputevent. class_keyboard,

Newkeyevent (Di, Di. mkeydowntime, curtime, down,

Keycode, 0, scancode,

(EV. Flags & windowmanagerpolicy. flag_woke_here )! = 0)

? Keyevent. flag_woke_here: 0 ));

}


This mthread creates another thread, inputdispatcherthread.

.......................

Mqueue = new keyq ();


Minputthread = new inputdispatcherthread ();


Policythread thr = new policythread (mpolicy, this, context, PM );

Thr. Start ();

.......................


In inputdispatcherthread, there is a handle for the keyboard:

In fact, this thread reads the key event from the keyq event queue.

.......................

Switch (EV. classtype ){

Case rawinputevent. class_keyboard:

Keyevent KE = (keyevent) eV. event;

If (KE. isdown ()){

Lastkey = ke;

Downtime = curtime;

Keyrepeatcount = 0;

Lastkeytime = curtime;

Nextkeytime = lastkeytime

+ Viewconfiguration. getlongpresstimeout ();

If (debug_input) log. V (

Tag, "sorted ed key down: first repeat @"

+ Nextkeytime );

} Else {

Lastkey = NULL;

Downtime = 0;

// Arbitrary long timeout.

Lastkeytime = curtime;

Nextkeytime = curtime + long_wait;

If (debug_input) log. V (

Tag, "sorted ed key up: Ignore repeat @"

+ Nextkeytime );

}

Dispatchkey (keyevent) eV. event, 0, 0 );

Mqueue. recycleevent (EV );

Break;

.......................


By inserting a pile into several files, from the startup log of the simulator, we can build the entire android keyboard system more intuitively:

.......................

I/systemserver (57): Window Manager

I/windowmanager (57): New the thread: mqueue = new key

I/keyinputqueue (57): enter into the constraction of the base class keyinputqueue

I/keyinputqueue (57): Start the mthread ???????????????????

I/windowmanager (57): After mqueue = new key

I/windowmanager (57): New the thread of minputthread

I/windowmanager (57): After minputthread

I/windowmanager (57): New the thread of minputthread

I/windowmanager (57): Begin the thread of policythread THR

I/keyinputqueue (57): Start the methods run of the mthread

I/keyinputqueue (57): Before the readevent (EV), this is a native Method

I/input (57): c ::::::::::: 4 :::::::::::::: entering into the JNI method-readevent

I/eventhub (57): c :::::::: eventhub. cpp :::::::: entering into the eventhub: getevent

I/eventhub (57): c :::::::: eventhub. cpp :::::::: entering into the eventhub :: openplatforminput

I/eventhub (57): c :::::::: eventhub. cpp :::::::: before scan_dir (device_path)

I/eventhub (57): c :::::::: eventhub. cpp :::::::: entering into the scan_dir (device_path)

I/eventhub (57): c :::::::: eventhub. cpp :::::::: entering into the open_device (device_path)

I/eventhub (57): opening device:/dev/input/event0

I/eventhub (57): opened device:/dev/input/event0 (0 failures)

I/eventhub (57): Add device 1:/dev/input/event0

I/eventhub (57): Bus: 0000

I/eventhub (57): vendor0000

I/eventhub (57): Product 0000

I/eventhub (57): Version 0000

I/eventhub (57): Name: "qwerty2"

I/eventhub (57): Location :""

I/eventhub (57): ID :""

I/eventhub (57): Version: 1.0.0

I/eventhub (57): new keyboard: publicid = 65536 device-> id = 0x10000 devname = 'qwerty2 'propname = 'hw. keyboards.65536.devname 'keylayout = '/system/usr/keylayout/Qwerty. KL'

I/eventhub (57): New Device: Path =/dev/input/event0 name = qwerty2 id = 0x10000 (of 0x1) index = 1 FD = 49 classes = 0x2f

I/eventhub (57): c :::::::: eventhub. cpp :::::::: entering into the open_device (device_path)

I/eventhub (57): opening device:/dev/input/mouse0

I/eventhub (57): opened device:/dev/input/mouse0 (0 failures)

E/eventhub (57): cocould not get driver version for/dev/input/mouse0, not a typewriter

I/eventhub (57): c :::::::: eventhub. cpp :::::::: entering into the open_device (device_path)

I/eventhub (57): opening device:/dev/input/Mice

I/eventhub (57): opened device:/dev/input/mice (0 failures)

E/eventhub (57): cocould not get driver version for/dev/input/mice, not a typewriter

I/eventhub (57): c ::::::: eventhub. CPP: ::::::: enter into the while (1) ot the eventhub: getevent

I/keyinputqueue (57): After the readevent (EV)

I/keyinputqueue (57): input event: Dev = 0x0 type = 0x10000000 scancode = 0 keycode = 0 value = 0

I/keyinputqueue (57): Device added: Id = 0x0, name = qwerty2, classes = 2f

I/keyinputqueue (57): X: Unknown values

I/keyinputqueue (57): Y: Unknown values

I/keyinputqueue (57): pressure: Unknown values

I/keyinputqueue (57): Size: Unknown values

I/keyinputqueue (57): No virtual keys found

I/keyinputqueue (57): Before the readevent (EV), this is a native Method

I/input (57): c ::::::::::: 4 :::::::::::::: entering into the JNI method-readevent

I/eventhub (57): c ::::::: eventhub. cpp :::::::: enter into the eventhub: getevent

I/eventhub (57): c ::::::: eventhub. CPP: :::::::: enter into the while (1) of the eventhub: getevent

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.