From 83b6a2967f203fee92c7d0aa03c347e6ae4b74b9 Mon Sep 17 00:00:00 2001 From: DeathofBrain <109609173+DeathofBrain@users.noreply.github.com> Date: Mon, 9 Nov 2026 22:24:08 +0800 Subject: [PATCH] feat(macos): add daily maintenance and proxy support Rebase the macOS daily capabilities onto the current main branch, resolve guest payload changes, and keep platform-specific disk, retention, and proxy routing isolated from Windows. --- README.en.md | 16 +- README.md | 16 +- internal/components/fetch.go | 4 +- internal/emu/COMPACT.md | 12 +- internal/emu/afterboot.go | 11 ++ internal/emu/appproxy.go | 31 +++- internal/emu/capture_policy.go | 24 ++- internal/emu/check.go | 21 ++- internal/emu/crash_archive.go | 9 +- internal/emu/crud.go | 6 +- internal/emu/disk.go | 30 +++- internal/emu/disk_links_darwin.go | 17 +++ internal/emu/disk_links_other.go | 2 +- internal/emu/fileuse_other.go | 23 +++ internal/emu/gates_other_test.go | 3 + internal/emu/launch.go | 19 ++- internal/emu/logs.go | 19 +-- internal/emu/platform.go | 12 ++ internal/emu/retention_darwin.go | 30 ++++ internal/emu/retention_other.go | 2 +- internal/emu/start.go | 2 +- internal/emu/status.go | 6 +- internal/emu/stop.go | 2 +- internal/guest/guest.go | 39 ++++- internal/guest/proxyd/README.md | 4 + internal/host/bound_other.go | 2 +- internal/host/disk_darwin.go | 20 +++ internal/host/disk_other.go | 7 + internal/host/lock_probe_darwin.go | 7 + internal/host/lock_probe_other.go | 5 + internal/host/proxy_darwin.go | 12 ++ internal/host/retention_darwin.go | 14 ++ internal/host/unsupported_other.go | 6 - internal/host/windows.go | 2 + internal/hostproxy/guest.go | 6 +- internal/hostproxy/hostproxy.go | 39 ++++- internal/hostproxy/system_darwin.go | 47 ++++++ internal/hostproxy/system_other.go | 2 +- internal/macos/disk_darwin.go | 172 ++++++++++++++++++++++ internal/macos/fileuse_darwin.go | 125 ++++++++++++++++ internal/macos/lock_darwin.go | 29 ++++ internal/macos/proxy_darwin.go | 55 +++++++ internal/macos/retention_darwin.go | 221 ++++++++++++++++++++++++++++ internal/root/platform.go | 11 ++ internal/root/root.go | 14 +- 45 files changed, 1072 insertions(+), 84 deletions(-) create mode 100644 internal/emu/disk_links_darwin.go create mode 100644 internal/emu/fileuse_other.go create mode 100644 internal/emu/retention_darwin.go create mode 100644 internal/host/disk_darwin.go create mode 100644 internal/host/disk_other.go create mode 100644 internal/host/lock_probe_darwin.go create mode 100644 internal/host/lock_probe_other.go create mode 100644 internal/host/proxy_darwin.go create mode 100644 internal/host/retention_darwin.go create mode 100644 internal/hostproxy/system_darwin.go create mode 100644 internal/macos/disk_darwin.go create mode 100644 internal/macos/fileuse_darwin.go create mode 100644 internal/macos/proxy_darwin.go create mode 100644 internal/macos/retention_darwin.go diff --git a/README.en.md b/README.en.md index 4ffb23b..5efac74 100644 --- a/README.en.md +++ b/README.en.md @@ -4,7 +4,7 @@ -The management program for [ModAVD](https://github.com/ModAVD/ModAVD): the graphical manager `ModAVD.exe`, and the CLI and MCP server `modavd.exe`. Written in Go, standard library only. It currently supports Windows x64 only; the platform-specific parts are already split into a platform layer. For the plans for other platforms, see [ModAVD#27](https://github.com/ModAVD/ModAVD/issues/27). +The management program for [ModAVD](https://github.com/ModAVD/ModAVD): the graphical manager `ModAVD.exe`, and the CLI and MCP server `modavd.exe`. Written in Go, standard library only. The CLI and MCP currently support Windows x64 and Apple Silicon macOS; the graphical manager remains Windows x64 only. The platform-specific parts are already split into a platform layer. For the plans for other platforms, see [ModAVD#27](https://github.com/ModAVD/ModAVD/issues/27). > **Version note (`main` and Releases)**: This document describes the implementation on the repository's `main`. `main` is currently at version `0.3.0`, the latest standalone Release is `v0.1.0` (matching ModAVD `0.36.0`), and `v0.2.0` has been drafted but not published. The background initialization on create, the `update` command and exit code 9, all new in `0.2.0`, are not in the `v0.1.0` download package. If you use a published package, go by the notes of the matching Release and the version inside the package. @@ -22,7 +22,7 @@ Usage instructions and guidance for contributing are on the ModAVD documentation ## What this is -- ModAVD is an Android emulator based on the AOSP Android Emulator plus a set of patches. It supports Windows today, and more platforms are planned. This repository holds the programs that manage it: create, change and delete instances; start and shut down; the computer check before starting; install APKs and the arm64 execution bridge; view the screen and the logs. +- ModAVD is an Android emulator based on the AOSP Android Emulator plus a set of patches. It supports Windows and Apple Silicon macOS today, and more platforms are planned. This repository holds the programs that manage it: create, change and delete instances; start and shut down; the computer check before starting; install APKs and the arm64 execution bridge; view the screen and the logs. - It manages one ModAVD root folder, that is, the folder the ModAVD release package unpacks to (it contains `mas-avd.json`, `sdk\` and `avd\`). The instance files and `mas-avd.json` are written the same way as in [AUTO-MAS](https://github.com/AUTO-MAS-Project/AUTO-MAS), and the tests compare against AUTO-MAS code byte for byte. - The manager `ModAVD.exe` is for people; the CLI `modavd.exe` and its MCP server are for scripts, AUTO-MAS and AI assistants. @@ -71,7 +71,7 @@ modavd [--root ] [--json] [--quiet] [--verbose] [args] | `bridge install\|uninstall\|verify` | Install, uninstall or check the arm64 execution bridge; it is installed automatically at start, so you normally do not run it by hand (see below) | | `playstore install\|uninstall\|status` | Add the Google Play Store to an instance, remove it, or check it (see below) | | `gles32 on\|off\|status` | Experimental: make an instance report GLES 3.2 (see below) | -| `disk compact` | Compact a stopped instance's data disk, or skip rewriting when estimated savings are too small. Verify before atomically replacing the original, and report host usage before and after, including growth. Large disks have budgets of many hours and effectively do not time out in normal use; cancel to stop an operation. Requires NTFS/ReFS, no snapshots and room for the temporary image. See [budgets and result fields](internal/emu/COMPACT.md) | +| `disk compact` | Compact a stopped instance's data disk, or skip rewriting when estimated savings are too small. Verify before atomically replacing the original, and report host usage before and after, including growth. Large disks have budgets of many hours and effectively do not time out in normal use; cancel to stop an operation. Supports NTFS/ReFS on Windows and APFS on Apple Silicon macOS; linked images and snapshots are rejected, and room for the temporary image is required. See [budgets and result fields](internal/emu/COMPACT.md) | | `check [--memory M]` | Computer check before starting | | `report-config [--no-clipboard]` | Copy the computer configuration and the game info from the running instances (read-only) | | `collect-info [--out-dir D] [--stage-dir D] [--keep-stage] [--no-explorer]` | Collect a problem report and zip it (read-only). Ctrl+C before ZIP completion returns `canceled`, deletes the unfinished ZIP and removes staging; `--keep-stage` preserves staging and includes its path in the error | @@ -84,6 +84,8 @@ modavd [--root ] [--json] [--quiet] [--verbose] [args] - Root folder: `--root`; if not given, the environment variable `MODAVD_ROOT`; otherwise the folder containing `modavd.exe`, or its parent. - From 0.3.0 there is no `restart`: `stop`, then `start`. An old call gets a usage error (exit code 2) that says so. +Apple Silicon macOS uses the SDK's native `qemu-img`. Host usage counts allocated filesystem blocks, excluding sparse holes. APFS clones can share extents, so a decrease in file allocation does not guarantee the same increase in volume free space. Ordinary log cleanup checks actual open files and preserves candidates that are active, changed, linked, or contain unexpected subdirectories. The diagnostics switch remains unavailable on macOS. + **The arm64 execution bridge**: - It applies only to the games on the built-in list; other apps keep using the original translation layer. The bridge is installed in the instance's own system / vendor overlay and needs an emulator from 0.36 on. @@ -274,7 +276,7 @@ Double-click `ModAVD.exe` in the package root: it starts a local server that lis ## Fetching the Google components -The ModAVD release package does not include adb (platform-tools 37.0.1) or the Android 14 Google APIs x86_64 system image (r14, about 1.5 GB, about 4.2 GB unpacked): they belong to Google, are governed by the Android Software Development Kit License Agreement, and cannot be redistributed. `modavd components fetch` downloads them from official channels and installs them into `sdk\`. The manager's "补全组件" button and this command share the same logic; the first interactive run asks for a download source and remembers it: +The ModAVD release package does not include adb (platform-tools 37.0.1) or a system image: Windows uses Android 14 Google APIs x86_64 (r14), while Apple Silicon macOS uses Android 15 Google APIs arm64-v8a (r9). They belong to Google, are governed by the Android Software Development Kit License Agreement, and cannot be redistributed. `modavd components fetch` downloads them from official channels and installs them into `sdk\`. The manager's "补全组件" button and this command share the same logic; the first interactive run asks for a download source and remembers it: - First it fetches the full license text from `repository2-3.xml` on a mirror and displays it (stating which mirror it came from and which components will be downloaded), and continues only if you type `y`; otherwise nothing is downloaded and `downloads\` gets no extra files. `--accept-license` skips the prompt, but the full text is still fetched and displayed, and if it cannot be fetched it still exits; with `--json` it is required, otherwise the command always reports `usage` (exit code 2), before it even looks at the root folder and whether or not components are missing (up to 0.3.0 it succeeded when nothing was missing). The license text and the prompt are not affected by `--quiet`. - Mirrors are tried in this order: googledownloads.cn → Tencent Cloud mirror → dl.google.com. When something is to be downloaded, a line "下载源:…" (download source) first says which ones this run uses and why (default / `--mirror` / `--mirror-url`). `--mirror` uses only one of them (case-insensitive); `--mirror-url` uses your own directory URL in place of those three (it can be given several times or comma-separated, and the URLs are tried in order). A mirror from which the license manifest could not be fetched is moved to the end when downloading. @@ -282,9 +284,9 @@ The ModAVD release package does not include adb (platform-tools 37.0.1) or the A - It unpacks to `sdk\.staging\`, and moves the result into place only after the whole package is unpacked and verified (key files, the SHA-256 pinned for the three adb files, the version); a missing `source.properties` is written in. A previously incomplete directory is renamed `.incomplete-