这不算一个深度剖析的文章,之前看源码解析,总觉得路径和代码太多,看不到一半就绕晕了,于是在写这篇文章的时分就想着尽量只说到主流程,防止内容过多被绕糊涂,共享一些怎么去追一些调用逻辑的办法,这样咱们就可以有一个清晰的概括,至于中间进程的其他细节就可以更轻松的自己去探索了。
源码环境是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
/**
* 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
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
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
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
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
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;
}
}
}
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入行列前给一次处理机会
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
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
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
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
}
mService便是WindowManagerService,mPolicy是在WindowManagerService的main函数调用结构时分传入,在SystemServer调用main时分传入的PhoneWindowManager