11 跟踪一个服务,直接找到驱动实现
如果说我自己学习整个系统,直到底层驱动的方法,我想说的就是我常用的就是跟踪震动这个模块,而为什么是这个,主要是简单,但是又是从上到下都具备,对于学习系统框架是最好的路径。
于是今天我们跟踪下这个代码,震动在 APP 中的使用方式。
代码中这样使用:
private Vibrator vibrator;
vibrator=(Vibrator)getSystemService(Service.VIBRATOR_SERVICE);
vibrator.vibrate(2000);
我们跟踪 getSystemService 代码,找到对应服务
这样子我们就要找初始化服务的地方,找下 SystemServiceRegistry 里面的静态代码块,可以看到有这段:
然后我们看 SystemVibrator 文件实现,
这个代码就是找到震动服务的代理,于是我们找下服务即可 VibratorService.java,这个就是我
们调用的时候真正实现的地方。
然后跟下去,找到往下走的代码:
调用到这个,就知道走下去了,因为标记了 native,说明是个本地方法,我们去找下:
我们通过检索找到代码:
在这里面又想讲下,观察这个 cpp 文件,找到注册方法,然后搜索这个注册方法:
会检索到这个/frameworks/base/services/core/jni/onload.cpp,这个是在虚拟机启动的时候,初
始化的所有系统相关的 jni 对应表,这个可以多看看。
要找它编译到哪里,从它目录往上找,找到一个 bp 或者 mk 即可。这里是
我们找到具体的实现地方,一般而言文件名或者函数名是一致的,我们这里可以看到是
hardware\libhardware\modules\vibrator 的 vibrator.c,我们打开看看这个代码:
定义了挂载位置:
static const char THE_DEVICE[] = “/sys/class/timed_output/vibrator/enable”;
最后我们就要找到真正驱动编写的地方,实际中能够通过这个路径,定位到驱动实现,这里
我用老代码演示,手头没有驱动代码:
static int __init vibrator_init(void)
{
return creat_vibrator_sysfs_file(); 这块会注册操作节/sys/class/timed_output/vibrator/enable";
}
static void __exit vibrator_exit(void)
{
remove_vibrator_sysfs_file();
}
module_init(vibrator_init);
module_exit(vibrator_exit);
此处在 creat_vibrator_sysfs_file 则会去进行注册设备,将设备的处理函数和设备进行绑定,
此时 open(THE_DEVICE, O_RDWR);
nwr = sprintf(value, “%d\n”, timeout_ms);
ret = write(fd, value, nwr);
这样子处理是,write 函数会对应到此设备进行注册的写入函数,这时向文件设备写入不同
的值,设备处理函数则会直接引起硬件操作,使得硬件真正跑起来。
这里简单说下__init 这个编译配置属性,这个代表把后面的方法编译到这个段里面,系统启
动后会找到这个段,这个段里面全部是驱动的初始化方法,可以直接遍历,执行系统的驱动
初始化。
这块定位的路线在 kernel 里面。https://www.bbsmax.com/A/qVdeaEY8dP/
简单说下就是找到这个段里面的方法,依次执行,完成驱动的初始化,系统层是通过 HAL
的统一接口去调用,然后这个 HAL 是 C 代码,然后使用注册 JNI 的方式提供给服务,然后服
务对应有客户端,使用 Binder 进行跨进程调用,完成使用这个驱动的整个回路。