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队列注入事件
相关推荐
ace望世界4 小时前
android的Parcelable
android
顾林海4 小时前
Android编译插桩之AspectJ:让代码像特工一样悄悄干活
android·面试·性能优化
叽哥4 小时前
Flutter Riverpod上手指南
android·flutter·ios
循环不息优化不止4 小时前
安卓开发设计模式全解析
android
诺诺Okami4 小时前
Android Framework-WMS-层级结构树
android
alexhilton16 小时前
面向开发者的系统设计:像建筑师一样思考
android·kotlin·android jetpack
CYRUS_STUDIO1 天前
用 Frida 控制 Android 线程:kill 命令、挂起与恢复全解析
android·linux·逆向
CYRUS_STUDIO1 天前
Frida 实战:Android JNI 数组 (jobjectArray) 操作全流程解析
android·逆向
用户091 天前
Gradle Cache Entries 深度探索
android·java·kotlin
循环不息优化不止1 天前
安卓 View 绘制机制深度解析
android