diff --git a/internal/avd/avd.go b/internal/avd/avd.go index a10f095..4924829 100644 --- a/internal/avd/avd.go +++ b/internal/avd/avd.go @@ -40,7 +40,8 @@ const ( // New instances default to 1080p. Existing instances are identified by their dimensions. DefaultResolution = 1080 TargetAPI = "android-34" - // image.sysdir.1, relative to the SDK root, with the trailing backslash AUTO-MAS writes. + // SystemImageSysdir is the Windows/AUTO-MAS value of image.sysdir.1. + // Create uses the host platform's system-image directory and path separator. SystemImageSysdir = `system-images\android-34\google_apis\x86_64\` ) @@ -628,6 +629,10 @@ func Create(r *root.Root, i int, opt CreateOptions) (*Instance, error) { for _, kv := range ConfigTemplate { cfg.Set(kv[0], kv[1]) } + p := root.CurrentPlatform() + cfg.Set("abi.type", p.GuestABI) + cfg.Set("hw.cpu.arch", p.GuestArch) + cfg.Set("target", p.TargetAPI) for _, kv := range [][2]string{ {"avd.id", name}, {"avd.name", name}, @@ -639,15 +644,15 @@ func Create(r *root.Root, i int, opt CreateOptions) (*Instance, error) { {"hw.lcd.height", display[1][1]}, {"hw.lcd.density", display[2][1]}, {"hw.lcd.vsync", strconv.Itoa(fps)}, - {"image.sysdir.1", SystemImageSysdir}, + {"image.sysdir.1", p.SystemImageDir + string(filepath.Separator)}, } { cfg.Set(kv[0], kv[1]) } ini := NewIni() ini.Set("avd.ini.encoding", "UTF-8") ini.Set("path", dir) - ini.Set("path.rel", root.AvdDir+`\`+name+".avd") - ini.Set("target", TargetAPI) + ini.Set("path.rel", filepath.Join(root.AvdDir, name+".avd")) + ini.Set("target", p.TargetAPI) if err := os.MkdirAll(r.AvdHome(), 0o755); err != nil { return nil, errs.Wrap(errs.Internal, err, fmt.Sprintf("建不了目录 %s:%v", r.AvdHome(), err)) diff --git a/internal/root/components.go b/internal/root/components.go index c9679cc..af40e09 100644 --- a/internal/root/components.go +++ b/internal/root/components.go @@ -96,10 +96,11 @@ func SDKComponents() []SDKComponent { if runtime.GOOS == "windows" { return WindowsComponents() } + p := CurrentPlatform() return []SDKComponent{ {ID: "platform-tools", Name: PlatformToolsName, FetchName: PlatformToolsName, Target: "platform-tools", - StatusFiles: []string{CurrentPlatform().ADB}}, - {ID: "system-image", Name: SystemImageName, FetchName: SystemImageName, Target: SystemImageDir, + StatusFiles: []string{p.ADB}}, + {ID: "system-image", Name: p.SystemImageName, FetchName: p.SystemImageName, Target: p.SystemImageDir, StatusFiles: systemImageFiles()}, } } diff --git a/internal/root/components_test.go b/internal/root/components_test.go index ec699e3..6ef6bd3 100644 --- a/internal/root/components_test.go +++ b/internal/root/components_test.go @@ -213,7 +213,7 @@ func TestComponentsUseTable(t *testing.T) { } } comps := r.Components() - if !comps[0].Installed || !comps[2].Installed || comps[0].Name != PlatformToolsName || comps[2].Name != SystemImageName { + if !comps[0].Installed || !comps[2].Installed || comps[0].Name != PlatformToolsName || comps[2].Name != CurrentPlatform().SystemImageName { t.Fatalf("%+v", comps) } os.Remove(filepath.Join(SDKComponents()[1].Dir(r.SDK()), SDKComponents()[1].StatusFiles[0])) diff --git a/internal/root/platform.go b/internal/root/platform.go index 4dda25b..5467eee 100644 --- a/internal/root/platform.go +++ b/internal/root/platform.go @@ -1,6 +1,9 @@ package root -import "runtime" +import ( + "runtime" + "strings" +) func platformKeyFiles() map[string][]string { p := CurrentPlatform() @@ -16,17 +19,22 @@ func platformKeyFiles() map[string][]string { } } -// Platform describes host-specific executable names and update identifiers. -// Callers use this table instead of embedding Windows names in shared logic. +// Platform describes host executable names, guest images and update identifiers. +// Callers use this table instead of embedding Windows or x86_64 values in shared logic. type Platform struct { - Emulator string - ADB string - QEMU string - QEMUHeadless string - QemuDir string - PackageSuffix string - MirrorOS string - MirrorArch string + Emulator string + ADB string + QEMU string + QEMUHeadless string + QemuDir string + PackageSuffix string + MirrorOS string + MirrorArch string + GuestABI string + GuestArch string + TargetAPI string + SystemImageDir string + SystemImageName string } // Supported reports whether the host matches one of the package's platform rows. @@ -41,13 +49,25 @@ func (p Platform) Windows() bool { return p.QemuDir == "windows-x86_64" && p.Mir func CurrentPlatform() Platform { switch { case runtime.GOOS == "darwin" && runtime.GOARCH == "arm64": - // The qemu directory on macOS is expected to be qemu/darwin-aarch64; - // #8 will verify the package layout before changing this table. - return Platform{Emulator: "emulator", ADB: "adb", QEMU: "qemu-system-aarch64", QEMUHeadless: "qemu-system-aarch64", PackageSuffix: "macos-arm64", MirrorOS: "macos", MirrorArch: "arm64"} + return Platform{ + Emulator: "emulator", ADB: "adb", QEMU: "qemu-system-aarch64", QEMUHeadless: "qemu-system-aarch64-headless", QemuDir: "darwin-aarch64", + PackageSuffix: "macos-arm64", MirrorOS: "macos", MirrorArch: "arm64", + GuestABI: "arm64-v8a", GuestArch: "arm64", TargetAPI: "android-35", + SystemImageDir: MacOSSystemImageDir, SystemImageName: MacOSSystemImageName, + } case runtime.GOOS == "linux" && runtime.GOARCH == "amd64": - return Platform{Emulator: "emulator", ADB: "adb", QEMU: "qemu-system-x86_64", QEMUHeadless: "qemu-system-x86_64", PackageSuffix: "linux-x64", MirrorOS: "linux", MirrorArch: "x64"} + return Platform{ + Emulator: "emulator", ADB: "adb", QEMU: "qemu-system-x86_64", QEMUHeadless: "qemu-system-x86_64", + PackageSuffix: "linux-x64", MirrorOS: "linux", MirrorArch: "x64", + GuestABI: "x86_64", GuestArch: "x86_64", TargetAPI: "android-34", + SystemImageDir: strings.ReplaceAll(SystemImageDir, `\`, "/"), SystemImageName: SystemImageName, + } case runtime.GOOS == "windows" && runtime.GOARCH == "amd64": - return Platform{Emulator: "emulator.exe", ADB: "adb.exe", QEMU: "qemu-system-x86_64.exe", QEMUHeadless: "qemu-system-x86_64-headless.exe", QemuDir: "windows-x86_64", PackageSuffix: "win-x64", MirrorOS: "win", MirrorArch: "x64"} + return Platform{ + Emulator: "emulator.exe", ADB: "adb.exe", QEMU: "qemu-system-x86_64.exe", QEMUHeadless: "qemu-system-x86_64-headless.exe", QemuDir: "windows-x86_64", + PackageSuffix: "win-x64", MirrorOS: "win", MirrorArch: "x64", + GuestABI: "x86_64", GuestArch: "x86_64", TargetAPI: "android-34", SystemImageDir: SystemImageDir, SystemImageName: SystemImageName, + } default: // An unlisted host must not inherit Windows names or MirrorChyan ids. return Platform{} diff --git a/internal/root/platform_test.go b/internal/root/platform_test.go index 855a7b0..91d73ed 100644 --- a/internal/root/platform_test.go +++ b/internal/root/platform_test.go @@ -9,17 +9,17 @@ func TestCurrentPlatformMatchesHost(t *testing.T) { p := CurrentPlatform() switch { case runtime.GOOS == "windows" && runtime.GOARCH == "amd64": - want := Platform{Emulator: "emulator.exe", ADB: "adb.exe", QEMU: "qemu-system-x86_64.exe", QEMUHeadless: "qemu-system-x86_64-headless.exe", QemuDir: "windows-x86_64", PackageSuffix: "win-x64", MirrorOS: "win", MirrorArch: "x64"} + want := Platform{Emulator: "emulator.exe", ADB: "adb.exe", QEMU: "qemu-system-x86_64.exe", QEMUHeadless: "qemu-system-x86_64-headless.exe", QemuDir: "windows-x86_64", PackageSuffix: "win-x64", MirrorOS: "win", MirrorArch: "x64", GuestABI: "x86_64", GuestArch: "x86_64", TargetAPI: "android-34", SystemImageDir: SystemImageDir, SystemImageName: SystemImageName} if p != want { t.Fatalf("Windows platform: %+v", p) } case runtime.GOOS == "darwin" && runtime.GOARCH == "arm64": - want := Platform{Emulator: "emulator", ADB: "adb", QEMU: "qemu-system-aarch64", QEMUHeadless: "qemu-system-aarch64", PackageSuffix: "macos-arm64", MirrorOS: "macos", MirrorArch: "arm64"} + want := Platform{Emulator: "emulator", ADB: "adb", QEMU: "qemu-system-aarch64", QEMUHeadless: "qemu-system-aarch64-headless", QemuDir: "darwin-aarch64", PackageSuffix: "macos-arm64", MirrorOS: "macos", MirrorArch: "arm64", GuestABI: "arm64-v8a", GuestArch: "arm64", TargetAPI: "android-35", SystemImageDir: "system-images/android-35/google_apis/arm64-v8a", SystemImageName: "系统镜像 Android 15 Google APIs arm64-v8a"} if p != want { t.Fatalf("darwin platform: %+v", p) } case runtime.GOOS == "linux" && runtime.GOARCH == "amd64": - want := Platform{Emulator: "emulator", ADB: "adb", QEMU: "qemu-system-x86_64", QEMUHeadless: "qemu-system-x86_64", PackageSuffix: "linux-x64", MirrorOS: "linux", MirrorArch: "x64"} + want := Platform{Emulator: "emulator", ADB: "adb", QEMU: "qemu-system-x86_64", QEMUHeadless: "qemu-system-x86_64", PackageSuffix: "linux-x64", MirrorOS: "linux", MirrorArch: "x64", GuestABI: "x86_64", GuestArch: "x86_64", TargetAPI: "android-34", SystemImageDir: "system-images/android-34/google_apis/x86_64", SystemImageName: SystemImageName} if p != want { t.Fatalf("linux platform: %+v", p) } diff --git a/internal/root/root.go b/internal/root/root.go index 6b14ead..ce74f54 100644 --- a/internal/root/root.go +++ b/internal/root/root.go @@ -213,18 +213,20 @@ func jsonOneLine(v *jsonord.Value) string { // ---- layout ------------------------------------------------------------------------------------------------------ +// SystemImageDir retains the Windows/AUTO-MAS layout; other hosts use Platform.SystemImageDir. const ( - SDKDir = "sdk" - AvdDir = "avd" - ComponentsDir = "components" - MetadataFile = "mas-avd.json" - LogsDir = "logs" - ShaderCacheDir = "shader-cache" - GuestPatchDir = "guest-patches" - ManifestFile = "modavd-manifest.json" - SystemImageDir = `system-images\android-34\google_apis\x86_64` - LauncherAPKName = "de.jrpie.android.launcher_57.apk" - ImeAPKName = "modavd-ime.apk" + SDKDir = "sdk" + AvdDir = "avd" + ComponentsDir = "components" + MetadataFile = "mas-avd.json" + LogsDir = "logs" + ShaderCacheDir = "shader-cache" + GuestPatchDir = "guest-patches" + ManifestFile = "modavd-manifest.json" + SystemImageDir = `system-images\android-34\google_apis\x86_64` + MacOSSystemImageDir = "system-images/android-35/google_apis/arm64-v8a" + LauncherAPKName = "de.jrpie.android.launcher_57.apk" + ImeAPKName = "modavd-ime.apk" ) // MinModBuild: emulators whose Pkg.BuildId is below mas- refuse to boot (AUTO-MAS MIN_MOD_AVD_BUILD). @@ -762,14 +764,16 @@ type ComponentStatus struct { } // Component names and fixed data (AUTO-MAS constants.py). +// SystemImageName retains the Windows name; other hosts use Platform.SystemImageName. const ( - PlatformToolsName = "平台工具(adb)" - EmulatorName = "Android 模拟器(emulator)" - SystemImageName = "系统镜像 Android 14 Google APIs x86_64" - LauncherName = "轻量桌面 µLauncher" - LauncherVersion = "0.2.12" - LauncherAPKSize = 4099556 - ImeName = "宿主输入法 org.modavd.ime" + PlatformToolsName = "平台工具(adb)" + EmulatorName = "Android 模拟器(emulator)" + SystemImageName = "系统镜像 Android 14 Google APIs x86_64" + MacOSSystemImageName = "系统镜像 Android 15 Google APIs arm64-v8a" + LauncherName = "轻量桌面 µLauncher" + LauncherVersion = "0.2.12" + LauncherAPKSize = 4099556 + ImeName = "宿主输入法 org.modavd.ime" ) // Advice for missing components (AUTO-MAS FETCH_COMPONENTS_ADVICE / PACKAGE_ADVICE; "回来点「检查」" is AUTO-MAS's