InputManagerService服务的初始化
来源:互联网 发布:淘宝网男包包 编辑:程序博客网 时间:2024/05/18 03:32
InputManagerService的初始化
- 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。
- InputManagerService服务的初始化
- InputManagerService之事件的初始化与分发
- InputManagerService之事件的初始化与分发
- Android5.0 输入系统(一)————InputManagerService服务及相关对象的创建与启动
- Android中InputManagerService里的InputReader和inputDispatcher
- InputManagerService分析一:IMS的启动与事件传递
- init.rc初始化启动的服务
- Linux-系统的初始化和服务
- dubbox -- 服务的启动与初始化
- Android系统源码阅读(11):Android的InputManagerService的工作过程
- Android4.1 InputManagerService 流程
- Android4.1 InputManagerService 流程
- InputManagerService按键接收过程
- InputManagerService分析(一)
- 关于APP接入TBS_X5浏览服务的初始化的坑
- 初始化异常服务
- dubbo 服务消费者初始化
- 系统初始化脚本(根据具体需求关闭不需要的服务)
- Android输入系统概述
- 【Android】EventBus 3.0 源码分析
- HOJX-1004
- UVA 442
- java实现二叉树的创建和各种遍历操作
- InputManagerService服务的初始化
- Lintcode删除排序链表中的重复元素
- C++学习,变量和基本类型
- MiXinJiang Professor of Langfang Teachers College
- Java 循环结构
- 51nod 1280 前缀后缀集合
- String类1
- 应用程序注册输入事件通道
- html布局