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

360qa · 2018年01月04日 · 最后由 guowee 回复于 2018年09月21日 · 最后更新自管理员 Lihuazhang · 3993 次阅读
本帖已被设为精华帖!

一、介绍

  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

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

不拿360手机做实验?

carl 回复

欢迎支持360手机😀

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

carl 回复

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

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

支持一下,很棒

codeskyblue 回复

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

simple 回复

😀

360qa #10 · 2018年01月04日 作者
codeskyblue 回复

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

360qa #11 · 2018年01月04日 作者
codeskyblue 回复

源代码作者很厉害

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

seveniruby 将本帖设为了精华贴 01月05日 00:02
360qa #14 · 2018年01月05日 作者
simple 回复

多谢😀

360qa #15 · 2018年01月05日 作者
codeskyblue 回复

敬请期待

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

360qa 回复

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

360qa #18 · 2018年01月24日 作者
cwqlc 回复

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

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

robin_123 回复

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

carl 回复

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

tmlong 回复

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

carl 回复

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

tmlong 回复

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

360qa #25 · 2018年05月04日 作者
codeskyblue 回复

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

360qa #26 · 2018年05月04日 作者
carl 回复

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

360qa #27 · 2018年05月04日 作者
robin_123 回复

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

360qa #28 · 2018年05月04日 作者
cwqlc 回复

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

360qa #29 · 2018年05月04日 作者
cwqlc 回复

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

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

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

360qa #31 · 2018年06月07日 作者
liuliuqiu 回复


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

360qa 回复

我试下,非常感谢!

再次请教,是否有修改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。

盼回复。

360qa 回复

你好,可否请教一下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 回复

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

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