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队列注入事件
相关推荐
Doro再努力40 分钟前
【Linux操作系统10】Makefile深度解析:从依赖推导到有效编译
android·linux·运维·服务器·编辑器·vim
Daniel李华1 小时前
echarts使用案例
android·javascript·echarts
做人不要太理性2 小时前
CANN Runtime 运行时组件深度解析:任务调度机制、存储管理策略与维测体系构建逻辑
android·运维·魔珐星云
我命由我123452 小时前
Android 广播 - 静态注册与动态注册对广播接收器实例创建的影响
android·java·开发语言·java-ee·android studio·android-studio·android runtime
朗迹 - 张伟3 小时前
Tauri2 导出 Android 详细教程
android
lpruoyu3 小时前
【Android第一行代码学习笔记】Android架构_四大组件_权限_持久化_通知_异步_服务
android·笔记·学习
独自破碎E4 小时前
【BISHI15】小红的夹吃棋
android·java·开发语言
李堇7 小时前
android滚动列表VerticalRollingTextView
android·java
lxysbly9 小时前
n64模拟器安卓版带金手指2026
android
游戏开发爱好者812 小时前
日常开发与测试的 App 测试方法、查看设备状态、实时日志、应用数据
android·ios·小程序·https·uni-app·iphone·webview