今天用一个洋气点的标题(不就是小学生也能看懂的英文吗),是因为 Android 自动化测试报了个错:Injecting to another application requires INJECT_EVENTS permission。为此我闹了点笑话
现在仍然是疫情期间,所以在家远程办公时收到同事发来的问题,于是在网上搜到一个答案

竟然是因为 USB 调试没打开呢?毕竟是在排查问题,只能先看看我远程的设备这一项是怎么样的。操作到开发者模式以后,发现远程设备是打开的,那得关闭一下,然后自己跑跑看会不会报上面的问题吧。于是我毫无预兆的点了关闭,紧接着也收到了一条提醒“device not found”
纳尼?这可是我唯一能调试的远程设备,我赶紧 adb devices 发现确实没了,我去**的,网上这都什么回答,把我坑惨了。求人不如求代码呢,我怒把异常堆栈翻出来,决定开始分析
1 2 3 4 5
| W System.err: java.lang.SecurityException: Injecting to another application requires INJECT_EVENTS permission W System.err: at android.os.Parcel.readException(Parcel.java:2013) W System.err: at android.os.Parcel.readException(Parcel.java:1959) W System.err: at android.app.IUiAutomationConnection$Stub$Proxy.injectInputEvent(IUiAutomationConnection.java:288) W System.err: at android.app.UiAutomation.injectInputEvent(UiAutomation.java:572)
|
从这个 IUiAutomationConnection$Stub$Proxy.injectInputEvent 方法开始 tracking,它的实现类是 UiAutomationConnection,最终是调用了 InputManagerService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| // InputManagerService.java
private boolean injectInputEventInternal(InputEvent event, int displayId, int mode) { ...
try { result = nativeInjectInputEvent(mPtr, event, displayId, pid, uid, mode, INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT); } finally { Binder.restoreCallingIdentity(ident); } switch (result) { case INPUT_EVENT_INJECTION_PERMISSION_DENIED: Slog.w(TAG, "Input event injection from pid " + pid + " permission denied."); throw new SecurityException( "Injecting to another application requires INJECT_EVENTS permission"); case INPUT_EVENT_INJECTION_SUCCEEDED: return true; case INPUT_EVENT_INJECTION_TIMED_OUT: Slog.w(TAG, "Input event injection from pid " + pid + " timed out."); return false; case INPUT_EVENT_INJECTION_FAILED: default: Slog.w(TAG, "Input event injection from pid " + pid + " failed."); return false; } }
|
当一个本地方法 nativeInjectInputEvent 返回的结果是 INPUT_EVENT_INJECTION_PERMISSION_DENIED 时,就会抛出我在一开始提到的那个异常了,至少在我的场景里,不是什么 USB 调试模式没有打开的情况
因此得出一个结论,在对框架比较了解并且具备源码的情况下,看代码时最直接的,不仅能多了解一点逻辑背后的内容,还能防止踩坑。咦?好像记起来一个事,我的远程设备已经被 USB 禁连了,这让远程办公还咋弄?!!!