移动测试开发 minicap 工具的剖析与修改
一、介绍
minicap 是开源项目 STF(Smartphone Test Farm)中的一个工具,负责屏幕显示,是 STF 框架的依赖工具之一。minicap 工具采用 NDK 开发的,属于 Android 的底层开发。
源码地址:https://github.com/openstf/minicap
但是在将其应用在一个真机云平台时,发现这个工具有一些不足之处,具体表现为:
旋转屏幕后,收到的图片有黑色区域,图片内容不完整。
接收的图片大小无法在 minicap 运行过程中动态修改,只能通过重启 minicap 服务进行修改。
为了解决这两个问题,需要在原有的代码基础上做一些修改,下面主要围绕剖析代码与修改代码这两部分展开讨论。
二、代码剖析
(一)minicap 运行流程
(1) 命令行方式启动
手机内部启动 minicap,可在命令行下查看 minicap 进程相关信息。
a.检测 minicap 是否可以正常启动
首先测试下 minicap 工具是否可用,命令如下 (其中-P 后面跟的参数为手机屏幕的尺寸,你可以修改成你自己设备的尺寸),最后输出 OK 就表明 minicap 可用。
b.启动 minicap
c.查看手机中 minicap 服务的相关信息
(2) 本地端口转发
(3) 创建 client 连接本地端口接收 minicap 产生的图片
(二)minicap 内部流程解析
(1) 解析 LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/minicap -P 1440x2560@1440x2560/0 启动行参数,设置相关配置。
其中:
-P:(x@x/{0|90|180|270}) minicap 产生的图片尺寸以及传递出来的图片尺寸,可修改该参数调整 client 收到的图片的宽度或高度。eg:1080x1920@360x640/0 指定 minicap 在手机内部产生图片分辨率为 1080x1920,而传递出来的图片分辨率为 360x640,0 表示手机目前是竖屏状态,逆时针旋转手机可根据不同角度设置此参数为 90、180、270。
-Q: 设置 minicap 内部对图片的压缩比:0—100
注:minicap 内部会对期望图片的分辨率做一个调整,如果期望的分辨率大小和手机的真实分辨率大小是等比的就不做调整,如果不等比则会调整期望的图片的分辨率大小。
(2) 初始化 minicap 内部对象
a.调用 setRealInfo、setDesiredInfo、applyConfigChanges 函数设置相关配置
b.minicap->setFrameAvailableListener(&gWaiter):创建一个监听手机帧率的对象
c.填充 minicap 协议的头信息 24 个字节
(3) 监听 client 的连接(内部只支持连接一个 client 对象)
(4) server 端使用连接到的套接字发送 minicap 的头信息,判断 socket 是否能正常通信,若消息发送失败,则关闭该套接字,重新去监听请求。
(5) socket 正常通信情况下,不断传送图片信息
minicap 传出来的图片信息为:包括图片大小信息和图片二进制信息
即:
三、minicap 的修改
(1) 在 minicap 运行期间不断检测手机是否旋转并作出 minicap 相关适配修改
需求:手机进行旋转之后转换后收到图片依然正确
修改点:
1) 得到手机的真实屏幕分辨率和旋转角度(minicap 内部函数)
2) 修改目标图片变量的旋转角度
3) 重新修改 minicap 设置并应用
修改后:得到正确、完整的图片
(2) 在 minicap 的传送图片信息中加入图片旋转角度的字段
需求:无法识别图片的旋转角度,都会对图片按照竖屏形式显示,导致图片被错误拉伸。client 端可根据收到的图片旋转字段正确显示收到的图片(是否需要将图片旋转后显示)
修改点:
1) 修改图片对象的头字段长度
2) 发送图片前将图片的旋转角度加入图片对象头字段内
修改后:可从图片的信息中获取这张图片的旋转角度,前端根据旋转角度在显示前做旋转处理,使图片正确显示。
(3) 在 minicap 运行期间,通过动态修改收到的图片的配置来得到不同分辨率的图片。
需求:当使用 web 服务来操作手机时,实现一个类似于从标清到高清这样的一个清晰度切换。
修改点:
1) 得到手机的真实屏幕分辨率和旋转角度
2) 修改目标图片变量的宽度和高度
3) 重新修改 minicap 设置并应用
修改后:得到的图片分辨率变大,图片的清晰度提升
(4) 特殊手机的分辨率和旋转角度获取
需求:对于部分手机调用 minicap_try_get_display_info、try_get_framebuffer_display_info 失败可使用下述方法得到手机相关信息。
1) 获取手机分辨率方法:
a.通过 Android 函数获取屏幕的分辨率信息
b.adb 命令
wm size、dumpsys window displays、dumpsys display
2) 获取旋转角度:
a.Android 函数
b.adb 命令
dumpsys input | grep SurfaceOrientation
四、总结
优秀的代码会减少后期大量的维护成本
1.写代码之前先设计好易于维护和拓展的代码结构
2.代码简洁明了,避免晦涩难懂,减少 bug 产生机率