背景:
在android 10版本时候,讲解了一个触摸事件的注入项目,但是在android 14的版本上体验了一下会包如下错误:
Process: com.example.injectmotion, PID: 14429
java.lang.IllegalArgumentException: Targeted input event injection from pid 14429 was not directed at a window owned by uid 10185.
明显看到这里居然报错了,,,明明android 10版本是好的,那这个是为啥??
难道是没有权限,注入权限有提升?
通过dumpsys package查看下权限情况:
明显可以看到
android.permission.INJECT_EVENTS: granted=true
是被授权的,如果是没有权限理论上也不是报这个错误,应该是报如下错误:
Injecting input events requires the caller (or the source of the instrumentation, if any) to have the INJECT_EVENTS permission.
所以可以排除掉没有权限的问题,那么为啥还会报错呢?
问题分析和解决方法:
发现上面报错了,可以有以下两个思路:
1、类比法,难道android 14都是不可以进行触摸事件注入了么?但是明显scrcpy是可以进行模拟触摸注入的,所以可以参考scrcpy如何实现
2、也可以直接进行源码分析,通过源码分析来找出问题进行修改
先尝试第一种,看看scrcpy是哪个模拟触摸注入的方法:
这里实际上是反射调用了inputmanager相关方法
最后到了这里:
再继续往下看调用,注意这里又调用方法,但是多了一个参数就是targetUid,而且这里给的是一个固定的Process.INVALID_UID
然后才会调用到服务端IMS中,注意也是是个
那么看看课程的
frameworks/base/core/java/android/app/Instrumentation.java
里面的方法是怎么调用有啥不同么 ?
可以看如下截图,这里传递的targetUid明显传递是自己进程的Uid注意这里最后也调用IMS的远端方法,和scrcpy调用方法没有什么差别
哈哈,其实上面分析过程就已经找出了,为啥高版本课程的使用Instrumentation方法不行了,因为Instrumentation的方法调用InputManagerService接口时候对targetUid进行了指定,但是InputManager的方法并没有指定固定的targetUid而是用的Process.INVALID_UID。
验证猜想及修改
既然上面分析的Instrumentation已经不行了,也不太可能修改framework把Instrumentation代码修改或者扩展,这里就使用和scrcpy的方法一样,采用InputManager接口,但是接口又是hide的,可以和scrcpy一样采用反射方式,我这边给出一种新方法,不采用反射,用的是一个模拟假接口,类和接口和InputManager一模一样,但是空实现
可以看到在自己代码定义了这样一个InputManager类,报名等和系统的包名类名,方法名字一模一样,其实目的只是为了让系统编译通过而已。
最后调用采用如下调用方式:
InputManager.getInstance().injectInputEvent(clickDown,0);
正常签名运行,一切正常没有报错,模拟触摸搞定
更多framework实战干货,请关注下面“千里马学框架”