本文源代码基于 Android 7.0。
- /base/services/core/java/com/android/server/input/InputManagerService.java (IMS)
- /base/services/core/java/com/android/server/wm/WindowManagerService.java (WMS)
- /base/services/java/com/android/server/SystemServer.java
- /base/services/core/jni/com_android_server_input_InputManagerService.cpp
- /native/services/inputflinger/InputManager.cpp
- /native/services/inputflinger/InputReader.cpp
- /native/services/inputflinger/InputDispatcher.cpp
- /native/libs/input/InputTransport.cpp
- /base/core/jni/android_view_InputEventReceiver.cpp
- /base/core/java/android/view/ViewRootImpl.java
这篇文章来分析下 Android 的输入。
目录:
1. Android 的输入系统
输入事件的源头是位于 /dev/input/ 下的设备节点,而输入系统的终点是由 WMS 管理的某个窗口。最初的输入事件为内核产生的原始事件,最终封装成 KeyEvent 或者 MotionEvent 分发给窗口。流程图如下:
分析一下上图角色:
总结一下:
内核将原始事件写入到设备节点中,InputReader 不断地通过 EventHub 将原始事件取出来并翻译加工成 Android 输入事件,然后交给 InputDispatcher。InputDispatcher 根据 WMS 提供的窗口信息将事件交给合适的窗口。窗口的 ViewRootImpl 对象再沿着控件树将事件派发给感兴趣的控件。控件对其收到的事件作出响应,更新自己的画面、执行特定的动作。所有这些参与者以 IMS 为核心,构建了 Android 庞大而复杂的输入体系。
2. InputManagerService 的初始化
InputManagerService 和 ActivityManagerService、WindowManagerService 一样,都是运行在 system_server 进程,也是在 system_server 进程进行初始化的。
private void startOtherServices() {
// …
InputManagerService inputManager = null;
// 启动InputManagerService
inputManager = new InputManagerService(context);
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
inputManager.start();
// …
}
创建完后将自己传给 WindowManagerService,然后调用了 start 函数。
先看看构造器:
public InputManagerService(Context context) {
this.mContext = context;
// 运行在线程"android.display"
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
mUseDevInputEventForAudioJack =
context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
+ mUseDevInputEventForAudioJack);
// 初始化native对象,NativeInputManager
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
LocalServices.addService(InputManagerInternal.class, new LocalService());
}
private static native long nativeInit(InputManagerService service,
Context context, MessageQueue messageQueue);
里面初始化了 native 对象 (NativeInputManager),再来看看 start():
public void start() {
// 启动NativeInputManager对象
nativeStart(mPtr);
Watchdog.getInstance().addMonitor(this);
// 注册触摸点速度和是否显示功能的观察者
registerPointerSpeedSettingObserver();
registerShowTouchesSettingObserver();
registerAccessibilityLargePointerSettingObserver();
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
updateAccessibilityLargePointerFromSettings();
}
}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
// 更新触摸点的速度
updatePointerSpeedFromSettings();
// 是否在屏幕上显示触摸点
updateShowTouchesFromSettings();
updateAccessibilityLargePointerFromSettings();
}
private static native void nativeStart(long ptr);
看一下上面的 nativeInit() 和 nativeStart() 的实现。
/** 从InputManagerService的nativeInit调用进来,获取NativeInputManager的指针 */
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
// 获取native消息队列
sp messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == NULL) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
// 创建Native的InputManager
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
im->incStrong(0);
// 返回Native对象的指针
return reinterpret_cast(im);
}
nativeInit() 中主要是构造了一个 NativeInputManager 对象,而 NativeInputManager 对象中的 serviceObj 是 Java 层的InputManagerService 对象。来看看 NativeInputManager 的构造器:
/**
* NativeInputManager构造器
*/
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp& looper) :
mLooper(looper), mInteractive(true) {
JNIEnv* env = jniEnv();
// 上层IMS的context
mContextObj = env->NewGlobalRef(contextObj);
// 上层InputManagerService对象
mServiceObj = env->NewGlobalRef(serviceObj);
{
AutoMutex _l(mLock);
mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
mLocked.pointerSpeed = 0;
mLocked.pointerGesturesEnabled = true;
mLocked.showTouches = false;
}
mInteractive = true;
// 创建EventHub对象
sp eventHub = new EventHub();
// 创建InputManager对象,native层
mInputManager = new InputManager(eventHub, this, this);
}
NativeInputManager 的构造器中创建了 EventHub 对象,并把 EventHub 对象和 NativeInputManager 本身作为参数构造了 InputManager 对象。
nativeStart() 的实现:
/**
* 该方法的主要功能是启动两个线程:
*
* 启动线程“InputReader”
* 启动线程”InputDispatcher“
*
* InputReader:从EventHub取出事件并处理,再交给InputDispatcher
* InputDispatcher:接收来自InputReader的输入事件,并派发事件到合适的窗口。
*/
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
NativeInputManager* im = reinterpret_cast(ptr);
status_t result = im->getInputManager()->start();
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
}
InputManager 的构造器如下:
InputManager::InputManager(
const sp& eventHub,
const sp& readerPolicy,
const sp& dispatcherPolicy) {
mDispatcher = new InputDispatcher(dispatcherPolicy);//前面把NativeInputManager的对象传了进来,就是dispatcherPolicy和readerPolicy
mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
initialize();
}
创建了两个 JNI 层最重要的对象 InputDispatcher,InputReader,initialize() 方法如下:
void InputManager::initialize() {
mReaderThread = new InputReaderThread(mReader);
mDispatcherThread = new InputDispatcherThread(mDispatcher);
}
initialize() 函数把 reader 和 dispatch 对象传进去了,建了两个线程。最后来看看上面 nativeStart() 中 start() 的实现:
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;
}
主要工作是启动 InputReader 和 InputDispatcher 这两个线程。
InputManagerService 初始化过程包括:
3. InputReader & InputDispatcher 线程
上面在 nativeStart() 中启动了这两个线程,现在来看看它们的 run() 实现。
/**
* 启动线程循环
* threadLoop返回值true代表的是会不断地循环调用loopOnce()。
* 另外,如果当返回值为false则会 退出循环。整个过程是不断循环的地调用InputReader的loopOnce()方法,
* 先来回顾一下InputReader对象构造方法。
*/
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}
void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
Vector inputDevices;
{ // acquire lock
AutoMutex _l(mLock);
oldGeneration = mGeneration;
timeoutMillis = -1;
uint32_t changes = mConfigurationChangesToRefresh;
if (changes) {
mConfigurationChangesToRefresh = 0;
timeoutMillis = 0;
refreshConfigurationLocked(changes);
} else if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
}
} // release lock
// 从EventHub读取事件,其中EVENT_BUFFER_SIZE = 256
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{ // acquire lock
AutoMutex _l(mLock);
mReaderIsAliveCondition.broadcast();
if (count) {
// 处理事件
processEventsLocked(mEventBuffer, count);
}
if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
if (now >= mNextTimeout) {
#if DEBUG_RAW_EVENTS
ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
#endif
mNextTimeout = LLONG_MAX;
timeoutExpiredLocked(now);
}
}
if (oldGeneration != mGeneration) {
inputDevicesChanged = true;
getInputDevicesLocked(inputDevices);
}
} // release lock
// Send out a message that the describes the changed input devices.
if (inputDevicesChanged) {
// 输入设备发生改变
mPolicy->notifyInputDevicesChanged(inputDevices);
}
// 发送事件到inputDispatcher
mQueuedListener->flush();
}
第一个重要的函数 getEvents() 是读取每个设备的数据形成 RawEvent,放入 buffer 中,如果没有输入事件,就 epoll_wait 函数阻塞等待。因此 InputReaderThread 大部分的时间在 epoll_wait 上,有输入设备事件到来则唤醒线程,读数据封装成 RawEvent,放在 mEventBuffer 中然后调用 processEventsLocked()。具体的 getEvents() 函数就不看了,也比较长。这边来看下 processEventsLocked() 的实现。
/**
* 处理事件
* 事件处理总共有下几类类型:
* DEVICE_ADDED(设备增加)
* DEVICE_REMOVED(设备移除)
* FINISHED_DEVICE_SCAN(设备扫描完成)
* 数据事件
*/
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: %d Count: %d", 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;
}
}
这个函数处理 RawEvent 分成两类,一类是设备发生变化的 Event,包括增加,移除,扫描设备结束;另一类是设备自身产生的Event,比如按键的 Event。这类 Event,会从 RawEvent 的 mEventBuffer 中不断读取出来然后调用processEventsForDeviceLocked() 函数处理。
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
const RawEvent* rawEvents, size_t count) {
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
if (deviceIndex < 0) {
ALOGW("Discarding event for unknown deviceId %d.", deviceId);
return;
}
InputDevice* device = mDevices.valueAt(deviceIndex);
if (device->isIgnored()) {
//ALOGD("Discarding event for ignored deviceId %d.", deviceId);
return;
}
// 调用InputDevice.process
device->process(rawEvents, count);
}
最终经过一系列的包装处理,输出 KeyEvent 和 MotionEvent。然后发送事件到 inputDispatcher (mQueuedListener->flush())。
// 启动循环,整个过程不断循环地调用InputDispatcher的dispatchOnce()来分发事件
bool InputDispatcherThread::threadLoop() {
mDispatcher->dispatchOnce();
return true;
}
/**
* 线程执行Looper->pollOnce,进入epoll_wait等待状态,当发生以下任一情况则退出等待状态:
*
* callback:通过回调方法来唤醒;
* timeout:到达nextWakeupTime时间,超时唤醒;
* wake: 主动调用Looper的wake()方法;
*/
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
AutoMutex _l(mLock);
// 唤醒等待线程,monitor()用于监控dispatcher是否发生死锁
mDispatcherIsAliveCondition.broadcast();
if (!haveCommandsLocked()) {
// 当mCommandQueue不为空时处理
dispatchOnceInnerLocked(&nextWakeupTime);
}
if (runCommandsLockedInterruptible()) {
nextWakeupTime = LONG_LONG_MIN;
}
} // release lock
nsecs_t currentTime = now();
int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
// 进入epoll_wait
mLooper->pollOnce(timeoutMillis);
}
也就是 InputReader 线程有发送数据后调用 mLooper 的 wake() 函数,唤醒 InputDispatcher 线程来发送给应用线程信息。其中dipatchOnceInnerLocked() 就是分发信息的。
/**
* 该方法主要功能:
mDispatchFrozen用于决定是否冻结事件分发工作不再往下执行;
当事件分发的时间点距离该事件加入mInboundQueue的时间超过500ms,则认为app切换过期,即isAppSwitchDue=true;
mInboundQueue不为空,则取出头部的事件,放入mPendingEvent变量;并重置ANR时间;
根据EventEntry的type类型分别处理,比如按键调用dispatchKeyLocked分发事件;再根据分发结果来决定是否进入done;
执行完成(done)的处理:
根据dropReason(默认NOT_DROPPED不处理)来决定是否丢失事件; dropInboundEventLocked
释放当前正在处理的事件(即mPendingEvent); releasePendingEventLocked
关于dispatchKeyLocked分发事件,
不会执行done过情况:
当前Event时间小于唤醒时间;
让policy有机会执行拦截操作;
调用findFocusedWindowTargetsLocked方法的返回结果是INPUT_EVENT_INJECTION_PENDING, 即targets没有处于Ready状态;
会执行done的情况:
该事件需要丢弃, 即dropReason != DROP_REASON_NOT_DROPPED;
findFocusedWindowTargetsLocked的返回结果不是INPUT_EVENT_INJECTION_PENDING(没有正在处理的事件);
接下来以按键为例来展开说明, 则进入dispatchKeyLocked.
*/
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
// 当前时间
nsecs_t currentTime = now();
// Reset the key repeat timer whenever normal dispatch is suspended while the
// device is in a non-interactive state. This is to ensure that we abort a key
// repeat if the device is just coming out of sleep.
// 默认值为false
if (!mDispatchEnabled) {
// 重置操作
resetKeyRepeatLocked();
}
// If dispatching is frozen, do not process timeouts or try to deliver any new events.
// 默认值为false
if (mDispatchFrozen) {
#if DEBUG_FOCUS
ALOGD("Dispatch frozen. Waiting some more.");
#endif
// 当分发被冻结,则不再处理超时和分发事件的工作,直接返回
return;
}
// 优化app切换延迟,当切换超时,则抢占分发,丢弃其他所有即将要处理的事件。
bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
if (mAppSwitchDueTime < *nextWakeupTime) {
*nextWakeupTime = mAppSwitchDueTime;
}
// If we don't already have a pending event, go grab one.
if (! mPendingEvent) {
if (mInboundQueue.isEmpty()) {
if (isAppSwitchDue) {
resetPendingAppSwitchLocked(false);
isAppSwitchDue = false;
}
// Synthesize a key repeat if appropriate.
if (mKeyRepeatState.lastKeyEntry) {
if (currentTime >= mKeyRepeatState.nextRepeatTime) {
mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
} else {
if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
*nextWakeupTime = mKeyRepeatState.nextRepeatTime;
}
}
}
if (!mPendingEvent) {
// 没有事件需要处理,则直接返回
return;
}
} else {
// 从mInboundQueue取出头部的事件
mPendingEvent = mInboundQueue.dequeueAtHead();
traceInboundQueueLengthLocked();
}
if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
pokeUserActivityLocked(mPendingEvent);
}
// 重置ANR信息
resetANRTimeoutsLocked();
}
ALOG_ASSERT(mPendingEvent != NULL);
bool done = false;
DropReason dropReason = DROP_REASON_NOT_DROPPED;
if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
dropReason = DROP_REASON_POLICY;
} else if (!mDispatchEnabled) {
dropReason = DROP_REASON_DISABLED;
}
if (mNextUnblockedEvent == mPendingEvent) {
mNextUnblockedEvent = NULL;
}
switch (mPendingEvent->type) {
case EventEntry::TYPE_CONFIGURATION_CHANGED: {
ConfigurationChangedEntry* typedEntry =
static_cast(mPendingEvent);
done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
break;
}
case EventEntry::TYPE_DEVICE_RESET: {
DeviceResetEntry* typedEntry =
static_cast(mPendingEvent);
done = dispatchDeviceResetLocked(currentTime, typedEntry);
dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped
break;
}
case EventEntry::TYPE_KEY: {
KeyEntry* typedEntry = static_cast(mPendingEvent);
if (isAppSwitchDue) {
if (isAppSwitchKeyEventLocked(typedEntry)) {
resetPendingAppSwitchLocked(true);
isAppSwitchDue = false;
} else if (dropReason == DROP_REASON_NOT_DROPPED) {
dropReason = DROP_REASON_APP_SWITCH;
}
}
if (dropReason == DROP_REASON_NOT_DROPPED
&& isStaleEventLocked(currentTime, typedEntry)) {
dropReason = DROP_REASON_STALE;
}
if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
dropReason = DROP_REASON_BLOCKED;
}
// 分发按键事件
done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
break;
}
case EventEntry::TYPE_MOTION: {
MotionEntry* typedEntry = static_cast(mPendingEvent);
if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
dropReason = DROP_REASON_APP_SWITCH;
}
if (dropReason == DROP_REASON_NOT_DROPPED
&& isStaleEventLocked(currentTime, typedEntry)) {
dropReason = DROP_REASON_STALE;
}
if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
dropReason = DROP_REASON_BLOCKED;
}
done = dispatchMotionLocked(currentTime, typedEntry,
&dropReason, nextWakeupTime);
break;
}
default:
ALOG_ASSERT(false);
break;
}
// 分发操作完成,则进入该分支
if (done) {
if (dropReason != DROP_REASON_NOT_DROPPED) {
dropInboundEventLocked(mPendingEvent, dropReason);
}
mLastDropReason = dropReason;
releasePendingEventLocked();
*nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
}
}
分发不同类型的事件,这边来看看按键事件的分发:
/**
* 分发按键事件
在以下场景下,有可能无法分发事件:
当前时间小于唤醒时间(nextWakeupTime)的情况;
policy需要提前拦截事件的情况;
需要drop事件的情况;
寻找聚焦窗口失败的情况;
如果成功跳过以上所有情况,则会进入执行事件分发的过程。
*/
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
// Preprocessing.
if (! entry->dispatchInProgress) {
if (entry->repeatCount == 0
&& entry->action == AKEY_EVENT_ACTION_DOWN
&& (entry->policyFlags & POLICY_FLAG_TRUSTED)
&& (!(entry->policyFlags & POLICY_FLAG_DISABLE_KEY_REPEAT))) {
if (mKeyRepeatState.lastKeyEntry
&& mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode) {
entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
resetKeyRepeatLocked();
mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
} else {
resetKeyRepeatLocked();
mKeyRepeatState.nextRepeatTime = entry->eventTime + mConfig.keyRepeatTimeout;
}
mKeyRepeatState.lastKeyEntry = entry;
entry->refCount += 1;
} else if (! entry->syntheticRepeat) {
resetKeyRepeatLocked();
}
if (entry->repeatCount == 1) {
entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
} else {
entry->flags &= ~AKEY_EVENT_FLAG_LONG_PRESS;
}
entry->dispatchInProgress = true;
logOutboundKeyDetailsLocked("dispatchKey - ", entry);
}
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) {
// case1: 当前时间小于唤醒时间,则进入等待状态。
if (currentTime < entry->interceptKeyWakeupTime) {
if (entry->interceptKeyWakeupTime < *nextWakeupTime) {
*nextWakeupTime = entry->interceptKeyWakeupTime;
}
return false; // wait until next wakeup
}
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
entry->interceptKeyWakeupTime = 0;
}
// Give the policy a chance to intercept the key.
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
// case2: 让policy有机会执行拦截操作
if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
CommandEntry* commandEntry = postCommandLocked(
& InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
if (mFocusedWindowHandle != NULL) {
commandEntry->inputWindowHandle = mFocusedWindowHandle;
}
commandEntry->keyEntry = entry;
entry->refCount += 1;
return false; // wait for the command to run
} else {
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
}
} else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
if (*dropReason == DROP_REASON_NOT_DROPPED) {
*dropReason = DROP_REASON_POLICY;
}
}
// case3: 如果需要丢弃该事件,则执行清理操作
if (*dropReason != DROP_REASON_NOT_DROPPED) {
setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
return true;
}
// Identify targets.
Vector inputTargets;
// case4: 寻找焦点
int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime);
if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
return false;
}
setInjectionResultLocked(entry, injectionResult);
if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
return true;
}
addMonitoringTargetsLocked(inputTargets);
// Dispatch the key.
// 只有injectionResult是成功,才有机会执行分发事件
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
中间经过层层调用,会到达 publishKeyEvent() 函数:
status_t InputPublisher::publishKeyEvent(...) {
if (!seq) {
return BAD_VALUE;
}
InputMessage msg;
msg.header.type = InputMessage::TYPE_KEY;
msg.body.key.seq = seq;
msg.body.key.deviceId = deviceId;
msg.body.key.source = source;
msg.body.key.action = action;
msg.body.key.flags = flags;
msg.body.key.keyCode = keyCode;
msg.body.key.scanCode = scanCode;
msg.body.key.metaState = metaState;
msg.body.key.repeatCount = repeatCount;
msg.body.key.downTime = downTime;
msg.body.key.eventTime = eventTime;
//通过InputChannel来发送消息
return mChannel->sendMessage(&msg);
}
最终调用 InputChannel 发送事件消息。
4. InputChannel
代码位于 InputTransport.cpp:
status_t InputChannel::sendMessage(const InputMessage* msg) {
size_t msgLength = msg->size();
ssize_t nWrite;
do {
nWrite = ::send(mFd, msg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
} while (nWrite == -1 && errno == EINTR);
if (nWrite < 0) {
int error = errno;
#if DEBUG_CHANNEL_MESSAGES
ALOGD("channel '%s' ~ error sending message of type %d, errno=%d", mName.string(),
msg->header.type, error);
#endif
if (error == EAGAIN || error == EWOULDBLOCK) {
return WOULD_BLOCK;
}
if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED || error == ECONNRESET) {
return DEAD_OBJECT;
}
return -error;
}
if (size_t(nWrite) != msgLength) {
#if DEBUG_CHANNEL_MESSAGES
ALOGD("channel '%s' ~ error sending message type %d, send was incomplete",
mName.string(), msg->header.type);
#endif
return DEAD_OBJECT;
}
#if DEBUG_CHANNEL_MESSAGES
ALOGD("channel '%s' ~ sent message of type %d", mName.string(), msg->header.type);
#endif
return OK;
}
最后会通过 socket 发送。
5. 客户端接收事件
前面 JNI 层最后调用了 InputChannel 的 sendMessge(),最后是通过 socket 发送的,那我们再来看看客户端的接收。
JNI 层发通过 socket 发信息过来,就会用 epoll 机制唤醒线程,并且处理其事件,代码在 android_view_InputEventReceiver.cpp:
void NativeInputEventReceiver::setFdEvents(int events) {
if (mFdEvents != events) {
mFdEvents = events;
int fd = mInputConsumer.getChannel()->getFd();
if (events) {
mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL);
} else {
mMessageQueue->getLooper()->removeFd(fd);
}
}
}
int Looper::addFd(int fd, int ident, int events, const sp& callback, void* data) {
............
int epollEvents = 0;
if (events & EVENT_INPUT) epollEvents |= EPOLLIN;
if (events & EVENT_OUTPUT) epollEvents |= EPOLLOUT;
{ // acquire lock
AutoMutex _l(mLock);
Request request;
request.fd = fd;
request.ident = ident;
request.callback = callback;
request.data = data;
struct epoll_event eventItem;
memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
eventItem.events = epollEvents;
eventItem.data.fd = fd;
ssize_t requestIndex = mRequests.indexOfKey(fd);
if (requestIndex < 0) {
int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, & eventItem);
if (epollResult < 0) {
ALOGE("Error adding epoll events for fd %d, errno=%d", fd, errno);
return -1;
}
mRequests.add(fd, request);
} else {
int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_MOD, fd, & eventItem);//将当前fd加入到epoll中
if (epollResult < 0) {
ALOGE("Error modifying epoll events for fd %d, errno=%d", fd, errno);
return -1;
}
mRequests.replaceValueAt(requestIndex, request);
}
} // release lock
return 1;
}
addFd() 函数将参数 fd 加入 epoll,然后在 mRequests 列表中加入一个 Request 对象,这个对象的 events 成员带有 EPOLLIN 标记,然后它的 callBack 成员变量指向 NativeInputEventReceiver。以前分析 looper 机制的时候知道,线程处理消息循环会调用looper 的 poolOnce() 函数,而这个函数又会调用 pollInner 函数:
int Looper::pollInner(int timeoutMillis) {
..........
struct epoll_event eventItems[EPOLL_MAX_EVENTS];
int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);//事件到来
..........
for (int i = 0; i < eventCount; i++) {
int fd = eventItems[i].data.fd;
uint32_t epollEvents = eventItems[i].events;
if (fd == mWakeReadPipeFd) {//管道事件,就是调用wakeup函数的
if (epollEvents & EPOLLIN) {
awoken();
} else {
ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents);
}
} else {//其它事件,就包括InputChannel的socket
ssize_t requestIndex = mRequests.indexOfKey(fd);//获取request的index
if (requestIndex >= 0) {
int events = 0;
if (epollEvents & EPOLLIN) events |= EVENT_INPUT;
if (epollEvents & EPOLLOUT) events |= EVENT_OUTPUT;
if (epollEvents & EPOLLERR) events |= EVENT_ERROR;
if (epollEvents & EPOLLHUP) events |= EVENT_HANGUP;
pushResponse(events, mRequests.valueAt(requestIndex));//加入mResponses列表
} else {
ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
"no longer registered.", epollEvents, fd);
}
}
}
............
// Invoke all response callbacks.处理所有的mResponses元素
for (size_t i = 0; i < mResponses.size(); i++) {
Response& response = mResponses.editItemAt(i);
if (response.request.ident == POLL_CALLBACK) {
int fd = response.request.fd;
int events = response.events;
void* data = response.request.data;
int callbackResult = response.request.callback->handleEvent(fd, events, data);//调用回调事件
if (callbackResult == 0) {
removeFd(fd);
}
// Clear the callback reference in the response structure promptly because we
// will not clear the response vector itself until the next poll.
response.request.callback.clear();
result = POLL_CALLBACK;
}
}
return result;
}
把客户端 socket 的 fd 加入客户端线程消息机制中的 epoll,当有事件过来,最总会调用回调。也就会调用NativeInputEventReceiver::handleEvent() 函数:
int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
..........
if (events & ALOOPER_EVENT_INPUT) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
status_t status = consumeEvents(env, false /*consumeBatches*/, -1, NULL);
mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
return status == OK || status == NO_MEMORY ? 1 : 0;
}
..........
}
consumeEvents() 函数如下,先读取 socket 的信息然后反调 Java 层 WindowInputEventReceiver 的 dispatchInputEvent() 方法,这是父类的方法,然后再到子类 WindowInputEventReceiver 的 onInputEvent() 方法:
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
......
for (;;) {
uint32_t seq;
InputEvent* inputEvent;
status_t status = mInputConsumer.consume(&mInputEventFactory,//读取InputChannel的socket信息
consumeBatches, frameTime, &seq, &inputEvent);
........
if (inputEventObj) {//反调java层的WindowInputEventReceiver的dispatchInputEvent方法
env->CallVoidMethod(receiverObj.get(),
gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
.....
}
这就到了 ViewRootImpl 的内部类 WindowInputEventReceiver.onInputEvent():
final class WindowInputEventReceiver extends InputEventReceiver {
public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
}
@Override
public void onInputEvent(InputEvent event) {
enqueueInputEvent(event, this, 0, true);
}
@Override
public void onBatchedInputEventPending() {
if (mUnbufferedInputDispatch) {
super.onBatchedInputEventPending();
} else {
scheduleConsumeBatchedInput();
}
}
@Override
public void dispose() {
unscheduleConsumeBatchedInput();
super.dispose();
}
}
void enqueueInputEvent(InputEvent event,
InputEventReceiver receiver, int flags, boolean processImmediately) {
adjustInputEventForCompatibility(event);
QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
QueuedInputEvent last = mPendingInputEventTail;
if (last == null) {
mPendingInputEventHead = q;
mPendingInputEventTail = q;
} else {
last.mNext = q;
mPendingInputEventTail = q;
}
mPendingInputEventCount += 1;
Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
mPendingInputEventCount);
if (processImmediately) {
// 收到InputDispatcher的事件分发,开始处理分发事件
doProcessInputEvents();
} else {
scheduleProcessInputEvents();
}
}
/**
* InputDispatcher线程调用InputPublisher的publishKeyEvent向UI主线程发送input事件;
*
* UI主线程接收到该事件后,调用InputConsumer的consumeEvents来处理该事件, 一路执行到ViewRootImpl.deliverInputEvent()方法;
*
* UI主线程经过一系列的InputStage来处理, 当事件分发完成,则会执行finishInputEvent()方法.
* 再进一步调用InputConsumer::sendFinishedSignal 告知InputDispatcher线程该时事件已处理完成.
*
* InputDispatcher线程收到该事件后, 执行InputDispatcher::handleReceiveCallback();
* 最终会调用doDispatchCycleFinishedLockedInterruptible()方法 ,将dispatchEntry事件从等待队列(waitQueue)中移除.
*/
void doProcessInputEvents() {
// Deliver all pending input events in the queue.
while (mPendingInputEventHead != null) {
QueuedInputEvent q = mPendingInputEventHead;
mPendingInputEventHead = q.mNext;
if (mPendingInputEventHead == null) {
mPendingInputEventTail = null;
}
q.mNext = null;
mPendingInputEventCount -= 1;
Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
mPendingInputEventCount);
long eventTime = q.mEvent.getEventTimeNano();
long oldestEventTime = eventTime;
if (q.mEvent instanceof MotionEvent) {
MotionEvent me = (MotionEvent)q.mEvent;
if (me.getHistorySize() > 0) {
oldestEventTime = me.getHistoricalEventTimeNano(0);
}
}
mChoreographer.mFrameInfo.updateInputEventTime(eventTime, oldestEventTime);
// 分发事件
deliverInputEvent(q);
}
// We are done processing all input events that we can process right now
// so we can clear the pending flag immediately.
if (mProcessInputEventsScheduled) {
mProcessInputEventsScheduled = false;
mHandler.removeMessages(MSG_PROCESS_INPUT_EVENTS);
}
}
/**
* 经过一系列的InputStage调用, 最终会分发到真正需要处理该事件的窗口. 当处理完后会调用finishInputEvent()
* @param q
*/
private void deliverInputEvent(QueuedInputEvent q) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
q.mEvent.getSequenceNumber());
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
}
InputStage stage;
if (q.shouldSendToSynthesizer()) {
stage = mSyntheticInputStage;
} else {
stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
}
if (stage != null) {
stage.deliver(q);
} else {
finishInputEvent(q);
}
}
经过一系列的 InputStage 调用,最终会分发到真正需要处理该事件的窗口,当处理完后会调用 finishInputEvent()。