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队列注入事件
相关推荐
似霰40 分钟前
安卓智能指针sp、wp、RefBase浅析
android·c++·binder
大风起兮云飞扬丶40 分钟前
Android——网络请求
android
干一行,爱一行43 分钟前
android camera data -> surface 显示
android
断墨先生1 小时前
uniapp—android原生插件开发(3Android真机调试)
android·uni-app
无极程序员3 小时前
PHP常量
android·ide·android studio
萌面小侠Plus4 小时前
Android笔记(三十三):封装设备性能级别判断工具——低端机还是高端机
android·性能优化·kotlin·工具类·低端机
慢慢成长的码农4 小时前
Android Profiler 内存分析
android
大风起兮云飞扬丶4 小时前
Android——多线程、线程通信、handler机制
android
L72564 小时前
Android的Handler
android
清风徐来辽4 小时前
Android HandlerThread 基础
android