Input子系统架构包括内核层与框架层详解.docx

上传人:b****5 文档编号:5626611 上传时间:2022-12-29 格式:DOCX 页数:56 大小:87.81KB
下载 相关 举报
Input子系统架构包括内核层与框架层详解.docx_第1页
第1页 / 共56页
Input子系统架构包括内核层与框架层详解.docx_第2页
第2页 / 共56页
Input子系统架构包括内核层与框架层详解.docx_第3页
第3页 / 共56页
Input子系统架构包括内核层与框架层详解.docx_第4页
第4页 / 共56页
Input子系统架构包括内核层与框架层详解.docx_第5页
第5页 / 共56页
点击查看更多>>
下载资源
资源描述

Input子系统架构包括内核层与框架层详解.docx

《Input子系统架构包括内核层与框架层详解.docx》由会员分享,可在线阅读,更多相关《Input子系统架构包括内核层与框架层详解.docx(56页珍藏版)》请在冰豆网上搜索。

Input子系统架构包括内核层与框架层详解.docx

Input子系统架构包括内核层与框架层详解

AndroidInput子系统架构

Input服务的启动

在Android的开机过程中,系统中的服务很多都是由SystemServer中启动的。

SystemServer的代码中有这么一句话。

Framework/base/services/java/com/android/server/SystemServer.java

Slog.i(TAG,"WindowManager");

wm=WindowManagerService.main(context,power,

factoryTest!

=SystemServer.FACTORY_TEST_LOW_LEVEL,!

firstBoot);

在这里new了一个WindowManagerService的类,我们找到这个类的构造函数。

Framework/base/services/java/com/android/server/wm/WindowManagerServer.java

privateWindowManagerService(Contextcontext,PowerManagerServicepm,

booleanhaveInputMethods,booleanshowBootMsgs){

……

mInputManager=newInputManager(context,this);

……

mInputManager.start();

……

}

在WindowManagerService的构造函数中又new了一个InputManager类。

InputManager类是整个android的input的上层代码最重要的类,就是通过这个类繁衍出了整个复杂的Android的input子系统。

作用就好像Zygote的孕育着Android的各个服务,而InputManager就是负责将整个android的Input子系统。

Framework/base/services/java/com/android/server/wm/WindowManagerServer.java

publicInputManager(Contextcontext,WindowManagerServicewindowManagerService){

……

Looperlooper=windowManagerService.mH.getLooper();

nativeInit(mContext,mCallbacks,looper.getQueue());

……

}

在InputManger的构造函数中,调用了nativeInit这个方式,看到native开头或者结尾的函数,一般都是JNI。

在InputManager的JNI可以找到这个函数的实现。

Framework/base/services/jni/com_android_server_InputManager.java

staticJNINativeMethodgInputManagerMethods[]={

{"nativeInit","(Landroid/content/Context;"

"Lcom/android/server/wm/InputManager$Callbacks;Landroid/os/MessageQueue;)V",

(void*)android_server_InputManager_nativeInit},

简单介绍下JNI的代码风格,第一个引号括起来的函数就是我们java代码的函数原型,中间的引号中的就是代表java原型函数的参数。

而最后的那个函数就是在对应的函数。

一般都是c++代码。

Framework/base/services/jni/com_android_server_InputManager.java

staticvoidandroid_server_InputManager_nativeInit(JNIEnv*env,jclassclazz,

jobjectcontextObj,jobjectcallbacksObj,jobjectmessageQueueObj){

……

gNativeInputManager=newNativeInputManager(contextObj,callbacksObj,looper);

……

}

在JNI的代码中,又构造了一个重要的NativeInputManager类,这是个C++的本地类。

已经不在是之前了那个java的InputManager类。

接下来看看NativeInputManager的构造函数。

Framework/base/services/jni/com_android_server_InputManager.java

NativeInputManager:

:

NativeInputManager(jobjectcontextObj,

jobjectcallbacksObj,constsp&looper):

mLooper(looper){

……

speventHub=newEventHub();

mInputManager=newInputManager(eventHub,this,this);

……

}

这里new了两个类,EventHub和InputManager类。

EventHub就是Input子系统的HAL层了,负责将linux的所有的input设备打开并负责轮询读取他们的上报的数据,后面会详细介绍,这里先简单介绍一下。

InputManager类主要是负责管理inputEvent,有InputReader从EventHub读取事件,然后交给InputDispatcher进行分发。

Framework/base/services/input/InputManager.cpp

InputManager:

:

InputManager(

constsp&reader,

constsp&dispatcher):

mReader(reader),

mDispatcher(dispatcher){

initialize();

}

voidInputManager:

:

initialize(){

mReaderThread=newInputReaderThread(mReader);

mDispatcherThread=newInputDispatcherThread(mDispatcher);

}

在InputManager中的initialize的初始化了两个线程。

一个是inputReaderThread,负责从EventHub中读取事件,另外一个是InputDispatcherThread线程,主要负责分发读取的事件去处理。

Framework/base/services/java/com/android/server/wm/WindowManagerServer.java

privateWindowManagerService(Contextcontext,PowerManagerServicepm,

booleanhaveInputMethods,booleanshowBootMsgs)

mInputManager.start();

……

}

在开始的时候,new了一个InputManager,然后在继续调用其start方法。

Framework/base/services/java/com/android/server/wm/WindowManagerServer.java

publicvoidstart(){

Slog.i(TAG,"Startinginputmanager");

nativeStart();

registerPointerSpeedSettingObserver();

registerShowTouchesSettingObserver();

updatePointerSpeedFromSettings();

updateShowTouchesFromSettings();

}

NativeStart()跑到JNI的代码中去了,跟上面的方式一样。

Framework/base/services/jni/com_android_server_InputManager.java

staticJNINativeMethodgInputManagerMethods[]={

……

{"nativeStart","()V",(void*)android_server_InputManager_nativeStart},

……

}

staticvoidandroid_server_InputManager_nativeStart(JNIEnv*env,jclassclazz){

……

status_tresult=gNativeInputManager->getInputManager()->start();

……

}

在java代码中用了nativeStart(),然后JNI中又调用了NativeInputManager的start方法。

在Native的InputManager中找到start的实现。

Framework/base/services/input/InputManager.cpp

status_tInputManager:

:

start(){

status_tresult=mDispatcherThread->run("InputDispatcher",PRIORITY_URGENT_DISPLAY);

……

result=mReaderThread->run("InputReader",PRIORITY_URGENT_DISPLAY);

……

}

这个方法就是在前面InputManager中的构造函数initialize中的两个线程运行起来。

先看Input

Dispatcher线程运行的情况,然后就是InputReader线程。

Framework/base/services/input/InputDispatcher.cpp

boolInputDispatcherThread:

:

threadLoop(){

mDispatcher->dispatchOnce();

returntrue;

}

InputDispatcher线程调用了Dispatcher的dispatchOnce的方法。

同样的InputReader线程也会调用Reader的ReaderOnce的方法。

Framework/base/services/input/InputDispatcher.cpp

voidInputDispatcher:

:

dispatchOnce(){

……

dispatchOnceInnerLocked(&nextWakeupTime);

……

inttimeoutMillis=toMillisecondTimeoutDelay(currentTime,nextWakeupTime);

mLooper->pollOnce(timeoutMillis);

}

dispatchOnceInnerLocked是处理input输入消息,mLooper->pollOnce(timeoutMillis)是等待下次输入消息的事件。

先看下消息在dispatchOnceInnerLocked函数中是如何处理的。

Framework/base/services/input/InputDispatcher.cpp

voidInputDispatcher:

:

dispatchOnceInnerLocked(nsecs_t*nextWakeupTime){

……

caseEventEntry:

:

TYPE_KEY

……

done=dispatchKeyLocked(currentTime,typedEntry,&dropReason,nextWakeupTime);

caseEventEntry:

:

TYPE_MOTION:

{

……

done=dispatchMotionLocked(currentTime,typedEntry,&dropReason,nextWakeupTime);

……

}

这个函数比较长,input事件在android的上层通过两个队列来保存,分别是InboundQueue和outboundQueue。

当有input事件产生时候,会判断InboundQueue是否为空,如果事件不为空的话,就从队列中取出这个input事件,然后根据input事件的类型来分发事件给不同的处理函数,比较常见的是KEY和Motion事件。

不管是Key事件也好还是Motion事件都会调用dispatchEventToCurrentInputTargetsLocked(currentTime,entry,false);这个函数来继续处理。

Framework/base/services/input/InputDispatcher.cpp

voidInputDispatcher:

:

dispatchEventToCurrentInputTargetsLocked(nsecs_tcurrentTime,

EventEntry*eventEntry,boolresumeWithAppendedMotionSample){

……

prepareDispatchCycleLocked(currentTime,connection,eventEntry,&inputTarget,

resumeWithAppendedMotionSample);

……

}

在这个函数中会继续调用prepareDispatchCycleLocked方法来继续处理。

而在prepareDispatch

CycleLocked中又会继续调用startDispatchCycleLocked(currentTime,connection)来进一步处理。

Framework/base/services/input/InputDispatcher.cpp

voidInputDispatcher:

:

startDispatchCycleLocked(nsecs_tcurrentTime,

constsp&connection){

……

switch(eventEntry->type){

caseEventEntry:

:

TYPE_KEY:

{

status=connection->inputPublisher.publishKeyEvent

caseEventEntry:

:

TYPE_MOTION:

{

……

status=connection->inputPublisher.publishMotionEvent

……

status=connection->inputPublisher.sendDispatchSignal();

……

}

这个函数主要是根据input事件的类型来分发给不同的函数去处理,如果是KEY类型的事件就调用inputPublisher类的publishKeyEvent,如果是MOTION类的事件就会调用inputPublisher类的publishMotionEvent方法。

并在最后发一个sendDispatchSignal。

Framework/base/libs/ui/InputTransport.cpp

status_tInputPublisher:

:

publishInputEvent(

……

intashmemFd=mChannel->getAshmemFd();

intresult=ashmem_pin_region(ashmemFd,0,0);

……

mSemaphoreInitialized=true;

mSharedMessage->consumed=false;

mSharedMessage->type=type;

mSharedMessage->deviceId=deviceId;

mSharedMessage->source=source;

……

}

利用publisher中的publishInputEvent将inputevent写入共享内存。

这边产生了事件,另外一边必然会有个地方回去消费这个事件。

注意到上面的代码中,最后发送了一个sendDispatchS

ignal。

Framework/base/libs/ui/InputTransport.cpp

status_tInputPublisher:

:

sendDispatchSignal(){

……

returnmChannel->sendSignal(INPUT_SIGNAL_DISPATCH);

……

}

这个函数直接调用了inputChannel的sendSignal方法。

继续找到inputChannel的sendSignal实现。

Framework/base/libs/ui/InputTransport.cpp

status_tInputChannel:

:

sendSignal(charsignal){

……

do{

nWrite=:

:

write(mSendPipeFd,&signal,1);

}while(nWrite==-1&&errno==EINTR);

……

}

而在注册InputChannel的时候就曾经注册了当Looper接收到了信号的一个回调函数。

Framework/base/services/input/InputDispatcher.cpp

status_tInputDispatcher:

:

registerInputChannel(constsp&inputChannel,

constsp&inputWindowHandle,boolmonitor){

……

mLooper->addFd(receiveFd,0,ALOOPER_EVENT_INPUT,handleReceiveCallback,this);

……

}

在handleReceiveCallback中,作为回调函数然后调用InputConsumer的consume函数来消费从inputReader中读取过来的InputEvent。

Framework/base/core/jni/android_view_InputQueue.cpp

intNativeInputQueue:

:

handleReceiveCallback(intreceiveFd,intevents,void*data){

……

status=connection->inputConsumer.consume(&connection->inputEventFactory,&inputEvent);

……

}

回过头来看之前的InputReader线程,在inputManager的start方法被调用了,Input的线程也就开始运行了。

Framework/base/services/input/InputReader.cpp

boolInputReaderThread:

:

threadLoop(){

mReader->loopOnce();

returntrue;

}

在InputReader的loopOnce中会调用EventHub的getevents方法。

这个方法会和linux内核的input子系统打交道。

Framework/base/services/input/InputReader.cpp

voidInputReader:

:

loopOnce(){

……

size_tcount=mEventHub->getEvents(timeoutMillis,mEventBuffer,EVENT_BUFFER_SIZE);

……

if(count){

processEventsLocked(mEventBuffer,count);

}

……

}

这个函数主要通过EventHub的getEvents来获取input事件。

Framework/base/services/input/EventHub.cpp

size_tEventHub:

:

getEvents(inttimeoutMillis,RawEvent*buffer,size_tbufferSize){

……

structinput_eventreadBuffer[bufferSize];

……

for(;;){

……

if(mNeedToScanDevices){

mNeedToScanDevices=false;

scanDevicesLocked();

mNeedToSendFinishedDeviceScan=true;

}

……

在eventHub初始化的时候mNeedToScanDevices的值是ture的,所以会直接进入到scanDevices

Locked。

而在内核里面所有的inputdevice在注册的时候都会在linux的文件系统下的/dev/input下面,所以按照一般的HAL的思想,如果要去操作这个设备,首先还是要打开这个设备节点的。

Framework/base/services/input/EventHub.cpp

voidEventHub:

:

scanDevicesLocked(){

status_tres=scanDirLocked(DEVICE_PATH);

if(res<0){

LOGE("scandirfailedfor%s\n",DEVICE_PATH);

}

}

status_tEventHub:

:

scanDirLocked(constchar*dirname)

{

……

openDeviceLocked(devname);

……

}

代码中的while循环会对DEVICE_PATH(/dev/input)下的所有的设备节点调用openDeviceLocked

方法。

Framework/base/services/input/EventHub.cpp

status_tEventHub:

:

openDeviceLocked(constchar*devicePath){

……

intfd=open(devicePath,O_RDWR);

……

Inpu

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 简洁抽象

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1