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 ready
ConcurrentUtils.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_EVENTS
ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
#endif
processEventsForDeviceLocked(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 happen
break;
}
}
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 through
mListener->notifyKey(args);
}
InputClassifier的mListener是mDispatcher
frameworks\native\services\inputflinger\InputDispatcher.cpp:
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
...
bool needWake;
{ // acquire lock
mLock.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 lock
if (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_SWITCH
ALOGD("App switch is pending!");
#endif
mAppSwitchDueTime = 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去处理事件。