IMS:injectInputEvent注入Input事件

IMS:injectInputEvent注入Input事件

android11-release
IMS:InputManagerService启动简要
IMS:InputReader线程获取输入事件
IMS:InputDispatcher线程分发事件


adb命令输入KEYCODE_VOLUME_UP


adb shell input keyevent KEYCODE_VOLUME_UP

frameworks\base\core\java\android\view\KeyEvent.java
frameworks\base\cmds\input\src\com\android\commands\input\Input.java

在这里插入图片描述在这里插入图片描述
injectKeyEvent(event); 调用IMS.injectInputEvent,最终走到通过JNI调用InputDispatcher::injectInputEvent

public class Input extends BaseCommand {
    // ... ... ... ...
    Input() {
        COMMANDS.put("text", new InputText());
        COMMANDS.put("keyevent", new InputKeyEvent());
        COMMANDS.put("tap", new InputTap());
        COMMANDS.put("swipe", new InputSwipe());
        COMMANDS.put("draganddrop", new InputDragAndDrop());
        COMMANDS.put("press", new InputPress());
        COMMANDS.put("roll", new InputRoll());
        COMMANDS.put("motionevent", new InputMotionEvent());
    }
    @Override
    public void onRun() throws Exception {
        String arg = nextArgRequired();
        int inputSource = InputDevice.SOURCE_UNKNOWN;

        // Get source (optional).
        if (SOURCES.containsKey(arg)) {
            inputSource = SOURCES.get(arg);
            arg = nextArgRequired();
        }

        // Get displayId (optional).
        int displayId = INVALID_DISPLAY;
        if ("-d".equals(arg)) {
            displayId = getDisplayId();
            arg = nextArgRequired();
        }

        // Get command and run.
        InputCmd cmd = COMMANDS.get(arg);
        if (cmd != null) {
            try {
                cmd.run(inputSource, displayId);
                return;
            } catch (NumberFormatException ex) {
                throw new IllegalArgumentException(INVALID_ARGUMENTS + arg);
            }
        }

        throw new IllegalArgumentException("Error: Unknown command: " + arg);
    }
    // ... ... ... ...
    class InputKeyEvent implements InputCmd {
        @Override
        public void run(int inputSource, int displayId) {
            String arg = nextArgRequired();
            final boolean longpress = "--longpress".equals(arg);
            if (longpress) {
                arg = nextArgRequired();
            }

            do {
                final int keycode = KeyEvent.keyCodeFromString(arg);
                sendKeyEvent(inputSource, keycode, longpress, displayId);
            } while ((arg = nextArg()) != null);
        }

        private void sendKeyEvent(int inputSource, int keyCode, boolean longpress, int displayId) {
            final long now = SystemClock.uptimeMillis();
            int repeatCount = 0;

            KeyEvent event = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, repeatCount,
                    0 /*metaState*/, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/, 0 /*flags*/,
                    inputSource);
            event.setDisplayId(displayId);

            injectKeyEvent(event);
            if (longpress) {
                repeatCount++;
                injectKeyEvent(KeyEvent.changeTimeRepeat(event, now, repeatCount,
                        KeyEvent.FLAG_LONG_PRESS));
            }
            injectKeyEvent(KeyEvent.changeAction(event, KeyEvent.ACTION_UP));
        }
    }

InputDispatcher::injectInputEvent注入Input事件


frameworks\base\services\core\java\com\android\server\input\InputManagerService.java
frameworks\base\services\core\jni\com_android_server_input_InputManagerService.cpp
frameworks\native\services\inputflinger\dispatcher\InputDispatcher.cpp

adb注入的是KeyEvent,InputDispatcher::injectInputEvent 将 injectedEntries(EventEntry队列)通过InputDispatcher::enqueueInboundEventLocked 添加到mInboundQueuemLooper->wake() 唤醒 InputDispatcher线程,最后返回注入结果injectionResult

int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t injectorPid,
                                          int32_t injectorUid, int32_t syncMode,
                                          std::chrono::milliseconds timeout, uint32_t policyFlags) {
#if DEBUG_INBOUND_EVENT_DETAILS
    ALOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
          "syncMode=%d, timeout=%lld, policyFlags=0x%08x",
          event->getType(), injectorPid, injectorUid, syncMode, timeout.count(), policyFlags);
#endif
    // ... ... ... ...
    std::queue<EventEntry*> injectedEntries;
    switch (event->getType()) {
        case AINPUT_EVENT_TYPE_KEY: {
            const KeyEvent& incomingKey = static_cast<const KeyEvent&>(*event);
            int32_t action = incomingKey.getAction();
            if (!validateKeyEvent(action)) {
                return INPUT_EVENT_INJECTION_FAILED;
            }

            int32_t flags = incomingKey.getFlags();
            int32_t keyCode = incomingKey.getKeyCode();
            int32_t metaState = incomingKey.getMetaState();
            accelerateMetaShortcuts(VIRTUAL_KEYBOARD_ID, action,
                                    /*byref*/ keyCode, /*byref*/ metaState);
            KeyEvent keyEvent;
            keyEvent.initialize(incomingKey.getId(), VIRTUAL_KEYBOARD_ID, incomingKey.getSource(),
                                incomingKey.getDisplayId(), INVALID_HMAC, action, flags, keyCode,
                                incomingKey.getScanCode(), metaState, incomingKey.getRepeatCount(),
                                incomingKey.getDownTime(), incomingKey.getEventTime());

            if (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY) {
                policyFlags |= POLICY_FLAG_VIRTUAL;
            }

            if (!(policyFlags & POLICY_FLAG_FILTERED)) {
                android::base::Timer t;
                mPolicy->interceptKeyBeforeQueueing(&keyEvent, /*byref*/ policyFlags);
                if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
                    ALOGW("Excessive delay in interceptKeyBeforeQueueing; took %s ms",
                          std::to_string(t.duration().count()).c_str());
                }
            }

            mLock.lock();
            KeyEntry* injectedEntry =
                    new KeyEntry(incomingKey.getId(), incomingKey.getEventTime(),
                                 VIRTUAL_KEYBOARD_ID, incomingKey.getSource(),
                                 incomingKey.getDisplayId(), policyFlags, action, flags, keyCode,
                                 incomingKey.getScanCode(), metaState, incomingKey.getRepeatCount(),
                                 incomingKey.getDownTime());
            injectedEntries.push(injectedEntry);
            break;
        }
        // ... ... ... ...
    }
    // ... ... ... ...
    bool needWake = false;
    while (!injectedEntries.empty()) {
        needWake |= enqueueInboundEventLocked(injectedEntries.front());
        injectedEntries.pop();
    }

    mLock.unlock();
    if (needWake) {
        mLooper->wake();
    }
// ... ... ... ...
#if DEBUG_INJECTION
    ALOGD("injectInputEvent - Finished with result %d. injectorPid=%d, injectorUid=%d",
          injectionResult, injectorPid, injectorUid);
#endif

    return injectionResult;
}

mInboundQueue分发查看IMS:InputDispatcher线程分发事件,这里可以看到注入 Input 事件直接加入到mInboundQueue由InputDispatcher分发,没有经过InputReader

IMS:injectInputEvent注入反馈结果

在这里插入图片描述在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xhBruce

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值