> 文章列表 > Android—IMS的InputReader

Android—IMS的InputReader

Android—IMS的InputReader

 在startOtherServices中

frameworks\\base\\services\\java\\com\\android\\server\\SystemServer.java:

            traceBeginAndSlog("StartInputManagerService");inputManager = new InputManagerService(context);traceEnd();traceBeginAndSlog("StartWindowManagerService");// WMS needs sensor service readyConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);mSensorServiceStart = null;wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);ServiceManager.addService(Context.INPUT_SERVICE, inputManager,/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);traceEnd();traceBeginAndSlog("SetWindowManagerService");mActivityManagerService.setWindowManager(wm);traceEnd();traceBeginAndSlog("WindowManagerServiceOnInitReady");wm.onInitReady();traceEnd();...traceBeginAndSlog("StartInputManager");inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());inputManager.start();traceEnd();

会先去创建IMS,再去创建启动WMS,因为双方需要合作,IMS接受各种input事件,发送到WMS的各个窗口。 最好WMS准备好之后启动IMS。

我们先看IMS的构造函数:

frameworks\\base\\services\\core\\java\\com\\android\\server\\input\\InputManagerService.java:

    public InputManagerService(Context context) {this.mContext = context;this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());mUseDevInputEventForAudioJack =context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="+ mUseDevInputEventForAudioJack);mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());String doubleTouchGestureEnablePath = context.getResources().getString(R.string.config_doubleTouchGestureEnableFile);mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :new File(doubleTouchGestureEnablePath);LocalServices.addService(InputManagerInternal.class, new LocalService());}

1. this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());

2. mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());

Handler可能是用来处理某种Msg,我们可以先不用管,找到对应的Msg再看。

先看nativeInit,注意:该方法将Handler的MsgQueue作为参数传入,意味着后面可能就是在Native层发送信息到改队列中,由IMS的Handler进行处理。

frameworks\\base\\services\\core\\jni\\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 == nullptr) {jniThrowRuntimeException(env, "MessageQueue is not initialized.");return 0;}NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,messageQueue->getLooper());im->incStrong(0);return reinterpret_cast<jlong>(im);
}NativeInputManager::NativeInputManager(jobject contextObj,jobject serviceObj, const sp<Looper>& looper) :mLooper(looper), mInteractive(true) {JNIEnv* env = jniEnv();mServiceObj = env->NewGlobalRef(serviceObj);{AutoMutex _l(mLock);mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;mLocked.pointerSpeed = 0;mLocked.pointerGesturesEnabled = true;mLocked.showTouches = false;mLocked.pointerCapture = false;mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;}mInteractive = true;mInputManager = new InputManager(this, this);defaultServiceManager()->addService(String16("inputflinger"),mInputManager, false);
}InputManager::InputManager(const sp<InputReaderPolicyInterface>& readerPolicy,const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {mDispatcher = new InputDispatcher(dispatcherPolicy);mClassifier = new InputClassifier(mDispatcher);mReader = createInputReader(readerPolicy, mClassifier);initialize();
}sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy,const sp<InputListenerInterface>& listener) {return new InputReader(new EventHub(), policy, listener);
}void InputManager::initialize() {mReaderThread = new InputReaderThread(mReader);mDispatcherThread = new InputDispatcherThread(mDispatcher);
}

 这里创建了NativeInputManager -> InputManger -> InputReaderThread、InputDispatcherThread

现在要搞清楚InputReaderThread、InputDispatcherThread是干啥的。

回到一开始我们知道创建完IMS,然后等WMS准备完成后会启动IMS。

            inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
            inputManager.start();

frameworks\\base\\services\\core\\java\\com\\android\\server\\input\\InputManagerService.java:

    public void start() {Slog.i(TAG, "Starting input manager");nativeStart(mPtr);....}

frameworks\\base\\services\\core\\jni\\com_android_server_input_InputManagerService.cpp:

static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);status_t result = im->getInputManager()->start();if (result) {jniThrowRuntimeException(env, "Input manager could not be started.");}
}

frameworks\\native\\services\\inputflinger\\InputManager.cpp:

status_t InputManager::start() {status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);if (result) {ALOGE("Could not start InputDispatcher thread due to error %d.", result);return result;}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;
}

 mDispatcherThread和mReaderThread都集成了Thread,这里调用了run方法会调用到threadLoop,threadLoop返回false会退出循环,true则继续循环,这里涉及的知识点大家可以另外查找。

我们先看mReaderThread

frameworks\\native\\services\\inputflinger\\InputReaderBase.cpp:

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

frameworks\\native\\services\\inputflinger\\InputReader.cpp:

void InputReader::loopOnce() {int32_t oldGeneration;int32_t timeoutMillis;bool inputDevicesChanged = false;std::vector<InputDeviceInfo> inputDevices;....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;}
#if DEBUG_RAW_EVENTSALOGD("BatchSize: %zu Count: %zu", batchSize, count);
#endifprocessEventsForDeviceLocked(deviceId, rawEvent, batchSize);} else {switch (rawEvent->type) {case EventHubInterface::DEVICE_ADDED:addDeviceLocked(rawEvent->when, rawEvent->deviceId);break;case EventHubInterface::DEVICE_REMOVED:removeDeviceLocked(rawEvent->when, rawEvent->deviceId);break;case EventHubInterface::FINISHED_DEVICE_SCAN:handleConfigurationChangedLocked(rawEvent->when);break;default:ALOG_ASSERT(false); // can't happenbreak;}}count -= batchSize;rawEvent += batchSize;}
}

忽略掉一些代码,可以看出这里从EventHub中获取input事件,然后调用

1.processEventsLocked(mEventBuffer, count);

2.mQueuedListener->flush();

EventHub简单来说就主要是利用Linux的inotify和epoll机制,监听设备事件:包括设备插拔及各种触摸、按钮事件等,可以看作是一个不同设备的集线器,主要面向的是/dev/input目录下的设备节点,比如说/dev/input/event0上的事件就是输入事件,通过EventHub的getEvents就可以监听并获取该事件。

1.processEventsLocked(mEventBuffer, count);

processEventsLocked里面区分了输入事件的处理,输入设备的处理。我们只看输入事件的处理。

processEventsForDeviceLocked里面的流程比较长,这里代码就不列出来,主要的流程就是:

processEventsForDeviceLocked->process->KeyboardInputMapper::process->processKey->QueuedInputListener::notifyKey

frameworks\\native\\services\\inputflinger\\InputListener.cpp:

void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {mArgsQueue.push_back(new NotifyKeyArgs(*args));
}

 mArgsQueue是Vector队列,在尾部插入 。

2.mQueuedListener->flush();

frameworks\\native\\services\\inputflinger\\InputListener.cpp:

void QueuedInputListener::flush() {size_t count = mArgsQueue.size();for (size_t i = 0; i < count; i++) {NotifyArgs* args = mArgsQueue[i];args->notify(mInnerListener);delete args;}mArgsQueue.clear();
}void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {listener->notifyKey(this);
}

InputManager::InputManager(
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = new InputDispatcher(dispatcherPolicy);
    mClassifier = new InputClassifier(mDispatcher);
    mReader = createInputReader(readerPolicy, mClassifier);
    initialize();
}

从之前创建InputReader的地方我们知道这里的listener是InputClassifier

void InputClassifier::notifyKey(const NotifyKeyArgs* args) {// pass throughmListener->notifyKey(args);
}

InputClassifier的mListener是mDispatcher

frameworks\\native\\services\\inputflinger\\InputDispatcher.cpp:

void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {...bool needWake;{ // acquire lockmLock.lock();...KeyEntry* newEntry = new KeyEntry(args->sequenceNum, args->eventTime,args->deviceId, args->source, args->displayId, policyFlags,args->action, flags, keyCode, args->scanCode,metaState, repeatCount, args->downTime);needWake = enqueueInboundEventLocked(newEntry);mLock.unlock();} // release lockif (needWake) {mLooper->wake();}
}bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {bool needWake = mInboundQueue.isEmpty();mInboundQueue.enqueueAtTail(entry);traceInboundQueueLengthLocked();switch (entry->type) {case EventEntry::TYPE_KEY: {// Optimize app switch latency.// If the application takes too long to catch up then we drop all events preceding// the app switch key.KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);if (isAppSwitchKeyEvent(keyEntry)) {if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {mAppSwitchSawKeyDown = true;} else if (keyEntry->action == AKEY_EVENT_ACTION_UP) {if (mAppSwitchSawKeyDown) {
#if DEBUG_APP_SWITCHALOGD("App switch is pending!");
#endifmAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;mAppSwitchSawKeyDown = false;needWake = true;}}}break;}case EventEntry::TYPE_MOTION: {// Optimize case where the current application is unresponsive and the user// decides to touch a window in a different application.// If the application takes too long to catch up then we drop all events preceding// the touch into the other window.MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);if (motionEntry->action == AMOTION_EVENT_ACTION_DOWN&& (motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)&& mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY&& mInputTargetWaitApplicationToken != nullptr) {int32_t displayId = motionEntry->displayId;int32_t x = int32_t(motionEntry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X));int32_t y = int32_t(motionEntry->pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y));sp<InputWindowHandle> touchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y);if (touchedWindowHandle != nullptr&& touchedWindowHandle->getApplicationToken()!= mInputTargetWaitApplicationToken) {// User touched a different application than the one we are waiting on.// Flag the event, and start pruning the input queue.mNextUnblockedEvent = motionEntry;needWake = true;}}break;}}return needWake;
}

notifyKey最终将数据封装成KeyEntry然后添加到mInboundQueue队尾,然后唤醒Looper。

所以processEventsLocked(mEventBuffer, count)就是去添加事件到队列,mQueuedListener->flush();就是去唤醒InputDispatcher去处理事件。