该系列文章总纲链接:专题分纲目录 Android系统基础
1 Android 原生源码编译
1.1 源码编译
@1 设置环境变量 并选择自己需要的目标版本
source build/envsetup.sh //用来设置android的编译环境
lunch aosp_arm-eng //选择产品线上的产品,这里选的是模拟器版本
该命令表示针对模拟器进行完整编译,且所有调试功能均启用。如果没有提供任何参数就运行命令,lunch
将提示从菜单中选择一个目标。这里所有的编译目标都采用 BUILD-BUILDTYPE
形式,其中 BUILD
是表示特定功能组合的代号。BUILDTYPE 是以下类型之一:
google pixel设备编译时对应的编译配置表如下所示:
设备 | 代号 | 编译配置 |
---|---|---|
Pixel 3a XL | bonito | aosp_bonito-userdebug |
Pixel 3a | sargo | aosp_sargo-userdebug |
Pixel 3 XL | crosshatch | aosp_crosshatch-userdebug |
Pixel 3 | blueline | aosp_blueline-userdebug |
Pixel 2 XL | taimen | aosp_taimen-userdebug |
Pixel 2 | walleye | aosp_walleye-userdebug |
Pixel XL | marlin | aosp_marlin-userdebug |
Pixel | sailfish | aosp_sailfish-userdebug |
@2 编译代码:make操作
Android源码编译是可以使用 make
编译任何代码的。GNU Make 可以借助 -jN
参数处理并行任务,通常使用的任务数 N 介于编译时所用计算机上硬件线程数的 1-2 倍之间。例如,在一台双核 E5520 计算机(2 个 CPU,每个 CPU 4 个内核,每个内核 2 个线程)上,要实现最快的编译速度,可以使用介于 make -j16
到 make -j32
之间的命令。常见操作如下:
make -j4
常见的一些make编译命令如下所示:
make //编译整个工程,整体编译时间较长
make module //对单个模块进行编译,对其所依赖的模块也进行编译,整体编译时间较长
mm //先进入子目录,对其目录对应的模块进行编译,编译时间短
mmm //编译制定目录下的模块,不编译其所依赖的其他模块,第一次一般都会报错,编译时间短
make生成镜像文件:
make bootimage //生成boot.img文件
make snod //重新打包生成system.img文件
make userdataimage //生成userdata.img文件
make adb //编译出对应版本的adb命令文件
make fastboot //编译出对应版本的fastboot刷机工具
@3 关于运行
可以在模拟器上运行自己的版本,也可以将其刷到设备上。(注意:因为之前已使用 lunch
选择编译目标,因此很可能无法在编译目标之外的目标上运行已编译的版本)如果是前者,编译流程会自动将模拟器添加到您的路径中。要运行模拟器,输入以下命令:
emulator
即可。如果是设备,则需要使用 fastboot来刷机
(编译成功后,会包含在out对应的的路径中)
@4 编译Android Studio中用到的SDK android.jar
说明:在Android 进行系统源码修改后,比如新API添加、新Service添加等,此时如果 开发APP的 合作伙伴 想要获得 新的API或者Service,那么就可以通过该方法 替换android.jar实现 Android Studio中 可以使用自定义API和Service的功能。
步骤如下:
source build/envsetup.sh //用来设置android的编译环境
lunch sdk-eng //注意:虽然列表中没有该选项,但依然支持
make update-api // 更新API版本
make //编译过完整的ROM
make sdk //开始编译SDK 最后生成android.jar
编译出来的 android.jar 在out目录下,通过find命令查找即可。找到后拷贝出来 替换掉Android Studio中的 android.jar。找到对应路径拷贝即可。
- 在MAC电脑上的位置:/Users/$用户名$/Library/Android/sdk/platforms/android-XX/android.jar
- 在Windows上位置是:D:\Sdk\platforms\android-XX\android.jar(说明:这也和安装位置有关,该路径仅参考)
1.2 排查编译错误
@1 JDK匹配问题
如果尝试编译的 Android 版本与自己的 Java 版本不一致,make
将会终止并显示诸如以下消息:
************************************************************
You are attempting to build with the incorrect version
of java.
Your version is: WRONG_VERSION.
The correct version is: RIGHT_VERSION.
Please follow the machine setup instructions at
https://source.android.com/source/initializing.html
************************************************************
这可能是由以下原因引起的:
未能安装 JDK要求中指定的正确 JDK。关于指定定JDK要求:
- Android 7.0 (Nougat) - Android 10.0 (Q):Ubuntu - OpenJDK 8;
- Android 5.x (Lollipop) - Android 6.0 (Marshmallow):Ubuntu - OpenJDK 7;
- Android 2.3.x (Gingerbread) - Android 4.4.x (KitKat):Ubuntu - Java JDK 6;
- Android 1.5 (Cupcake) - Android 2.2.x (Froyo):Ubuntu - Java JDK 5
或者是 之前安装的另一个 JDK 出现在您的路径中。将正确的 JDK 附加到路径开头,或者移除有问题的 JDK。
@2 Python版本问题
Repo 是基于 Python 2.x 中的特定功能构建的,但遗憾的是与 Python 3 不兼容。要使用 Repo,请安装 Python 2.x:
$sudo apt-get install python
@3 没有USB权限
如果 adb 已在运行,并且在这些规则设置完成后无法连接到设备,您可以使用 adb kill-server
将其终止。这将使 adb 采用新的配置重启。
3 通用Android fastboot镜像烧写流程
说明:一般都要先获取root权限,然后执行相关命令。
3.1 启动fastboot模式
Fastboot
是一种引导加载程序模式,可以在该模式下刷写设备。在设备冷启动过程中,可使用以下组合键进入 fastboot
模式,这里以google的pixel系列手机为例进行说明(Nexus版本太多了,命名规范也。。。都绕晕了,但是大体上类似):
Pixel XL | marlin | 按住音量调低键,然后按住电源键。 |
Pixel | sailfish | 按住音量调低键,然后按住电源键。 |
当然也可以使用命令 adb reboot bootloader
直接在 Android 系统中重新启动进入引导加载程序,而无需使用任何组合键。
3.2 解锁引导加载程序
只有在引导加载程序允许的情况下,您才可以刷写定制系统,而引导加载程序默认处于锁定状态。您可以解锁引导加载程序,但这样做会导致系统出于隐私原因而删除用户数据。(注意:解锁之后,系统会清空设备上的所有数据,即应用中的个人数据以及可通过 USB 访问的共享数据(包括照片和影片)。请先备份设备上的所有重要文件,然后再尝试解锁引导加载程序)
只需解锁引导加载程序一次,并可视需要将其重新锁定。
解锁新款设备:自2014 年以来发布的所有 Nexus 和 Pixel 设备(从 Nexus 6 和 Nexus 9 开始)都内置有恢复出厂设置保护功能,需要执行多个步骤才能解锁引导加载程序。
- 如需在设备上启用 OEM 解锁功能,请执行以下操作:
- 在“设置”中,点按关于手机,然后点按版本号七 (7) 次。
- 当看到“您已处于开发者模式”这条消息后,点按返回按钮。
- 点按开发者选项,然后启用 OEM 解锁和 USB 调试(如果 OEM 解锁处于停用状态,请连接到互联网,以便设备可以至少检入一次。如果“OEM 解锁”仍处于停用状态,则说明设备可能已被运营商锁定 SIM 卡,系统无法解锁引导加载程序)。
- 重新启动进入引导加载程序,然后使用
fastboot
解锁。- 对于新款设备(2015 年及之后发布的设备):
fastboot flashing unlock fastboot flashing lock //如果需要重新锁定
- 对于老款设备(2014 年及之前发布的设备):
fastboot oem unlock fastboot oem lock //如果需要重新锁定
- 对于新款设备(2015 年及之后发布的设备):
- 在屏幕上通过音量键 上下,电源键确认 来解锁即可。
3.3 使用刷写锁定状态
getFlashLockState()
系统 API 会传输引导加载程序状态,PersistentDataBlockManager.getFlashLockState()
系统 API 会返回兼容设备上引导加载程序的锁定状态。
返回值 | 条件 |
---|---|
FLASH_LOCK_UNKNOWN | 仅升级到 Android 7.x 或更高版本且符合以下条件的设备会返回此值:设备支持刷写锁定/解锁功能,但之前不支持获取刷写锁定状态所需的引导加载程序变更。
|
FLASH_LOCK_LOCKED | 不支持刷写锁定/解锁的所有设备(即设备始终处于锁定状态)或支持刷写锁定/解锁且处于锁定状态的所有设备会返回此值。 |
FLASH_LOCK_UNLOCKED | 支持刷写锁定/解锁且处于解锁状态的所有设备会返回此值。 |
制造商应测试由已锁定/解锁引导加载程序的设备返回的值。举例来说,Android 开源项目 (AOSP) 包含一个参考实现,该实现返回基于 ro.boot.flash.locked
引导属性的值。示例代码位于以下目录中:
frameworks/base/services/core/java/com/android/server/PersistentDataBlockService.java
frameworks/base/core/java/android/service/persistentdata/PersistentDataBlockManager.java
3.4 刷机流程
使用fastboot命令 可以刷写整个 Android 系统;这样做可验证并确保正在被刷写的系统与已安装的引导加载程序和无线驱动程序兼容,还可以将启动、恢复和系统分区一起写入,然后重新启动系统。与 fastboot oem unlock
类似,刷写设备也会清空所有用户数据。
在设备处于 fastboot 模式后,可以运行以下命令进行相关的初始化:
$adb reboot bootloader //进入 fastboot 模式
$fastboot devices //查看设备是否连接成功
可以一次性刷机,命令如下:
#方法1
$fastboot update -w google_img.zip //完整刷机,google_img.zip为完整刷机包
#方法2,进入到out目录,直接执行
$fastboot flashall -w
注意:-w 选项会擦除设备上的 /data 分区;该选项在第一次刷写特定设备时非常有用,但在其他情况下则没必要使用
刷机相关的命令如下(可以根据自己的需要刷写特定的部分):
$fastboot flash aboot emmc_appsboot.mbn //烧写bootloader分区
$fastboot flash boot boot.img //烧写kernel分区
$fastboot flash system system.img //烧写system分区
$fastboot flash userdata userdata.img //烧写userdata分区
$fastboot flash persist persist.img //烧写persist分区
$fastboot flash cache cache.img //烧写cache分区
$fastboot reboot //重启
说明:以下img或者其他文件有可能会根据项目不同导致烧写的方式不同,fastboot特殊分区烧写方式如下:
$adb reboot bootloader
$fastboot flash persist persist.img //烧写persist分区
$fastboot flash cache cache.img //烧写cache分区
$fastboot flash modem NON-HLOS.bin //烧写modem分区
$fastboot flash tz tz.mbn
$fastboot flash sbl1 sbl1.mbn
$fastboot flash rpm rpm.mbn