转载请注明出处
早想写这篇,一直没空,现在总结下。
需求:
需要在程序内模拟用户输入,比如点击屏幕,或者输入键盘。模拟用户的滑动等。具体的需求,比如测试的时候,测试打开浏览器1000次。或者通过网络发送命令给手机,在手机上执行点击或者输入。再或者,平板和蓝牙鼠标通过蓝牙通信,通过鼠标让平板上的鼠标能移动和点击。这些都需要用到事件注入。
分析:
模拟用户输入的方式有几种,一是monkeyrunner,这个的原理是在PC上,通过python调用android的一些包,然后通过机器的调试端口和机器通信,机器接收到相应的命令后再往硬件写入相应的事件。这个常用语测试。并且,不是所有的机器都开了调试端口,并且需要连接PC。二是IwindowManager的injectInputEventNoWait,这个调用方便,也很简单,但是从1.5(1.6?)后android系统做了限制,不允许跨进程注入,这个方法只能在自己这个程序内用,home出去就不行了。三是直接往linux底层/dev/input/event*写事件,这个实现起来复杂,需要root权限,但是却能实现跨进程,比如蓝牙鼠标的需求,也只能用这种方法实现。讲这个具体实现的不多,本文详细介绍下。对linux了解些的人应该一看就懂知道怎么回事。android上实现只不过有些地方比较绕而已。
1.android界面点击事件流程。
有必要先说下android界面捕获事件的流程。用户在屏幕上点击一下后,程序里面的OnClickListener是怎样收到这个事件的。大致流程如下
用户点击-(硬件驱动部分)硬件产生一个中断,往/dev/input/event*写入一个相应的信号->jni部分,android循环读取/dev/input/event*的事件,再分发给WindowManagerServer,最后再发到相应的ViewGroup和View。这里可以通过往/dev/input/event*写信号的方式,来达到模拟事件的目的,接下来关心的就是信号的协议了。
2.按键协议分析
连接手机,adb shell,输入getevent,关掉手机的自动旋转屏幕,按一下手机的menu键,会看到类似如下输出。
linux上的硬件会分别对应/dev/input/event*,这里的*一般是0-9的数字,getevent开头那部分已经显示,event2是keypad,event1是touchscreen等。
最下面的0001 008b 00000001分别叫做type,code,value。
参考linux input,type 对应 【#define EV_KEY 0x01】,code 对应【#define KEY_MENU 139】(8b == 139),value 1表示按下,0表示松开。那么按键的协议就很清楚了,试着在adb shell里面输入“sendevent /dev/input/event2 0 139 1”和”sendevent /dev/input/event2 0 139 2“后发现menu弹出来了,和按键的效果一样。
3.触摸协议分析
ok,来点复杂的。触摸协议稍微麻烦点,分单点触摸和多点触摸。
先说单点触摸,打开模拟器。同样关闭自动旋屏,进入adb shell。鼠标点击一下屏幕,要足够快,不然数据太多。得到输出和下面类似。
可以看到模拟器上的设备数少了很多,单点触摸的协议每次点击会写6条信号。参考linux_input对应的值以及分析分别如下
/dev/input/event0: 0003 0000 00000117 EV_ABS ABS_X 0x117
触摸点的x坐标
/dev/input/event0: 0003 0001 0000020f EV_ABS ABS_Y 0x20f
触摸点的y坐标
/dev/input/event0: 0001 014a 00000001 EV_KEY BTN_TOUCH 1
touch down
/dev/input/event0: 0000 0000 00000000 EV_SYN 0 0
同步信号量
/dev/input/event0: 0001 014a 00000000 EV_KEY BTN_TOUCH 0
touch up
/dev/input/event0: 0000 0000 00000000 EV_SYN 0 0
同步信号量
使用4.0的模拟器,settings-developer options-show touches 和pointer locations勾上后,可以看到点击的轨迹,adb shell后分别用sendevent输入以上消息,可以看到屏幕上出现点击效果。
再看多点触摸协议,使用adb shell 进入手机,关掉旋屏,getevent后快速点一下屏幕,可以看到类似如下输出。(每个厂商的协议可能不同,以下数据为小米1的)
第一个坐标
/dev/input/event1: 0003 0039 00000000 EV_ABS ABS_MT_TRACKING_ID 0
/dev/input/event1: 0003 0035 000001b0 EV_ABS ABS_MT_POSITION_X 0x1b0
/dev/input/event1: 0003 0036 000000d7 EV_ABS ABS_MT_POSITION_Y 0xd7
/dev/input/event1: 0003 003a 00000001 EV_ABS ABS_MT_PRESSURE 0x1
/dev/input/event1: 0003 0032 00000001 EV_ABS ABS_MT_WIDTH_MAJOR 0x1
/dev/input/event1: 0000 0002 00000000 EV_SYN SYN_MT_REPORT 0
/dev/input/event1: 0000 0000 00000000 EV_SYN SYN_REPORT 0
第二个坐标
/dev/input/event1: 0003 0039 00000000 EV_ABS ABS_MT_TRACKING_ID 0
/dev/input/event1: 0003 0035 000001b0 EV_ABS ABS_MT_POSITION_X 0x1b0
/dev/input/event1: 0003 0036 000000d7 EV_ABS ABS_MT_POSITION_Y 0xd7
/dev/input/event1: 0003 003a 00000001 EV_ABS ABS_MT_PRESSURE 0x1
/dev/input/event1: 0003 0032 00000001 EV_ABS ABS_MT_WIDTH_MAJOR 0x1
/dev/input/event1: 0000 0002 00000000 EV_SYN SYN_MT_REPORT 0
/dev/input/event1: 0000 0000 00000000 EV_SYN SYN_REPORT 0
第三个坐标
/dev/input/event1: 0003 0039 00000000 EV_ABS ABS_MT_TRACKING_ID 0
/dev/input/event1: 0003 0035 00000191 EV_ABS ABS_MT_POSITION_X 0x191
/dev/input/event1: 0003 0036 00000098 EV_ABS ABS_MT_POSITION_Y 0x98
/dev/input/event1: 0003 003a 00000001 EV_ABS ABS_MT_PRESSURE 0x1
/dev/input/event1: 0003 0032 00000001 EV_ABS ABS_MT_WIDTH_MAJOR 0x1
/dev/input/event1: 0000 0002 00000000 EV_SYN SYN_MT_REPORT 0
/dev/input/event1: 0000 0000 00000000 EV_SYN SYN_REPORT 0
松开
/dev/input/event1: 0000 0002 00000000 EV_SYN SYN_MT_REPORT 0
/dev/input/event1: 0000 0000 00000000 EV_SYN SYN_REPORT 0
这里是一次点击,注意到ABS_MT_TRACKING_ID都是一样的。系统检测到三个点,每次会发送点的x,y,以及收到的压力,触摸的范围。最后两条表示松开这个点。如果两个手指同时点击,可以发现ABS_MT_TRACKING_ID会有两个不同的值,分别是两个点。据说最多支持5点。
每个厂商实现协议不一样。htc g3如下
/dev/input/event1: 0003 003a 002a0002
/dev/input/event1: 0003 0039 8b8c0ddc
/dev/input/event1: 0003 003a 00000002
/dev/input/event1: 0003 0039 8bac0dde
/dev/input/event1: 0003 003a 00000000
/dev/input/event1: 0003 0039 802814b1
4.可能遇到的问题
实际实现的时候,还可能遇到问题
一是root,getevent和sendevent需要/dev/input/event*的权限。一般应用是没有这个权限的,需要在程序里面获取su后,执行chmod 666 /dev/input/event*。
二是设备名称。因为你不知道触摸屏或者按键到底对应的event*是多少。需要有一个初始化的过程,大致思路是往event0-event9分别写入按键和触摸信号,同时监听activity里的onkeydown和view的onclick,这样来侦测设备。
三是厂商的实现不一样,这个没办法,只能一个一个适配了,一般来说都还是标准的,有些厂商会有单独的实现。
参考
http://lxr.free-electrons.com/source/include/uapi/linux/input.h#L803
http://source.android.com/tech/input/touch-devices.html
http://cjix.info/blog/misc/internal-input-event-handling-in-the-linux-kernel-and-the-android-userspace/
相关推荐
这样服务就与系统服务在同一权限级别,可以跨进程注入事件。但是,这需要在Android源码环境中编译,并在`Android.mk`文件中指定`LOCAL_CERTIFICATE := platform`来确保服务被签名为系统应用。 下面是`Android.mk`...
Android进程注入是一种技术,它允许一个应用程序在另一个应用程序的进程中运行其代码,通常是出于调试、监控或增强功能的目的。在Android系统中,由于其安全模型,这种操作需要深入理解操作系统的工作原理以及相应的...
通过ADB的`shell`命令,我们可以启动其他应用、注入输入事件、甚至修改系统设置,从而实现跨进程的控制。 例如,`am start`命令可以用来启动一个应用或者指定的Activity,`input`命令可以模拟用户输入,如点击、...
它能够帮助开发者查看和操纵运行中的Android进程,包括读取和写入内存,查找特定的代码或数据,以及注入自定义的库,从而实现对程序行为的深度控制。 2. 功能详解: - 检查进程:cpp工具可以列出系统中所有正在...
总之,InjectDemo是一个关于Android进程注入的示例项目,它展示了如何利用root权限和ptrace系统调用在Android上实现这一功能。理解和掌握这些知识点,对于从事Android底层开发、安全研究或逆向工程的人员来说,都是...
Monkey 通过模拟用户随机的触摸事件、按键输入、轨迹球运动以及系统级事件来实现这一目标,帮助开发者发现应用程序中的不稳定性和崩溃问题。在深入理解 Monkey 源码之前,我们首先需要了解 Monkey 的基本工作原理。 ...
更具体的测试类如ApplicationTestCase、ProviderTestCase2和ServiceTestCase分别针对应用程序、ContentProvider和Service进行测试,它们能够注入模拟的系统对象以隔离测试环境。 InstrumentationTestCase类则进一步...
它使用Android的Instrumentation机制,允许测试代码与目标应用程序在同一进程中运行,并能够操控应用程序的生命周期。 Android的测试API还提供了几个特定于组件的测试用例类,例如ActivityInstrumentationTestCase2...
然而,修改系统进程并不是一项简单的任务,它可能涉及到权限提升、进程注入等技术。这些操作需要对操作系统有深入的理解,同时也可能带来安全风险。不恰当的修改可能会导致系统不稳定,甚至被恶意软件利用。因此,...
4. `ServiceTestCase`:用于测试Service,可以注入模拟的Context或Application,以便于控制Service的生命周期。 5. `InstrumentationTestCase`:这是最重要的测试类,因为它扩展了JUnit的`TestCase`并且集成了...
在Android系统中,shellcode是一种特殊的代码片段,用于在获得程序执行权限后,实现特定功能,比如控制系统、执行恶意操作等。随着Android设备的广泛使用,Android系统的安全性变得至关重要,而shellcode的编写和...
Bad Behavior部分是DevTools中的故障注入工具,用于模拟应用程序或系统的错误情况。例如,开发者可以故意使主线程崩溃、辅助线程崩溃、本地进程崩溃,甚至破坏系统服务器,以测试应用程序的错误处理机制。Report a ...
这两者通过Binder框架实现了跨进程调用,从而使得Monkey能够从外部向正在运行的应用程序注入事件。 - **injectEvent的完整流程**:从调用WM.injectKeyEvent()开始,经过WM.dispatchKey()到达窗口状态(WindowState)...
### Android软件安全审计及漏洞修复经验谈 #### 一、背景与安全机制 ...通过上述方法和技术手段,我们可以有效地进行Android软件的安全审计和漏洞修复工作,从而提高应用程序的安全性和用户体验。
11. Dagger 2或Hilt(Android Jetpack的一部分):对于依赖注入,Dagger 2或Hilt可以帮助我们编写可测试的代码,通过提供构造函数或方法注入,使测试更容易隔离。 12. Room Persistence Library测试:如果你的项目...
在Android系统中,导航栏是用户界面不可或缺的一部分,通常包含BACK、HOME和RECENT(最近应用)这三个关键按钮,为用户提供基本的操作导航。在Android 4.0(Ice Cream Sandwich)版本中,虽然这个功能是默认存在的且...
13. **Android架构组件**:理解MVVM(Model-View-ViewModel)模式,以及如何利用 Dagger 或 Hilt 进行依赖注入。 14. **进程和应用的启动优化**:如何优化冷启动时间,理解进程优先级,以及如何避免应用被系统杀死...
在Android开发领域,初学者经常会面临寻找合适的学习资源的挑战。这份名为"Android-Android...这个压缩包的资源无疑为Android学习者提供了一条便捷的途径,让他们能够在短时间内获得大量实用信息,加速他们的学习进程。
例如,不要在日志中打印SQL语句,防止SQL注入攻击,以及对用户输入进行适当验证。 9. **数据库版本管理** 当数据库结构需要变更时,通过修改`SQLiteOpenHelper`的版本号,并重写`onUpgrade()`方法,可以实现数据库...
- **自动化模拟模块**:模拟用户操作,触发应用程序的各种功能。 - **服务器端**:包括三个核心模块: - **数据库模块**:存储已知恶意行为的特征值序列。 - **数据预处理模块**:清洗和整理从客户端收集的数据...