![Input子系統(tǒng)架構(gòu)包括內(nèi)核層與框架層詳解_第1頁(yè)](http://file2.renrendoc.com/fileroot_temp3/2021-8/28/6830748b-aa4c-4928-8bcb-a974a81b66bc/6830748b-aa4c-4928-8bcb-a974a81b66bc1.gif)
![Input子系統(tǒng)架構(gòu)包括內(nèi)核層與框架層詳解_第2頁(yè)](http://file2.renrendoc.com/fileroot_temp3/2021-8/28/6830748b-aa4c-4928-8bcb-a974a81b66bc/6830748b-aa4c-4928-8bcb-a974a81b66bc2.gif)
![Input子系統(tǒng)架構(gòu)包括內(nèi)核層與框架層詳解_第3頁(yè)](http://file2.renrendoc.com/fileroot_temp3/2021-8/28/6830748b-aa4c-4928-8bcb-a974a81b66bc/6830748b-aa4c-4928-8bcb-a974a81b66bc3.gif)
![Input子系統(tǒng)架構(gòu)包括內(nèi)核層與框架層詳解_第4頁(yè)](http://file2.renrendoc.com/fileroot_temp3/2021-8/28/6830748b-aa4c-4928-8bcb-a974a81b66bc/6830748b-aa4c-4928-8bcb-a974a81b66bc4.gif)
![Input子系統(tǒng)架構(gòu)包括內(nèi)核層與框架層詳解_第5頁(yè)](http://file2.renrendoc.com/fileroot_temp3/2021-8/28/6830748b-aa4c-4928-8bcb-a974a81b66bc/6830748b-aa4c-4928-8bcb-a974a81b66bc5.gif)
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第1章 android input子系統(tǒng)架構(gòu)1.1 input服務(wù)的啟動(dòng)在android的開機(jī)過(guò)程中,系統(tǒng)中的服務(wù)很多都是由systemserver中啟動(dòng)的。systemserver的代碼中有這么一句話。framework/base/services/java/com/android/server/systemserver.javaslog.i(tag, window manager); wm = windowmanagerservice.main(context, power, factorytest != systemserver.factory_test_low_level,!first
2、boot);在這里new了一個(gè)windowmanagerservice的類,我們找到這個(gè)類的構(gòu)造函數(shù)。framework/base/services/java/com/android/server/wm/windowmanagerserver.javaprivate windowmanagerservice(context context, powermanagerservice pm, boolean haveinputmethods, boolean showbootmsgs) minputmanager = new inputmanager(context, this);minputma
3、nager.start();在windowmanagerservice的構(gòu)造函數(shù)中又new了一個(gè)inputmanager類。inputmanager類是整個(gè)android的input的上層代碼最重要的類,就是通過(guò)這個(gè)類繁衍出了整個(gè)復(fù)雜的android的input子系統(tǒng)。作用就好像zygote的孕育著android的各個(gè)服務(wù),而inputmanager就是負(fù)責(zé)將整個(gè)android的input子系統(tǒng)。framework/base/services/java/com/android/server/wm/windowmanagerserver.javapublic inputmanager(conte
4、xt context, windowmanagerservice windowmanagerservice) looper looper = windowmanagerservice.mh.getlooper();nativeinit(mcontext, mcallbacks, looper.getqueue();在inputmanger的構(gòu)造函數(shù)中,調(diào)用了nativeinit這個(gè)方式,看到native開頭或者結(jié)尾的函數(shù),一般都是jni。在inputmanager的jni可以找到這個(gè)函數(shù)的實(shí)現(xiàn)。framework/base/services/jni/com_android_server_inp
5、utmanager.javastatic jninativemethod ginputmanagermethods = nativeinit, (landroid/content/context;lcom/android/server/wm/inputmanager$callbacks;landroid/os/messagequeue;)v, (void*) android_server_inputmanager_nativeinit ,簡(jiǎn)單介紹下jni的代碼風(fēng)格,第一個(gè)引號(hào)括起來(lái)的函數(shù)就是我們java代碼的函數(shù)原型,中間的引號(hào)中的就是代表java原型函數(shù)的參數(shù)。而最后的那個(gè)函數(shù)就是在對(duì)應(yīng)的函
6、數(shù)。一般都是c+代碼。framework/base/services/jni/com_android_server_inputmanager.javastatic void android_server_inputmanager_nativeinit(jnienv* env, jclass clazz, jobject contextobj, jobject callbacksobj, jobject messagequeueobj) gnativeinputmanager = new nativeinputmanager(contextobj, callbacksobj, looper);在
7、jni的代碼中,又構(gòu)造了一個(gè)重要的nativeinputmanager類,這是個(gè)c+的本地類。已經(jīng)不在是之前了那個(gè)java的inputmanager類。接下來(lái)看看nativeinputmanager的構(gòu)造函數(shù)。framework/base/services/jni/com_android_server_inputmanager.javanativeinputmanager:nativeinputmanager(jobject contextobj, jobject callbacksobj, const sp& looper) :mlooper(looper) sp eventhub = ne
8、w eventhub(); minputmanager = new inputmanager(eventhub, this, this);這里new了兩個(gè)類,eventhub和inputmanager類。eventhub就是input子系統(tǒng)的hal層了,負(fù)責(zé)將linux的所有的input設(shè)備打開并負(fù)責(zé)輪詢讀取他們的上報(bào)的數(shù)據(jù),后面會(huì)詳細(xì)介紹,這里先簡(jiǎn)單介紹一下。inputmanager類主要是負(fù)責(zé)管理input event,有inputreader從eventhub讀取事件,然后交給inputdispatcher進(jìn)行分發(fā)。framework/base/services/input/inputm
9、anager.cppinputmanager:inputmanager( const sp& reader, const sp& dispatcher) : mreader(reader), mdispatcher(dispatcher) initialize();void inputmanager:initialize() mreaderthread = new inputreaderthread(mreader); mdispatcherthread = new inputdispatcherthread(mdispatcher);在inputmanager中的initialize的初始化
10、了兩個(gè)線程。一個(gè)是inputreaderthread,負(fù)責(zé)從eventhub中讀取事件,另外一個(gè)是inputdispatcherthread線程,主要負(fù)責(zé)分發(fā)讀取的事件去處理。framework/base/services/java/com/android/server/wm/windowmanagerserver.javaprivate windowmanagerservice(context context, powermanagerservice pm, boolean haveinputmethods, boolean showbootmsgs) minputmanager.start
11、();在開始的時(shí)候,new了一個(gè)inputmanager,然后在繼續(xù)調(diào)用其start方法。framework/base/services/java/com/android/server/wm/windowmanagerserver.javapublic void start() slog.i(tag, starting input manager); nativestart(); registerpointerspeedsettingobserver(); registershowtouchessettingobserver(); updatepointerspeedfromsettings(
12、); updateshowtouchesfromsettings(); nativestart()跑到j(luò)ni的代碼中去了,跟上面的方式一樣。framework/base/services/jni/com_android_server_inputmanager.javastatic jninativemethod ginputmanagermethods = nativestart, ()v, (void*) android_server_inputmanager_nativestart ,static void android_server_inputmanager_nativestart(j
13、nienv* env, jclass clazz) status_t result = gnativeinputmanager-getinputmanager()-start();在java代碼中用了nativestart(),然后jni中又調(diào)用了nativeinputmanager的start方法。在native的inputmanager中找到start的實(shí)現(xiàn)。framework/base/services/input/inputmanager.cppstatus_t inputmanager:start() status_t result = mdispatcherthread-run(i
14、nputdispatcher, priority_urgent_display);result = mreaderthread-run(inputreader, priority_urgent_display);這個(gè)方法就是在前面inputmanager中的構(gòu)造函數(shù)initialize中的兩個(gè)線程運(yùn)行起來(lái)。先看inputdispatcher線程運(yùn)行的情況,然后就是inputreader線程。framework/base/services/input/inputdispatcher.cppbool inputdispatcherthread:threadloop() mdispatcher-di
15、spatchonce(); return true;inputdispatcher線程調(diào)用了dispatcher的dispatchonce的方法。同樣的inputreader線程也會(huì)調(diào)用reader的readeronce的方法。framework/base/services/input/inputdispatcher.cppvoid inputdispatcher:dispatchonce() dispatchonceinnerlocked(&nextwakeuptime); int timeoutmillis = tomillisecondtimeoutdelay(currenttime,
16、nextwakeuptime); mlooper-pollonce(timeoutmillis);dispatchonceinnerlocked是處理input輸入消息,mlooper-pollonce(timeoutmillis)是等待下次輸入消息的事件。先看下消息在dispatchonceinnerlocked函數(shù)中是如何處理的。framework/base/services/input/inputdispatcher.cppvoid inputdispatcher:dispatchonceinnerlocked(nsecs_t* nextwakeuptime) case eventent
17、ry:type_keydone = dispatchkeylocked(currenttime, typedentry, &dropreason, nextwakeuptime);case evententry:type_motion: done = dispatchmotionlocked(currenttime, typedentry, &dropreason, nextwakeuptime);這個(gè)函數(shù)比較長(zhǎng),input事件在android的上層通過(guò)兩個(gè)隊(duì)列來(lái)保存,分別是inboundqueue和outboundqueue。當(dāng)有input事件產(chǎn)生時(shí)候,會(huì)判斷inboundqueue是否為空
18、,如果事件不為空的話,就從隊(duì)列中取出這個(gè)input事件,然后根據(jù)input事件的類型來(lái)分發(fā)事件給不同的處理函數(shù),比較常見(jiàn)的是key和motion事件。不管是key事件也好還是motion事件都會(huì)調(diào)用dispatcheventtocurrentinputtargetslocked(currenttime, entry, false);這個(gè)函數(shù)來(lái)繼續(xù)處理。framework/base/services/input/inputdispatcher.cppvoid inputdispatcher:dispatcheventtocurrentinputtargetslocked(nsecs_t curr
19、enttime, evententry* evententry, bool resumewithappendedmotionsample) preparedispatchcyclelocked(currenttime, connection, evententry, & inputtarget, resumewithappendedmotionsample);在這個(gè)函數(shù)中會(huì)繼續(xù)調(diào)用preparedispatchcyclelocked方法來(lái)繼續(xù)處理。而在preparedispatchcyclelocked中又會(huì)繼續(xù)調(diào)用startdispatchcyclelocked(currenttime, c
20、onnection)來(lái)進(jìn)一步處理。framework/base/services/input/inputdispatcher.cppvoid inputdispatcher:startdispatchcyclelocked(nsecs_t currenttime, const sp& connection) switch (evententry-type) case evententry:type_key: status = connection-inputpublisher.publishkeyeventcase evententry:type_motion: status = connec
21、tion-inputpublisher.publishmotioneventstatus = connection-inputpublisher.senddispatchsignal();這個(gè)函數(shù)主要是根據(jù)input事件的類型來(lái)分發(fā)給不同的函數(shù)去處理,如果是key類型的事件就調(diào)用inputpublisher類的publishkeyevent,如果是motion類的事件就會(huì)調(diào)用inputpublisher類的publishmotionevent方法。并在最后發(fā)一個(gè)senddispatchsignal。framework/base/libs/ui/inputtransport.cppstatus_
22、t inputpublisher:publishinputevent(int ashmemfd = mchannel-getashmemfd();int result = ashmem_pin_region(ashmemfd, 0, 0);msemaphoreinitialized = true; msharedmessage-consumed = false; msharedmessage-type = type; msharedmessage-deviceid = deviceid;msharedmessage-source = source;利用publisher中的publishinp
23、utevent將input event寫入共享內(nèi)存。這邊產(chǎn)生了事件,另外一邊必然會(huì)有個(gè)地方回去消費(fèi)這個(gè)事件。注意到上面的代碼中,最后發(fā)送了一個(gè)senddispatchsignal。framework/base/libs/ui/inputtransport.cppstatus_t inputpublisher:senddispatchsignal() return mchannel-sendsignal(input_signal_dispatch);這個(gè)函數(shù)直接調(diào)用了inputchannel的sendsignal方法。繼續(xù)找到inputchannel的sendsignal實(shí)現(xiàn)。framework
24、/base/libs/ui/inputtransport.cppstatus_t inputchannel:sendsignal(char signal) do nwrite = :write(msendpipefd, & signal, 1); while (nwrite = -1 & errno = eintr);而在注冊(cè)inputchannel的時(shí)候就曾經(jīng)注冊(cè)了當(dāng)looper接收到了信號(hào)的一個(gè)回調(diào)函數(shù)。framework/base/services/input/inputdispatcher.cppstatus_t inputdispatcher:registerinputchannel
25、(const sp& inputchannel, const sp& inputwindowhandle, bool monitor) mlooper-addfd(receivefd, 0, alooper_event_input, handlereceivecallback, this);在handlereceivecallback中,作為回調(diào)函數(shù)然后調(diào)用inputconsumer的consume函數(shù)來(lái)消費(fèi)從inputreader中讀取過(guò)來(lái)的inputevent。framework/base/core/jni/android_view_inputqueue.cppint nativeinpu
26、tqueue:handlereceivecallback(int receivefd, int events, void* data) status = connection-inputconsumer.consume(& connection-inputeventfactory, & inputevent);回過(guò)頭來(lái)看之前的inputreader線程,在inputmanager的start方法被調(diào)用了,input的線程也就開始運(yùn)行了。framework/base/services/input/inputreader.cppbool inputreaderthread:threadloop()
27、 mreader-looponce(); return true;在inputreader的looponce中會(huì)調(diào)用eventhub的getevents方法。這個(gè)方法會(huì)和linux內(nèi)核的input子系統(tǒng)打交道。framework/base/services/input/inputreader.cppvoid inputreader:looponce() size_t count = meventhub-getevents(timeoutmillis, meventbuffer, event_buffer_size);if (count) processeventslocked(meventbu
28、ffer, count); 這個(gè)函數(shù)主要通過(guò)eventhub的getevents來(lái)獲取input事件。framework/base/services/input/eventhub.cppsize_t eventhub:getevents(int timeoutmillis, rawevent* buffer, size_t buffersize) struct input_event readbufferbuffersize;for (;) if (mneedtoscandevices) mneedtoscandevices = false; scandeviceslocked(); mnee
29、dtosendfinisheddevicescan = true; 在eventhub初始化的時(shí)候mneedtoscandevices的值是ture的,所以會(huì)直接進(jìn)入到scandeviceslocked。而在內(nèi)核里面所有的input device在注冊(cè)的時(shí)候都會(huì)在linux的文件系統(tǒng)下的/dev/input 下面,所以按照一般的hal的思想,如果要去操作這個(gè)設(shè)備,首先還是要打開這個(gè)設(shè)備節(jié)點(diǎn)的。framework/base/services/input/eventhub.cppvoid eventhub:scandeviceslocked() status_t res = scandirlock
30、ed(device_path); if(res 0) loge(scan dir failed for %sn, device_path); status_t eventhub:scandirlocked(const char *dirname)opendevicelocked(devname);代碼中的while循環(huán)會(huì)對(duì)device_path(/dev/input)下的所有的設(shè)備節(jié)點(diǎn)調(diào)用opendevicelocked方法。framework/base/services/input/eventhub.cppstatus_t eventhub:opendevicelocked(const ch
31、ar *devicepath) int fd = open(devicepath, o_rdwr);inputdeviceidentifier identifier;if(ioctl(fd, eviocgname(sizeof(buffer) - 1), &buffer) next = mopeningdevices; mopeningdevices = device;return 0;首先通過(guò)open系統(tǒng)調(diào)用得到設(shè)備節(jié)點(diǎn)的文件描述符,然后新構(gòu)造一個(gè)叫inputdeviceidentifier類。接著通過(guò)對(duì)剛才得到的設(shè)備節(jié)點(diǎn)描述下ioctl的命令獲取設(shè)備的一些簡(jiǎn)單信息,譬如:設(shè)備的名字,設(shè)備驅(qū)
32、動(dòng)的版本號(hào),設(shè)備的唯一id,和描述符輪詢的方式。得到的這些信息保存在inputdeviceidentifier類里面。最后又構(gòu)造了一個(gè)device類,其中設(shè)備描述符和剛才的構(gòu)造inputdeviceidentifier類作為參數(shù)重新構(gòu)造了device類。然后在構(gòu)造成功了device類又會(huì)通過(guò)ioctl系統(tǒng)調(diào)用獲取input設(shè)備的一些比較重要的參數(shù)。比如:設(shè)備上報(bào)事件的類型是相對(duì)事件還是絕對(duì)事件,相對(duì)事件一般是指像鼠標(biāo)滑動(dòng),絕對(duì)事件就好比觸摸屏上報(bào)的坐標(biāo),設(shè)備所屬的class等一些比較重要的信息。舉一些例子:input_device_class_keyboard(按鍵類型),input_devi
33、ce_class_cursor(帶游標(biāo)類型:鼠標(biāo)和軌跡球等),input_device_class_touch(觸摸類型:?jiǎn)吸c(diǎn)觸摸或多點(diǎn)觸摸),input_device_class_touch_mt(這個(gè)類型特指多點(diǎn)觸摸)等。如果一個(gè)設(shè)備的驅(qū)動(dòng)沒(méi)有指明設(shè)備的類型的話,那么他在android中上報(bào)的數(shù)據(jù)時(shí)不會(huì)被處理的。這個(gè)函數(shù)的最后是將input設(shè)備的文件描述符加入到輪詢的集合中去,如果接收到事件就會(huì)去處理。framework/base/services/input/inputreader.cppvoid inputreader:looponce() size_t count = meventh
34、ub-getevents(timeoutmillis, meventbuffer, event_buffer_size);if (count) processeventslocked(meventbuffer, count); 回到之前的inputreader的線程中,通過(guò)eventhub的getevents方法得到了input事件。函數(shù)返回的是獲取的事件數(shù)目。如果事件不為零或者負(fù)數(shù)就會(huì)調(diào)用processeventlocked來(lái)處理。framework/base/services/input/inputreader.cppvoid inputreader:processeventslocked
35、(const rawevent* rawevents, size_t count) processeventsfordevicelocked(deviceid, rawevent, batchsize);case eventhubinterface:device_added: adddevicelocked(rawevent-when, rawevent-deviceid);case eventhubinterface:device_removed: removedevicelocked(rawevent-when, rawevent-deviceid);case eventhubinterf
36、ace:finished_device_scan: handleconfigurationchangedlocked(rawevent-when);在處理input的事件時(shí)候,如果不是設(shè)備的添加,刪除和完成掃描的時(shí)候。就會(huì)調(diào)用processeventsfordevicelocked來(lái)處理。framework/base/services/input/inputreader.cppvoid inputreader:processeventsfordevicelocked(int32_t deviceid, const rawevent* rawevents, size_t count) devic
37、e-process(rawevents, count);這個(gè)函數(shù)也很簡(jiǎn)單直接回調(diào)了device的process方法來(lái)進(jìn)行處理,這個(gè)device就是在之前的eventhub打開設(shè)備時(shí)候構(gòu)造了一個(gè)device類。下面來(lái)具體看看device的process是如何進(jìn)行處理的。framework/base/services/input/inputreader.cppvoid inputdevice:process(const rawevent* rawevents, size_t count) for (size_t i = 0; i process(rawevent); 這里直接調(diào)用了mapper的p
38、rocess。那inputmapper是什么時(shí)候初始化的呢?前面提到如果設(shè)備不是設(shè)備的添加或刪除的時(shí)候就調(diào)用processeventsfordevicelocked來(lái)處理。也就是說(shuō)當(dāng)設(shè)備第一次添加的時(shí)候,就會(huì)調(diào)用adddevicelocked。inputmapper就是從這個(gè)地方注冊(cè)過(guò)來(lái)的。具體看下面的代碼:framework/base/services/input/inputreader.cppvoid inputreader:adddevicelocked(nsecs_t when, int32_t deviceid) inputdevice* device = createdevicel
39、ocked(deviceid, name, classes);inputdevice* inputreader:createdevicelocked(int32_t deviceid,const string8& name, uint32_t classes) inputdevice* device = new inputdevice(&mcontext, deviceid, name, classes);if (classes & input_device_class_switch) device-addmapper(new switchinputmapper(device);if (cla
40、sses & input_device_class_cursor) device-addmapper(new cursorinputmapper(device);if (classes & input_device_class_touch_mt) device-addmapper(new multitouchinputmapper(device); else if (classes & input_device_class_touch) device-addmapper(new singletouchinputmapper(device);if (classes & input_device_
41、class_joystick) device-addmapper(new joystickinputmapper(device);return device;從上面的代碼可以非常明顯的看出,inputmapper是根據(jù)inputdevice的class來(lái)構(gòu)造的這么一個(gè)類。也就是說(shuō)如果我們的設(shè)備是switch類就為這個(gè)設(shè)備構(gòu)造一個(gè)switchinputmapper類,我們假設(shè)我們現(xiàn)在的事件是由觸摸屏上報(bào)的事件處理流程。在前面處理的過(guò)程中我們就會(huì)調(diào)用multitouchinputmapper的process來(lái)繼續(xù)處理。也就是說(shuō)當(dāng)處理到mapper-process的時(shí)候,代碼就會(huì)根據(jù)具體的設(shè)備cla
42、ss類型來(lái)處理相應(yīng)的事件。這么多inputmapper,我們就以multitouchinputmapper的流程繼續(xù)來(lái)分析事件的處理流程。framework/base/services/input/inputreader.cppvoid multitouchinputmapper:process(const rawevent* rawevent) touchinputmapper:process(rawevent); mmultitouchmotionacess(rawevent);void multitouchmotionaccumulator:process(c
43、onst rawevent* rawevent) switch (rawevent-scancode) case abs_mt_position_x: slot-minuse = true; slot-mabsmtpositionx = rawevent-value;case abs_mt_position_y: slot-minuse = true; slot-mabsmtpositiony = rawevent-value;case abs_mt_touch_major: slot-minuse = true; slot-mabsmttouchmajor = rawevent-value;
44、 break;case abs_mt_touch_minor: slot-minuse = true; slot-mabsmttouchminor = rawevent-value; slot-mhaveabsmttouchminor = true;在這個(gè)處理過(guò)程中將上報(bào)的原始事件的一些重要參數(shù)都賦值給了一個(gè)叫slot的結(jié)構(gòu)的成員。我們知道多點(diǎn)觸摸上報(bào)的一些參數(shù)主要包括:x軸和y軸的坐標(biāo)點(diǎn),abs_mt_touch_major代表手指和觸摸屏接觸面的長(zhǎng)軸(如果假定人手指和觸摸屏接觸面一般都是橢圓),abs_mt_touch_minor代表手指和屏幕接觸面的短軸等等一些重要的參數(shù)都對(duì)號(hào)入座的賦值
45、給了一個(gè)叫slot的結(jié)構(gòu)體成員,具體更多的參數(shù)代表什么意思我就不多說(shuō)了(大家可以參照l(shuí)inux內(nèi)核文檔,多點(diǎn)觸摸協(xié)議)。multitouchinputmapper的process處理分了兩部分,首先是調(diào)用了touchinputmapper的process方法,然后調(diào)用了mmultitouchmotionacess來(lái)進(jìn)行處理。先看touchinputmapper的處理流程。framework/base/services/input/inputreader.cppvoid touchinputmapper:process(const rawevent* rawevent
46、) if (rawevent-type = ev_syn & rawevent-scancode = syn_report) sync(rawevent-when); 在linux內(nèi)核往上層上報(bào)input event的時(shí)候是由順序的,以觸摸屏為例,input_report_abs會(huì)被用來(lái)上報(bào)一些絕對(duì)事件(如:接觸面積半徑,x和y軸的坐標(biāo)點(diǎn)),但是在每一次上報(bào)完成后都會(huì)調(diào)用input_sync(input_dev);來(lái)表示一次完整的事件上報(bào),換句話說(shuō)這個(gè)rawevent-type為ev_syn的事件就是許多input event的分隔符。framework/base/services/input
47、/inputreader.cppvoid touchinputmapper:sync(nsecs_t when) bool havepointerids = true; mcurrentrawpointerdata.clear();synctouch(when, &havepointerids);cookpointerdata();dispatchhoverexit(when, policyflags);dispatchtouches(when, policyflags);dispatchhoverenterandmove(when, policyflags);通過(guò)同步觸摸事件,然后調(diào)用coo
48、kpointerdata來(lái)計(jì)算x和y的坐標(biāo),前后兩次上報(bào)數(shù)據(jù)的距離,和根據(jù)縮放的大小及方向來(lái)判斷是不是需要旋轉(zhuǎn)屏幕。然后dispatchtouches中又調(diào)用了disaptchmotion方法。framework/base/services/input/inputreader.cppvoid touchinputmapper:dispatchmotion(nsecs_t when, uint32_t policyflags, uint32_t source,) getlistener()-notifymotion(&args);通過(guò)getlister的方法得到inputlistener并調(diào)用其
49、notifymotion。void queuedinputlistener:notifymotion(const notifymotionargs* args) margsqueue.push(new notifymotionargs(*args);在構(gòu)造了一個(gè)notifymotionargs類之后,我們回到之前的inputreader的looponce方法中,在最后調(diào)用了mqueuedlistener-flush();flush函數(shù)就是要把margsqueue中的所有notifyargs進(jìn)行處理。為描述方便,先看看其代碼:framework/base/services/input/input
50、lisenter.cppvoid queuedinputlistener:flush() size_t count = margsqueue.size(); for (size_t i = 0; i notify(minnerlistener); delete args; margsqueue.clear();繼續(xù)在notifyargs中調(diào)用了其notify的方法。還是在這個(gè)文件中可以看看我們notifymotionargs的notify方法。framework/base/services/input/inputlisenter.cppvoid notifymotionargs:notify(const sp& listener) const listener-notifymotion(this);在inputdispatcher.h中inputdispatcherinterface是繼承inputlistenerinterface,父類調(diào)用了子類的虛函數(shù)notifymotion的實(shí)例化。在inputdispacher的notifymotion中繼續(xù),這就重新回到了我們上面分析的inputdispatch線程的代碼。正好完成了一邊生產(chǎn)事件而在另一邊消費(fèi)事件。
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 機(jī)械制造工藝測(cè)試題+參考答案
- 包裝設(shè)計(jì)師模擬習(xí)題+答案
- 第六單元課外古詩(shī)詞誦讀《卜算子·黃州定慧院寓居作》教學(xué)設(shè)計(jì)-2023-2024學(xué)年統(tǒng)編版語(yǔ)文八年級(jí)下冊(cè)
- 2025年新型復(fù)合型菌劑合作協(xié)議書
- 2025年阻燃塑料電表箱行業(yè)深度研究分析報(bào)告
- 人教版初中歷史與社會(huì)七年級(jí)上冊(cè) 1.2 .1鄉(xiāng)村聚落 教學(xué)設(shè)計(jì)
- 中國(guó)自控技術(shù)項(xiàng)目投資可行性研究報(bào)告
- 推拿治療學(xué)習(xí)題庫(kù)與答案
- 機(jī)械制造技術(shù)練習(xí)題庫(kù)與答案
- 單獨(dú)招生機(jī)電類模擬練習(xí)題及答案
- 2023年部編人教版六年級(jí)道德與法治下冊(cè)全冊(cè)課件【全套】
- 肌肉注射的常見(jiàn)并發(fā)癥及預(yù)防處理措施
- 景觀模型設(shè)計(jì)與制作:第7章 建筑模型制作基本技法
- 關(guān)愛(ài)婦女防治兩癌講座課件
- DL∕T 584-2017 3kV~110kV電網(wǎng)繼電保護(hù)裝置運(yùn)行整定規(guī)程
- 2024-2030年傷口護(hù)理管理行業(yè)市場(chǎng)現(xiàn)狀供需分析及重點(diǎn)企業(yè)投資評(píng)估規(guī)劃分析研究分析報(bào)告
- (正式版)FZ∕T 80018-2024 服裝 防靜電性能要求及試驗(yàn)方法
- 北師大版八年級(jí)下冊(cè)生物教案全冊(cè)
- 混凝土攪拌站安全生產(chǎn)風(fēng)險(xiǎn)分級(jí)管控體系方案全套資料2021-2022完整實(shí)施方案模板
- 新生兒紅臀的預(yù)防和護(hù)理
- DL-T5704-2014火力發(fā)電廠熱力設(shè)備及管道保溫防腐施工質(zhì)量驗(yàn)收規(guī)程
評(píng)論
0/150
提交評(píng)論