InputManagerService服务的初始化

来源:互联网 发布:淘宝网男包包 编辑:程序博客网 时间:2024/05/18 03:32

InputManagerService的初始化

    • InputManagerService的初始化
      • 简介
      • 初始化流程
      • 总结

1.简介

Android系统的输入事件是由InputManagerService服务来监控的,而InputManagerService是由窗口管理服务WindowManagerService来启动的。WindowManagerService服务是在system_server进程中启动关键服务时启动的。

2.初始化流程

InputManagerService也是一个系统服务,在SystemServer中初始化,其初始化流程如下:

2.1 SystemServer.startOtherServices()

private void startOtherServices() {    ....    inputManager = new InputManagerService(context);//构造InputManagerService服务,见2.2    wm = WindowManagerService.main(context, inputManager,            mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,            !mFirstBoot, mOnlyCore);//将InputManagerService设置到WindowManagerService中,见2.12    ServiceManager.addService(Context.WINDOW_SERVICE, wm);    ServiceManager.addService(Context.INPUT_SERVICE, inputManager);    inputManager.setWindowManagerCallbacks(wm.getInputMonitor());// 将InputMonitor对象保存在InputManagerService对象中    inputManager.start();//启动InputManagerService服务,见2.13    ....}

可以看到,在SystemServer的startOtherService方法中,不但构造了InputManagerService服务,而且在启动InputManagerService之前,将其自身注入到WindowMangerService中,进行关联。

2.2 InputManagerService()

public InputManagerService(Context context) {    this.mContext = context;    this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());//初始化Handler,运行在“android.display”线程    .....     mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());// 调用本地方法初始化,见2.3    ......    LocalServices.addService(InputManagerInternal.class, new LocalService());}

nativeInit方法在com_android_server_input_InputManagerService.cpp文件中实现

2.3 nativeInit()

static jlong nativeInit(JNIEnv* env, jclass /* clazz */,    jobject serviceObj, jobject contextObj, jobject messageQueueObj) {    //获取InputManagerService对应的native消息队列    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);    if (messageQueue == NULL) {        jniThrowRuntimeException(env, "MessageQueue is not initialized.");        return 0;    }    // 构造NativeInputManager,见2.4    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,        messageQueue->getLooper());    im->incStrong(0);    return reinterpret_cast<jlong>(im);//返回native指针,保存在InputManagerService的mPtr变量中。}

android_os_MessageQueue_getMessageQueue方法主要是获取Java层消息队列对应的native消息队列。

sp<MessageQueue> android_os_MessageQueue_getMessageQueue(JNIEnv* env, jobject messageQueueObj) {    jlong ptr = env->GetLongField(messageQueueObj, gMessageQueueClassInfo.mPtr);//获取InputManagerService中mHanlder对应的消息队列    return reinterpret_cast<NativeMessageQueue*>(ptr);}

2.4 NativeInputManager()

NativeInputManager::NativeInputManager(jobject contextObj,    jobject serviceObj, const sp<Looper>& looper) :    mLooper(looper), mInteractive(true) {    JNIEnv* env = jniEnv();    mContextObj = env->NewGlobalRef(contextObj);//保存InputManagerService中的Context    mServiceObj = env->NewGlobalRef(serviceObj);// 保存InputManagerService对象    {        AutoMutex _l(mLock);        mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;        mLocked.pointerSpeed = 0;        mLocked.pointerGesturesEnabled = true;        mLocked.showTouches = false;    }    mInteractive = true;    sp<EventHub> eventHub = new EventHub();//构建EventHub,见2.5    mInputManager = new InputManager(eventHub, this, this);//构建InputManager,见2.6}

在NativeInputManager的构造过程中,会创建一个EventHub实例,并且把这个EventHub作为参数来创建InputManager对象。EventHub类是真正执行监控键盘事件操作的地方。mLooper是指“android.display”线程的Looper。

2.5 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);//获取锁    mEpollFd = epoll_create(EPOLL_SIZE_HINT);//创建epoll句柄    mINotifyFd = inotify_init();    // 此处DEVICE_PATH为“/dev/input”,监听该设备路径    int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);    // 构建需要监控的epoll事件    struct epoll_event eventItem;    memset(&eventItem, 0, sizeof(eventItem));    eventItem.events = EPOLLIN;    eventItem.data.u32 = EPOLL_ID_INOTIFY;    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);// 监控mINotifyFd文件描述符    int wakeFds[2];    result = pipe(wakeFds);//创建管道    mWakeReadPipeFd = wakeFds[0];//管道的读端    mWakeWritePipeFd = wakeFds[1];//管道的写端    result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);// 将pipe的读设置为非阻塞模式    result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);// 将pipe的写设置为非阻塞模式    eventItem.data.u32 = EPOLL_ID_WAKE;    // 添加管道的读端到epoll实例    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);    int major, minor;    getLinuxRelease(&major, &minor);    mUsingEpollWakeup = major > 3 || (major == 3 && minor >= 5);}

在构造EventHub时,主要是通过IO多路复用机制epoll来监控输入事件是否已经准备好了。

2.6 InputManager()

InputManager::InputManager(    const sp<EventHubInterface>& eventHub,    const sp<InputReaderPolicyInterface>& readerPolicy,    const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {    //构建InputDispatcher对象,见2.7    mDispatcher = new InputDispatcher(dispatcherPolicy);    //构建InputReader对象,见2.8    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);    initialize();//初始化操作,见2.9}

这里主要是创建一个InputDispatcher对象和一个InputReader对象,并且分别保存在成员变量mDispatcher和mReader中。InputDispatcher类是负责把输入消息分发给当前激活的Activity窗口的,而InputReader类则是通过EventHub类来实现读取输入事件的。

这里的readerPolicy和dispatcherPolicy都是指向NativeInputManager对象,即InputDispatcher和InputReader的mPolicy成员变量都是指向NativeInputManager对象。

2.7 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);//构建一个属于InputDispatcher的Looper对象    mKeyRepeatState.lastKeyEntry = NULL;    policy->getDispatcherConfiguration(&mConfig);}

mPolicy变量指向NativeInputManager对象,在构建InputDispatcher时,会创建一个属于自己线程的Looper实例,在Looper会通过epoll监控唤醒事件。

2.8 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) {    // 构建一个QueuedInputListener监听器    mQueuedListener = new QueuedInputListener(listener);    { // acquire lock        AutoMutex _l(mLock);        refreshConfigurationLocked(0);        updateGlobalMetaStateLocked();    } // release lock}QueuedInputListener::QueuedInputListener(const sp<InputListenerInterface>& innerListener) :    mInnerListener(innerListener) {}

mPolicy变量指向NativeInputManager对象,mQueueListener数据类型为QueuedInputListener,通过其内部成员变量mInnerListener指向InputDispatcher对象。这个mQueueListener对象便是InputDispatcher跟InputReader交互的中间枢纽。

2.9 InputManager.initialize()

void InputManager::initialize() {    // 构建InputReaderThread线程,见2.10    mReaderThread = new InputReaderThread(mReader);    // 构建InputDispatchThread线程,见2.11    mDispatcherThread = new InputDispatcherThread(mDispatcher);}

在这个函数中,创建了一个InputDispatcherThread线程实例和InputReaderThread线程实例。这里的InputReader实例mReader就是通过这里的InputReaderThread线程实例mReaderThread来读取键盘事件的,而InputDispatcher实例mDispatcher则是通过这里的InputDispatcherThread线程实例mDispatcherThread来分发键盘消息的。

2.10 InputReaderThread()

InputReaderThread线程定义及初始化。

/* Reads raw events from the event hub and processes them, endlessly. */class InputReaderThread : public Thread {    public:    InputReaderThread(const sp<InputReaderInterface>& reader);    virtual ~InputReaderThread();    private:    sp<InputReaderInterface> mReader;    virtual bool threadLoop();};// --- InputReaderThread ---InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :    Thread(/*canCallJava*/ true), mReader(reader) {}InputReaderThread::~InputReaderThread() {}bool InputReaderThread::threadLoop() {    //调用InputReader的loopOnce方法    mReader->loopOnce();    return true;}

这里mReader变量指向InputReader对象。

2.11 InputDispatcherThread()

InputDispatcherThread定义及初始化。

/* Enqueues and dispatches input events, endlessly. */class InputDispatcherThread : public Thread {public:    explicit InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher);    ~InputDispatcherThread();private:    virtual bool threadLoop();    sp<InputDispatcherInterface> mDispatcher;};// --- InputDispatcherThread ---InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :    Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {}InputDispatcherThread::~InputDispatcherThread() {}bool InputDispatcherThread::threadLoop() {    // 调用InputDispatcher的dispatchOnce方法    mDispatcher->dispatchOnce();    return true;}

这里mDispatcher变量指向InputDispatcher对象。

至此InputManagerService的初始化工作以及完成了,在初始化InputManager类的时候,同时也初始化了InputDispatcher、InputReader以及InputReaderThread和InputDispatcherThread。其中InputReaderThread和InputDispatcherThread是由InputManager管理的两个重要线程,其作用和具体的逻辑均与InputReader和InputDispatcher相关。接着回到2.1中WindowManagerService的初始化工作。

2.12 WindowManagerService.main()

public static WindowManagerService main(final Context context,        final InputManagerService im,        final boolean haveInputMethods, final boolean showBootMsgs,        final boolean onlyCore) {    final WindowManagerService[] holder = new WindowManagerService[1];    DisplayThread.getHandler().runWithScissors(new Runnable() {        @Override        public void run() {            holder[0] = new WindowManagerService(context, im,                    haveInputMethods, showBootMsgs, onlyCore);// 构建WindowManagerService        }    }, 0);    return holder[0];}private WindowManagerService(Context context, InputManagerService inputManager,        boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {    mContext = context;    .....    mInputManager = inputManager;//关联InputManagerService对象    .....}

在构建WindowManagerService服务时,会与InputManagerService服务进行关联。在构建完WindowManagerService服务之后,会启动InputManagerService服务中的线程,调用InputManagerService的start方法。

2.13 InputManagerService.start()

public void start() {    //调用本地方法启动InputReaderThread和InputDispatcherThread线程    nativeStart(mPtr);//调用本地方法,见2.14    .....}

这个函数主要是启动InputDispatcherThread线程和InputReaderThread线程来分别分发和读取输入事件。

2.14 InputManager.nativeStart()

static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);    //调用InputManager的start方法启动线程    status_t result = im->getInputManager()->start();    if (result) {        jniThrowRuntimeException(env, "Input manager could not be started.");    }}

nativeStart方法最终调用是InputManager的start方法,启动InputReaderThread和InputDispatcherThread线程。

status_t InputManager::start() {    // 启动InputDispatcherThread线程,见2.15    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);    if (result) {        ALOGE("Could not start InputDispatcher thread due to error %d.", result);        return result;    }    // 启动InputReaderThread线程,见2.17    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;}

InputDispatcherThread和InputReaderThread线程调用他们的run方法之后,就会进入到他们的threadLoop函数中,只要threadLoop函数返回true,函数threadLoop就会一直被循环调用,于是这两个线程就起到了不断地读取和分发键盘消息的作用。

2.15 InputDispatcherThread.threadLoop()

bool InputDispatcherThread::threadLoop() {      mDispatcher->dispatchOnce();  见2.16    return true;  } 

mDispatcher变量是前面创建的InputDispatcher对象,调用它的dispatchOnce成员函数进行一次输入消息的分发操作;

2.16 InputDispatcher.dispatchOnce()

void InputDispatcher::dispatchOnce() {    nsecs_t nextWakeupTime = LONG_LONG_MAX;    {        AutoMutex _l(mLock);        mDispatcherIsAliveCondition.broadcast();        if (!haveCommandsLocked()) {            dispatchOnceInnerLocked(&nextWakeupTime);//处理输入消息        }        if (runCommandsLockedInterruptible()) {            nextWakeupTime = LONG_LONG_MIN;        }    }     nsecs_t currentTime = now();    int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);    mLooper->pollOnce(timeoutMillis);//等待下一次输入消息}

在该方法中,主要做了两件事情,一个将输入消息交给dispatchOnceInnerLocked函数来处理,另外一个是调用Looper的pollOnce()方法来等待下一次输入消息的到来。

在Looper类中,会创建一个管道,当调用Looper类的pollOnce函数时,如果管道中没有内容可读,那么当前线程就会进入到空闲等待状态;当有输入事件发生时,InputReader就会往这个管道中写入新的内容,这样就会唤醒前面正在等待键盘事件发生的线程。

2.17 InputReaderThread.threadLoop()

bool InputReaderThread::threadLoop() {      mReader->loopOnce(); //见2.18    return true;  }

mReader变量是前面创建的InputReader对象,调用它的loopOnce成员函数执行一次输入事件的读取操作。

2.18 InputReader.loopOnce()

void InputReader::loopOnce() {    int32_t oldGeneration;    int32_t timeoutMillis;    bool inputDevicesChanged = false;    Vector<InputDeviceInfo> inputDevices;    { // acquire lock        AutoMutex _l(mLock);        oldGeneration = mGeneration;        timeoutMillis = -1;        uint32_t changes = mConfigurationChangesToRefresh;        if (changes) {            mConfigurationChangesToRefresh = 0;            timeoutMillis = 0;            refreshConfigurationLocked(changes);        } else if (mNextTimeout != LLONG_MAX) {            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);            timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);        }    } // release lock    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);//1.读取输入事件,可能阻塞    { // acquire lock        AutoMutex _l(mLock);        mReaderIsAliveCondition.broadcast();        if (count) {            processEventsLocked(mEventBuffer, count);//2.处理消息        }        if (mNextTimeout != LLONG_MAX) {            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);            if (now >= mNextTimeout) {                mNextTimeout = LLONG_MAX;                timeoutExpiredLocked(now);            }        }        if (oldGeneration != mGeneration) {            inputDevicesChanged = true;            getInputDevicesLocked(inputDevices);        }    } // release lock    if (inputDevicesChanged) {        mPolicy->notifyInputDevicesChanged(inputDevices);    }    mQueuedListener->flush();}

在loopOnce函数中,主要通过mEventHub来负责输入事件的读取工作,该方法是阻塞的方法。如果当前有输入事件发生,或者有输入事件等待处理,则通过mEventHub的getEvent函数就可以得到这个事件。然后交由processEventsLocked函数进行处理,这个函数的主要作用是唤醒前面的InputDispatcherThread线程,通知它有新的输入事件发生了。InputDispatcherThread线程需要进行一次输入消息的分发操作。如果没有输入事件发生或者没有输入事件等待处理,那么调用mEventHub的getEvent函数时就会进入等待状态。

至此InputManagerService的初始化工作完成了。

3.总结

输入系统的主要组成部分有:

  • Native层的InputReader,负责从读取出EventHub事件并处理,再交给InputDispatcher处理;
  • Native层的InputDispatcher,负责接收来自InputReader的输入事件,并记录处于激活Activity的窗口信息,用于派发事件到合适的窗口;
  • Java层的InputManagerService,负责跟WindowManagerService交互,WindowManagerService记录了所有的窗口信息,并同步更新到了InputManagerService中,这样InputDispatcher就可以正确派发事件到ViewRootImpl中。

输入系统的类图如下:

在初始化InputManagerService的过程中,mPtr成员变量记录了Native层的NativeInputManager对象,同时也创建了一些native对象,这些对象分别为:

  • NativeInputManager
  • EventHub,InputManager
  • InputReader,InputDispater
  • InputReaderThread,InputDispatcherThread

在初始化InputManagerService的过程中,会启动两个线程:

  • InputReader线程:从EventHub读取出事件并处理,然后交给InputDispatcher线程处理;
  • InputDispatcher线程:接收来自InputReader的输入事件,并分发事件到合适的窗口;

Java层的InputManagerService和JNI层的NativeInputManager都是采用“android.display”线程处理Message,他们共用一个消息队列MessageQueue。

NativeInputManager中的mLooper对象指向“android.display”线程的Looper对象。InputDispatcher对象的mLooper对象指向它自己线程的Looper对象。

输入事件的一个大致处理流程: Linux kernel ——> InputManagerService(InputReader——>InputDispatcher) ——> WindowManagerService ——> ViewRootImpl。