Android 输入系统架构 笔记1

1. 首先看下服务的启动:

    Android系统启动的时候,会启动很多服务,一般都是在SystemServer中启动的,代码如下:

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

                         wm = WindowManagerService.main(context, power,factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,!firstBoot);

  这里创建了一个WindowManagerService的类,我们来看看这个类的构造函数:

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

   private WindowManagerService(Context context, PowerManagerService pm,boolean haveInputMethods, boolean showBootMsgs) {
    ……
    mInputManager = new InputManager(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
 
public InputManager(Context context, WindowManagerService windowManagerService) { 
……
Looper loo
per = windowManagerService.mH.getLooper();
nativeInit(mContext, mCallbacks, looper.getQueue());
……
}

在InputManger的构造函数中调用了nativeInit这个方式看到native开头或者结尾的函数一般都是JNI。在InputManager的JNI可以找到这个函数的实现。

 Framework/base/services/jni/com_android_server_InputManager.java
 
static JNINativeMethod gInputManagerMethods[] = {
{ "nativeInit", "(Landroid/content/Context;"   "Lcom/android/server/wm/InputManager$Callbacks;Landroid/os/MessageQueue;)V",
                                                              (void*) android_server_InputManager_nativeInit },
 

Framework/base/services/jni/com_android_server_InputManager.java
 
static void android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz,        
            jobject contextObj, jobject callbacksObj, jobject messageQueueObj) {
……
            gNativeInputManager = new NativeInputManager(contextObj, callbacksObj, looper);
            ……
           }
 
在JNI的代码中又构造了一个重要的NativeInputManager类这是个C++的本地类。已经不在是之前了那个java的InputManager类。接下来看看NativeInputManager的构造函数。 

Framework/base/services/jni/com_android_server_InputManager.java
 
NativeInputManager::NativeInputManager(jobject contextObj,  
jobject callbacksObj, const sp<Looper>& looper) :mLooper(looper) {
……
sp<EventHub> eventHub = new EventHub();
mInputManager = new InputManager(eventHub, this, this);
……
}
 
这里new了两个类EventHub和InputManager类。EventHub就是Input子系统的HAL层了负责将linux的所有的input设备打开并负责轮询读取他们的上报的数据后面会详细介绍这里先简单介绍一下。InputManager类主要是负责管理input Event有InputReader从EventHub读取事件然后交给InputDispatcher进行分发。


Framework/base/services/input/InputManager.cpp
 
InputManager::InputManager(
const sp<InputReaderInterface>& reader,        
const sp<InputDispatcherInterface>& dispatcher) :
mReader(reader),
mDispatcher(dispatcher) {
initialize();
}
 
void InputManager::initialize() {
mReaderThread = new InputReaderThread(mReader);
mDispatcherThread = new InputDispatcherThread(mDispatcher);
}

在InputManager中的initialize的初始化了两个线程。一个是inputReaderThread负责从EventHub中读取事件另外一个是InputDispatcherThread线程主要负责分发读取的事件去处理。

Framework/base/services/java/com/android/server/wm/WindowManagerServer.java
 
private WindowManagerService(Context context, PowerManagerService pm, boolean haveInputMethods, boolean showBootMsgs){
 
mInputManager.start();
……
}

在开始的时候new了一个InputManager然后在继续调用其start方法。 
Framework/base/services/java/com/android/server/wm/WindowManagerServer.java
 
public void start() {     
Slog.i(TAG, "Starting input manager");
nativeStart();
registerPointerSpeedSettingObserver();       
registerShowTouchesSettingO
bserver();
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
}   
 
NativeStart()跑到JNI的代码中去了跟上面的方式一样。


Framework/base/services/jni/com_android_server_InputManager.java
 
static JNINativeMethod gInputManagerMethods[] = {



{ "nativeStart", "()V", (void*) android_server_InputManager_nativeStart },
…… 
}
 
static void android_server_InputManager_nativeStart(JNIEnv* env, jclass clazz) {
……
status_t result = gNativeInputManager->getInputManager()->start();
……
}

在java代码中用了nativeStart()然后JNI中又调用了NativeInputManager的start方法。在
Native的InputManager中找到start的实现。 


Framework/base/services/input/InputManager.cpp
 
status_t InputManager::start() {
status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
……
result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
……
}

这个方法就是在前面InputManager中的构造函数initialize中的两个线程运行起来。先看InputDispatcher线程运行的情况然后就是InputReader线程。

Framework/base/services/input/InputDispatcher.cpp
 
bool InputDispatcherThread::threadLoop() {
mDispatcher->dispatchOnce();
return true;
}

InputDispatcher线程调用了Dispatcher的dispatchOnce的方法。同样的InputReader线程也会调用Reader的ReaderOnce的方法。

Framework/base/services/input/InputDispatcher.cpp
 
void InputDispatcher::dispatchOnce() {
   ……
   dispatchOnceInnerLocked(&
   nextWakeupTime);
   ……
   int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
   mLooper->pollOnce(timeoutMillis);
}

dispatchOnceInnerLocked是处理input输入消息mLooper->pollOnce(timeoutMillis)是等待下次输入消息的事件。先看下消息在dispatchOnceInnerLocked函数中是如何处理的。


Framework/base/services/input/InputDispatcher.cpp
 
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
 ……
 case EventEntry::TYPE_KEY
 ……
 done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
 case EventEntry::
    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
 
void InputDispatcher::dispatchEventToCurrentInputTargetsLocked(nsecs_t currentTime,
EventEntry* eventEntry, bool resumeWithAppendedMotionSample) {
……
prepareDispatchCycleLocked(currentTime, connection, eventEntry, & inputTarget,
resumeWithAppendedMotionSample); 
……
}


在这个函数中会继续调用prepareDispatchCycleLocked方法来继续处理。而在prepareDispatchCycleLocked中又会继续调用startDispatchCycleLocked(currentTime, connection)来进一步处理。
Framework/base/services/input/InputDispatcher.cpp
 
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,const sp<Connection>& connection) {
……
switch (eventEntry->type) {
case EventEntry::TYPE_KEY: {
status = connection->inputPublisher.publishKeyEvent


case EventEntry::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_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中的publishInputEvent将input event写入共享内存。这边产生了事件另外一边必然会有个地方回去消费这个事件。注意到上面的代码中最后发送了一个sendDispatchSignal。 


Framework/base/libs/ui/InputTransport.cpp
 
status_t InputPublisher::sendDispatchSignal() {
……
return mChannel->sendSignal(INPUT_SIGNAL_DISPATCH);
……
}
 
这个函数直接调用了inputChannel的sendSignal方法。继续找到inputChannel的sendSignal实现。 
Framework/base/libs/ui/InputTransport.cpp
 
status_t InputChannel::sendSignal(char signal) {
……
do {
nWrite = ::write(mSendPipeFd, & signal, 1);   

while (nWrite == -1 && errno == EINTR); 
…… 
}
 
而在注册InputChannel的时候就曾经注册了当Looper接收到了信号的一个回调函数。


Framework/base/services/input/InputDispatcher.cpp
 
status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,const sp<InputWindowHandle>& inputWindowHandle, bool monitor) { 
……
mLooper->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
……
}


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


Framework/base/core/jni/android_view_InputQueue.cpp
 
int NativeInputQueue::handleReceiveCallback(int receiveFd, int events, void* data) {
……
status = connection->inputConsumer.consume(& connection->inputEventFactory, & inputEvent);
……
}
 
回过头来看之前的InputReader线程,在inputManager的start方法被调用了Input的线程也就开始运行了。 


Framework/base/services/input/InputReader.cpp 
bool InputReaderThread::threadLoop() {
mReader->loopOnce();    
return true;
}
 
在InputReader的loopOnce中会调用EventHub的getevents方法。这个方法会和linux内核的input子系统打交道。 


Framework/base/services/input/InputReader.cpp
void InputReader::loopOnce() {
……
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); 
……
if (count) {            
processEventsLocked(mEventBuffer, count);
}
……
}
 
这个函数主要通过EventHub的getEvents来获取input事件。 
Framework/base/services/input/EventHub.cpp
 
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
……
struct input_event readBuffer[bufferSize];
……
for (;;) {
……


if (mNeedToScanDevices) {            
mNeedToScanDevices = false;
scanDevicesLocked();
mNeedToSendFinishedDeviceScan = true;
}
……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值