移动测试 | 解析 Totoro 无侵入、全场景截图及图像技术体系

本文涉及的产品
mPaaS订阅基础套餐,标准版 3个月
简介: Totoro 框架是由 蚂蚁金服终端工程技术部-实验平台技术组 自研的一套自动化解决方案。目前以实验 SDK 形式输出能力,及凭借蚂蚁云测 SLM 平台能力,目前已有阿里系域内 16+ 业务接入。

为提高业务研发的开发效率,解决业务基础工具技术痛点,让研发主要精力回归业务核心问题解决上,我们在不同的维度做了大量体系化的技术构建,为不同的自动化场景提供稳定、易用的自动化底盘。

本文主要分享 Totoro 框架在移动端截图及图像处理及在全链路体系上的技术方案和业务支持能力。

基础截图技术方案

一台手机上获取屏幕截图简单,但是想要兼容集群环境云真机平台上的大量移动设备,突破系统各种安全限制、安全页面(密码、转账等页面)反截图安全限制、及 ROM 差异性等不同维度的兼容性问题,且是非侵入方式,则会有一点技术小挑战。

这里从基础截图方案和突破系统限制达到截图能力全场景覆盖两方面分享 Totoro 的一些实践。

1. 一般常见截图方案选型及改造

在移动端自动化(测试)场景, 最长见的截图方法就是使用adb shell screencapuiautomator截图接口。然而 adb shell screencap 方式使用很不方便,需要将截图先保存到手机磁盘上,然后再pull到 PC 设备上。
Totoro 框架中采用了一次性的获取方式如下:

adb -s sn exec-out screencap -p >  name
AI 代码解读

但是即使采用adb exec-out方式也存在图片无法压缩导致的截图耗时较长的问题,并且 Java 项目中每次都要 Process 创建进程,遇到频繁截图情况,耗费系统资源,影响稳定性。所以在 Totoro 框架中提供的 SDK 默认 API 底层采用的的是 Uiautomator 提供的接口方法。

UI Automator 测试框架提供了一组 API,用于构建在用户应用和系统应用上执行交互的界面测试。通过 UI Automator API,您可以执行在测试设备中打开“设置”菜单或应用启动器等操作。

同样发现,UIAutomator 提供默认截图方法 生成图片文件也是非常大,压缩算法并没生效。导致截图链路上整体耗时会造成每次截图在平均 2-5s 左右,影响到了自动化整体时间。 考虑到单独引进一套压缩算法较重,且可能后续无资源维护,所以决定研究安卓源码,试图从根本解决压缩无效的问题。

    /**
     * Write a compressed version of the bitmap to the specified outputstream.
     * If this returns true, the bitmap can be reconstructed by passing a
     * corresponding inputstream to BitmapFactory.decodeStream(). Note: not
     * all Formats support all bitmap configs directly, so it is possible that
     * the returned bitmap from BitmapFactory could be in a different bitdepth,
     * and/or may have lost per-pixel alpha (e.g. JPEG only supports opaque
     * pixels).
     *
     * @param format   The format of the compressed image
     * @param quality  Hint to the compressor, 0-100. 0 meaning compress for
     *                 small size, 100 meaning compress for max quality. Some
     *                 formats, like PNG which is lossless, will ignore the
     *                 quality setting
     * @param stream   The outputstream to write the compressed data.
     * @return true if successfully compressed to the specified stream.
     */
    public boolean compress(CompressFormat format, int quality, OutputStream stream) {
      ...
    }

public boolean takeScreenshot(File storePath, int quality) {
        Bitmap screenshot = mUiAutomation.takeScreenshot();
        ...
        BufferedOutputStream bos = null;
        try {
            bos = new BufferedOutputStream(new FileOutputStream(storePath));
                screenshot.compress(Bitmap.CompressFormat.PNG, quality, bos);
        }
  ...
        return true;
    }
AI 代码解读

根据以上安卓源码,跟踪到系统压缩方法。看注释,似乎发现了问题所在,看 takeScreenshot 方法, 调用了 Bitmap 的 Compress 压缩方法,传的参数写死了 Bitmap.CompressFormat.PNG,格式,根据注释说明,Compress 方法又对 png 格式图片的压缩忽略的,所以导致获取到的图片都很大。马上重写系统方法,直接调用压缩方法,传入 JPEG 去验证可行性,马上得出了解决方案。

找到问题所在,解决方案也就出来了,主要改造逻辑可以通过三个核心步骤完成:

  1. 自行获取 Bitmap 文件。
  2. 调用 Bitmap 压缩方法,指定 jpeg 格式,并传入自定义压缩值。
  3. 获取压缩流数据,直接 Base64 编码传递给 SDK 层。

通过以上优化,减少了两次文件读写,并且有效压缩了图片大小,整体一次截图时间控制在了 200-800ms,对比原来速度最少提升 2-3 倍以上。

2.突破系统安全限制做到截图全覆盖

Totoro 的最大业务需求 来自 钱包系 相关 App 的自动化业务,而支付宝属于安全隐私要求较高
App,各个 ROM 针对钱包或者钱包自身都会做大量安全保护,例如在密码输入页面或转账页面,会导致截图获取失败,并且我们发现有些限制级别较高页面,连系统自身的截图功能也无法使用。

但是在测试场景下,数据及安全级别是可控的,多个业务线强烈提出 能否通过技术手段 获取到这些被限制的页面截图,来满足业务验证逻辑的正确性,去除人工页面截图审核死角,来进一步提高研发效能质量。

由于 Totoro 框架是对 App 是非侵入式的,也给我们的技术实现添加来不小挑战。但是,本着业务价值首位考虑,为了保障开发者使用效率,我们开始调研安卓各种截图方案,跟踪安卓截图源码,试图采用Hook方式绕过安全校验机制。

针对安卓平台各种全局截图方法的深入研究,最后发现,各种入口类的系统接口调用到底层都会调用SurfaceControl类或对应的 c 层代码, SurfaceControl 类成了关键研究对象。然而,从 Java 层的 SurfaceControl 类中各种 Hook 接口调用尝试发现,只要被安全页面限制,该方案下的截图方案就会失败或截到一张黑屏。这意味着系统针对截图的安全限制可以覆盖到目前我们了解到的任何场景,让我们的解决方案一时陷入困境,失去了思路方向。

然而在做 SLM 云测平台设备远程租用过程中,发现录屏功能在这些截图限制页面依然是可以正常使用,这说明系统或安全限制只是针对截图相关 API,这给我们的截图提供了新的思路,通过录屏来获取屏幕截屏。所以开始研究系统的录屏功能,能否在录屏过程中拉一帧的画面,作为截图新的实现方式。

A.自研技术方案

实现原理很简单,通过直接解码 Surface 获取屏幕视频流,然后从视频中获取一张可用帧,转换为 JPEG 格式,最后回传给 PC 上的接口。该方案从 Java 层实现,兼容性强,成本底,下面是关键代码逻辑:

    MediaCodec mcodec = MediaCodec.createEncoderByType("video/avc");//创建解码器
    Surface surface = codec.createInputSurface();//构造目标Surface
    SurfaceControl.setDisplaySurface(display, surface);//通过反射SurfaceControl,将构造的Surface设置到系统
     int outputBufferId = codec.dequeueOutputBuffer(bufferInfo, -1);//开始解码
    //判断有效帧
    ...
    Bitmap  bitmap = mediaMetadataRetriever.getFrameAtTime(index);//获取屏幕bitmap值
    bitmap.compress(Bitmap.CompressFormat.JPEG, quailty, fos);//保存截图
    ...
    //截图回传到PC接口层
AI 代码解读

然后就是打包程序,利用系统 app_process 服务,可以避开各种权限弹窗问题,直接运行程序,即可获取到屏幕截图。
目前该方式已全面应用到 Totoro 底层截图方案,可以兼容安卓 5.0-10 版本,但是仍然有改进地方,后续还可从以下几点进一步优化:

  • 视频流有效帧判断逻辑优化,减少截图时间。
  • 目前仍然需要一次手机端的文件保持读写逻辑,后续可考虑读流方式,直接获取图片 Base64 值。
  • 可执行文件参数标准化,可满足多场景技术输出。
B.备用兜底方案

以上 A 方法主要针对 5.0+ 的安卓设备,且针对个别 OPPO、VIVO 设备开启了系统恶意录屏功能,就会造成录屏功能限制,引起截图失败。针对这部分的设备,我们设想 Android 能否像 Linux 系统一样,绕过 Java 层权限限制,直接从C层读取操作系统 framebuffer(Linux 设备/dev/graphics/fb0),来获取屏幕图像。

期间调研了开源的 minicap 录屏方案,发现 Surface 方案在个别设备不能兼容情况下, minicap 依然可以使用,其底层原理就是采用 NDK 开发的工具,直接读取操作系统 framebuffer,为了不重复造轮子,决定把 minicap 工具中的手机端的服务单独剥离出来集成到 Totoro,作为备用兜底方法提供截图能力。

String cmd = String.format("adb -s %s shell LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/minicap -P %sx%s@%sx%s/0 -Q 90 -s -t > %s", deviceId, w, h, w, h, localPathFile);
AI 代码解读

按照上面命令单独调用 minicap 工具截图,并从流中解析到图片保持到制定目录,经大量测试,该命令并不一定稳定,有时会报格式错误,有时会报流处理错误,所以我们添加了降级方案,如以下命令。

String cmd = String.format("adb -s %s shell \"LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/minicap -P %sx%s@%sx%s/0 -Q 90 -s -t > /sdcard/.totoro/%s\"", deviceId, w, h, w, h, name);

//然后将图片Pull到PC上制定目录
AI 代码解读

两种技术方案相互降级搭配使用,这样正好弥补了 Java 层 Surface 方案的一些可能失败场景,作为兜底方法集成到了 Totoro 框架中,目前为止暂未发现两种方法都失败场景,保障了截图能力的底盘稳定性。

业务多场景支持

1.基础截图场景

通过以上相关多层技术方案兼容,Totoro 目前可以提供稳定的基础截图能力,业务层无需关注底层的具体技术实现方案或兜底方案,只需要调用一个 Totoro 实验 SDK 暴露的 API 即可。

    String path = BizUtils.saveScreen(name);
AI 代码解读

2.长截屏技术方案

长截图能力一直是业务方提出的痛点需求,一直到 19 年末我们才抽出时间弥补了 Totoro 这块能力缺失。
起先,先调研了行业内其他实现方案,基本思路都是滑动截图,然后合并多张截图,最后生成长截图。然而,难点在多张截图的完美合并,针对移动端的页面截图,存在页头、页尾、小 banner 更新、小红点等多重影响,给长截图的实现增加了不少难度。

可行方案分析:

  1. 直接利用第三方拼接工具。需要添加额外依赖,其在移动端个别极限场景拼接存在问题,维护成本高。
  2. 利用算法部门资源,特征值直接匹配。需要添加算法库,且要推动算法部门不断迭代更新,后续更新可能不及时。
  3. 自己实现一套,难度大,初期成本高。需要兼容移动端页面各种情况,但是后续维护成本低,升级方便且及时。

权衡利弊后,最终我们采用了方案 3,决定自己实现了一套针对移动端截图特征的拼接能力,采用了自研像素行灰度值末尾优先对比技术方案,核心逻辑思路是默认向上滑动生成的图片组,两两从底部优先开始对比行像素的灰度值,找到拼接点和裁剪点。为了减少噪点及个别红点、红线、小 banner、及底部导航栏影响,在不同的对比点及区域添加了对应的参数。其核心代码思路如下:

    public static File mergeImg(File imgA, File imgB, String mergedImgPathName) {
            int[][] listA = getPX(imgA);//获取像素数组
            int samePartEnd = 0, sameBottom = srcALen;//定义查找目标位置
            int samePart = mergeLen >> 2;//定义相似颗粒
            for (int al = Math.max(0, listA.length - mergeLen + (samePart >> 1)), l = listA.length - 1; l >= al; l--) {
                for (int x = mergeLen - (listA.length - l), y = Math.max(0, (samePart >> 1)); x >= y; x--) {
                    if (compareRowPx(listA[l], listB[x])) {// 对比行灰度相似度
                        //找到基础对比点
                        for (int i = 0, partLen = (l == listA.length - 1) ? samePart : samePart >> 1; i < partLen; i++) {
                            //寻找拼接点
                            if (compareRowPx(listA[curA], listB[curB])) {
                                if (i == partLen - 1) {
                                    //相同区域达到阀值,找到拼接点
                                    samePartEnd = x;
                                    sameBottom = l - 1;
                                    break;
                            } else {
                                //寻找底部相同区域,如底部导航Tab栏
                                break;
                            }
                        }
                        if (matchedBottom || samePartEnd > 0) {
                            //拼接参数找到,提取结束循环
                            break;
                        }
                    }
                }
            }

            String fileSuffixA = getFileRealExt(imgA);//读取二进制流,获取原始图文件真实后缀
            String fileSuffixB = getFileRealExt(imgB);
            String fileSuffixC = mergedImgPathName.substring(1 + mergedImgPathName.lastIndexOf("."));
            if (samePartEnd == mergeLen - 1) {
                //图片相同,直接返回第一张图片
                imgA.renameTo(file);
                return file;
            }
            //开始合并逻辑
            int newY = srcALen - (srcALen - sameBottom) + (mergeLen - samePartEnd);
            ...//读取原始图片值
            if (sameBottom > 0) {
                  //    去除底部导航tab栏
            } else {
                //没有底部操作tab栏
                newA = reader.read(0);
            }
            ...//重新拼接图片
            imgNew.setRGB(0, newA.getHeight(), width, newB.getHeight(), imgArrayB, 0, width);
            ImageIO.write(imgNew, fileSuffixC, file);
              ..//其他资源回收
            return file;
    }
AI 代码解读

效果图如下:

totoro - 长图.png

该方案目前已全量上线,并且满足了目前业务方需求,在遇到长截图拼接有重叠或缺少问题时,也可以通过调节对比参数,快速优化合并逻辑代码,达到了既定研发目标。

3.局部控件截图

在自动化过程中,有些业务需要获取某个控件的截图, iOS 端可以通过 WDA 相关接口实现,但是安卓端是没有现成方案的。因此,Totoro 采用了按照坐标截图切割方式,结合控件坐标信息,可以在 PC 端实现一套局部控件获取方法。该 API 可以同时适用到
iOS 和安卓双平台,局部控件截图核心实现思路:

    src = BizUtils.saveScreen(name);
    WebElement element = driver.findElement(By);
    ...//根据element获取到element的坐标信息
    ImageCheckUtils.imageCut( src,  dest,  x,  y,  width,  height);//根据坐标信息切图,获取到控件截图dest文件
AI 代码解读

4.多屏幕截屏

目前 Totoro 中只集成了 adb 原生方式,用来为一些支付 IoT 设备,提供多屏幕截图能力。

#附屏幕截屏
adb shell screencap -d /dev/graphics/fb1 fb1.png
#主屏幕截屏
adb shell screencap -d /dev/graphics/fb0 fb0.png
AI 代码解读

后续根据需求反馈,会调研采用 UIAutomater 或 Surface 方式实现。

图像智能算法分析

Totoro 借助兄弟团队(工程数据技术组)的算法能力,针对截图实现了页面智能分析、检测等能力,完成了图片相关技术体系小闭环。智能算法能力集成可以归类为以下三种。

1.控件分析

Totoro -图片2.png

如上截图所示,可以通过以下 API 获取页面控件信息,可识别控件类型如 button、image、label、progress、switch、more、editView、popUp、checkBox、return、close 等。

2.页面异常检测

异常检测能力可抽象分为通用异常和业务异常,具体说明如下:

  • 通用异常分析,如:黑白屏、加载失败、图片或文字截断,控件排列重叠等常见页面 UI 问题;
  • 业务异常分析,如:业务弹窗、授权弹窗阻断等,且更加不同的业务异常场景需求,可定制化服务。

Totoro 中可通过一个接口获取页面异常信息,业务中通过自动化的检测,完成了之前很多无法实现的自动化场景。

3.业务场景识别

为实现更加智能的页面分析,为后续自动化测试场景中自遍历或自填充提供基础能力支撑,依赖算法能力可以智能分析当前页面场景,例如可以通过算法相关接口来自动判断当前页面属于哪个业务流程,比如登录流程场景、输入场景等。

目前内部只开放了登录场景的识别,已上线并应用到小程序自动化注入及巡检场景,可以代替小程序登录繁杂脚本工作量,大大减少用例脚本维护成本。

4.图片相似度分析

totoro 效果对比.png

如上两张截图,由于存在大面积 Banner 变化和背景渐变颜色差异,如果单纯通过像素对比,很难分析出是一个页面上的截图,这里主要借助算法能力,通过提取页面特征值、图像指纹、颜色通道等多维度来精确计算出两个截图的相似度。

Totoro 图.jpeg

如以上截图所示,可以通过 Totoro 封装的 API 得出两张图相似度为 54,业务层代码可通过相似度应用到自己的实际业务场景。(只要相似度 >=50 则可认为两个截图是一个相似业务场景)

后续计划

针对很小的一个图片业务能力,都需要投入量巨大的努力 来保障 Totoro 的自动化底盘易用性和稳定性,业务不断扩张过程中,图片相关能力体系还是有多个细节仍需要不断调优,其中明确需要投入研究和后期开发计划有以下几点:

  • 截图技术方法模块化抽离,进一步优化调用链路,加快整体截图获取速度。
  • 长截图技术方案优化,泛化拼接方向,组件化包装,可单独灵活对外输出技术能力。
  • 多屏截图场景优化,调研更加便捷稳定的多屏截图方案,满足越来越多的 IoT 场景。
  • 进一步推动算法能力深化,通过埋点上报,加大算法数据闭环支持。
目录
打赏
0
0
0
0
38
分享
相关文章
PP-DocBee:百度飞桨多模态文档解析神器,中文场景SOTA准确率一键提取表格图表
PP-DocBee 是百度飞桨推出的专注于文档图像理解的多模态大模型,基于 ViT+MLP+LLM 架构,具备强大的中文文档解析能力,适用于文档问答、复杂文档解析等场景,支持多种部署方式。
102 1
穿戴科技新风尚:智能服装设计与技术全解析
穿戴科技新风尚:智能服装设计与技术全解析
118 85
HarmonyOS Next~鸿蒙AI功能开发:Core Speech Kit与Core Vision Kit的技术解析与实践
本文深入解析鸿蒙操作系统(HarmonyOS)中的Core Speech Kit与Core Vision Kit,探讨其在AI功能开发中的核心能力与实践方法。Core Speech Kit聚焦语音交互,提供语音识别、合成等功能,支持多场景应用;Core Vision Kit专注视觉处理,涵盖人脸检测、OCR等技术。文章还分析了两者的协同应用及生态发展趋势,展望未来AI技术与鸿蒙系统结合带来的智能交互新阶段。
54 31
深入解析Tiktokenizer:大语言模型中核心分词技术的原理与架构
Tiktokenizer 是一款现代分词工具,旨在高效、智能地将文本转换为机器可处理的离散单元(token)。它不仅超越了传统的空格分割和正则表达式匹配方法,还结合了上下文感知能力,适应复杂语言结构。Tiktokenizer 的核心特性包括自适应 token 分割、高效编码能力和出色的可扩展性,使其适用于从聊天机器人到大规模文本分析等多种应用场景。通过模块化设计,Tiktokenizer 确保了代码的可重用性和维护性,并在分词精度、处理效率和灵活性方面表现出色。此外,它支持多语言处理、表情符号识别和领域特定文本处理,能够应对各种复杂的文本输入需求。
63 6
深入解析Tiktokenizer:大语言模型中核心分词技术的原理与架构
RTSP协议规范与SmartMediaKit播放器技术解析
RTSP协议是实时流媒体传输的重要规范,大牛直播SDK的rtsp播放器基于此构建,具备跨平台支持、超低延迟(100-300ms)、多实例播放、高效资源利用、音视频同步等优势。它广泛应用于安防监控、远程教学等领域,提供实时录像、快照等功能,优化网络传输与解码效率,并通过事件回调机制保障稳定性。作为高性能解决方案,它推动了实时流媒体技术的发展。
阿里云服务器ECS通用型规格族解析:实例规格、性能基准与场景化应用指南
作为ECS产品矩阵中的核心序列,通用型规格族以均衡的计算、内存、网络和存储性能著称,覆盖从基础应用到高性能计算的广泛场景。通用型规格族属于独享型云服务器,实例采用固定CPU调度模式,实例的每个CPU绑定到一个物理CPU超线程,实例间无CPU资源争抢,实例计算性能稳定且有严格的SLA保证,在性能上会更加稳定,高负载情况下也不会出现资源争夺现象。本文将深度解析阿里云ECS通用型规格族的技术架构、实例规格特性、最新价格政策及典型应用场景,为云计算选型提供参考。
可穿戴设备如何重塑医疗健康:技术解析与应用实战
可穿戴设备如何重塑医疗健康:技术解析与应用实战
33 4
AI技术如何重塑客服系统?解析合力亿捷AI智能客服系统实践案例
本文探讨了人工智能技术在客服系统中的应用,涵盖技术架构、关键技术和优化策略。通过感知层、认知层、决策层和执行层的协同工作,结合自然语言处理、知识库构建和多模态交互技术,合力亿捷客服系统实现了智能化服务。文章还提出了用户体验优化、服务质量提升和系统性能改进的方法,并展望了未来发展方向,强调其在客户服务领域的核心价值与潜力。
51 6
静态IP代理与动态IP代理:提升速度与保障隐私的技术解析
本文探讨了静态IP代理和动态IP代理的特性和应用场景。静态IP代理通过高质量服务提供商、网络设置优化、定期更换IP与负载均衡及性能监控提升网络访问速度;动态IP代理则通过隐藏真实IP、增强安全性、绕过封锁和提供独立IP保障用户隐私。结合实际案例与代码示例,展示了两者在不同场景下的优势,帮助用户根据需求选择合适的代理服务以实现高效、安全的网络访问。
41 1

热门文章

最新文章

推荐镜像

更多
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等