InputReader负责获取设备的输入数据,然后发给InputDispatcher去处理,为了让2个处理独立起来,不相互影响,它们是在不同的线程中执行的,
InputDispatcher里的threadLoop方法是继承的Thread的方法,会在一个while中不停的调用起来,
不停的调用,会不会太占用资源?
4623bool InputDispatcherThread::threadLoop() { 4624 mDispatcher->dispatchOnce(); 4625 return true; 4626}
查看dispatchOnce方法,里面使用了 mLooper->pollOnce(timeoutMillis);来进行阻塞,就避免了不断的执行循环,
269void InputDispatcher::dispatchOnce() { 270 nsecs_t nextWakeupTime = LONG_LONG_MAX; 271 { // acquire lock 272 AutoMutex _l(mLock); 273 mDispatcherIsAliveCondition.broadcast(); 274 275 // Run a dispatch loop if there are no pending commands. 276 // The dispatch loop might enqueue commands to run afterwards. 277 if (!haveCommandsLocked()) { 278 dispatchOnceInnerLocked(&nextWakeupTime); 279 } 280 281 // Run all pending commands if there are any. 282 // If any commands were run then force the next poll to wake up immediately. 283 if (runCommandsLockedInterruptible()) { 284 nextWakeupTime = LONG_LONG_MIN; 285 } 286 } // release lock 287 288 // Wait for callback or timeout or wake. (make sure we round up, not down) 289 nsecs_t currentTime = now(); 290 int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime); 291 mLooper->pollOnce(timeoutMillis); 292}
这里阻塞住了,我们可以猜想,InputReader传送数据过来的时候,就不再阻塞,
InputReader传送touch事件的时候,调用到InputDispatcher中的notifyMotion方法,
2527void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
2590 // Just enqueue a new motion event. 2591 MotionEntry* newEntry = new MotionEntry(args->eventTime, 2592 args->deviceId, args->source, policyFlags, 2593 args->action, args->actionButton, args->flags, 2594 args->metaState, args->buttonState, 2595 args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime, 2596 args->displayId, 2597 args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0); 2598 2599 needWake = enqueueInboundEventLocked(newEntry); 2600 mLock.unlock(); 2601 } // release lock 2602 2603 if (needWake) { 2604 mLooper->wake(); 2605 }
就解除了dispatchOnce中的looper阻塞,在handler的相关调用中,Looper都隐藏的很深,几乎是透明的存在,看不到其身影,而这里,Looper现身了,不再隐藏,这里直接使用了其阻塞和唤醒功能来实现2个线程间的交互。