InputManager启动流程

InputManager启动流程

InputReader源码分析

InputDispather源码分析

一. InputManagerService的创建

SystemServer.java

private void startOtherServices() {
    
    // ...省略
    // 创建InputManagerService对象
    inputManager = new InputManagerService(context);
    // 将服务添加到SystemManager中
    ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
                    /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
    // 调用start方法开启线程
    inputManager.start();
    // ... 省略
}

InputManagerService.java

    public InputManagerService(Context context) {
        this.mContext = context;
        this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
        // native初始化
        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
        // ... 省略
    }

com_android_server_input_InputManagerService.cpp

static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
    // Java端传进来的messagequeue,转化成native的
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == NULL) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }
    // 创建NativeIputManager
    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    im->incStrong(0);
    // 地址返回到Java端保存
    return reinterpret_cast<jlong>(im);
}
  1. 获取Java端MessageQueue
  2. 创建一个NativeInputManager
  3. 将NativeInputManager的地址返回,也就是说InputManagerService拥有NativeManager的指针
二. NativeInputManager的创建过程

再看创建NativeInputManager的过程

NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
    JNIEnv* env = jniEnv();// 将context和InputManagerService变成全局引用
    mContextObj = env->NewGlobalRef(contextObj);
    mServiceObj = env->NewGlobalRef(serviceObj);
    // ... 省略
     // 创建一个EventHub
    sp<EventHub> eventHub = new EventHub();
     // 创建InputManager
    mInputManager = new InputManager(eventHub, this, this);
}

这里主要将context和InputManagerService的引用变为全局,可能后面会用,创建了一个EventHub(下面分析)以及创建了一个InptuManager

也就是说,NativeInputManager包含了一个InputManager,InputManager包含了一个EventHub

继续看EventHub的创建

三. EventHub的创建过程
EventHub::EventHub(void) :
        mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),
        mOpeningDevices(0), mClosingDevices(0),
        mNeedToSendFinishedDeviceScan(false),
        mNeedToReopenDevices(false), mNeedToScanDevices(true),
        mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
    acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
    // 创建epoll
    mEpollFd = epoll_create(EPOLL_SIZE_HINT);
    LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);
    // 初始化inotify
    mINotifyFd = inotify_init();
     // static const char *DEVICE_PATH = "/dev/input";
    // inotify添加DEVICE_PATH路径进行监听
    int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
    LOG_ALWAYS_FATAL_IF(result < 0, "Could not register INotify for %s.  errno=%d",
            DEVICE_PATH, errno);struct epoll_event eventItem;
    memset(&eventItem, 0, sizeof(eventItem));
    eventItem.events = EPOLLIN;
    eventItem.data.u32 = EPOLL_ID_INOTIFY;
      // 添加fd到epoll
    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance.  errno=%d", errno);// ... 省略
}

EventHub的构造方法中主要是创建了一个epoll以及inotify的初始化,是为了监听/dev/input目录的文件变化,猜测应该是为了热插拔

接下来再看InputManager的创建过程

四. InputManager的创建过程
InputManager::InputManager(       
        const sp<EventHubInterface>& eventHub,                                              // 前面创建的eventhub
        const sp<InputReaderPolicyInterface>& readerPolicy,                       // inputReader
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {    // inputDispatcher
        // 前面构造方法中传的是this说明NativeInputManager实现了InputReaderPolicyInterface和InputDispatcherPolicyInterface
        // 创建InputDispatcher
    mDispatcher = new InputDispatcher(dispatcherPolicy);
         // 创建InputReader
    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
    // 线程创建,后面说
    initialize();
}

上面这段主要是创建了InputDispatcher和InputReader的对象,并在initialize中创建了InputDispatcher的线程和InputReader的线程,其中在创建InputReader的时候给eventhub和InputDispatcher传进去了,接下来分析InputDispatcher和InputReader的创建过程

五. InputDispatcher的创建过程
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
    mPolicy(policy),
    mPendingEvent(NULL), mLastDropReason(DROP_REASON_NOT_DROPPED),
    mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
    mNextUnblockedEvent(NULL),
    mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
    mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
    mLooper = new Looper(false);
​
    mKeyRepeatState.lastKeyEntry = NULL;
​
    policy->getDispatcherConfiguration(&mConfig);
}

好像没看到很关键的东西,暂时跳过,继续看InputReader的创建过程

六. InputReader的创建过程
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);{ // acquire lock
        AutoMutex _l(mLock);refreshConfigurationLocked(0);
        updateGlobalMetaStateLocked();
        //!!! Changed,for control touch device enable, modify by ZhouYou,Start
        mPropertyMonitorThread = new PropertyMonitorThread(this);
        mTouchEnable = true;
        mPropertyMonitorThread->run("PropertyMonitorThread", PRIORITY_URGENT_DISPLAY);
        //!!! Changed,for control touch device enable, modify by ZhouYou,End
    } // release lock
}

好像也没啥关键的,我们目前只需要知道他们的关系就行了

  1. NativeInputManager创建了InputManager
  2. InputManager创建了EventHub,InputReader,InputDispatcher

继续看initialize()

七. 工作线程创建
void InputManager::initialize() {
    mReaderThread = new InputReaderThread(mReader);
    mDispatcherThread = new InputDispatcherThread(mDispatcher);
}

上面这个比较简单,就是创建了两个线程,仅仅是创建,并未启动

简单总结一下:

  1. SystemServer创建了InputManagerService
  2. InputManagerService创建了NativeInputManager
  3. NativeInputManager创建了InputManager
  4. InputManager创建了EventHub,InputReader,InputDispatcher,以及InputReaderThread,InputDispatcherThread
  5. Java端的InputManagerService持有NativeInputManager的指针

基本关系如上

继续往回分析,所有的对象都创建完成之后,NativeInputManager的构造方法也就结束了,如下:

 NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
 return reinterpret_cast<jlong>(im);

将NativeInputManager的指针返回后nativeInit方法也就结束了

    public InputManagerService(Context context) {
      // ... 省略
        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
     // ... 省略
    }

nativeInit返回后,InputManagerService也创建完成了,我们回过去继续看SystemServer的代码,如下

private void startOtherServices() {
    
    // ...省略
    // 创建InputManagerService对象
    inputManager = new InputManagerService(context);
    // 将服务添加到SystemManager中
    ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
                    /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
    // 调用start方法开启线程
    inputManager.start();
    // ... 省略
}

在创建完成InputManagerService之后,除了将它添加到ServiceManager中之外,还调用了它的start方法,我们继续看start方法

八. 线程启动
    public void start() {
        Slog.i(TAG, "Starting input manager");
        nativeStart(mPtr);  // 这里就是nativeInit返回的NativeInputManager的指针地址,这里又传回去了
        // ... 省略
    }

继续分析native方法 com_android_server_input_InputManagerService.cpp

static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
    // 将上面传进来的地址转化成NativeInputManager的指针
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
    // 调用了InputManager的start方法
    status_t result = im->getInputManager()->start();
    if (result) {
        jniThrowRuntimeException(env, "Input manager could not be started.");
    }
}

继续看start方法

status_t InputManager::start() {
    // 前面我们知道,在initialize方法中创建了两个线程,就是下面的两个线程,现在调用了他们的run方法
    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
    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;
}

调用完start方法,mDispatcherThread和mReaderThread就跑起来了,至此,InputManager启动流程就结束了

九. 总结

总结:

  1. 比较关键的三个地方是EventHub,InputReader,InputDispatcher
  2. 其中EventHub用来读取驱动的原始事件
  3. InputReader用来解析事件,包装事件
  4. InputDispatcher用来事件分发

具体的启动流程跟着代码走一遍就行了。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无敌的娃哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值