技术 · 2026年11月4日 · 阅读约 5 分钟
Android 模拟器镜像现已达到 60 fps
Device MCP 现在能以 60 fps 显示 Android 模拟器绘制的每一帧。本文介绍模拟器镜像以前为什么卡顿、我们测量了什么,以及做了哪些改变。
作者:Device MCP 团队

Device MCP 刚支持 Android 模拟器时,iPhone 和 iOS 模拟器的镜像已经达到 60 fps,模拟器却没有。滚动一顿一顿的,视频卡顿,画面一复杂,帧率可能掉到 10 fps。
Android 模拟器的镜像现已达到 60 fps。Device MCP 会显示模拟器绘制的每一帧,而这些帧由你 Mac 的 GPU 绘制。下面是同一个 YouTube 视频在同一台模拟器上,之前和现在的对比:
视频里的数字不是手动填上去的,而是逐秒统计每段录像中新出现的画面得出的。
我们测量了什么
一台运行 Android 16 的 Pixel 9 Pro 模拟器,在 YouTube 中以 1080p60 全屏播放 Big Buck Bunny,运行在搭载 M5 Max 的 MacBook Pro 上。对每种配置,我们读取两个数字:Android 自身把视频的新一帧显示到屏幕上的频率(来自 SurfaceFlinger 自己的时间戳),以及有多少新画面到达了 Mac。
| 配置 | Android 绘制 | 你看到的 |
|---|---|---|
| 之前的 Device MCP:模拟器不带窗口,使用 scrcpy 的 H.264 视频 | ~44 fps | ~23 fps |
| Android Studio 对 Android 16 的默认设置(Automatic 图形) | ~45 fps | ~45 fps |
| 现在的 Device MCP:使用 Mac 的 GPU 和模拟器自己的视频流 | 60 fps | 60 fps |
视频是个公平的测试,但不是最难的。在软件渲染的配置下,重绘整个屏幕的页面(比如 canvas 动画)只能画到 10 到 15 fps。那些“10 fps”的反馈就是这么来的。
拖累旧镜像的有两件事:模拟器的绘制方式,以及画面传到 Mac 的方式。
问题一:软件渲染
Android 模拟器既可以用 Mac 的 GPU 绘制,也可以在 CPU 上用软件绘制。Device MCP 以前用 -no-window 启动模拟器,因为它的镜像就充当了模拟器的窗口。没有自己的窗口时,模拟器会选择软件渲染器:SwiftShader 或 Lavapipe。
Android 16 让情况更糟。在 Mac 上,模拟器的 Automatic 图形设置对 Android 16 系统映像也会选择软件渲染(“API level 36 requires GLES 3.1”)。所以,用默认设置从 Android Studio 启动的模拟器,同样是软件绘制。对大多数界面来说这没问题,但全屏视频或动画会吃掉它能拿到的所有 CPU 核心。
问题二:在 Android 内部编码
Device MCP 以前用 scrcpy 获取屏幕画面。scrcpy 在真机上表现出色:它在 Android 内部运行,捕获屏幕画面,并用手机的硬件视频编码器编码成 H.264。
模拟器没有硬件编码器。scrcpy 只能退回到 Android 的软件编码器,而它运行在模拟器自己的虚拟 CPU 上,也就是正在绘制你所看 App 的那些 CPU。在上面的测试中,编码器占用的 CPU 比模拟器里任何其他东西都多,镜像只拿到了 Android 所绘制帧数的一半左右。打开 GPU 也无济于事:这时 scrcpy 必须在编码前把每一帧从 GPU 拷贝回来,镜像掉到了 3 到 5 fps。
解决方法:模拟器自己的屏幕
Android 模拟器本来就有一条快速通道。它在你的 Mac 上运行一个 gRPC 服务,其中一个调用 streamScreenshot 会在模拟器绘制出新一帧的那一刻,把这一帧以原始 RGB 像素发送出来。Android Studio 就是这样在它的 Running Devices 窗口中显示模拟器的。
Device MCP 现在也这样做:
- 直接读取模拟器的帧:不做任何编码或解码。Device MCP 从每个模拟器都会写入的发现文件中找到它的服务,把每一帧转换为 Mac 的像素格式并显示到屏幕上。一帧 Pixel 9 Pro 画面有 11 MB,每秒 60 帧就是约 660 MB/s。这对网络来说很多,但对一台 Mac 自己和自己通信来说不值一提。
- 以隐藏窗口、GPU 渲染的方式启动模拟器:Device MCP 现在运行
emulator -avd <name> -qt-hide-window -gpu host -grpc-use-token,也就是 Android Studio 用于其内嵌模拟器的那些参数,再加上硬件图形渲染。如果你在 Android Studio 中把某个 AVD 设为 Software,Device MCP 会尊重这个设置。 - scrcpy 保留,但只负责输入:它的服务端仍负责发送你的点击、按键、文本和剪贴板,视频功能则已关闭。触控的落点与以前完全一致。
Inspector 会显示镜像走的是哪条路径。对于模拟器,Mirror 现在显示 emulator gRPC,Quality 显示的是 RGB 格式的完整屏幕分辨率:

在别处启动的模拟器
你什么都不用改。当 Device MCP 准备镜像一台无法以 60 fps 串流的模拟器时(比如 Android Studio 以软件渲染启动的,或脚本用 -no-window 启动的),它会自动用快速的方式重新启动这台模拟器。启动画面会显示 15 到 20 秒,Agent 的 MCP 调用会一直等到它恢复。每次运行 Device MCP 时,每台模拟器只会这样重启一次。
有几点需要了解:
- 第一次重启是冷启动:软件渲染时保存的 Quick Boot 快照无法在 GPU 上加载,所以原来打开的 App 会被关闭。已安装的 App 及其数据都会保留。之后的重启会保留快照。
- 调试会话会结束:如果 Android Studio 正在这台模拟器上运行或调试你的 App,Device MCP 重启模拟器时,这个会话会停止。Android Studio 的 Running Devices 窗口会自动重新接上这台模拟器。
- 以你的参数为准:如果模拟器启动时用了 Device MCP 不会传入的选项,例如
-writable-system、-http-proxy、-port或软件渲染的-gpu,Device MCP 会原样保留它,按它能达到的速度镜像。
对 Agent 意味着什么
和以前一样,Agent 的截图来自 Android 本身。不过,当 Agent 询问屏幕上有什么、而辅助功能树又给不出答案时(比如在游戏或 Web 视图中),Device MCP 还会读取镜像画面,识别其中的文字。这个画面现在是未经压缩的完整 2856×1280 屏幕,而不是缩小到 2048 像素的 H.264 帧,所以小字识别得更清楚。
测量方法
视频由 Device MCP 窗口的两段录屏组成,它们先后录制,使用同一台模拟器、同一个 YouTube 视频和同一个画质设置,再按影片的场景切换对齐。模拟器的视频流只在屏幕变化时才发送一帧,所以每次更新都算作一个新画面。scrcpy 的解码器也会显示与上一帧几乎没有差别的帧,所以对于旧路径,我们只统计有明显变化的帧。录屏工具本身每 60 帧只能捕获 57 或 58 帧,这就是视频里的计数差一点到 60 的原因。“Android 绘制”一栏来自 SurfaceFlinger 的帧时间戳,Android Studio 的数字则来自读取其 Running Devices 窗口所读取的同一视频流。你的数字会因 Mac、AVD 和屏幕内容而异,但差距依然存在。
试试看
更新 Device MCP,从侧边栏启动一台模拟器,然后播放一些动起来的内容。
Big Buck Bunny © copyright 2008, Blender Foundation, peach.blender.org,采用 CC BY 3.0 许可协议。
下一步
- 文档Android 模拟器在 Device MCP 中启动、镜像和控制 Android Studio 模拟器,并让 AI Agent 用同一套 MCP 工具在模拟器上测试你的 Android App。
- 文档MCP将 Claude Code、Codex、Cursor 或任何 MCP 客户端连接到 Device MCP,让 AI Agent 在 iPhone 和 iPad 上查看、轻点、输入和测试。
- 文档Android 设备即将推出在 Mac 上镜像和控制 Android 手机与平板电脑,并让 AI Agent 在上面进行测试。即将推出。
Device MCP 由 Proxyman LLC 打造,我们也开发了
Proxyman、
Tiny Shield 和
TCP Viewer。