Linux/Android——Input系统之frameworks层InputManag - 新闻资讯 - 云南小程序开发|云南软件开发|云南网站建设-昆明葵宇信息科技有限公司

159-8711-8523

云南网建设/小程序开发/软件开发

知识

不管是网站,软件还是小程序,都要直接或间接能为您产生价值,我们在追求其视觉表现的同时,更侧重于功能的便捷,营销的便利,运营的高效,让网站成为营销工具,让软件能切实提升企业内部管理水平和效率。优秀的程序为后期升级提供便捷的支持!

您当前位置>首页 » 新闻资讯 » 技术分享 >

Linux/Android——Input系统之frameworks层InputManag

发表时间:2020-10-19

发布人:葵宇科技

浏览次数:38


      上一篇Linux/Android——input体系之 kernel层 与 frameworks层交互 (五)  中有介绍kernel层一下以及与android这边frameworks层之间的接洽,算是打通android 应用层与 kernel驱动层,半数个input体系的进修是至关重要的,个中frameworks层只是简单记录了几个接入点,这里开端分析frameworks层的细节部分。
                                            撰写不易,转载需注明出处:http://blog.csdn.net/jscese/article/details/42392311

input办事的启动:


 android启动的时刻会启动很多个service,这个可以参考SystemServer.java ,会启动InputManagerService这个办事:
   Slog.i(TAG, "Input Manager");
            inputManager = new InputManagerService(context, wmHandler);

...

            ServiceManager.addService(Context.INPUT_SERVICE, inputManager);

直接看InputManagerService.java中的start函数:
    public void start() {
        Slog.i(TAG, "Starting input manager");
        nativeStart(mPtr);   //调用了本处所法,JNI对应的cpp 在server下的jni目次下

...

}

这个牵扯到android的server的jni,最开端是在SystemServer中加载android_server这个动态库,
至于这个动态库的编译可参考/frameworks/base/services/jni/Android.mk中的内容
所以在调用这个nativeStart办法时,相干的动态库已经加载到SystemServer的过程中。
先看下这个start函数在jni文件中的实现,frameworks/base/services/jni/com_android_server_input_InputManagerService.cpp中:
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.");
    }
}

其实熟悉JNI的话,我分析到这里,就应当差不多了。。对于JNI 不是很懂得的话可以参考我之前的博客:Andorid——ubuntu下的 NDK / JNI



看下NativeInputManager构造函数中的:
    sp<EventHub> eventHub = new EventHub();
    mInputManager = new InputManager(eventHub, this, this);

这里的JNI部分就不多说了,如今就看这个InputManager的start办法,膳绫擎提到到Android.mk,可以看到include了一个libinput的动态库,
而这个动态库的路径是在/frameworks/base/services/input下,这就清楚明潦攀啦.此目次下有InputManager.cpp . EventHub.cpp等
直接看start:
status_t InputManager::start() {
    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);  //这个mDispatcherThread是在InputManager构造函数里调用initialize初始化,这里很明显启动了这个名为InputDispatcher的线程
    if (result) {
        ALOGE("Could not start InputDispatcher thread due to error %d.", result);
        return result;
    }

    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY); //同上,开启线程
    if (result) {
        ALOGE("Could not start InputReader thread due to error %d.", result);

        mDispatcherThread->requestExit();
        return result;
    }

    return OK;
}


到这里算是看到真面貌的感到,看这两个线程,字面意思,一个是分发给input事宜给当前的activity的,一个是攫取大年夜基层发上来的input事宜的

InputDispatcher分发:


 大年夜膳绫擎的线程启动分析:
bool InputDispatcherThread::threadLoop() {
    mDispatcher->dispatchOnce();
    return true;
}
调用分发一次的函数:
void InputDispatcher::dispatchOnce() {
    nsecs_t nextWakeupTime = LONG_LONG_MAX;
    { // acquire lock
        AutoMutex _l(mLock);
        mDispatcherIsAliveCondition.broadcast();

        // Run a dispatch loop if there are no pending commands.
        // The dispatch loop might enqueue commands to run afterwards.
        if (!haveCommandsLocked()) {           //如不雅有缓存的敕令就调用下面的runCommand去履行,没有的话这里去检查是否有新的input事宜,这里定义一个唤醒时光┞菲握
            dispatchOnceInnerLocked(&nextWakeupTime);
        }

        // Run all pending commands if there are any.
        // If any commands were run then force the next poll to wake up immediately.
        if (runCommandsLockedInterruptible()) {
            nextWakeupTime = LONG_LONG_MIN;
        }
    } // release lock

    // Wait for callback or timeout or wake.  (make sure we round up, not down)
    nsecs_t currentTime = now();
    int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
    mLooper->pollOnce(timeoutMillis);  //履行膳绫擎一次分发之后,就进入了loop,这个loop会持续的检测对应的管道中是否有内容可读,而别的一个线程InputReader 攫取到input事宜之后就会往这个管道写入
}

这个是处理input事宜的,后续分析,先看怎么攫取事宜.

InputReader攫取:


  源码位于frameworks/base/libs/ui/InputReader.cpp ,开启线程如下:
bool InputReaderThread::threadLoop() {
    mReader->loopOnce();
    return true;
}

这里看这个loopOnce:
void InputReader::loopOnce() {

...

   size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);  //这里去获取event事宜

...

        if (count) {
            processEventsLocked(mEventBuffer, count); //如不雅获取到事宜,就处理
        }

...

}

可以看到这里就到了获取event事宜了。上一篇中有提到!
getEvent中会一向read,直到get到event之后,经由过程precessevent处理,最终会唤醒膳绫擎介绍到的InputDispatcherThread,通知它有新的事沂攀来了

相关案例查看更多