Android 输入子系统

input服务的启动流程

1. android启动的时候会启动很多个service,参考SystemServer.java,会启动InputManagerService这个服务:
inputManager = new InputManagerService(context, wmHandler);  
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);  
2.InputManagerService.java中的start函数:
public void start() {  
        Slog.i(TAG, "Starting input manager");  
        nativeStart(mPtr);
//调用了本地方法,JNI对应的cpp 在server下的jni目录下  
start函数在jni文件中的实现
}
3. jni NativeStart

frameworks/base/services/jni/com_android_server_input_InputManagerService.cpp

static jint nativeInit(JNIEnv* env, jclass clazz,
        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == NULL) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }

    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    im->incStrong(0);
    return reinterpret_cast<jint>(im);
}
static void nativeStart(JNIEnv* env, jclass clazz, jint ptr) {  
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);  //这个NativeInputManager 是在上面InputMangerService构造的时候调用nativeInit时new出来的  

    status_t result = im->getInputManager()->start(); //这里是调用了NativeInputManager中的InputManager中的start方法,同样这个InputManager是NativeInputManager构造的时候new出来的  
    if (result) {  
        jniThrowRuntimeException(env, "Input manager could not be started.");  
    }  
}  

NativeInputManager构造函数中的会创建EventHub和InputManager

NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper) {
    JNIEnv* env = jniEnv();

    mContextObj = env->NewGlobalRef(contextObj);
    mServiceObj = env->NewGlobalRef(serviceObj);

    {
        AutoMutex _l(mLock);
        mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
        mLocked.pointerSpeed = 0;
        mLocked.pointerGesturesEnabled = true;
        mLocked.showTouches = false;
    }

    sp<EventHub> eventHub = new EventHub();
    mInputManager = new InputManager(eventHub, this, this);
}
4. InputManager

InputManager(base/services/input/InputManager.cpp ,libinput.so)
InputManager是系统事件处理的核心,主要负责管理工作,EventHub作为参数传入。

InputManager::InputManager(
        const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = new InputDispatcher(dispatcherPolicy);
    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
    initialize();
}

InputManager创建使用两个线程:

1) InputReaderThread,它负责读取并预处理RawEvent,applies policy并且把消息送入DispatcherThead管理的队列中。

2) InputDispatcherThread,它在队列上等待新的输入事件,并且异步地把这些事件分发给应用程序。

InputReaderThread类与InputDispatcherThread类不共享内部状态,所有的通信都是单向的,从 InputReaderThread到InputDispatcherThread。两个类可以通过InputDispatchPolicy进行交互。
(InputDispatchPolicy就是com_android_server_input_InputManagerService 里的NativeInputManager, 参数会传入this)

“`C
class NativeInputManager : public virtual RefBase,
public virtual InputReaderPolicyInterface,
public virtual InputDispatcherPolicyInterface,
public virtual PointerControllerPolicyInterface


InputManager类从不与Java交互,而InputDispatchPolicy负责执行所有与系统的外部交互,包括调用DVM业务。

InputReaderThread( 
mQueueListener->flush()
getListener->notifykey() )

==> 传入到Inputdispatcher.cpp 
Inputdispatcher.cpp (mPolicy->interceptKeyBeforeQueueing)

==> com_android_server_input_InputManagerService.cpp (gServiceclassInfo.interceptKeyBeforeQueueing )   

==>
InputManagerService.java(mWindowManagerCallbacks.interceptKeyBeforeQueueing ) 

==.>
InputMonitor.java (mService.mPolicy.interceptKeyBeforeQueueing )


##### 5. InputReader

/frameworks/base/services/input/InputReader.cpp

```C
bool InputReaderThread::threadLoop() {  
    mReader->loopOnce();  
    return true;  
}  
void InputReader::loopOnce() {  
    int32_t oldGeneration;  
    int32_t timeoutMillis;  

...  

   size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); //这里就是关键了,通过另外一个中间者EventHub 获取的input事件  

...  

}  





<div class="se-preview-section-delimiter"></div>

InputReader从EventHub中读取原始事件数据(RawEvent),并由各个InputMapper处理之后输入对应的inputlistener.

6. EventHub

/frameworks/base/services/input/EventHub.cpp
它是系统中所有事件的中央处理站。它管理所有系统中可以识别的输入设备的输入事件,此外,当设备增加或删除时,EventHub将产生相应的输入事件给系统。
EventHub通过getEvents函数,给系统提供一个输入事件流。它也支持查询输入设备当前的状态(如哪些键当前被按下)。而且EventHub还跟踪每个输入调入的能力,比如输入设备的类别,输入设备支持哪些按键。

size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {  

...  

    for (;;) {  

...  

            scanDevicesLocked(); //这个往里走就是通过EventHub::openDeviceLocked  打开*DEVICE_PATH = "/dev/input" 这个设备 ,最终用的open,实际到kernel层就是input设备注册的open  

...  

    int32_t readSize = read(device->fd, readBuffer, //这里的device->fd就是/dev/input/event%d这个设备文件,就是从这里读取出event的buffer  
                        sizeof(struct input_event) * capacity);  

...  

 }  

..  

}  




<div class="se-preview-section-delimiter"></div>
7. InputDispatcher分发:

InputDispatcher负责把事件分发给输入目标,其中的一些功能(如识别输入目标)由独立的policy对象控制。

如何得到当前焦点窗口
InputDispatcher==>
InputMonitor==>
WMS IMS的WindowManagerCallbacks==>
InputMonitor==>
InputDispatcher

  InputMonitor为WMS提供一些访问InputDispatcher的接口。
   比如更新当前焦点窗口updateInputWindowsLw




<div class="se-preview-section-delimiter"></div>
InputDispatcher 如何通知应用程序窗口有按键事件的,这是跨进程的,没有用Binder机制,而是socket.
  dispatchEventLocked ==>
  prepareDispatchCycleLocked ==>
  enqueueDispatchEntriesLocked ==>
  connection->inputPublisher.publishKeyEvent ==> 
  mChannel->sendMessage ==> 
  ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL); 实际最后调用的socket发出数据了.
8. 其他的一些类

InputEvent 有两个子类KeyEvent MotionEvent
InputEvent 有接口GetDevice ,得到当前事件的硬件源, SOURCE_KEYBOARD SOURCE_MOUSE
SOURCE_GAMEPAD …

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值