Windows下载AOSP-CSDN博客

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

关于repo

repo只是谷歌做的方便下载安卓源码的工具本质上是对下载清单进行批量处理然后使用git克隆。
在windows上下载源码只需要自己处理即可。

具体做法

首先使用git克隆安卓源码清单

git clone https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest

随后进入manifest目录查看所有tag

git tag

在这里插入图片描述

tag名就是安卓源码的版本选择你要的版本记下来。例如android-13.0.0_r9
随后切换分支

git checkout android-13.0.0_r9

在这里插入图片描述
记住文件夹中的default.xml的路径
以上操作完成了清单的下载接下来我们只需要执行按清单下载的操作即可。
我提供两个我编写的脚本一个python环境一个golang环境。
注意该脚本不支持断点续传如需使用请保持网络环境良好或自行修改脚本。

Python环境

该Python下载脚本仅支持单线程下载不过git仍可以跑满你的网速

import xml.dom.minidom
import os
from subprocess import call

version = "android-13.0.0_r9"

# 1. 源码要保存的路径
rootdir = "D:/AOSP/"+version

# 2. git 的路径
git = r"C:\Program Files\Git\cmd\git.exe"

# 3. default.xml 的路径
dom = xml.dom.minidom.parse(r"D:\AOSP\manifest\default.xml")
root = dom.documentElement

# 4. 只支持单一镜像源
prefix = git + " clone https://aosp.tuna.tsinghua.edu.cn/"
suffix = ".git"

if __name__ == '__main__':

    if not os.path.exists(rootdir):
        os.mkdir(rootdir)

    for node in root.getElementsByTagName("project"):
        os.chdir(rootdir)
        d = node.getAttribute("path")
        last = d.rfind("/")
        if last != -1:
            d = rootdir + "/" + d[:last]
            if not os.path.exists(d):
                os.makedirs(d)
            os.chdir(d)
        cmd = prefix + node.getAttribute("name") + suffix
        # 单线程下载
        call(cmd)

Golang环境

该golang脚本支持从多个镜像站并发下载可限制每个镜像站同时下载的线程个数以及总线程个数。
注意 * 总线程个数应小于等于各个镜像站线程个数相加*
resource.go

package main

import (
	"sync"
)

type Resource struct {
	Url  string
	Lock chan struct{}
}

type ResourcePool struct {
	resources []*Resource
	cond      *sync.Cond
}

func NewResourcePool(list []*Resource) *ResourcePool {
	pool := &ResourcePool{
		cond: sync.NewCond(&sync.Mutex{}),
	}
	pool.resources = list

	return pool
}

func (pool ResourcePool) GetResource() *Resource {
	pool.cond.L.Lock()
	defer pool.cond.L.Unlock()

	for {
		for _, resource := range pool.resources {
			select {
			case resource.Lock <- struct{}{}:
				return resource
			default:
				continue
			}
		}

		pool.cond.Wait()
	}
}

func (pool ResourcePool) ReleaseResource(resource *Resource) {
	<-resource.Lock

	pool.cond.Signal()
}

main.go

package main

import (
	"encoding/xml"
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"sync"
)

type Project struct {
	XMLName xml.Name `xml:"project"`
	Name    string   `xml:"name,attr"`
	Path    string   `xml:"path,attr"`
}

type Manifest struct {
	XMLName xml.Name  `xml:"manifest"`
	Project []Project `xml:"project"`
}

var (
	concurrentNum int
	rootDir       string
	manifestPath  string

	wg sync.WaitGroup
)

var resourceA = &Resource{Url: "https://mirrors.bfsu.edu.cn/git/AOSP/%s.git", Lock: make(chan struct{}, 4)}
var resourceB = &Resource{Url: "https://aosp.tuna.tsinghua.edu.cn/%s.git", Lock: make(chan struct{}, 3)}

//var resourceC = &Resource{Url: "https://mirror.nju.edu.cn/%s.git", Lock: make(chan struct{}, 3)}

//var resourceC = &Resource{Url: "https://mirrors.shanghaitech.edu.cn/%s.git", Lock: make(chan struct{}, 3)}

func init() {
	flag.IntVar(&concurrentNum, "concurrentNum", 7, "Number of concurrent goroutines")
	flag.StringVar(&rootDir, "root", "D:/AOSP/android-13.0.0_r9", "Root dir of AOSP.")
	flag.StringVar(&manifestPath, "manifest", "D:/AOSP/manifest/default.xml", "Manifest of AOSP.")
}

func errorHandle(str string, err error) {
	if err != nil {
		log.Fatalf("Failed to %s: %v", str, err)
		os.Exit(-6)
	}
}

func main() {
	flag.Parse()
	manifestXML, err := os.ReadFile(manifestPath)
	errorHandle("Read manifest file", err)

	var manifest Manifest
	err = xml.Unmarshal(manifestXML, &manifest)
	errorHandle("Parse manifest XML", err)

	err = os.MkdirAll(rootDir, 0755)
	errorHandle("Create root directory", err)

	sem := make(chan struct{}, concurrentNum)

	pool := NewResourcePool([]*Resource{
		resourceA, resourceB,
	})

	for _, node := range manifest.Project {
		wg.Add(1)
		go func(project Project) {
			defer wg.Done()
			sem <- struct{}{}
			defer func() { <-sem }()

			cmdDir := rootDir

			d := project.Path
			last := strings.LastIndex(d, "/")
			if last != -1 {
				d = filepath.Join(rootDir, d[:last])
				if err := os.MkdirAll(d, 0755); err != nil {
					errorHandle("Create d directory", err)
				}

				cmdDir = d
			}
			resource := pool.GetResource()
			if resource == nil {
				fmt.Println("No resource available")
				os.Exit(2)
				return
			}

			cmd := exec.Command("git", "clone", fmt.Sprintf(resource.Url, project.Name))
			cmdDir = strings.ReplaceAll(cmdDir+"\\", "/", "\\")
			cmd.Dir = cmdDir
			if err := cmd.Run(); err != nil {
				fmt.Printf("Failed to clone node: %v %s \n", err, cmd)
				return
			}
			pool.ReleaseResource(resource)

			fmt.Printf("Cloned node: %s \n", project.Name)
		}(node)
	}

	wg.Wait()
}

截至到23年10月3日完全可用的镜像站仅剩清华其他AOSP的镜像或多或少均有问题
python的脚本足矣经测试均速16m/s一晚上可以下载好android-13.0.0_r9的所有源码
go的脚本推荐大家不要乱用过多的下载进程会对镜像站造成巨大的负载
在这里插入图片描述

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: windows