转转QA IOS 远程真机控制实践

笑哼 for 转转QA · 2019年05月26日 · 最后由 哲豪 回复于 2019年08月30日 · 4814 次阅读

作者 | 赵新源

简介

移动端的远程控制是为了将手机资源更好的分配,提高利用率,可以提供给用户更丰富的选择。现阶段我们完成了 Android 的 stf 搭建,并做了一些二次开发,以适应我们的移动端管理平台(MCP)。在 IOS 方面,由于相关技术一直比较封闭,没有非常成熟的开源技术可供选择,所以我们经过一段时间调研以及试错,还有客户端组同学的帮助下,完成了 IOS 远程控制的基本功能,目前可以提供给用户使用。

方案调研

远程控制就是用户通过浏览器实现远程 ios 设备的查看和操作,所以我们有以下几个主要目标:

  • 远程真机画面可以实时在用户浏览器上流畅显示
  • 用户可以在浏览器上实时操作远程真机
  • 提供常用的功能以方便用户便捷使用(比如实时日志和安装应用)
  • 尽可能的减少硬件资源占用

为了解决这些问题,我们调研了比较多的技术方案。在手机操作这块我们调研了常用的 ios 自动化驱动,主要有:

  • WedDriverAgent
  • 苹果官方提供的 XCTest 和 XCUITest
  • Appium
  • UIAutomation

经过调研分析,UIAutomation 在 xcode8 以后就被弃用了,所以不做选择。Appium 在 iOS 自动化测试中使用了 WDA 作为事件驱动,而 WDA 底层使用的是苹果的 XCTest 以及 XCUITest。所以我们选择 facebook 开源的 iOS 自动化框架 WedDriverAgent 作为 iOS 驱动技术方案。
在桌面获取技术方面有以下几个方案:

IOS-Minicap
最开始的时候因为 stf 的使用给我们留下了深刻的印象,所以在 IOS 这块第一个想到就是 openstf 里面提供的 IOS-Minicap 组件,在做示例的时候发现视频流确实非常的流畅,能够达到 30 帧的速度,但是不幸的是 IOS-Minicap 的截图方式不支持一个 mac 同时对应多台 ios 设备,其原理是使用 AVFoundation 和 CoreMediaIO 库函数实现的屏幕获取。
Airplay Mirror
Airplay 是苹果提供的一种多媒体多屏互动技术,就是将数据通过局域网的方式传输,因为这个是苹果私有协议方案,传输的数据进行了加密,只能逆向破解,技术难度很高,所以暂不做考虑。
Idevicescreenshot
idevicescreenshot 属于开源工具集 libimobiledevice 的子集,可以在 pc 上对连接的 ios 设备进行截图,将图片保存在本地,但是效率比较慢,大概在 3~5 帧左右,也有人提出过对这个工具进行修改,不保存图片到本地,直接进行图片传输,效率应该会有提高,但我们没有具体尝试过,感觉这个成本比较高。
二次开发的 wda
wda 本身就提供手机操作以及截图功能,所以对 wda 进行二次开发来实现远程控制,也能更简单的维护整个服务,二次开发主要包括通过 websocket 进行截屏数据通信,优化操作事件的效率等。这样就能提供稳定高效的远程控制服务。

架构设计


因为我们已有设备管理平台,这个是对其缺失的 ios 远程控制进行的补充,所以只有 master Web 服务和连接设备的 agent 端,用户的浏览器客户端通过 Websocket 和 agent 通信,再通过 libimobiledevice 的开源工具 iproxy 对数据进行 Mac 主机和 ios 设备之间的转发。

细节问题解决方案

整个项目最主要的部分就是设备的查看和操作,如何提高效率是至关重要的,因此我们对 wda 进行了二次开发,主要针对的就是截图的效率,数据的传输,事件驱动等,接下来我们就对这些点进行分析。

  • 截图效率 在参考 fork 版本 guadaran/WebDriverAgent 中,我们找到了更为高效的截图方法 https://github.com/guadaran/WebDriverAgent 截图的速度可以达到 20ms-30ms 之间,但是图片的大小会比较大,对网络 IO 要求比较高,所以我们要对其进行压缩。 根据不同的业务要求,我们可以在有限的网络资源下尽可能的调整 scale 的值(0.1-1),但是这个压缩的过程随着值的提高,所耗费的时间也在增加,如果是 1 的话可能需要和截图一样的时间,这样就会降低我们的帧率,所以我们根据不同的分辨率手机设置不同的 scale 值,像 iPhone X 我们设置的就是 0.4,这样就能保证一次完整的截图所耗时在 40ms 内,在保证流畅度的情况下使它的清晰度更高。
  • WDA 应用资源消耗 在不断截图的过程中,截图的速度上来了,消耗的资源也变高了,当 cpu 长时间过高后,或者内存消耗不断增加的过程中,都会导致我们的应用崩溃掉,所以我们在截图效率和资源消耗之间做了妥协,截图的间隔时间根据设备的性能而定,同时也要及时释放一些图片的对象,比如 @autoreleasepool {}
  • Websocket 通信 在已有的 wda 中引入 websocket,添加开启和关闭接口。在开启远程控制的时候开始建立 websocket 连接并根据需要附带一些处理,比如先前的压缩比例。还有就是在网络资源比较紧张的时候,对于 websocket 传输数据,我们可以做一些优化,如果两张图片一样的话,我们可以不让它反复的发送出去,这样可以减少大量的网络 IO,只有需要的图片数据被客户端接收。
  • 操作事件 wda 里面的操作事件比如 tap、swipe、dragfromtoforduration 等,都是有同步等待机制的。所以我们替换成 XCEventGenerator.h 私有 api 实现,这样的话操作事件执行效率非常的高。以前一个操作可能要等待 2s、5s 甚至更长的时间,现在可以做到命令下发即可执行。比如: 很多事件都可以通过 pressAtPoint 这个方法模拟出来

后期规划

  • 在我们的 ios 远程真机控制实践方案中,视频流可以达到 20 帧之上,事件流在毫秒级别,一台 Mac mini 可以连接 10 台以上的 ios 设备,实际的使用体验可以逼近测试人员真机测试使用的感受。
  • 同时我们还有许多需要继续优化的部分,比如 ios 操作易用性的提高、ios 代理设置、多机操作、UI 自动化测试整合等,我们也会不断打磨产品,提供更好的使用体验。
共收到 8 条回复 时间 点赞

牛 X~(破音)

handleTap 的那个函数,你把下面的那个 shouldApplyOrientationWorkaround 注释了,手机横屏的时候,点击坐标不会出错吗?

codeskyblue 回复

首先我们这边的设备都没有横屏实时传输的需求,横屏状态下确实点击会出错,如果有横屏需求的话,这个时候是不是可以对这个异常捕捉下,然后对其处理呢?

笑哼 回复

你把注释掉的那行保留了就 ok

codeskyblue 回复

嗯嗯

求 git 地址拜读下,谢谢啦!

求 git 地址拜读下

求 git 地址拜读下,谢谢

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