input事件分发的过程
我们都知道事件一般会传递到 activity 根布局 view 的 dispatchTouchEvent 方法,那么事件的源头在哪里?
IMS的启动过程
SystemServer.java的main方法
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
try {
//启动引导服务
startBootstrapServices();
//启动核心服务
startCoreServices();
//启动其他服务
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
}
// For debug builds, log event loop stalls to dropbox for analysis.
if (StrictMode.conditionallyEnableDebugLogging()) {
Slog.i(TAG, "Enabled StrictMode for system server main thread.");
}
// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
- startBootstrapServices主要启动ActivityManagerService、PowerManagerServer、PackageManagerServer
- startCoreServices启动BatteryService、UsageStatsService和WebViewUpdateService
- startOtherServices启动CameraService(摄像头相关服务)、AlarmManagerService(定时器管理服务)、InputManagerService(管理输入事件)、WindowManagerService(窗口管理服务)、LocationManagerService(定位管理服务)
startOtherServices源码分析
private void startOtherServices() {
//创建IMS
inputManager = new InputManagerService(context);
Slog.i(TAG, "Window Manager");
//WMS的main方法,第二个参数就是IMS
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
mActivityManagerService.setWindowManager(wm);
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
inputManager.start();
}
InputManagerService的构造函数
public InputManagerService(Context context) {
this.mContext = context;
//创建一个InputManagerHandler
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());
LocalServices.addService(InputManagerInternal.class, new LocalService());
}
com_android_server_input_InputManagerService.cpp的nativeInit方法
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
//创建一个NativeInputManager
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();;
//创建EventHub并传给InputManager
sp<EventHub> eventHub = new EventHub();
mInputManager = new InputManager(eventHub, this, this);
}
namespace android {
InputManager::InputManager(
const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
mDispatcher = new InputDispatcher(dispatcherPolicy);
mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
initialize();
}
void InputManager::initialize() {
mReaderThread = new InputReaderThread(mReader);
mDispatcherThread = new InputDispatcherThread(mDispatcher);
}
- EventHub通过Linux内核的INotify与Epoll机制监听设备节点
- 通过EventHub的getEvent函数读取设备节点的增删事件和原始输入事件
InputManagerService.start源码分析
public void start() {
nativeStart(mPtr);
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
}
watchDog用于定时检测系统关键服务(AMS和WMS)是否可能产生死锁
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
//获取NativeInputManager
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
// im->getInputManager()实际是InputManager
status_t result = im->getInputManager()->start();
}
status_t InputManager::start() {
//运行InputDispatchThread
status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
//运行InputReaderThread
result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
return OK;
}
1、InputDispatchThread的启动过程分析
InputDispatch.cpp
bool InputDispatcherThread::threadLoop() {
mDispatcher->dispatchOnce();
return true;
}
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
AutoMutex _l(mLock);
mDispatcherIsAliveCondition.broadcast();
//检测是否有等待的命令
if (!haveCommandsLocked()) {
//没有等待的命令,将输入事件分发给合适的window
dispatchOnceInnerLocked(&nextWakeupTime);
}
if (runCommandsLockedInterruptible()) {
nextWakeupTime = LONG_LONG_MIN;
}
} // release lock
//获取当前时间
nsecs_t currentTime = now();
//获取睡眠的时间
int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
//InputDispatchThread进入睡眠状态
mLooper->pollOnce(timeoutMillis);
}
- InputReader则会唤起InputDispatchThread
dispatchOnceInnerLocked函数处理进行事件分发
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
nsecs_t currentTime = now();
//1、判断是否被冻结,如果被冻结,则直接return
if (mDispatchFrozen) {
#if DEBUG_FOCUS
ALOGD("Dispatch frozen. Waiting some more.");
#endif
return;
}
//2、isAppSwitchDue为true则说明没有及时响应Home键等操作
bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
if (mAppSwitchDueTime < *nextWakeupTime) {
*nextWakeupTime = mAppSwitchDueTime;
}
// 3、如果还没有待分发的时间,去mInboundQueue中取出一个事件
if (! mPendingEvent) {
//如果mInboundQueue为空,并且没有待分发的事件,就return
if (mInboundQueue.isEmpty()) {
if (!mPendingEvent) {
return;
}
} else {
//如果不为空,则取出队头的EventEntry赋值给mPendingEvent
mPendingEvent = mInboundQueue.dequeueAtHead();
traceInboundQueueLengthLocked();
}
// Poke user activity for this event.
if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
pokeUserActivityLocked(mPendingEvent);
}
// Get ready to dispatch the event.
resetANRTimeoutsLocked();
}
//事件丢弃的原因
DropReason dropReason = DROP_REASON_NOT_DROPPED;
//4、根据不同的type做分区处理
switch (mPendingEvent->type) {
case EventEntry::TYPE_MOTION: {
MotionEntry* typedEntry = static_cast<MotionEntry*>(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;
}
//5、这个事件寻找合适的窗口
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();
//让InputDispatcher快速处理下一个请求
*nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
}
}
dispatchMotionLocked分发到窗口
bool InputDispatcher::dispatchMotionLocked(
nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
if (! entry->dispatchInProgress) {
//当前进入分发的过程
entry->dispatchInProgress = true;
logOutboundMotionDetailsLocked("dispatchMotion - ", entry);
}
//如果事件需要丢弃,则返回true
if (*dropReason != DROP_REASON_NOT_DROPPED) {
....
return true;
}
bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
//目标窗口列表存储在inputTargets
Vector<InputTarget> inputTargets;
bool conflictingPointerActions = false;
int32_t injectionResult;
if (isPointerEvent) {
//处理点击形式的事件,比如触摸屏幕
injectionResult = findTouchedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime, &conflictingPointerActions);
} else {
//处理非触摸形式的事件,比如轨迹球
injectionResult = findFocusedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime);
}
//输入事件被挂起,说明找到了窗口并且窗口无响应
if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
return false;
}
setInjectionResultLocked(entry, injectionResult);
//输入事件分发成功,说明没有找到合适窗口
if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
if (injectionResult != INPUT_EVENT_INJECTION_PERMISSION_DENIED) {
CancelationOptions::Mode mode(isPointerEvent ?
CancelationOptions::CANCEL_POINTER_EVENTS :
CancelationOptions::CANCEL_NON_POINTER_EVENTS);
CancelationOptions options(mode, "input event injection failed");
synthesizeCancelationEventsForMonitorsLocked(options);
}
return true;
}
// TODO: support sending secondary display events to input monitors
if (isMainDisplay(entry->displayId)) {
//分发目标添加到inputTargets列表中
addMonitoringTargetsLocked(inputTargets);
}
// Dispatch the motion.
if (conflictingPointerActions) {
CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
"conflicting pointer actions");
synthesizeCancelationEventsForAllConnectionsLocked(options);
}
//将事件分发给inputTargets列表中的目标
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
findTouchedWindowTargetsLocked点击
int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
const MotionEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime,
bool* outConflictingPointerActions) {
if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
// 遍历所有的 mWindowHandles
size_t numWindows = mWindowHandles.size();
for (size_t i = 0; i < numWindows; i++) {
sp<InputWindowHandle> windowHandle = mWindowHandles.itemAt(i);
const InputWindowInfo* windowInfo = windowHandle->getInfo();
if (windowInfo->displayId != displayId) {
//如果displayId不匹配,开始下一次循环
continue; // wrong display
}
int32_t flags = windowInfo->layoutParamsFlags;
if (windowInfo->visible) {
// 可见,并且 flags 属性不是 InputWindowInfo::FLAG_NOT_TOUCHABLE
if (! (flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE
| InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;
// 点击的是不是当前 window 的覆盖
if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
// found touched window, exit window loop
// 找到了当前触摸的 window
newTouchedWindowHandle = windowHandle;
break;
}
}
}
}
mTempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
} else {
...
}
// 再把 mTempTouchState 收集到的 windows 添加到 inputTargets 中
for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);
addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
touchedWindow.pointerIds, inputTargets);
}
...
return injectionResult;
}
dispatchEventLocked源码分析
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {
#if DEBUG_DISPATCH_CYCLE
ALOGD("dispatchEventToCurrentInputTargets");
#endif
ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
pokeUserActivityLocked(eventEntry);
for (size_t i = 0; i < inputTargets.size(); i++) {
const InputTarget& inputTarget = inputTargets.itemAt(i);
//遍历inputTargets列表
ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
if (connectionIndex >= 0) {
//获取保存在mConnectionsByFd容器中的Connection
sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
} else {
#if DEBUG_FOCUS
ALOGD("Dropping event delivery to target with channel '%s' because it "
"is no longer registered with the input dispatcher.",
inputTarget.inputChannel->getName().string());
#endif
}
}
}
2、InputReaderThread的启动过程
InputReader.cpp
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}
void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
Vector<InputDeviceInfo> inputDevices;
{
//通过eventHub的getEvents函数获取事件信息存在mEventBuffer中.事件信息主要有两种,一种是设备节点的增删事件(设备事件),一种是原始输入事件
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{
if (count) {
//如果有事件信息,调用processEventsLocked函数对事件进行加工处理
processEventsLocked(mEventBuffer, count);
}
}
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
//处理deviceId所对应的设备的原始输入事件
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;
}
}
- inputReader的processEventsLocked函数首先遍历所有事件,这些事件用RawEvent对象表示
- 事件分为原始事件和设备事件
- 设备事件分为DEVICE_ADDED、DEVICE_ADDED、FINISHED_DEVICE_SCAN,生成时机是EventHub的getEvent函数中生成得
- 如果是DEVICE_ADD事件(设备添加事件),InputReader会新建InputDevice对象,用来存储设备信息
processEventsForDeviceLocked源码分析
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
const RawEvent* rawEvents, size_t count) {
//根据deviceId获取deviceIndex
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
//deviceIndex根据deviceIndex获取InputDevice
InputDevice* device = mDevices.valueAt(deviceIndex);
//调用InputDevice的process
device->process(rawEvents, count);
}
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
size_t numMappers = mMappers.size();
//遍历InputDevice所有事件
for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
#if DEBUG_RAW_EVENTS
#endif
//mDropUntilNextSync默认是false,如果设备设备事件缓存区溢出则为true
if (mDropUntilNextSync) {
#endif
} else {
//遍历所有的事件
for (size_t i = 0; i < numMappers; i++) {
//加工原始数据的是InputMapper对象
InputMapper* mapper = mMappers[i];
mapper->process(rawEvent);
}
}
}
}
这里以KeyboardInputMapper为例
void KeyboardInputMapper::process(const RawEvent* rawEvent) {
switch (rawEvent->type) {
case EV_KEY: {//按键类型
int32_t scanCode = rawEvent->code;
int32_t usageCode = mCurrentHidUsage;
mCurrentHidUsage = 0;
if (isKeyboardOrGamepadKey(scanCode)) {
processKey(rawEvent->when, rawEvent->value != 0, scanCode, usageCode);
}
break;
}
}
}
void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode,
int32_t usageCode) {
//封装参数
NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
getListener()->notifyKey(&args);
}
InputListenerInterface* InputReader::ContextImpl::getListener() {
return mReader->mQueuedListener.get();
}
InputDispatcher继承了InputDispatcherInterface,也就是说实际调用的是InputDispatch的notifyKey方法
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
bool needWake;
{ // acquire lock
mLock.lock();
if (shouldSendKeyToInputFilterLocked(args)) {
mLock.unlock();
policyFlags |= POLICY_FLAG_FILTERED;
if (!mPolicy->filterInputEvent(&event, policyFlags)) {
return; // event was consumed by the filter
}
mLock.lock();
}
int32_t repeatCount = 0;
//分局NotifyKeyArgs封装成KeyEntry独享
KeyEntry* newEntry = new KeyEntry(args->eventTime,
args->deviceId, args->source, policyFlags,
args->action, flags, keyCode, args->scanCode,
metaState, repeatCount, args->downTime);
//根据newEntry判断是否需要唤醒
needWake = enqueueInboundEventLocked(newEntry);
mLock.unlock();
} // release lock
if (needWake) {
//Looper进行唤醒操作
mLooper->wake();
}
}
- IMS启动了InputDispatchThread和InputReadThread,分别用来运行InputDispatcher和InputReader
- InputDispatcher的dispatchOnceInnerLocked函数用来将事件分发给合适的window,inputDispatcher没有输入事件处理会进入睡眠状态,等待InputReader通知唤醒
- InputReader通过EventHub的getEvents函数获取事件信息,如果是原始输入事件,就将这些原始输入事件交由不同的InputMapper来处理,最终交由InputDispatcher来进行分发。
-
InputDispatcher的notifyKey函数中会根据按键数据来判断InputDispatcher是否要被唤醒,InputDispatcher被唤醒后,会重新调用dispatchOnceInnerLocked函数将输入事件分发给合适的Window。
image.png
参考文章
Android输入系统——http://liuwangshu.cn/framework/ims/2-inputevent.html
网友评论