恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
安卓5.1源码编译实战:从环境搭建到系统镜像定制
首页
资讯中心
/
安卓5.1源码编译实战:从环境搭建到系统镜像定制
安卓5.1源码编译实战:从环境搭建到系统镜像定制
发布时间:2026/10/11 10:37:38
简介Android 5.1 Lollipop 源码压缩包zip 格式约 27.07MB面向安卓系统开发者、ROM 定制者及希望深入理解系统底层原理的进阶程序员。源码涵盖 Linux 内核、Android 框架层Activity Manager、Content Provider 等核心组件、androidx 兼容库、Java 标准库java/javax、第三方开源库com/org并包含多窗口支持实现、性能基准测试代码、mock Android 模拟环境以及 JUnit/JSR166 测试与并发工具。其中 kernel 部分体现处理器调度、内存管理与驱动支持android 目录展示组件生命周期与 IPC 机制androidx 提供跨版本 UI 与数据绑定能力benchmarks 与 mock_android 则分别用于性能评估和模拟环境测试。通过研读源码读者可掌握系统进程通信、电源优化等关键机制理解 Android 生态各组件的协作方式为开发高质量应用、进行系统级调试或定制个性化 ROM 提供直接参考。该资源已有 664 人学习浏览适合具备一定 Android 基础、追求从源码层面解决问题的高级学习者。1. 安卓5.1源码一份能真正跑通的系统级开发素材搜安卓5.1源码的人多半不是路过而是手头压着一个具体任务给老设备定制系统、做车载或工控的ROM、或者终于决定把Binder和HAL彻底搞清楚。5.1Lollipop是Android进入Material Design之后最稳的一个分支比4.4多了默认ART和多用户支持比6.0更轻、更好编又恰好横在Android.mk构建体系的成熟期源码结构没被后来复杂构建系统搅浑。它不是最新但做源码学习和设备二次开发投入产出比很高。这份资源能解决的问题很具体把它拉下来、编出system.img、改HAL、加系统应用就能摸清整套Android系统开发链路而不是停留在“读过源码”的层面。适合想进系统定制方向的人比如嵌入式开发者、做设备方案的工程师、跨平台开发的进阶者只想写普通App的人可以先不用碰。2. 源码角色分工为什么5.1比4.4与6.0更适合动手2.1 先看源码树里“干活”的架子AOSP 5.1目录结构不是课堂知识它直接决定你改代码时去哪个目录翻文件。顶层目录粗看很多实际动手时高频出入的就那么几个。我把常用目录按“二次开发时动它的频率”排了个序。目录管什么第二次开发你会动它吗build编译框架、脚本和图像打包逻辑基本不动但要读懂frameworksJava框架层SystemServer、ActivityManager等核心服务在这改系统服务、加API在这hardwareHAL接口与具体实现做驱动适配、Sensor/Camera调试在这kernelLinux内核独立git仓库拉取改驱动、设备树、内核配置在这device具体设备配置、BoardConfig、启动参数锁bootloader适配、改分区大小在这vendor厂商闭源二进制和额外配置放GPU等闭源驱动、预置库packages系统应用源码、Launcher、设置等预置APK、加系统应用在这external第三方库源码换库版本、加协议实现5.1全树同步下来大约30G含.git元数据out编译产物还会再占60到80Gkernel单独拉取另算。所以第3章会专门说磁盘规划——这是第一次编5.1最容易翻车的地方。另一个容易被忽略的事实5.1的构建体系是Android.mk Jack编译器。如果你之前接触的是7.0以后的项目会看到大量Android.bp文件但5.1里根本没有。别拿新版的Soong思路去套5.1代码否则你会在“如何编写一个模块”这种基础问题上卡住半天。2.2 为什么选5.1而不是4.4或6.0先说结论5.1是5.0的修复版5.0著名的内存泄漏问题在5.1里被大面积修掉系统进程不再频繁被重建。API等级同为22但5.1的稳定性明显高于5.0这是我把这条分支作为二次开发首选的最直接理由。与4.4相比5.1默认ART运行时且支持64位设备。4.4时代Dalvik和ART并存App兼容性调试要兼顾两套运行时成本高一截。5.1直接默认ART老设备跑起来虽然比4.4多占一点内存但长期运行的稳定性更好很多国内老设备方案最后定格在5.1就是这个原因。与6.0相比6.0引入运行时权限模型framework层改动大涉及权限申请的代码逻辑全部要重写对做HAL适配和设备定制的工程师来说5.1的“安装时授权”模型简单直接你改系统应用时少掉一大类权限判断的坑。构建系统层面6.0还处于Jack向Soong过渡的混乱期5.1反而更纯粹。对比项4.45.16.0默认运行时DalvikART可选ARTART权限模型安装时授权安装时授权运行时动态申请构建系统Android.mkAndroid.mk Jack开始引入Soong过渡期混乱64位支持有限完善完善二次开发适配成本较低但性能弱低稳定中高权限逻辑复杂所以5.1并不是“老”而是老代码里最适合动手的一条线功能完整、构建统一、权限简单、资料多。2.3 这份源码适合谁、谁应该绕道适合三类人。一类是刚入行的嵌入式或系统工程师需要一条完整链路练手从repo下载、环境搭建、编译烧录到修改框架层代码。5.1代码量适中核心服务不像高版本那样被拆得面目全非容易对照教程阅读。另一类是给存量设备做系统维护的开发者比如工控机、教育平板、车载中控这些设备大量停留在Android 5.x你需要这份源码来做安全补丁或功能裁剪。第三类是学习HAL和Binder的人5.1的HAL接口相对传统代码路径清晰不像高版本有大量AIDL和Treble结构叠加。不适合的人也要说清楚。想直接做现代App兼容测试的绕道。需要新蓝牙协议栈比如BLE Mesh完整实现或新版WPA3支持的绕道。5.1的蓝牙还是Bluedroid老结构WiFi还是wpa_supplicant传统框架这些在高版本里都重构过。另外如果你的外设芯片比较新厂商只提供新版内核的驱动那5.1内核一般基于3.10、3.18或4.1很可能没有对应驱动需要自己合内核补丁这是这份资源解决不了的范围。我一般会建议先确认你的设备平台和内核版本再用官方模拟器x86镜像作为第一编译目标跑通全流程后再适配真机。不要一上来就挑战冷门板子5.1的坑大部分在工具链和存储规划上不在板子本身。3. 拉取与编译准备先算清磁盘、内存和JDK三笔账3.1 硬件和分区三个硬指标5.1源码下载和编译对机器要求不高但三个硬指标必须先满足否则中途失败浪费几个小时。第一是磁盘源码同步后约30G编译产物约60到80G日志文件还会额外占几G我建议直接按150G以上可用空间准备。第二是内存官方早年只写“至少8G”但实际开Jack编译时8G很容易OOM16G是舒服线8G的话必须配8G以上swap。第三是文件系统必须ext4或xfsFAT32和exFAT不支持源码里的符号链接和权限位同步到一半就会报错。先用几条命令确认当前机器状态df -h / free -g nproc逻辑说明df -h /查看根分区剩余空间free -g以G为单位看物理内存和swapnproc输出CPU核数。这三个值分别对应磁盘、内存、并行度后面make -j的参数就要拿nproc的结果做参考。如果你的根分区不够大常见做法是把out目录挂到独立大分区mkdir -p /data/android_out cd ~/android-5.1 ln -s /data/android_out out这里把out目录软链接到/data/android_out源码树本身不动编译中间产物全部写到大分区。注意一定要在第一次编译之前做编到一半再改软链增量缓存会乱掉。3.2 用repo拉取源码命令拆解与参数边界5.1源码必须用repo工具拉取不能用git clone直接抓全树因为AOSP由几百个独立git仓库组成manifest文件负责把它们组合起来。repo脚本本身不大下载它并赋予执行权限mkdir -p ~/android-5.1 cd ~/android-5.1 curl -sSL https://mirrors.tuna.tsinghua.edu.cn/git/git-repo -o repo chmod x repo参数说明-sSL三连-s静默不打印进度条-S出错时显示错误信息-L跟随HTTP重定向。把repo脚本下载到当前目录而不是系统目录是为了保持源码树自包含换机器重来也方便。下载完成后用它初始化manifest./repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest -b android-5.1.1_r38 ./repo sync -j8-u指定manifest仓库地址-b指定分支标签。这里用android-5.1.1_r38举例这类release tag是AOSP官方维护的5.1分支快照。关键是-b不能省——镜像站默认manifest指向master分支不指定分支会把高版本代码混进来源码结构和编译脚本对不上后面编译一定崩。repo sync -j8表示用8个并发任务同步数字参考CPU核数最大不要超过核数的两倍。sync过程中掉线或断流是常态直接重新执行一遍./repo sync即可repo会断点续传已经下载完的仓库不会重复拉取。整个树同步完成大约1到3小时取决于网络环境中途不要轻易删.repo目录那是repo的缓存数据库。3.3 JDK与编译依赖5.1的工具链脾气Android 5.1源码编译要求JDK 7这个版本卡得很死。装JDK 8或JDK 11的话编译到dex阶段会直接报class版本不兼容错误。Ubuntu 16.04之后自带的都是OpenJDK 8以上需要单独准备Jdk7。常见做法是下载OpenJDK 7的tar.gz包解压到/opt然后手动切换PATHsudo mkdir -p /opt/java sudo tar -zxf openjdk-7u80-linux-x64.tar.gz -C /opt/java export JAVA_HOME/opt/java/jdk1.7.0_80 export PATH$JAVA_HOME/bin:$PATH检查版本java -version确认输出类似openjdk version 1.7.0_80。这里的JAVA_HOME和PATH建议写进~/.bashrc每次开新终端自动生效不然下次编译又回到系统默认JDK。除了JDK还需要一堆编译依赖Ubuntu/Debian系直接装sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl libc6-dev libncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev这些包各自负责不同环节flex和bison用来生成编译分析器libncurses5-dev是内核菜单配置的基础库lib32z1-dev提供32位兼容库x11相关的是为了编译某些图形测试工具。如果漏装后面编译可能在某个模块突然中断报No rule to make target之类的错排查起来很费时间。4. 编译全流程从source到system.img的命令链与参数边界4.1 初始化环境与选择targetsource不是白写的每次打开新终端准备编译时第一件事是进入源码目录并初始化环境cd ~/android-5.1 source build/envsetup.sh lunchsource build/envsetup.sh会把一批构建函数加载进当前shell比如后面要用的mmm、mm、croot、m。这些函数不是系统命令只是shell函数不source直接敲会报“command not found”。lunch会弹出产品菜单让你选择编译目标。菜单里常见选项对应关系如下产品target含义说明aosp_arm32位ARM通用镜像适合入门纯软件模拟aosp_arm6464位ARM镜像需要arm64模拟支持full_x86x86架构全量镜像官方模拟器首选full_x86_64x86_64全量镜像桌面级开发机推荐full_generic通用无厂商定制适合做纯源码验证我一般直接执行lunch full_x86-userdebug省去交互菜单选择。最后一段的userdebug是构建类型常见有三种eng是工程师版默认带root和调试工具userdebug接近正式版但保留root调试能力user是没有root的正式版。做源码调试选userdebug最合适既能跑系统又能adb root。这个full_x86字符串不是随便填的它在build/target/product目录下有对应的full_x86.mk文件。产品名、架构、构建类型三段式组合决定了最终镜像的产物路径和系统属性。4.2 全量编译与第一份system.img初始化完成后全量编译的核心命令其实就一条make -j8 21 | tee build.logmake在AOSP里默认编译整个系统镜像-j8是并行度。并行度怎么定最稳的经验是16G内存选-j832G内存可以到-j16内存不够时并行度太高会先耗尽内存再报Jack错误。21 | tee build.log把标准输出和错误输出合并后同时打印到屏幕并写入build.log这个日志文件是后续排错的唯一依据。第一次冷编译时间跨度很大8核16G内存的机器一般在4到6小时更高配置可以在2小时左右完成。编完后到out目录看产物ls -lh out/target/product/full_x86/关键产物就这几类system.img是系统分区镜像boot.img是内核加ramdiskuserdata.img是数据分区ramdisk.img是启动内存盘。做模拟器测试时system.img、userdata.img和kernel三个文件直接被Android模拟器引用。这里有第二个容易踩的坑编译过程中途断电或手动CtrlC下次再make会做增量编译但如果源码改动较大增量可能比全量更慢而且会产生过期的中间产物。遇到诡异报错时make clean清掉out目录重新来往往最省时间。4.3 单独编译调试期的加速手段全量编译是给最终打包用的日常调试改一个模块没必要重新编整个系统。AOSP提供了模块级编译函数前提是已经source过环境source build/envsetup.sh lunch full_x86-userdebug mmm packages/apps/Settingsmmm会编译指定目录下的模块这里以Settings为例改完设置应用的代码后只需要几分钟就能出新APK。编译产物输出到out/target/product/full_x86/system/下对应的目录不会动到其他模块。还有两个变体mm是在当前目录编译模块适合你已经在模块目录里操作croot回到源码根目录。这些函数名都很短老手喜欢这么用新手容易以为是什么魔法其实就是shell函数封装。模块编译完成后需要重新打包system.img让改动生效。5.1里跑make systemimage这会基于现有out目录快速重打镜像不停留直接全量重建。注意单独编译一个模块后只执行make systemimage不要又跑一遍全量make。5. 编译避坑记录同步中断、JDK版本与Jack Server五个高频故障5.1 同步与磁盘先被绊倒的都是这两个坑1repo sync中断报early EOF现象同步进行到某个仓库时终端报fatal: early EOF或index-pack failedsync进程退出且无法继续。原因单个git仓库数据量大网络波动导致传输被截断镜像站并发连接太多时也会主动断开。解决直接重跑./repo syncrepo会从断点继续。如果反复在同一个仓库失败先清掉该仓库的临时索引再同步./repo sync 21 | tee sync.log查看sync.log里卡住的仓库路径删除.repo/projects/路径里对应的临时文件后重新sync。坑2同步完只有.repo目录没有实际源码现象sync结束后进入源码树发现只有.repo隐藏目录没有frameworks、packages这些源码头文件夹。原因repo的工作区是在sync阶段“展开”出来的如果manifest里定义的符号链接在文件系统上创建失败比如在FAT32或不支持symlink的挂载点上就会出现只有repo元数据没有源码的情况。解决确认源码所在分区是ext4/xfs后重新执行./repo sync。如果还是空检查df -h看磁盘是否真的满了inode耗尽也会造成文件创建失败用df -i查看inode余量。坑3编译时报No space left on device现象全量编译跑到中途终端报磁盘空间不足编译进程退出。原因只按源码大小30G准备磁盘没算out目录的60到80G需求或者日志文件build.log写满了分区。解决按第3章的方案把out目录软链到独立大分区给日志单独挂一个目录避免tee build.log把根分区写爆。这条建议在第一次编译前就要做完不要等报错再来挪。5.2 编译环境JDK与Jack Server的恩怨坑4dex阶段报Unsupported class file major version现象make进行到某个APK的dex处理阶段抛出类似Unsupported class file major version 52的异常编译停止。原因系统默认JDK是8或115.1的dx工具按照JDK 7标准编译遇到JDK 8生成的class文件就拒收。这不是源码问题是工具链版本错位。解决确认当前java -version输出必须是1.7.0_xx。如果装了多个JDK用sudo update-alternatives --config java切换。切换后重新source build/envsetup.sh再继续make。这个坑看起来和源码无关但九成新人在环境准备时都卡在这里。坑5Jack server启动失败或编译中途崩现象编译过程中报Jack server is not running或Out of memory error有时伴随Jack server failed to start。原因5.1的Java代码编译依赖Jack默认VM参数偏保守在并行编译和高内存占用时Jack server进程容易被系统杀掉或自己崩溃。解决在编译前设置环境变量把Jack的堆内存调大export ANDROID_JACK_VM_ARGS-Xmx4g -Dfile.encodingUTF-8 -XX:TieredCompilation如果Jack server已经处于异常状态先杀掉再重新编译jack-admin kill-server然后把~/.jack-server目录下老旧日志清掉重新启动编译进程。5.3 报错后怎么定位三看日志第一次编5.1的人最怕看到满屏红色报错但其实定位路径很固定按顺序看三个地方。一是看sync日志尾部。tail -100 sync.log搜索fatal:所有同步问题都会留在这里而且repo会准确告诉你哪个仓库挂了。二是看编译日志里的FAILED标记。命令grep -n FAILED: build.log | tail -20它会列出失败的目标模块和一条定位路径顺着路径能找到具体报错文件。三是看out目录里的中间产物。修改某个模块后重新编译发现改动没生效先检查模块APK的时间戳ls -l out/target/product/full_x86/system/app/你的模块/你的模块.apk如果时间戳还是旧的说明这个模块根本没被重新编译问题在处理流程而不是代码本身。6. 进阶用法把自研APK带签名编入system.img并验证6.1 新增一个系统应用并编进镜像全流程跑通之后最有价值的实践是在源码里加一个自己的系统应用。这里不是简单adb install而是让APK直接进system.img并获得系统签名权限。做法是在packages/apps下新建一个工程目录mkdir -p packages/apps/HelloPlatform/src/com/example/hello在packages/apps/HelloPlatform/下创建Android.mkLOCAL_PATH : $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS : optional LOCAL_SRC_FILES : $(call all-subdir-java-files) LOCAL_CERTIFICATE : platform LOCAL_PACKAGE_NAME : HelloPlatform include $(BUILD_PACKAGE)参数说明LOCAL_SRC_FILES收集子目录下所有Java源码LOCAL_CERTIFICATE : platform是核心指定使用平台签名而不是测试签名这样APK能获得system权限可以调用系统级APIBUILD_PACKAGE表示按APK规则打包。把写好Java源码的工程放进去后执行source build/envsetup.sh lunch full_x86-userdebug mmm packages/apps/HelloPlatform make systemimagemmm单独编模块make systemimage把新编好的APK打包进system.img两分钟就能验证一轮。6.2 验证签名与安装路径编译完成后启动模拟器用ADB验证应用是否真的以系统身份运行adb shell pm list packages | grep hello adb shell dumpsys package com.example.hello | grep signatures第一个命令确认包存在第二个命令查看签名信息看到signatures里包含platform签名特征就说明这个APK走的系统权限链路。用adb root后可以把它直接推到system分区adb root adb remount adb push out/target/product/full_x86/system/app/HelloPlatform/HelloPlatform.apk /system/app/HelloPlatform/这种方式适合频繁调试阶段不用每次rebuild system.img。改完APK里的代码重新编译单模块再push一次就行。这个流程后来成了我验证framework改动前必走的一步——先确认模块本身工作正常再怀疑系统服务问题。从那以后我每次拿到一份5.1源码都强制先做三件事确认JDK版本、确认磁盘余量、先把单模块编译流程跑一遍再动全量。这套习惯帮我少走了很多弯路希望帮到你。本文还有配套的精品资源点击获取