InputManagerService的启动过程(一)
作者:互联网
从 SystemServer 的main方法开始==》
SystemServer#
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
//引导服务:ActivityManagerService、PowerManagerService、PackageManagerService等服务
startBootstrapServices();
//核心服务:teryService、UsageStatsService和WebViewUpdateService
startCoreServices();
//其他服务:eraService、AlarmManagerService、VrManagerService、InputManagerService等服务
startOtherServices();
}
而InputManagerService的启动是在 startOtherServices中,startOtherServices方法还启动了其他的一些服务,这里只关注InputManagerService。
SystemServer#
private void startOtherServices() {
WindowManagerService wm = null;
InputManagerService inputManager = null;
//创建InputManagerService实例
inputManager = new InputManagerService(context);
//内部会创建WindowManagerService实例,并且持有inputManager引用
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore, new PhoneWindowManager());
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
//将InputManagerService实例添加到ServiceManager统一管理
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
//启动InputManagerService
inputManager.start();
}
WindowManagerService是输入系统的中转站,因此它必定持有了InputManagerService的引用。
InputManagerService的构建
public InputManagerService(Context context) {
//拿到“android.display”线程的Looper创建一个InputManagerHandler
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
//初始化InputManagerService
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
}
private static native long nativeInit(InputManagerService service,
Context context, MessageQueue messageQueue);
继续跟进com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == NULL) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
//可以看到创建了一个native层的NativeInputManager对象
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
im->incStrong(0);
//将native层的NativeInputManager对象的地址返回给java层
return reinterpret_cast<jlong>(im);
}
NativeInputManager对象的构造
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper), mInteractive(true) {
//创建EventHub用来监视设备节点
sp<EventHub> eventHub = new EventHub();
//构造一个InputManager对象
mInputManager = new InputManager(eventHub, this, this);
}
输入事件比如触摸屏幕最终会被输入子系统采集,最终会传递给这些设备节点,就会被EventHub监视到,而InputManagerService就是通过EventHub来获取这些输入事件的。
InputManager::InputManager(
const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
//用来将输入事件分发给合适的window
mDispatcher = new InputDispatcher(dispatcherPolicy);
//用来不停的读取eventHub中的输入事件,并且持有InputDispatcher的引用
mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
initialize();
}
void InputManager::initialize() {
//InputDispatcher和InputReader的执行都比较耗时,放到单独的线程中执行。
mReaderThread = new InputReaderThread(mReader);
mDispatcherThread = new InputDispatcherThread(mDispatcher);
}
到这里InputManagerService的创建就结束了,接下来分析它的启动方法
SystemServer#
private void startOtherServices() {
WindowManagerService wm = null;
InputManagerService inputManager = null;
//...
//启动InputManagerService
inputManager.start();
}
SystemServer#
public void start() {
//直接调用了native层的启动方法,把native层NativeInputManager对象的指针传过去。
nativeStart(mPtr);
}
继续往下查看com_android_server_input_InputManagerService.cpp
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
//获取NativeInputManager对象的指针
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
//启动
status_t result = im->getInputManager()->start();
}
然后调用了InputManager的start方法,回顾下InputManager的创建
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper), mInteractive(true) {
sp<EventHub> eventHub = new EventHub();
mInputManager = new InputManager(eventHub, this, this);
}
继续跟踪InputManager.cpp的start方法
InputManager.cpp#
status_t InputManager::start() {
status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
return OK;
}
直接调用了mDispatcherThread和mReaderThread这两个线程的run方法,这两个线程的创建前面已经提过。
先来分析下InputReaderThread这个类,它的实现位于InputReader.h
/* Reads raw events from the event hub and processes them, endlessly. */
/* 从event hub 中不停的读取原始事件,然后处理它们 */
InputReader.h#
class InputReaderThread : public Thread {
public:
explicit InputReaderThread(const sp<InputReaderInterface>& reader);
virtual ~InputReaderThread();
private:
sp<InputReaderInterface> mReader;
virtual bool threadLoop();
};
回顾下前面的分析,InputReaderThread持有InputReader,InputReader持有EventHub和InputDispatcher,这样在InputReaderThread线程中就可以不停的通过EventHub获取原始的输入事件,然后交由InputDispatcher处理了。这里有个虚方法threadLoop啥意思呢?源码中调用的是run方法和threadLoop有什么关系呢?
找到InputReaderThread的父类Thread的头文件
namespace android {
class Thread : virtual public RefBase
{
public:
// Start the thread in threadLoop() which needs to be implemented.
virtual status_t run( const char* name,
int32_t priority = PRIORITY_DEFAULT,
size_t stack = 0);
private:
// 1) loop: if threadLoop() returns true, it will be called again if
// requestExit() wasn't called.
// 2) once: if threadLoop() returns false, the thread will exit upon return.
virtual bool threadLoop() = 0;
}
}
注释可以说很贴心了,调用run方法,最终会启动threadLoop,如果threadLoop返回true会被循环执行,如果返回false,只会被执行一次。ok跑题了,继续分析InputReaderThread的实现。
InputReader.cpp#
InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
Thread(/*canCallJava*/ true), mReader(reader) {
}
InputReaderThread::~InputReaderThread() {
}
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}
调用run会导致调用threadLoop方法,并且由于threadLoop返回true,threadLoop会被循环调用。在threadLoop内部又调用了mReader的loopOnce方法,而mReader就是InputReader继续跟进==》
InputReader.cpp#
//InputReader构造方法
//可以看到在初始化列表中将eventHub给到成员mEventHub,用QueuedInputListener来包装InputDispatcher
InputReader::InputReader(const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& policy,
const sp<InputListenerInterface>& listener):mEventHub(eventHub)...{
mQueuedListener = new QueuedInputListener(listener);
}
void InputReader::loopOnce() {
//通过mEventHub的getEvents方法获取设备节点所有的事件信息保存到mEventBuffer中
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{
//如果有事件就对其进行加工处理。
if (count) {
processEventsLocked(mEventBuffer, count);
}
mQueuedListener->flush();
}
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
//遍历所有的事件
for (const RawEvent* rawEvent = rawEvents; count;) {
int32_t type = rawEvent->type;
size_t batchSize = 1;
if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
//这条分支用来处理输入事件
int32_t deviceId = rawEvent->deviceId;
while (batchSize < count) {
if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
|| rawEvent[batchSize].deviceId != deviceId) {
break;
}
batchSize += 1;
}
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
} else {
//这条分支用来处理设备事件,我们不关注
}
count -= batchSize;
rawEvent += batchSize;
}
}
事件分为设备事件和原始的输入事件,我们这里只关注输入事件。
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
const RawEvent* rawEvents, size_t count) {
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
InputDevice* device = mDevices.valueAt(deviceIndex);
device->process(rawEvents, count);
}
根据代码的语义,首先通过deviceId从mDevices获取到deviceIndex,然后再根据deviceIndex获取具体的输入设备,再调用InputDevice的process去处理具体的输入事件。
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
size_t numMappers = mMappers.size();
for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
if (mDropUntilNextSync) {
if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
mDropUntilNextSync = false;
}
} else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
mDropUntilNextSync = true;
reset(rawEvent->when);
} else {
for (size_t i = 0; i < numMappers; i++) {
InputMapper* mapper = mMappers[i];
//调用InputMapper去处理事件
mapper->process(rawEvent);
}
}
}
}
遍历所有的原始事件,然后将这些事件交给每一个InputMapper去处理。InputMapper的实现类有很多,JoystickInputMapper(用于处理游戏手柄输入事件)、MultiTouchInputMapper(用于处理多点触摸输入事件)、KeyboardInputMapper( 用于处理键盘输入事件)、SingleTouchInputMapper(用于处理单点触摸输入事件)、CursorInputMapper( 用于处理鼠标输入事件)等。因为输入设备有很多,因此就会有不同的 InputMapper 来处理不同类型的事件。这里以SingleTouchInputMapper为例,来分析输入事件到底是怎么分发出去的?会省略部分代码,只关注主线。
SingleTouchInputMapper#
void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
//调用父类TouchInputMapper的process
TouchInputMapper::process(rawEvent);
mSingleTouchMotionAccumulator.process(rawEvent);
}
TouchInputMapper#
void TouchInputMapper::process(const RawEvent* rawEvent) {
sync(rawEvent->when);
}
void TouchInputMapper::sync(nsecs_t when) {
processRawTouches(false /*timeout*/);
}
void TouchInputMapper::processRawTouches(bool timeout) {
cookAndDispatch(mCurrentRawState.when);
}
void TouchInputMapper::cookAndDispatch(nsecs_t when) {
//看起来有点像事件的分发方法了
if (!mCurrentMotionAborted) {
dispatchButtonRelease(when, policyFlags);
dispatchHoverExit(when, policyFlags);
dispatchTouches(when, policyFlags);
dispatchHoverEnterAndMove(when, policyFlags);
dispatchButtonPress(when, policyFlags);
}
}
}
void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
dispatchMotion(...);
}
void TouchInputMapper::dispatchMotion(...) {
//将经过加过的事件封装成NotifyMotionArgs
NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,
action, actionButton, flags, metaState, buttonState, edgeFlags,
mViewport.displayId, pointerCount, pointerProperties, pointerCoords,
xPrecision, yPrecision, downTime);
//调用getListener的notifyMotion方法
getListener的()->notifyMotion(&args);
}
调用getListener的notifyMotion方法最终会走到InputDispatcher.cpp的notifyMotion方法
InputDispatcher.cpp#
void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
// Just enqueue a new motion event.
//将事件进一步封装
MotionEntry* newEntry = new MotionEntry(args->eventTime,
args->deviceId, args->source, policyFlags,
args->action, args->actionButton, args->flags,
args->metaState, args->buttonState,
args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
args->displayId,
args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0);
//将事件插入队列
needWake = enqueueInboundEventLocked(newEntry);
if (needWake) {
//如果需要就唤醒InputDispatcherThread
mLooper->wake();
}
}
InputDispatcherThread线程被唤醒之后就会对事件进行分发。mLooper怎么救能唤醒InputDispatcherThread呢,
InputDispatcher.cpp#
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
//通过代码可以看出来,它就是InputDispatcher直接new出来的一个成员而已
mLooper = new Looper(false);
}
mLooper先放放。先来分析下InputDispatcherThread这个线程,前面分析过InputManager在构造时会调用initialize方法,这个方法如下创建了InputDispatcherThread线程,它持有InputDispatcher引用
void InputManager::initialize() {
//InputDispatcher和InputReader的执行都比较耗时,放到单独的线程中执行。
mReaderThread = new InputReaderThread(mReader);
mDispatcherThread = new InputDispatcherThread(mDispatcher);
}
// --- InputDispatcherThread ---
InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
}
InputDispatcherThread::~InputDispatcherThread() {
}
bool InputDispatcherThread::threadLoop() {
mDispatcher->dispatchOnce();
return true;
}
它的threadLoop方法直接调了InputDispatcher的dispatchOnce方法。
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
AutoMutex _l(mLock);
mDispatcherIsAliveCondition.broadcast();
// Run a dispatch loop if there are no pending commands.
// The dispatch loop might enqueue commands to run afterwards.
if (!haveCommandsLocked()) {
//这里分发输入事件给window
dispatchOnceInnerLocked(&nextWakeupTime);
}
// Run all pending commands if there are any.
// If any commands were run then force the next poll to wake up immediately.
if (runCommandsLockedInterruptible()) {
nextWakeupTime = LONG_LONG_MIN;
}
} // release lock
// Wait for callback or timeout or wake. (make sure we round up, not down)
nsecs_t currentTime = now();
int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
//休眠timeoutMillis时间
mLooper->pollOnce(timeoutMillis);
}
这里调用了mLooper->pollOnce使InputDispatcherThread休眠, 有两种方法来唤醒mLooper,一是mLooper->wake(),二是nextWakeupTime时间到达后 。
结合前面的分析知道,InputReader读取到输入事件,会把事件通过InputDispatcher的enqueueInboundEventLocked插入队列,然后通过mLooper来唤醒 InputDispatcherThread , InputDispatcherThread 被唤醒后会去分发输入事件给具体的窗口。
到现在InputManagerService的启动已经分析完成了。
标签:const,启动,InputManagerService,void,args,new,过程,rawEvent 来源: https://blog.csdn.net/start_mao/article/details/115053284