测试基础 minicap 工具的剖析与修改

opentest-oper@360.cn · 2018年01月04日 · 最后由 opentest-oper@360.cn 回复于 2019年12月24日 · 13819 次阅读
本帖已被设为精华帖!

一、介绍

  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 产生机率

五、福利分享

用户手册: http://bbs.360.cn/thread-15319710-1-1.html

体验地址:http://opentest.360.cn/phonerenter.html

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 47 条回复 时间 点赞

不拿 360 手机做实验?

bauul 回复

欢迎支持 360 手机😀

印象中 minicap 它的更新速度很快,并不是每次都刷整个屏幕的,只刷新变动的地方,但是本文中没看到相关信息

bauul 回复

本文中主要针对的是对旋转和分辨率修改这两个需求展开的,具体 minicap 的相关知识官网有详细说明😀

这个 NB,可以考虑下合并到官方的版本,所以自己重新开源出来了。

支持一下,很棒

codeskyblue 回复

这个我们目前是在内部执行做了一个对比,会保留上一张的图片,如果该张图片和上张图片是一样的,就不会传送出来,从而减少了图片的输出帧率

codeskyblue 回复

主要就是为了解决相应特殊手机例如三星的问题,再一方面就是针对分辨率的动态调整(在网络不好的情况下,web 端的压力变小)

codeskyblue 回复

源代码作者很厉害

希望有生之年能看到你们的 pr 😀

思寒_seveniruby 将本帖设为了精华贴 01月05日 00:02
simple 回复

多谢😀

codeskyblue 回复

敬请期待

请问楼主
在 minicap 运行期间不断检测手机是否旋转并作出 minicap 相关适配修改
这个我在多台手机上(包括 4.X、7.X 的机器)试了都不成功,不管是横屏还是竖屏旋转返回的都是 1,只有一台 6.x 的手机可以
这是否就是你说的部分手机调用 minicap_try_get_display_info、try_get_framebuffer_display_info 失败的情况?
你说针对这样的失败,可以用安卓代码来检测,那怎么动态传递给 minicap 呢?

这个可以问下是怎么检测不一样的吗?
minicap 本身不是已经做了帧变化监听吗,只有画面发生变化时才会传送数据出来,假如手机画面一直没有变化(极端情况,比如黑屏),就不会产生新的图片吧?

零飞飞 回复

可以通过 socket server 传输当前屏幕的旋转角度

@360qa
楼主,有编译好的 micicap 可执行文件吗?从 Github 上下载的源码不知道要怎么推送到安卓手机上;
谢谢

lb 回复

下载下来(git clone),执行 ndk-build 命令根目录会下生成 lib 文件,里面就有了

bauul 回复

你晓得什么方式么,文档没找到,同问

唐明龙 回复

我之前看 minicap 输出猜测可能是有支持的,文档的话,我就不知道了

bauul 回复

Android4.3,原生就支持,不需要另外的处理,可以看我提的 Issue https://github.com/openstf/minicap/issues/123

唐明龙 回复

你的 issue 与我向楼主提的问题是根本不是一个意思,我是在问楼主是不是有局部更新图片的方法😅

codeskyblue 回复

下篇文章就能看到我们的产品了,欢迎使用

bauul 回复

这个目前还没发现呢,局部更新的话可以去看看图片的处理技术上,可以找到变化的区域从而进行更新

lb 回复

执行 adb push 就可以把文件推到手机上,ndk-build 就可以在本地生成可执行文件,若有需要可联系

零飞飞 回复

你可以看看 minicap 的日志,单独调试下问题是否那两个函数获取旋转角度失败,然后再进行相应修改;如果是获取旋转角度失败的话可以使用 adb 命令或 android 获取;传递的话使用信号的发送或者 socket 都可以实现

零飞飞 回复

是的,如果手机是黑屏就不会产生图片的

在 minicap 运行期间不断检测手机是否旋转,想问下,是在源码的什么地方做的检测呢? 我尝试修改 minicap.cpp, 发现一旦开始传输图片流(源码 while 循环那里),就不能再通过 minicap->applyConfigChanges() 修改配置,不然会在运行时报错。

所以非常想知道,您的动态检测,是在什么时机进行的。

liuliuqiu 回复


这个循环之后去检测的,
修改代码。若有崩溃原因,可以查看日志具体哪里崩溃

我试下,非常感谢!

再次请教,是否有修改 minicap-shared/aosp/src/minicap_**.cpp 的代码?
我这样修改代码:while (! gWaiter.isStopped() && (pending = gWaiter.waitForFrame()) > 0) {检测,修改 desiredInfo.orientation = info.orientation;setDesiredInfo(desiredInfo),applyConfigChanges()..., 再下面就是原有代码逻辑 }

问题出在 applyConfigChanges(); 执行中的错误信息如下
ERROR: (external/MY_minicap/src/minicap_21.cpp:123: errno: No such file or direc
tory) Unable to lock next buffer BAD_VALUE (-22)
ERROR: (jni/minicap/minicap.cpp:523: errno: No such file or directory) Unable to
consume pending frame。

我看了 applyConfigChanges() 的代码,里面会销毁一些目前的对象,内存等。然后重新 new, 应该是这个导致了上面的报错。

所以想知道,你是修改了 applyConfigChanges() 么?

不知道是否方便加你 qq 或邮件详细聊。

我的 qq:87872229, 邮箱 87872229@qq.com。

盼回复。

你好,可否请教一下 minicap 的问题,我只是想用 minicap 代替 android 自带的 screencap 在 tasker 中调用(想尽量的减小截图的体积,可以极大的牺牲清晰度)。由于是程序小白,完全不知道如何下载源码及编译 minicap,从 csdn 找到一个编译好的包:https://download.csdn.net/download/hanning563128766/10313132
根据自己手机选择了相应版本,因为是 root 过的手机,直接把文件复制到要求的位置了,并改了两个文件的权限为 777,用命令截图

LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/minicap -P 1080x1920@1080x1920/0 -Q 50 -s > /storage/emulated/0/DCIM/taskertest/mini/1.jpg

可以看到 1.jpg 文件,可是大小是 0k。

由于找不到其他来源的编译好的包,我也不知道是下载的这个包有问题,还是我输入的命令有问题,还是我的手机系统的问题(是用的类 cm 系统的 DU 7.1.2),而且在另一台 kindle hdx 8.9 平板上(刷的 aosp 类三方 rom,AEX 7.1.2 系统),截图的大小也是 0k。
另外请教下,除了 jpg 的质量参数(0-100),分辨率能用更小一些的吗(就是不对应自己手机的分辨率)
谢谢。

liuliuqiu 回复

你好,请问你的问题解决了吗?我也遇到类似的问题,求指教呀

请问楼主用什么 IDE 做 NDK 的开发环境?我从 GitHub 上下载编译运行以后很多机型都是段错误,没有 Android C++ 代码的调试经验,求指导,gdb 可以用吗

AntonyBonn 回复

不用 IDE,我用的是 sublime,直接编辑使用,编辑好后在命令行编译的。要安装下 ndk 环境

liuliuqiu 回复

你在修改后加上 continue;试试

7emper 回复

分辨率可以调小,不过需要修改 minicap 里面代码,从 cmd 修改大小是无效的,对于官方版本来说

7emper 回复

截图这个你试试 google 手机呢,测试下 minicap 有没有崩溃,你可以想试试看能不能得到手机图片,内部的截图功能依赖于是否取到设备图片

simple 专栏文章:[精华帖] 社区历年精华帖分类归总 中提及了此贴 12月13日 14:44
simple [精彩盘点] TesterHome 社区 2018 年 度精华帖 中提及了此贴 01月07日 12:08

请问有没有人在 Windows 下碰到 segmentation fault 的情况,怎么解决?

牛逼!!,不过我看不懂 c++,还是不知道怎么改

oujimahei 回复

内存访问错误,估计是代码逻辑有问题,静下心看看。

46楼 已删除

请问下楼主,修改后是在 windows 还是 Linux 下编译的?我在 Windows 下编译后,生成的 minicap.so 文件只有 6KB,推送到手机后有问题。

可以补充一下具体的执行命令行和返回结果么?

您好,我目前做到竖屏,但是视频和游戏需要支持横屏,看了你的文章是需要修改源码吗?是修改 minicap.cpp 的文件内容吗?怎么修改方便指导一下么,如果大神有时候帮忙将详细方式发我邮箱谢谢啦:1461585371@qq.com

横竖屏可以用 Android 反射接口实现,向前端传输图片时,告知前端是横屏还是竖屏

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册