当前位置: 首页 > 工具软件 > Screen Record > 使用案例 >

备忘:通过screen record打通Android从app layer到native layer的通道

淳于思淼
2023-12-01

这是之前做的蛮长时间的一个功能,怕以后忘记了,做个记录。

公司的平台是v4.4,所以screenrecord还没有开放到sdk(据说5.0的sdk有,没深究),但是可以用命令实现录屏功能,所以在Android源码中是有相关功能的,那么怎么样才能把native的功能暴露到上层呢?做这个的时候基本参考RemoteDisplay。

1、以什么方式暴露

      如果是直接做到系统里面,那不用说,就是调用某个类的某个方法。

      如果是要想sdk那样暴露api的话,显然是不能像上面那样做的,应该像一些系统服务一样(e.g CONNECTIVITY_SERVICE),在ContextImpl.java中registerService,然后在自己的app那里使用context.getSystemService(XXXXX)。

2、java layer(ScreenRecord.java)的调用

      直接在ScreenRecord.java使用native调用,到C++ layer。

3、native layer的入口

      对系统启动有点研究的应该知道,系统会默认加载AndroidRuntime.so,所以native入口在AndroidRuntime.cpp中,不需要再另外加载动态库。将一些注册配置做好后,就进入了C++的世界

4、native layer client端设计

     native layer也不是直接调用某个方法来实现录屏的,一来这样是同步的,而来这是一个模块功能,可能其他地方也要用到(比如media play,SurfaceFlinger),所以应该将它做成一个service(native layer),通过ServiceManager调用,即IPC通信。在client端建立的对象只是一个proxy,与server端通信,不涉及具体业务。参考RemoteDisplay,screen record挂在Media Player这个进程中,故是调用IMediaPlayerService_bp(defaultServiceManager().getService(String16("media.player")))的startScreenRecord方法

5、native layer server设计

      由于client端和server端要持续通信,所以彼此都要有对方的对象。在startScreenRecord的参数中传入一个client_bn,在server端就是bp了,其server端返回一个bn,在client端就成了bp。这样client端对server端的操作,以及server端对client端的回馈都清楚了。

6、备注

     其实native的通道是mediaplayerservice,我们要设计的只是自己的bn+bp,然后在IMediaPlayerService_bp中将自己的对象正确的序列话之后写入通道,就能正常完成IPC通信。

PS:在做这个的时候有个问题要注意,就是从app layer不要传一个文件路径,然后在底层创建。因为media player进程不允许创建文件,所以上层应该传入一个FileDescriptor,在底层直接用

    

 类似资料: