这不算一个深度剖析的文章,之前看源码解析,总觉得路径和代码太多,看不到一半就绕晕了,于是在写这篇文章的时分就想着尽量只说到主流程,防止内容过多被绕糊涂,共享一些怎么去追一些调用逻辑的办法,这样咱们就可以有一个清晰的概括,至于中间进程的其他细节就可以更轻松的自己去探索了。

源码环境是Android13,一切非必要代码都做了省掉处理,最大程度简化骨干剖析进程

1. 代码剖析小目标

依照3个小问题来看下KeyEvent的传递进程

  1. PhoneWindowManager是怎么收到事情的
  2. Activity是怎么收到KeyEvent的
  3. View的keyListener是怎么收到事情的

Step 1: SystemServermain办法创立InputManagerServiceWindowManagerService对象,并将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发送事情,这个流程略微长一点,涉及到InputReaderInputDevice, 从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,所以实践调用NativeInputManagerinterceptKeyBeforeQueueing

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便是WindowManagerServicemPolicy是在WindowManagerServicemain函数调用结构时分传入,在SystemServer调用main时分传入的PhoneWindowManager

Step 7: WMS回调PhoneWindowManagerinterceptKeyBeforeQueueing,至此,PhoneWindowManager怎么收到的KeyEvent就完毕了,这个时分KeyEvent还没有进入分发流程