Android Input事件注入

  1. Android可以通过adb shell input xxx命令注入输入事件,调用IMS.injectInputEvent,最终走到通过JNI调用InputDispatcher注入事件,没有经过InputReader
java 复制代码
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));
        }
    }
  1. 通过InputManager提供的接口注入
java 复制代码
        invokeSetDisplayId(mMotionSetDisplayId, ev, displayId); 
            Class clm = MotionEvent.class;
            m.invoke(ev, displayId);   // mMotionSetDisplayId = clm.getMethod("setDisplayId", int.class);            
        InjectionUtil.getInstance().injectInputEvent(ev, INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
            invokeInjectInputEvent(event, mode);
                Class cl = InputManager.class;
                Method method = cl.getMethod("getInstance");            
                mInjectInputEvent = cl.getMethod("injectInputEvent", InputEvent.class, int.class);
                mInjectInputEvent.invoke(inputManager, event, mode);  //InputManager::injectInputEvent
@frameworks/base/core/java/android/hardware/input/InputManager.java
                    return mIm.injectInputEvent(event, mode);
                        ......
@frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp                 
                            InputDispatcher::injectInputEvent
@frameworks/native/include/input/Input.h          
                                event->getDisplayId()
                                    needWake |= enqueueInboundEventLocked(std::move(injectedEntries.front()));
                                        mInboundQueue.push_back(std::move(newEntry));  //向InputDispatcher中的mInboundQueue队列注入事件
相关推荐
帅次35 分钟前
Android 高级工程师面试:Java 基础知识 近1年高频追问 22 题
android·java·面试
私人珍藏库2 小时前
[Android] zip解压缩管理-全格式压缩包一键解压+打包
android·app·生活·工具·多功能
雨白2 小时前
C语言:动态内存分配
android
Android-Flutter3 小时前
android compose 自定义Painter绘制图形 使用
android·kotlin·compose
我是一颗柠檬3 小时前
【Java项目技术亮点】覆盖索引与索引下推优化
android·java·开发语言
vigor5124 小时前
MySQL通过Mango实现分库分表
android·数据库·mysql
阿pin7 小时前
Android随笔-Zygote中fork究竟是什么?
android·zygote·fork
Go-higher8 小时前
DriverTest 驾考知识卡片学习助手 —— 一款基于 Jetpack Compose 的现代 Android 学习APP
android·学习
安卓修改大师8 小时前
安卓修改大师APK控件修改实战教程
android