Andriod事件分发的事件从何而来(三)
我们已经知道了事件分发是从InputDispatcher->InputManagerService->WMS->ViewRootImpl。那就再问一步InputDispatcher的事件来源是什么。
首先要知道InputDispatcher的事件已经和app没关系了,这时候肯定是系统起来的时候就由InputManagerService来获取了并且分发给对应的app消费。所以看InputManagerService的创建和启动。
//frameworks/base/services/java/com/android/server/SystemServer.java
inputManager = new InputManagerService(context);
inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
inputManager.start();
在SystemServer会启动各种系统服务,InputManagerService当然也在其中。
//frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
public InputManagerService(Context context) {
this(new Injector(context, DisplayThread.get().getLooper()));
}
@VisibleForTesting
InputManagerService(Injector injector) {
// The static association map is accessed by both java and native code, so it must be
// initialized before initializing the native service.
mStaticAssociations = loadStaticInputPortAssociations();
mContext = injector.getContext();
mHandler = new InputManagerHandler(injector.getLooper());
mNative = injector.getNativeService(this);
mUseDevInputEventForAudioJack =
mContext.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
+ mUseDevInputEventForAudioJack);
String doubleTouchGestureEnablePath = mContext.getResources().getString(
R.string.config_doubleTouchGestureEnableFile);
mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
new File(doubleTouchGestureEnablePath);
injector.registerLocalService(new LocalService());
}
创建已经很熟悉了,主要是创建了一个NativeInputManagerService.NativeImpl对象,封装了native方法。根据配置确定是否支持音频设备插入事件,是否允许双手操作等,然后通过injector注册当前的InputManagerService到LocalServices中。接下来就看start方法。
public void start() {
Slog.i(TAG, "Starting input manager");
mNative.start();
// Add ourselves to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
//后面都是监听各种配置
registerPointerSpeedSettingObserver();
registerShowTouchesSettingObserver();
registerAccessibilityLargePointerSettingObserver();
registerLongPressTimeoutObserver();
registerMaximumObscuringOpacityForTouchSettingObserver();
registerBlockUntrustedTouchesModeSettingObserver();
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
updateAccessibilityLargePointerFromSettings();
updateDeepPressStatusFromSettings("user switched");
}
}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
updateAccessibilityLargePointerFromSettings();
updateDeepPressStatusFromSettings("just booted");
updateMaximumObscuringOpacityForTouchFromSettings();
updateBlockUntrustedTouchesModeFromSettings();
}
主要就是mNative.start()正式通过native启动服务。剩下都是监听一些配置和注册配置修改的广播。通过com_android_server_input_InputManagerService中的JNINativeMethod中 {"start", "()V", (void*)nativeStart}
可以知道start在com_android_server_input_InputManagerService
//frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static void nativeStart(JNIEnv* env, jobject nativeImplObj) {
NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
status_t result = im->getInputManager()->start();
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
}
这里很熟悉了im就是InputManager
status_t InputManager::start() {
status_t result = mDispatcher->start();
if (result) {
ALOGE("Could not start InputDispatcher thread due to error %d.", result);
return result;
}
result = mReader->start();
if (result) {
ALOGE("Could not start InputReader due to error %d.", result);
mDispatcher->stop();
return result;
}
return OK;
}
启动了mDispatcher和mReader的start,也就是在InputManager的构造函数中初始化的两个变量。先看mDispatcher的start。
InputDispatcher::start
//frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
status_t InputDispatcher::start() {
if (mThread) {
return ALREADY_EXISTS;
}
mThread = std::make_unique<InputThread>(
"InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });
return OK;
}
创建了一个InputThread
//frameworks/native/services/inputflinger/InputThread.cpp
InputThread::InputThread(std::string name, std::function<void()> loop, std::function<void()> wake)
: mName(name), mThreadWake(wake) {
mThread = new InputThreadImpl(loop);
mThread->run(mName.c_str(), ANDROID_PRIORITY_URGENT_DISPLAY);
}
class InputThreadImpl : public Thread {
public:
explicit InputThreadImpl(std::function<void()> loop)
: Thread(/* canCallJava */ true), mThreadLoop(loop) {}
~InputThreadImpl() {}
private:
std::function<void()> mThreadLoop;
bool threadLoop() override {
mThreadLoop();
return true;
}
};
InputThread创建了一个InputThreadImpl,看InputThreadImpl发现是一个Thread也就是一个线程,所以InputDispatcher::start就是启动了一个名字叫InputDispatcher的线程,执行内容是dispatchOnce。
//frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
std::scoped_lock _l(mLock);
mDispatcherIsAlive.notify_all();
// Run a dispatch loop if there are no pending commands.
// The dispatch loop might enqueue commands to run afterwards.
if (!haveCommandsLocked()) {//先判断有没有Commands,没有的话执行dispatchOnceInnerLocked
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 (runCommandsLockedInterruptable()) {//如果有Commands就执行
nextWakeupTime = LONG_LONG_MIN;
}
// If we are still waiting for ack on some events,
// we might have to wake up earlier to check if an app is anr'ing.
//判断下一次唤醒时间
const nsecs_t nextAnrCheck = processAnrsLocked();
nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);
// We are about to enter an infinitely long sleep, because we have no commands or
// pending or queued events
if (nextWakeupTime == LONG_LONG_MAX) {
mDispatcherEnteredIdle.notify_all();
}
} // 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);
//利用mLooper阻塞当前线程timeoutMillis时间
mLooper->pollOnce(timeoutMillis);
}
dispatchOnce就是分发一次,有两个重要的函数
- 首先通过haveCommandsLocked判断有没有Commands需要执行,没有的话dispatchOnceInnerLocked分发一次事件
- dispatchOnceInnerLocked结束之后执行runCommandsLockedInterruptable
这里只看下常见的KEY事件
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
nsecs_t currentTime = now();//anr计时的起点
......
if (!mPendingEvent) {
if (mInboundQueue.empty()) {
if (isAppSwitchDue) {//切换app相关
// The inbound queue is empty so the app switch key we were waiting
// for will never arrive. Stop waiting for it.
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;
}
}
}
// Nothing to do if there is no pending event.
if (!mPendingEvent) {//如果没有事件就返回了
return;
}
} else {
// Inbound queue has at least one entry.
mPendingEvent = mInboundQueue.front();//把mInboundQueue第一个事件拿到
mInboundQueue.pop_front();
traceInboundQueueLengthLocked();
}
}
switch (mPendingEvent->type) {
.........
case EventEntry::Type::KEY: {
std::shared_ptr<KeyEntry> keyEntry = std::static_pointer_cast<KeyEntry>(mPendingEvent);
......//中间有各种判断丢弃这次事件
//分发事件
done = dispatchKeyLocked(currentTime, keyEntry, &dropReason, nextWakeupTime);
break;
}
........
}
//分发结束
if (done) {
if (dropReason != DropReason::NOT_DROPPED) {
dropInboundEventLocked(*mPendingEvent, dropReason);
}
mLastDropReason = dropReason;
releasePendingEventLocked();
*nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
}
}
这个方法是InputDispatcher真正执行分发的函数。从mInboundQueue中拿到了event,通过一系列判断之后key类型的event通过dispatchKeyLocked分发。
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<KeyEntry> entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
.......
// Identify targets.
std::vector<InputTarget> inputTargets;
//在findFocusedWindowTargetsLocked中会处理anr的判断,
InputEventInjectionResult injectionResult =
findFocusedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime);
.....
// Dispatch the key.
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
这也是通过各种判断是否需要执行这个event,最后要执行就获取要分发的target,调用dispatchEventLocked的重载方法分发。
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
std::shared_ptr<EventEntry> eventEntry,
const std::vector<InputTarget>& inputTargets) {
ATRACE_CALL();
if (DEBUG_DISPATCH_CYCLE) {
ALOGD("dispatchEventToCurrentInputTargets");
}
updateInteractionTokensLocked(*eventEntry, inputTargets);
ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
pokeUserActivityLocked(*eventEntry);
for (const InputTarget& inputTarget : inputTargets) {
sp<Connection> connection =
getConnectionLocked(inputTarget.inputChannel->getConnectionToken());
if (connection != nullptr) {
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().c_str());
}
}
}
}
这里就找到了InputDispatcher和WMS创建的连接connection,然后分发给WMS。这样一次事件分发就结束了。从获取事件的过程可以知道,事件是从mInboundQueue中获取的,现在就需要知道是谁往里放的。
InputReader::start
//frameworks/native/services/inputflinger/reader/InputReader.cpp
status_t InputReader::start() {
if (mThread) {
return ALREADY_EXISTS;
}
mThread = std::make_unique<InputThread>(
"InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
return OK;
}
和InputDispatcher一样,创建了一个名字叫InputReader的线程,然后调用loopOnce
void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
std::vector<InputDeviceInfo> inputDevices;
//从mEventHub读取mEventBuffer
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{ // acquire lock
std::scoped_lock _l(mLock);
mReaderIsAliveCondition.notify_all();
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);
}
mNextTimeout = LLONG_MAX;
timeoutExpiredLocked(now);
}
}
if (oldGeneration != mGeneration) {
inputDevicesChanged = true;
inputDevices = getInputDevicesLocked();
}
} // release lock
// Send out a message that the describes the changed input devices.
if (inputDevicesChanged) {
mPolicy->notifyInputDevicesChanged(inputDevices);
}
//添加到mInboundQueue
mQueuedListener.flush();
}
loopOnce中做了下面几件事
- 从mEventHub获取事件
- processEventsLocked中处理事件
- mQueuedListener交给InputDispatcher
mEventHub后面再讲,先看看拿到mEventBuffer之后是怎么处理的
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);
}
//处理事件
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;
}
}
这个函数将event分为两类,一个是设备硬件的变化,一个是数据。处理数据事件交给了processEventsForDeviceLocked;
void InputReader::processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents,
size_t count) {
auto deviceIt = mDevices.find(eventHubId);
if (deviceIt == mDevices.end()) {
ALOGW("Discarding event for unknown eventHubId %d.", eventHubId);
return;
}
std::shared_ptr<InputDevice>& device = deviceIt->second;
if (device->isIgnored()) {
// ALOGD("Discarding event for ignored deviceId %d.", deviceId);
return;
}
device->process(rawEvents, count);
}
根据eventHubId获取是哪个设备的事件,调用device->process来处理。这里也用常见的按键设备。
//frameworks/native/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
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->readTime, rawEvent->value != 0, scanCode,
usageCode);
}
break;
}
case EV_MSC: {
if (rawEvent->code == MSC_SCAN) {
mCurrentHidUsage = rawEvent->value;
}
break;
}
case EV_SYN: {
if (rawEvent->code == SYN_REPORT) {
mCurrentHidUsage = 0;
}
}
}
}
在获得key之后通过processKey来处理
void KeyboardInputMapper::processKey(nsecs_t when, nsecs_t readTime, bool down, int32_t scanCode,
int32_t usageCode) {
int32_t keyCode;
int32_t keyMetaState;
uint32_t policyFlags;
if (getDeviceContext().mapKey(scanCode, usageCode, mMetaState, &keyCode, &keyMetaState,
&policyFlags)) {//将kode转换成keycode
keyCode = AKEYCODE_UNKNOWN;
keyMetaState = mMetaState;
policyFlags = 0;
}
if (down) {//记录按下了什么键
// Rotate key codes according to orientation if needed.
if (mParameters.orientationAware) {
keyCode = rotateKeyCode(keyCode, getOrientation());
}
// Add key down.
ssize_t keyDownIndex = findKeyDown(scanCode);
if (keyDownIndex >= 0) {
// key repeat, be sure to use same keycode as before in case of rotation
keyCode = mKeyDowns[keyDownIndex].keyCode;
} else {
// key down
if ((policyFlags & POLICY_FLAG_VIRTUAL) &&
getContext()->shouldDropVirtualKey(when, keyCode, scanCode)) {
return;
}
if (policyFlags & POLICY_FLAG_GESTURE) {
getDeviceContext().cancelTouch(when, readTime);
}
KeyDown keyDown;
keyDown.keyCode = keyCode;
keyDown.scanCode = scanCode;
mKeyDowns.push_back(keyDown);
}
mDownTime = when;
} else {//抬起了什么按键就去除
// Remove key down.
ssize_t keyDownIndex = findKeyDown(scanCode);
if (keyDownIndex >= 0) {
// key up, be sure to use same keycode as before in case of rotation
keyCode = mKeyDowns[keyDownIndex].keyCode;
mKeyDowns.erase(mKeyDowns.begin() + (size_t)keyDownIndex);
}
}
......
NotifyKeyArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), mSource,
getDisplayId(), policyFlags,
down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
getListener().notifyKey(&args);
}
processKey中就是具体的处理按键了,首先将硬件传过来的code转成应用端常见的keycode,然后记录是按下还是抬起。最后通过getListener().notifyKey(&args)添加到队列。先看看getListener的流程
InputListenerInterface& InputReader::ContextImpl::getListener() {
return mReader->mQueuedListener;
}
查看定义 QueuedInputListener mQueuedListener;
是一个QueuedInputListener,看下它的notifyKey
void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
traceEvent(__func__, args->id);
mArgsQueue.emplace_back(std::make_unique<NotifyKeyArgs>(*args));
}
将刚才的事件都添加到了mArgsQueue中。还记得loopOnce的最后吗。 mQueuedListener.flush();
void QueuedInputListener::flush() {
for (const std::unique_ptr<NotifyArgs>& args : mArgsQueue) {
args->notify(mInnerListener);
}
mArgsQueue.clear();
}
void NotifyConfigurationChangedArgs::notify(InputListenerInterface& listener) const {
listener.notifyConfigurationChanged(this);
}
通知了mInnerListener,调用listener的回调,通过查看这个变量的来源发现是构造函数中传进来的。
InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
const sp<InputReaderPolicyInterface>& policy,
InputListenerInterface& listener)
: mContext(this),
mEventHub(eventHub),
mPolicy(policy),
mQueuedListener(listener),
mGlobalMetaState(AMETA_NONE),
mLedMetaState(AMETA_NONE),
mGeneration(1),
mNextInputDeviceId(END_RESERVED_ID),
mDisableVirtualKeysTimeout(LLONG_MIN),
mNextTimeout(LLONG_MAX),
mConfigurationChangesToRefresh(0) {
refreshConfigurationLocked(0);
updateGlobalMetaStateLocked();
}
listener就是InputReader构造方法的参数,我们传入的就是InputDispatcher,所以listener.notifyConfigurationChanged就是InputDispatcher的函数。
void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
if (DEBUG_INBOUND_EVENT_DETAILS) {
ALOGD("notifyConfigurationChanged - eventTime=%" PRId64, args->eventTime);
}
bool needWake = false;
{ // acquire lock
std::scoped_lock _l(mLock);
std::unique_ptr<ConfigurationChangedEntry> newEntry =
std::make_unique<ConfigurationChangedEntry>(args->id, args->eventTime);
needWake = enqueueInboundEventLocked(std::move(newEntry));
} // release lock
if (needWake) {
mLooper->wake();
}
}
将事件通过enqueueInboundEventLocked放入mInboundQueue中,如果需要唤醒就通过 mLooper->wake();来唤醒mLooper来继续循环dispatchOnce()。
结论
InputReader和InputDispatcher都启动了一个线程,在InputDispatcher中不停的从队列中获取事件,然后分发给上层,如果没有事件就堵塞。InputReader不停的从硬件获取事件,将硬件事件封装成上层能使用的格式和keycode,然后通过notify通知InputDispatcher,添加到队列中,并唤醒InputDispatcher线程。