requires INJECT_EVENTS permission

Mar 03 2020

今天用一个洋气点的标题(不就是小学生也能看懂的英文吗),是因为 Android 自动化测试报了个错:Injecting to another application requires INJECT_EVENTS permission。为此我闹了点笑话

现在仍然是疫情期间,所以在家远程办公时收到同事发来的问题,于是在网上搜到一个答案

image

竟然是因为 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 禁连了,这让远程办公还咋弄?!!!