源码环境是Android13,所有非必要代码都做了省略处理,最大程度简化主干分析过程
1. 代码分析小目标
按照3个小问题来看下KeyEvent的传递过程
- PhoneWindowManager是如何收到事件的
- Activity是如何收到KeyEvent的
- View的keyListener是如何收到事件的
Step 1: SystemServer 的main 方法创建InputManagerService 和WindowManagerService 对象,并将WMS内部的InputManagerCallback传入IMS方便接收新数据
base/services/java/com/android/server/SystemServer.java
java
/**
* The main entry point from zygote.
*/
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
try {
startOtherServices(t);
} catch (Throwable ex) {
} finally {
}
}
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
// WMS needs sensor service ready
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);
/.../
inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
inputManager.start();
}
// InputManagerService.start内部其实是调用了他的mNative实现
public void start() {
Slog.i(TAG, "Starting input manager");
mNative.start();
}
Step 2: KeyEvent是从InputManager转发过来,真正的处理过程实际是Native去做的,所以我们先找到IMS的Native实现,众所周知,java转到Native肯定有jni定义,我们如何找到jni文件呢,jni文件一般是包名加类名 ,也就是com_android_server_input_InputManagerService.cpp ,C层最终业务的实际的实现类是InputManager.cpp,内部调用start创建并启动InputReader和InputDispatcher
/base/services/core/jni/com_android_server_input_InputManagerService.cpp
cpp
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.systemUiLightsOut = false;
mLocked.pointerSpeed = 0;
mLocked.pointerAcceleration = android::os::IInputConstants::DEFAULT_POINTER_ACCELERATION;
mLocked.pointerGesturesEnabled = true;
mLocked.showTouches = false;
mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;
}
mInteractive = true;
mTouchWakeup = property_get_bool("ro.duershow.touchwakeup.enable", 0);
InputManager* im = new InputManager(this, this);
mInputManager = im;
defaultServiceManager()->addService(String16("inputflinger"), im);
}
/native/services/inputflinger/InputManager.cpp
c++
InputManager::InputManager(
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
mDispatcher = createInputDispatcher(dispatcherPolicy);
mClassifier = std::make_unique<InputClassifier>(*mDispatcher);
mBlocker = std::make_unique<UnwantedInteractionBlocker>(*mClassifier);
// Dispatcher类被一层层包装后混进了Inputeader获取情报
mReader = createInputReader(readerPolicy, *mBlocker);
}
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;
}
Step 3: InputReader 借助EventHub 获取到设备事件,最终调用getListener()->notifyKey 发送事件,这个流程稍微长一点,涉及到InputReader 和InputDevice , 从Step 2最后一段代码可以知道,InputReader创建时候将InputDispatcher作为listener,所以实际调用的是InputDispatcher的notifyKey.
/native/services/inputflinger/reader/InputReader.cpp
InputReader::loopOnce() -> InputReader::processEventsLocked -> InputReader::processEventsForDeviceLocked
cpp
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);
}
逻辑转到InputDevice里面,调用process
/native/services/inputflinger/reader/InputDevice.cpp
cpp
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
// Process all of the events in order for each mapper.
// We cannot simply ask each mapper to process them in bulk because mappers may
// have side-effects that must be interleaved. For example, joystick movement events and
// gamepad button presses are handled by different mappers but they should be dispatched
// in the order received.
for_each_mapper_in_subdevice(rawEvent->deviceId, [rawEvent](InputMapper& mapper) {
mapper.process(rawEvent);
});
--count;
}
}
遍历map这个map保存的是不同设备的数据几何,比如我们现在探索的就是KeyboardInputMapper ,代表键盘设备,android有很多的InputMapper但是最终都是通过getListener 调用不同的函数将事件交给InputDispatcher
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;
}
}
}
cpp
void KeyboardInputMapper::processKey(nsecs_t when, nsecs_t readTime, bool down, int32_t scanCode,
int32_t usageCode) {
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);
}
Step 4: InputDispatcher收到事件是需要检查然后加入队列,在加入队列之前会先调用mPolicy->interceptKeyBeforeQueueing入队列前给一次处理机会
cpp
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
needWake = enqueueInboundEventLocked(std::move(newEntry));
} // release lock
if (needWake) {
mLooper->wake();
}
}
mPolicy的赋值是在InputDispatcher 的构造函数 处理,所以需要我们往回找他的实现,从Step 2 的代码可以知道InputDispatcher 是在InputManager 构造里创建的,且是透传的参数,InputManager 又是在com_android_server_input_InputManagerService.cpp 内创建,且参数传的都是this ,也就是NativeInputManager ,所以实际调用NativeInputManager 的interceptKeyBeforeQueueing
Step 5: NativeInputManager调用java层的同名函数
/base/services/core/jni/com_android_server_input_InputManagerService.cpp
cpp
void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,
uint32_t& policyFlags) {
if ((policyFlags & POLICY_FLAG_TRUSTED)) {
nsecs_t when = keyEvent->getEventTime();
JNIEnv* env = jniEnv();
jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
jint wmActions;
if (keyEventObj) {
// C反向调用java代码,也就是InputManagerService.java的interceptKeyBeforeQueueing
wmActions = env->CallIntMethod(mServiceObj,
gServiceClassInfo.interceptKeyBeforeQueueing,
keyEventObj, policyFlags);
} else {
if (interactive) {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
}
}
}
Step 6: InputManagerServcie继续透传到WMS
/base/services/core/java/com/android/server/input/InputManagerService.java
java
private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
// 还记得step 1提到的WMS安插的间谍
return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
}
/base/services/core/java/com/android/server/wm/InputManagerCallback.java
java
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
}
mService 就是WindowManagerService ,mPolicy 是在WindowManagerService 的main 函数调用构造时候传入,在SystemServer 调用main 时候传入的PhoneWindowManager