牛骨文教育服务平台(让学习变的简单)
博文笔记

Android6.0 按键流程(一)读取设备事件

创建时间:2016-10-13 投稿人: 浏览次数:280

之前我们整理过一篇按键流程,但是不是太详细有的细节的地方有遗漏,今天在Android6.0上重新总结下,先从读取按键值作为第一篇。


一、初始化

InputManagerService在SystemServer中新建,然后调用了start函数,这里我们就不讲了,从InputManagerService的构造函数讲起。


[java] view plain copy  在CODE上查看代码片派生到我的代码片
  1. public InputManagerService(Context context) {  
  2.     this.mContext = context;  
  3.     this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());  
  4.   
  5.     mUseDevInputEventForAudioJack =  
  6.             context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);  
  7.     Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="  
  8.             + mUseDevInputEventForAudioJack);  
  9.     mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());  
  10.   
  11.     LocalServices.addService(InputManagerInternal.class, new LocalService());  
  12. }  

nativeInit在com_android_server_input_InputManagerService.cpp中,实现如下:

[java] view plain copy  在CODE上查看代码片派生到我的代码片
  1. static jlong nativeInit(JNIEnv* env, jclass /* clazz */,  
  2.         jobject serviceObj, jobject contextObj, jobject messageQueueObj) {  
  3.     sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);  
  4.     if (messageQueue == NULL) {  
  5.         jniThrowRuntimeException(env, "MessageQueue is not initialized.");  
  6.         return 0;  
  7.     }  
  8.   
  9.     NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,  
  10.             messageQueue->getLooper());  
  11.     im->incStrong(0);  
  12.     return reinterpret_cast<jlong>(im);  
  13. }  

新建了一个NativeInputManager对象,并且把这个对象返回了保存在了InputManagerService的mPtr对象中,这只是保存了c层对象的地址,所以只要使用long保存地址就行了。

下面我们看下其构造函数:

[java] view plain copy  在CODE上查看代码片派生到我的代码片
  1. NativeInputManager::NativeInputManager(jobject contextObj,  
  2.         jobject serviceObj, const sp<Looper>& looper) :  
  3.         mLooper(looper), mInteractive(true) {  
  4.     JNIEnv* env = jniEnv();  
  5.   
  6.     mContextObj = env->NewGlobalRef(contextObj);  
  7.     mServiceObj = env->NewGlobalRef(serviceObj);  
  8.   
  9.     {  
  10.         AutoMutex _l(mLock);  
  11.         mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;  
  12.         mLocked.pointerSpeed = 0;  
  13.         mLocked.pointerGesturesEnabled = true;  
  14.         mLocked.showTouches = false;  
  15.     }  
  16.     mInteractive = true;  
  17.   
  18.     sp<EventHub> eventHub = new EventHub();  
  19.     mInputManager = new InputManager(eventHub, this, this);  
  20. }  

新建了一个InputManager和EventHub。


InputManager对象是在InputManager.cpp文件中

[cpp] view plain copy  在CODE上查看代码片派生到我的代码片
  1. InputManager::InputManager(  
  2.         const sp<EventHubInterface>& eventHub,  
  3.         const sp<InputReaderPolicyInterface>& readerPolicy,  
  4.         const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {  
  5.     mDispatcher = new InputDispatcher(dispatcherPolicy);  
  6.     mReader = new InputReader(eventHub, readerPolicy, mDispatcher);  
  7.     initialize();  
  8. }  

InputManager中新建了一个InputDispatcher和InputReader两个对象,然后调用了initialize函数:

[cpp] view plain copy  在CODE上查看代码片派生到我的代码片
  1. void InputManager::initialize() {  
  2.     mReaderThread = new InputReaderThread(mReader);  
  3.     mDispatcherThread = new InputDispatcherThread(mDispatcher);  
  4. }  

这两个变量就是两个线程我们就不看其构造函数了。


接着在InputManagerService中又调了start函数:

[cpp] view plain copy  在CODE上查看代码片派生到我的代码片
  1. public void start() {  
  2.     Slog.i(TAG, "Starting input manager");  
  3.     nativeStart(mPtr);  
  4.   
  5.     // Add ourself to the Watchdog monitors.  
  6.     Watchdog.getInstance().addMonitor(this);  
  7.   
  8.     registerPointerSpeedSettingObserver();  
  9.     registerShowTouchesSettingObserver();  
  10.   
  11.     mContext.registerReceiver(new BroadcastReceiver() {  
  12.         @Override  
  13.         public void onReceive(Context context, Intent intent) {  
  14.             updatePointerSpeedFromSettings();  
  15.             updateShowTouchesFromSettings();  
  16.         }  
  17.     }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);  
  18.   
  19.     updatePointerSpeedFromSettings();  
  20.     updateShowTouchesFromSettings();  
  21. }  

我们主要看下nativeStart函数:

[cpp] view plain copy  在CODE上查看代码片派生到我的代码片
  1. static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {  
  2.     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);  
  3.   
  4.     status_t result = im->getInputManager()->start();  
  5.     if (result) {  
  6.         jniThrowRuntimeException(env, "Input manager could not be started.");  
  7.     }  
  8. }  

我们先把InputManagerService保存的mPtr传下来的变量强制转成NativeInputManager,调用调用器getInputManager函数,也就是其InputManager的start函数

[cpp] view plain copy  在CODE上查看代码片派生到我的代码片
  1. status_t InputManager::start() {  
  2.     status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);  
  3.     if (result) {  
  4.         ALOGE("Could not start InputDispatcher thread due to error %d.", result);  
  5.         return result;  
  6.     }  
  7.   
  8.     result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);  
  9.     if (result) {  
  10.         ALOGE("Could not start InputReader thread due to error %d.", result);  
  11.   
  12.         mDispatcherThread->requestExit();  
  13.         return result;  
  14.     }  
  15.   
  16.     return OK;  
  17. }  


二、EventHub

在上一节中,在NativeInputManager构造函数中,还新建了一个EventHub对象,下面我们就来介绍下:

我们先来分析下其构造函数:

[cpp] view plain copy  在CODE上查看代码片派生到我的代码片
  1. EventHub::EventHub(void) :  
  2.         mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),  
  3.         mOpeningDevices(0), mClosingDevices(0),  
  4.         mNeedToSendFinishedDeviceScan(false),  
  5.         mNeedToReopenDevices(false), mNeedToScanDevices(true),  
  6.         mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {  
  7.     acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);  
  8.   
  9.     mEpollFd = epoll_create(EPOLL_SIZE_HINT);  
  10.     LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);  
  11.   
  12.     mINotifyFd = inotify_init();//INotify机制  
  13.     int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);//监控dev/input目录  
  14.     LOG_ALWAYS_FATAL_IF(result < 0, "Could not register INotify for %s.  errno=%d",  
  15.             DEVICE_PATH, errno);  
  16.   
  17.     struct epoll_event eventItem;  
  18.     memset(&eventItem, 0, sizeof(eventItem));  
  19.     eventItem.events = EPOLLIN;  
  20.     eventItem.data.u32 = EPOLL_ID_INOTIFY;  
  21.     result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);//将这个iNotify的fd加入epoll  
  22.     LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance.  errno=%d", errno);  
  23.   
  24.     int wakeFds[2];  
  25.     result = pipe(wakeFds);//创建了管道,用来唤醒epoll  
  26.     LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);  
  27.   
  28.     mWakeReadPipeFd = wakeFds[0];  
  29.     mWakeWritePipeFd = wakeFds[1];  
  30.   
  31.     result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);  
  32.     LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",  
  33.             errno);  
  34.   
  35.     result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);  
  36.     LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",  
  37.             errno);  
  38.   
  39.     eventItem.data.u32 = EPOLL_ID_WAKE;  
  40.     result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);  
  41.     LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",  
  42.             errno);  
  43.   
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。