Android输入系统IMS(3)--ims启动过程以及读取数据

艳阳高照的天气适合在出租屋做技术宅~~

一. InputManagerService的启动:

    1.在Android的SystemServer中的private void startOtherServices() {}函数中会启动InputManagerService,以及InputManagerService服务(这个服务后面会用于和InputChannel打交道获取输入事件分发给指定窗口,以后再单独写一篇讲解,这里知道有这回事就ok了)。

2.接着在InputManagerService构造函数中调用了mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());通过JNI调用到了com_android_server_input_InputManagerService.cpp里的static jlong nativeInit(JNIEnv* env, jclass clazz,
        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {}函数。直接上图吧。

     在nativeInit函数中new了一个NativeInputManager本地对象这个是负责读取输入设备节点,数据数据加工处理,分发的管家。

     在图中的步骤2我们可以看到new EventHub();这个就是通过epoll,notify机制读取输入事件已经检测输入设备热插拔的详情可以看之前的博客:Android输入系统IMS(1)--基础知识epoll和notifyhttps://blog.csdn.net/longruic/article/details/90139504。同时 new InputManager。

   在图中步骤3中我们可以看到new了一个mDispatcher 和一个mReader 同时把eventHub,mDispatcher传给了mReader。其中eventHub用于读取输入事件,mDispatcher用于分发事件。步骤4分别创建了读取线程mReaderThread 和分发线程mDispatcherThread 。至此native层的读取,分发初始化流程已经走完了。

new EventHub详细图:

 

二. 线程mReaderThread读取输入事件数据的过程:

有图有真相:

     通过这个时序图可以看出读取线程平时是睡眠阻塞在mEventHub->getEvents()这里的但有触摸事件产生是会退出睡眠读取数据往下执行。事件保存在mEventBuffer变量最终会传递到mArgsQueue这个变量里。{mArgsQueue 是 QueuedInputListener类的私有成员变量。C++父类的私有变量,子类能继承,但是子类不能直接访问,需要使用父类提供的方法才能访问该变量。该方法是从继承得到 的protected、public方法来访问}。

    InputReader::processEventsLocked函数里会根据不同的情况调用不同的函数进行处理。这里我们以按键事件路线进行分析,其它事件大同小异。processEventsForDeviceLocked(deviceId, rawEvent, batchSize);因为Android是同时支持多个输入设备的如usb键盘 鼠标 触摸屏 按键,所以这里有个deviceId用于识别当前设备,然后根据deviceId在mDevices找到对应的InputDevice* device并调用它的处理函数device->process(rawEvents, count);InputDevice又可以支持不同的InputMapper。 mapper->process(rawEvent);可以看到virtual void process(const RawEvent* rawEvent) = 0;是个纯虚函数,实现在子类里这是c++的多态性。根据类的继承关系class KeyboardInputMapper : public InputMapper ;所以是调用了void KeyboardInputMapper::process(const RawEvent* rawEvent) 。

     getListener()->notifyKey(&args)函数最终是调用到了哪里?

 

      由上面的图片中继承 调用关系可知最终调用到了void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) 此时事件保存在mEventBuffer变量的数据被转换封装成NotifyKeyArgs放入mArgsQueue变量中,到这里读取输入事件已经完成了。

    我们再来看看28.mQueuedListener->flush();最终调用到了哪里?

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

class InputDispatcher : public InputDispatcherInterface {}
class InputDispatcherInterface : public virtual RefBase, public InputListenerInterface {}

class InputReader : public InputReaderInterface {
	sp<QueuedInputListener> mQueuedListener;
}
InputReader::InputReader(const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& policy,
        const sp<InputListenerInterface>& listener) :
        mContext(this), mEventHub(eventHub), mPolicy(policy),
        mGlobalMetaState(0), mGeneration(1),
        mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
        mConfigurationChangesToRefresh(0) {
    mQueuedListener = new QueuedInputListener(listener);//AA mDispatcher

    { // acquire lock
        AutoMutex _l(mLock);

        refreshConfigurationLocked(0);
        updateGlobalMetaStateLocked();
    } // release lock
}

mQueuedListener->flush();//BB call -> InputDispatcher::notifyKey(const NotifyKeyArgs* args)

QueuedInputListener::QueuedInputListener(const sp<InputListenerInterface>& innerListener) :
        mInnerListener(innerListener) {//AA mDispatcher,mInnerListener=innerListener=mDispatcher
}

void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
    mArgsQueue.push(new NotifyKeyArgs(*args));
}
void QueuedInputListener::flush() {//BB
    size_t count = mArgsQueue.size();
    for (size_t i = 0; i < count; i++) {
        NotifyArgs* args = mArgsQueue[i];
        args->notify(mInnerListener);//AA mDispatcher,mInnerListener=innerListener=mDispatcher
        delete args;
    }
    mArgsQueue.clear();
}
/* Superclass of all input event argument objects */
struct NotifyArgs {
    virtual ~NotifyArgs() { }
    virtual void notify(const sp<InputListenerInterface>& listener) const = 0;
};
/* Describes a key event. */
struct NotifyKeyArgs : public NotifyArgs {
virtual void notify(const sp<InputListenerInterface>& listener) const;
}
void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {//listener=mDispatcher
    listener->notifyKey(this);//CC
}

class InputDispatcher : public InputDispatcherInterface {
	virtual void notifyKey(const NotifyKeyArgs* args);
}
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {} //DD
class InputDispatcherInterface : public virtual RefBase, public InputListenerInterface {}

class InputListenerInterface : public virtual RefBase {
    virtual void notifyKey(const NotifyKeyArgs* args) = 0; //CC, Pure virtual function is implemented in DD
};

通过上面的代码(函数和类只是关键部分而已),可以得出结论:最终调用到了InputDispatcher::notifyKey()。InputRead和InputDispatch都是操作 mArgsQueue ,通过NotifyArgs *args传递keycode值;mArgsQueue 是 QueuedInputListener类的私有成员变量。C++父类的私有变量,子类能继承,但是子类不能直接访问,需要使用父类提供的方法才能访问该变量。该方法是从继承中得到 的protected、public方法来访问。 到这里InputDispatch 已经得到带触摸数据的args了。

这篇先到这里结束。下篇再讲解InputDispatcher分发过程。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值