第1章 AOSP源码下载与Repo使用

1.1 Repo工具角色与设计原理

AOSP 仓库数量超过 800 个 Git 库,Google 设计 Repo 工具来统一管理这些子仓库元数据的拉取与切换。Repo 本质是对 Git 的批量操作封装,自身不存储代码,只维护一份 XML 清单文件,该文件描述每个子仓库的远程 URL、分支、标签和本地路径。

组件职责技术形态
repo 命令初始化、同步、分支切换、diff 查看Python 脚本 + 内嵌 Git 命令
manifest 仓库存放 default.xml(及其他变体)Git 仓库,通常托管在 android.googlesource.com
各子 Git 仓库实际业务代码(kernel、framework、bionic…)标准 Git 仓库,使用 detached HEAD 管理模式
设计取舍:Google 没有使用 git submodule,而是自研 Repo。原因是 submodule 在超大规模仓库(800+)下同步性能和分支切换灵活性都达不到 AOSP 开发需求。Repo 的 XML 清单允许在不同版本之间快速切换整个项目基线。

1.2 repo init 工作原理与参数

repo init 不拉取任何业务代码,只完成两件事:

  1. 在 .repo/manifests 目录克隆清单仓库。
  2. 在 .repo/manifest.xml 建立指向 default.xml 的符号链接。
mkdir ~/aosp
cd ~/aosp
# 使用国内镜像源加速初始化(清华大学 TUNA 镜像)
repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest \
          -b android-14.0.0_r15 \
          --depth=1 \
          --partial-clone
参数作用说明
-u <URL>manifest 仓库的远程地址
-b <分支>指定清单仓库的分支或 Tag,决定拉取哪个 Android 版本
--depth=1浅克隆,只下载最新提交,大幅减少首次同步数据量
--partial-clone启用 Git 部分克隆(promisor remote),按需下载对象
--worktree使用 Git worktree 替代符号链接,减少重复对象存储
执行 init 前必须确保环境变量 REPO_URL 指向正确的 Repo 引导脚本地址。如果遇到 fatal: cannot get manifest url,通常是网络代理未配置或镜像源不可用。

1.3 清单文件(manifest.xml)结构解析

清单文件是整个 AOSP 代码的“地图”。一个标准 default.xml 包含以下核心元素:

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
  <remote  name="aosp"
           fetch=".."
           review="https://android-review.googlesource.com/" />

  <default revision="refs/tags/android-14.0.0_r15"
           remote="aosp"
           sync-j="4" />

  <project path="build/make"       name="platform/build"      groups="pdk" />
  <project path="frameworks/base"   name="platform/frameworks/base" />
  <project path="kernel/build"     name="kernel/build"        revision="android-14.0.0_gki" />
  <project path="pdk/apps/Contacts" name="platform/pdk/apps/Contacts" />
  <!-- 仅 Linux 平台下载 -->
  <project path="prebuilts/clang/host/linux-x86"
           name="platform/prebuilts/clang/host/linux-x86"
           groups="notdefault,linux-x86" />

  <include name="another/manifest.xml" />
</manifest>
标签用途常见属性
<remote>定义可用的远程 Git 仓库别名name, fetch, review
<default>全局默认配置,各 project 可覆盖revision, remote, sync-j, sync-c
<project>声明一个子仓库,path 是本地路径,name 是远端路径path, name, revision, groups, upstream
<include>引用其他 XML 文件,支持分模块管理清单name
<remove-project>从父清单中移除特定项目,常用于自定义裁剪name
调试技巧:被 groups="notdefault" 标记的 project 不会出现在 repo sync 默认拉取列表里。如果编译时遇到“missing header”错误,可以检查对应 project 是否被 groups 排除,手动用 repo sync <path> 补拉。

1.4 repo sync 完整流程与断点续传

repo sync 是日常最频繁使用的命令。执行时 Repo 会按以下顺序处理:

  1. 读取 .repo/manifest.xml 中所有 project 条目。
  2. 对每个 project 执行 git fetch,必要时执行浅克隆或部分克隆。
  3. 如果本地库已经存在,执行 git pull --rebase 避免合并提交。
  4. 更新 m/<branch> 远程跟踪分支。
  5. 将子仓库 checkout 到 XML 中指定的 revision。
# 全量同步(所有 project)
repo sync -j8

# 只同步指定子仓库(减少等待时间)
repo sync frameworks/base build/make

# 强制覆盖本地未提交修改
repo sync --force-sync

# 丢弃所有本地修改并回到远端状态
repo sync --force-sync --detach
断点续传:repo sync 支持 --fail-fast 和自动重试。默认连续失败 3 次会跳过该仓库。网络中断后重新执行 repo sync 会仅拉取未完成的仓库,不会重头开始。

1.5 分支切换与源码基线管理

切换 AOSP 版本本质是更改清单文件的分支引用。不需要为每个版本单独下载一份源码,只需切换 manifest 的 revision:

# 查看当前所有已同步的分支
cd .repo/manifests
git branch -a

# 切换清单到 android-13.0.0_r30
cd ~/aosp
repo init -b android-13.0.0_r30
repo sync -j8

# 查看更详细的可用分支/标签
cd .repo/manifests
git ls-remote --tags origin | grep android-14
操作命令影响范围
切换所有子仓库分支repo init -b <branch> + repo sync整个源码树
单仓库切换分支cd <path> && git checkout <branch>仅当前仓库
查看当前基线 Revisionrepo version / head .repo/manifest.xml无修改
恢复到 Manifest 指定版本repo sync --detach所有子仓库强制 detached HEAD
不要在子仓库内直接 git commit 和 git push,除非你理解 Repo 的 review 流程。直接提交会导致后续 repo sync 出现冲突,需要使用 repo abandon <topic> 清理。

1.6 常见错误与调试方法

以下是在实际工作中最常见的 Repo 错误案例及解决方案:

# 错误1:SSL certificate problem
# 现象:fatal: unable to access 'https://...': SSL certificate problem
# 解决:关闭 SSL 验证(仅限内网环境)
export GIT_SSL_NO_VERIFY=1

# 错误2:无法解析 manifest URL
# 现象:fatal: manifest url '...' is not a valid URL
# 解决:检查 repo init -u 参数,确保末尾没有多余空格,协议使用 https

# 错误3:sync 中途连接中断
# 现象:error: Failed to connect to android.googlesource.com port 443
# 解决:配置 git 代理
git config --global http.proxy http://proxy:port
git config --global https.proxy https://proxy:port

# 错误4:.repo/repo 损坏或版本不匹配
# 现象:error: repo is not a git repository
# 解决:重新拉取 repo 工具
curl -s https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo

1.7 性能优化:使首次同步从 6 小时降到 20 分钟

大团队或 CI 环境中,优化首次同步速度至关重要:

  • 使用 --depth=1 --partial-clone 避免下载全部 Git 历史。
  • 指定 --clone-bundle(默认已启用)从服务器下载预打包的 .bundle 文件。
  • 尽量选择地理位置最近的镜像源(清华大学、中科大、华为云)。
  • 使用 repo sync -c --no-tags 跳过标签拉取,可再减少 10%~15% 数据传输。
# 面向首次同步的完整优化参数
repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest \
          -b android-14.0.0_r15 \
          --depth=1 \
          --partial-clone \
          --clone-bundle
repo sync -c --no-tags -j$(nproc)

以 Android 14(约 60GB 源码树,含 Git 历史则超过 100GB)为例,使用优化参数后磁盘占用减少约 40%,首次同步时间从常规的 5~6 小时缩短至 15~25 分钟(视网络带宽而定)。

AOSP 源码下载与 Repo 使用工作流 开发者输入命令 repo init -b android-14.0.0_r15 Manifest 仓库 default.xml 解析 manifest.xml 读取 project 条目列表 repo sync -j8 依次处理每个 project frameworks/base git fetch/checkout build/make git fetch/checkout kernel/build git fetch/checkout 其他 800+ 仓库 平行拉取 分支切换 repo init -b <tag> 源码就绪,可执行 lunch/m 📌 性能优化 --depth=1 --partial-clone repo sync -c --no-tags ⚠️ 常见错误 SSL 证书 / 代理 / 断网 manifest URL 无效