Skip to content

Latest commit

 

History

History
233 lines (166 loc) · 11 KB

File metadata and controls

233 lines (166 loc) · 11 KB

Aether Enhanced Tools(AET)

AET 是运行在Aether Engine虚拟机(Windows / Linux Guest)里的增强工具(Guest Additions),用于把 Guest 和宿主侧的 HarmonyOS 能力打通,并提供更像“原生系统功能”的集成体验(文件互通、碰一碰/分享联动、分布式相机、诊断与自动修复等)。

  • Aether Engine(仅一句话):Aether Engine 是宿主侧的 HarmonyOS 虚拟机 App(负责启动 QEMU、提供共享目录与系统能力)。AET 是它的配套 Guest 工具。

我们要解决的核心问题(AET 视角)

  • Guest ↔ Host 能力桥接:Guest 内的 AET 通过统一协议请求 Host(HarmonyOS App)能力,并拿到结果/数据。
  • 稳定在线与诊断:AET 常驻(Agent)维持在线心跳,UI 展示状态并引导修复(共享目录未挂载/驱动缺失/权限不足等)。
  • 统一交付体验(安装器):一个 AetherEnhancedToolsSetup.exe 完成:
    • VirtIO 必要驱动(共享目录 + vioserial)
    • AET(Agent + UI)
    • QEMU Guest Agent(QGA,可选但推荐)
  • 跨平台与多架构
    • 当前优先:Windows 11 ARM64 / Linux ARM64
    • 未来扩展:Windows x64 / Linux x64

总体架构(AET 专注版)

  • Guest 侧(你这个 .NET 解决方案要做的)

    • AetherEnhancedTools.Agent(常驻服务):负责在线/心跳、桥接调用、后台任务、对 UI 提供本机接口
    • AetherEnhancedTools.UI(Avalonia):负责可视化、用户操作入口、诊断与修复向导
    • AetherEnhancedTools.Core(共享库):协议、模型、日志、配置、跨平台工具
  • 通信通道(关键)

    • 共享目录(Linux:virtio-9p;Windows:virtio-fs/viofs;tag=hostshare:Guest 能看到一个“共享目录挂载点”(具体路径/盘符取决于 Guest 系统与驱动)。只要这个目录里能看到 .aether_bridge/req.aether_bridge/res,就算对接成功。
    • Aether Bridge(文件型 RPC):在共享目录里用 .aether_bridge/ 做“写请求文件→等响应文件”的 RPC

重要:AET Phase 1 选择“文件型 RPC”,避免长连接/端口/权限策略导致的不稳定;Host 侧可以严格控制权限边界(例如 Host 不把 QMP 暴露给 Guest)。

补充约定(Host↔Guest 对齐):

  • 共享根目录包含两个关键入口:
    • .aether_bridge/:内部协议目录(RPC + host_input 状态流),不建议作为用户文件入口
    • nearby-huaweis/:用户可见目录(“附近的华为”入口,适合做快捷方式/盘符映射)
  • 详见:docs/shared-folder-layout.md

解决方案结构(.NET 8)

你目前负责的 AetherEnhancedTools.sln 当前包含 5 个项目(都是 .NET 8):

  • AetherEnhancedTools.Core(Class Library)

    • 职责:跨平台“核心逻辑”,被 Agent 与 UI 共用
    • 建议内容
      • Aether Bridge 客户端:写 req/*.json、等待 res/*.json、timeout/重试、原子写(tmp→rename)
      • 协议模型:hello/heartbeat/status、统一错误码与日志结构
      • 挂载点探测:hostshare 是否可用、.aether_bridge 是否存在
      • 配置系统:JSON 配置、版本信息、feature flags
  • AetherEnhancedTools.Agent(Worker Service)

    • 职责:Guest 内“常驻 Agent”
    • 建议内容
      • 启动即 aet.hello,循环 aet.heartbeat(保持在线 TTL)
      • 维护本机状态(驱动/挂载/QGA 服务/网络等),暴露给 UI
      • 未来:订阅/消费 evt/(Host→Guest 事件),执行后台任务(文件同步/虚拟相机/剪贴板等)
    • 部署形态
      • Windows:最终做 Windows Service(或开机自启)
      • Linux:systemd service(或用户态 daemon)
  • AetherEnhancedTools.UI(Avalonia App)

    • 职责:给用户看的界面(Fluent 风格)
    • 建议界面模块
      • Dashboard:在线状态、版本、挂载点、最近一次错误与修复建议
      • Files:文件传输/“带来带走”辅助入口
      • Devices/Camera:分布式相机、设备列表等能力入口
      • Settings:开机自启、日志级别、实验功能开关

当前仓库已包含 AetherEnhancedTools.Setup(安装器/GUI)。另外 guest_aet/windows_setup/aether_enhanced_tools_setup.cpp 仍保留为 Windows Guest 侧的“引导/驱动安装”逻辑参考。

现在仓库里已新增 AetherEnhancedTools.Setup(Avalonia GUI 安装器),并提供脚本把 UI+Agent 发布产物打包进一个 Setup.exe

  • 说明文档:docs/windows-installer.md
  • 生成内置 payload:tools/installer/build_aet_bundle.ps1

Aether Bridge(文件型 RPC)协议(Phase 1:强烈建议先跑通)

协议版本aether.bridge.v1
位置:共享目录内:<mount>/.aether_bridge/

目录结构:

  • req/:Guest → Host 请求(*.json
  • res/:Host → Guest 响应(<requestId>.json
  • evt/:预留(Host→Guest 事件)
  • blob/:预留(大数据/文件载荷:相机帧等)
  • host_input/:Host → Guest 高频输入状态流(多指/笔压),不走 req/res(详见:docs/host-input-bridge.md

请求文件规则(必须遵守):

  • req/<id>.json.tmprenamereq/<id>.json(避免 Host 读到半截文件)

最小握手(必须):

  • aet.hello:启动后先发一次(版本/OS/实例 ID)
  • aet.heartbeat:每 4 秒一次(Host TTL 常见为 ~12 秒)
  • aet.getStatus:调试查询在线状态

本地自测(Mock Host,不依赖 HarmonyOS Host)

目标:在你本机先把 aet.hello + aet.heartbeat 的文件往返跑通,确认 .aether_bridge/req/res 协议无误。

  1. 准备一个“模拟共享目录”(随便找个空目录):
  • 例如:E:\temp\aet_mount
  1. 启动 Mock Host(它会轮询 req/ 并写回 res/):
powershell -ExecutionPolicy Bypass -File tools/mock_host_bridge.ps1 -MountPath E:\temp\aet_mount -CreateDirs
  1. 启动 Agent(两种方式任选其一):
  • 方式 A:环境变量(推荐)
set AETHER_BRIDGE_MOUNT=E:\temp\aet_mount
dotnet run --project AetherEnhancedTools.Agent
  • 方式 B:写配置:在 AetherEnhancedTools.Agent/appsettings.json 里设置:
    • AetherBridge:MountPath
  1. 观察结果:
  • Mock Host 窗口会打印:
    • handled aet.hello (...)
    • 然后每隔 ~4 秒:handled aet.heartbeat (...)

常见问题:

  • 看不到 heartbeat:Agent 默认把 heartbeat 记在 Debug 日志;但 Mock Host 端会持续打印,所以以 Mock Host 为准。
  • 想保留响应文件方便看内容:把 AetherEnhancedTools.Agent/appsettings.json 里的 DeleteResponseAfterRead 设为 false

“带来 / 带走”(Bring / Take)能力(基于宿主同款 Schema)

这两类能力都是 Guest(AET) 发起 RPC → Host(App) 执行系统能力 → 文件落到共享目录 的模式:

  • 带来(Host → Shared → Guest)
    • bridge.mediaPickToShared:宿主弹文件选择器,把选中的文件复制到共享目录的 .aether_bridge/blob/,并返回 relativePath
    • bridge.collabServiceImportToShared:宿主走协同/碰一碰等能力,把收到的文件落到 .aether_bridge/blob/,返回 files[]
  • 带走(Guest → Shared → Host → 外部设备)
    • files.take:Guest 先把要分享的文件复制到共享目录(比如 .aether_bridge/blob/accepted-files/),再传 items[].relativePath 给宿主;宿主用 ShareKit “碰一碰分享”把这些文件带走

重要约束(和宿主一致):

  • 需要 AET 在线:宿主会用 TTL 判断 AET 是否在线;未在线时会对部分方法返回 PERMISSION_DENIED
  • 所有路径都是相对共享目录relativePath 必须在共享目录内,且不能包含 ..

本地 Mock Host + CLI 测试带来/带走

我们提供了:

  • tools/mock_host_bridge.ps1:模拟宿主轮询 req/ 并写 res/(含 bring/take 方法)
  • AetherEnhancedTools.BridgeCli:用 同款 schema 发起这些方法(方便在 PC 上先跑通)
  1. 启动 Mock Host:
powershell -ExecutionPolicy Bypass -File tools/mock_host_bridge.ps1 -MountPath E:\temp\aet_mount -CreateDirs
  1. 带来(mediaPickToShared):把一个文件丢进 mock inbox,再调用 bring:
  • 把文件放到:E:\temp\aet_mount\_mock_inbox\
dotnet run --project AetherEnhancedTools.BridgeCli -- --mount E:\temp\aet_mount bring
  1. 带走(files.take):准备一个共享目录内的文件,然后调用 take:
dotnet run --project AetherEnhancedTools.BridgeCli -- --mount E:\temp\aet_mount take --item ".aether_bridge/blob/yourfile.txt|title"

Mock Host 会把“带走”的文件复制到:E:\temp\aet_mount\_mock_taken\(用于在 PC 上模拟“分享成功”)。

guest_aet

内容说明:

  • aet_minimal_windows.cpp

    • Windows Guest 最小 AET 客户端示例:发 aet.hello + aet.heartbeat
    • 运行示例(Guest 内):
      • aet_minimal_windows.exe --mount <MOUNT>
  • aet_minimal_linux.py

    • Linux Guest 最小 AET 示例 + 相机流 demo(camera.stream.start
    • 可选把帧喂给 v4l2loopback(用 ffmpeg)
  • aet_hdc_connect.py

    • Guest 内扫描局域网 HDC 端口并执行 hdc tconn,方便调试/部署
  • windows_setup/aether_enhanced_tools_setup.cpp

    • Windows Guest “总安装器/Bootstrapper”骨架:
      • 提权 → 解压 payload → pnputilvioser.inf +(vio9p.infviofs.inf
      • 静默装 AET(MSI 优先)
      • 静默装 QGA(MSI)

安装器(你要做的交付物:一把梭)

目标交付:AetherEnhancedToolsSetup.exe

推荐安装顺序:

  • VirtIO(先装):共享目录驱动(Windows 推荐 viofs + WinFsp;Linux 用 9p)+ vioserial(QGA 需要)
  • AET(再装):Agent + UI
  • QGA(最后装):qemu-guest-agent(可选,但建议默认装)

Payload 组织建议:

  • payload/virtio/:virtio-win 解压后的驱动树(不要改动签名文件)
  • payload/winfsp/:WinFsp 安装包(winfsp-*.msi,Windows 使用 virtio-fs/viofs 共享目录时必须)
  • payload/aet/:你的 AET MSI/EXE
  • payload/qga/:QGA MSI

注意:

  • 驱动/服务安装需要管理员权限(安装器必须提权)

QGA(QEMU Guest Agent)与我们 AET 的关系(AET 视角)

  • AET 是“产品集成层工具”:更关心用户体验与能力整合(文件/设备/相机/提示/修复)
  • QGA 是“标准 Guest Agent”:更适合做 VM 管理类能力(执行命令、查询 Guest 状态、关机/重启等)

当前已知状态(对接提醒):

  • Host 侧已有 QMPqmp.sock)用于控制/查询 QEMU
  • 但还需要在 QEMU 启动参数中补齐 guest-agent virtio-serial 通道,Host 才能通过 QMP 的 guest-* 系列命令与 QGA 协作