AOSP-下载、编译、调试、刷机
开启新世界,开始搞机啦,第一步就是先整系统源码。
准备工作
基于Ubuntu系统下的操作(Linux和MacOS也可以)。
Ubuntu设置中设置为永不休眠。
分配大一点的存储空间,至少200G(推荐500G+)。
下载AOSP源码
安装Git
用于下载和管理源码
1 | sudo apt-get install git |
安装依赖工具:
1 | sudo apt install git-core libssl-dev libffi-dev gnupg flex bison gperf build-essential zip curl zlib1g-dev |
接下来创建一个bin文件夹,并加入到PATH中,有点像Windows的环境变量。
1 | mkdir ~/bin |
然后初始化Git,邮箱和用户名
1 | git config --global user.email "xxx@gmail.com" |
安装Python环境
下载Python3
1 | cd Downloads |
解压Python3
1 | tar xvf Python-3.7.1.tgz |
编译与安装Python3
1 | ./configure |
配置Python版本
1 | sudo update-alternatives --install /usr/bin/python python /usr/bin/python2.7 2 |
选择Python版本
1 | sudo update-alternatives --config python |
如果Ubuntu自带Python环境的话
已有Python环境时可能会遇到这个错误
/usr/bin/env: ‘python’: No such file or directory
首先,检查Python环境,使用python/python2/python3 –version查看
1 | python3 --version |
查找Python安装位置
1 | whereis python3 |
为其创建符号连接
1 | sudo ln -s /usr/bin/python3 /usr/bin/python |
安装repo及配置
repo 是一个python 脚本(所以我们上面要配置Python环境),因为Android源码包含数百个git库,简化帮助管理git Android版本库的工具。
安装curl下载的库
1 | sudo apt-get install curl |
下载repo并设置可以运行权限
1 | curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo > ~/bin/repo |
添加下载源
google 的AOSP 的话,因为FQ和数据量太大,且需要需要翻墙影响速度,因此优先考虑国内的镜像(本文使用的是清华的源)。
1 | export REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/' |
初始化同步源码
第一次同步数据量特别大,如果网络不稳定,中间失败就要从头再来了。所以推荐使用打包的 AOSP 镜像,为一个 tar 包,大约 200G(单文件 200G,注意你的磁盘格式要支持)。这样你 就可以通过 HTTP(S) 的方式下载,该方法支持断点续传。
下载地址 https://mirrors.tuna.tsinghua.edu.cn/aosp-monthly/aosp-latest.tar
下载完成后记得根据 checksum.txt 的内容校验一下。
由于所有代码都是从隐藏的 .repo
目录中 checkout 出来的,所以我们只保留了 .repo
目录,下载后解压 再 repo sync
一遍即可得到完整的目录。
使用方法如下:
1 | tar xf aosp-latest.tar |
此后,每次只需运行 repo sync
即可保持同步。
同步代码过程中如果报错,进入 aosp/.repo/repo$
git status
查看是否已经落后远程分支,如果落后,git pull,然后再同步一次代码。
查看分支
1 | cd .repo/manifests |
查找并切换到对应的分支
1 | repo init -b android-12.0.0_r30 |
如果仅加载具体模块
1 | repo sync platform/prebuilts/clang/host/darwin-x86 |
防止下载源码执行脚本卡死
通过自定义Shell脚本启动源码下载可以有效防止,同步源码时脚本被卡死的问题。
在AOSP文件夹中新建down.sh文件
1 | !/bin/bash |
执行down.sh
1 | sh down.sh |
AOSP源码目录结构
abi Application Binary Interface 应用程序二进制接口,abi相信同学们在SO库调用上遇到过,如果不支持该平台的话就说不ABI不支持。
art Android Runtime 安卓运行时。这个会提前把字节码编译成二进制机器码保存起来,执行的时候加载速度比较快。Dalvik虚拟机则是在加载以后再去编译的,所以速度上ART会比Dalvik快一点。牺牲空间来赢取时间。
bionic 基础库,Android系统与Linux内核的桥梁。Bionic 音标为 bīˈänik,翻译为”仿生”。
bootable 系统启动引导相关程序
build 用于构建Android系统的工具,也就是用于编译Android系统的
cts Compatibility Test Suite 兼容性测试
dalvik dalvik虚拟机,用于解析执行dex文件的虚拟机
developers 开发者目录
developerment 开发目录,比如说应用,application就在里面了,apps
devices 设备相关的配置信息,什么索尼、HTC、自己的产品,就可以定义在这个目录下了
docs 文档
external 开源模组相关文件
frameworks 系统架构,Android的核心了
hardware hal层代码,硬件抽象层
libcore 核心库
libnativehelper native帮助库,实现JNI的相关文件
ndk native development kit
out 输出目录,编译以后生成的目录,相关的产出就在这里了
packages 应用程序包。一些系统的应用就在这里了,比如说蓝牙,Launcher,相机,拨号之类的。
pdk Plug-in Development Kit (PDK) is designed to help you build your own pattern projects
platform_testing 平台测试
prebuilts x86/arm架构下预编译的文件
sdk software development kit
system 底层系统文件
toolchain 工具链
tools 工具文件
Makefile mk文件,用于控制编译
AOSP源码编译
编译前准备
交换空间设置
编译时非常吃内存,比如Android12,16G都是不够的,我这边主机是32G的,虚拟机分配了16G,交换空间又给了32G。(一开始虚拟机分配了8G,结果编译到95%时OOM了……)
Linux 的交换分区(swap),或者叫内存置换空间(swap space),是磁盘上的一块区域,可以是一个分区,也可以是一个文件,或者是他们的组合。交换分区的作用是,当系统物理内存吃紧时,Linux 会将内存中不常访问的数据保存到 swap 上,这样系统就有更多的物理内存为各个进程服务,而当系统需要访问 swap 上存储的内容时,再将 swap上的数据加载到内存中,也就是常说的 swap out 和 swap in。我们安装的Ubuntu默认一般是2G左右的swap空间,(可以提供过free -m命令查看虚拟内存与交换空间大小)使用以下命令查看swap详情:
1 | swapon -s |
配置交换空间
停用交换文件:(根据自己虚拟机来指定/swapfile 还是其他的挂载文件)
1 | sudo swapoff /swapfile |
删除文件:
1 | sudo rm /swapfile |
删除后继续创建。
新建swap空间,以32G为例,创建文件:
1 | sudo fallocate -l 32G /swapfile |
这里我们是命名为“swapfile”,当然你也可以随意写。设置文件权限:
1 | sudo chmod 600 /swapfile |
挂载:
1 | sudo mkswap /swapfile |
激活启用:
1 | sudo swapon /swapfile |
接着把交换信息写入系统配置,不然Ubuntu重启后以上配置swap空间工作得重新做。
使用vim编辑器打开配置文件:
1 | sudo vim /etc/fstab |
如果提示vim找不到命令,使用以下命令安装vim,然后再次打开配置文件
1 | sudo apt-get install vim |
在最后一行插入(vim打开后按i进入编辑模式,移动光标到最后回车换行):
1 | /swapfile swap swap defaults 0 0 |
编辑好之后按ESC键退出编辑模式,然后依次输入:wq(英文冒号+wq)保存退出,并重启即可。
交换空间未使用
系统只有当虚拟内存不足才会启动Swap,比如系统默认内存只有6000KB时才会启用交换空间,但是此时系统可能已经卡死,无法启动swap,所以需要更改设置。
终端输入命令:
1 | sudo vim /etc/sysctl.conf |
在最后面添加如下语句(按i进入编辑模式,光标移到最后,插入语句)
1 | vm.min_free_kbytes=1500000 #大致1.5G |
保存退出(按ESC退出编辑模式,输入:wq保存退出)然后重启开机。
以上配置的意思是,当系统内存不足1.5G时就启用交换空间,这是因为我分配给Ubuntu
的内存为8G。而如果你虚拟机分配的内存是4G,那建议不要设置1.5G就启用交换空间,
可以调小一些,比如调整为1G:
vm.min_free_kbytes=1000000
配置java环境
已有请忽略
1 | sudo apt-get update |
进入AOSP文件夹进行编译
初始化编译环境
1 | source build/envsetup.sh |
删除上一次编译的结果,初次编译可以不需要这一步
1 | make clean |
选择与设备对应的编译版本
1 | lunch XX |
选择与设备对应的编译版本.如:编译开发工程师的版本lunch aosp_x86-eng
,可以方便debug
编译版本选择
如果lunch
命令没有加对应的编译版本则会有以下信息输出:
1 | You're building on Linux |
这里需要选择编译目标的格式(选择前面的序号,按回车即可),编译目标的格式组成为BUILD-BUILDTYPE
,比如aosp_arm-eng的BUILD为aosp_arm,BUILDTYPE为eng。 其中BUILD表示编译出的镜像可以运行在什么环境,aosp代表Android开源项目,arm表示系统是运行在arm架构的处理器上。 更多参考官方文档文档。
BUILDTYPE 指的是编译类型,有以下三种:
- user:用来正式发布到市场的版本,权限受限,如没有 root 权限,不能 dedug,adb默认处于停用状态。
- userdebug:在user版本的基础上开放了 root 权限和 debug 权限,adb默认处于启用状态。一般用于调试真机。
- eng:开发工程师的版本,拥有最大的权限(root等),具有额外调试工具的开发配置。一般用于模拟器。
如果你没有Nexus设备,只想编译完后运行在模拟器查看,那么BUILD可以选择aosp_x86,BUILDTYPE选择eng。
如果需要跑模拟器,则必须选择sdk开头的。
开始编译
1 | m或者make均可 |
j后面数字几就是多少线程,最多不超过你的cpu总线程,
编译成功会显示如下:
1 | Creating filesystem with parameters: |
会在源码跟目录out/target/product/angler目录下生成镜像文件:
- system.img:系统镜像
- ramdisk.img:根文件系统镜像
- userdata.img:用户数据镜像
- recovery.img:recovery镜像
- boot.img:启动镜像
- vendor.img:驱动镜像
最终会在 out/target/product/generic_x86/目录生成了三个重要的镜像文件: system.img、userdata.img、ramdisk.img。大概介绍着三个镜像文件:
- system.img:系统镜像,里面包含了Android系统主要的目录和文件,通过init.c进行解析并mount挂载到/system目录下。
- userdata.img:用户镜像,是Android系统中存放用户数据的,通过init.c进行解析并mount挂载到/data目录下。
- ramdisk.img:根文件系统镜像,包含一些启动Android系统的重要文件,比如init.rc。
编译错误解决
缺少libncurses.so.5
报错信息:
error while loading shared libraries: libncurses.so.5: cannot open shared object file: No such file or directory
解决方式:
1 | sudo apt-get update |
for 32-bit binaries :
1 | sudo apt-get install libncurses5:i386 |
for 64-bit binaries :
1 | sudo apt-get install libncurses5 |
缺少M4
报错信息:/bin/bash: m4: command not found
解决方式:
1 | sudo apt-get install m4 |
去除所有本地化设置
报错信息:FAILED: out/host/linux-x86/obj/EXECUTABLES/checkpolicy_intermediates/policy_scan.c
解决方法:
1 | export LC_ALL=C |
LC_ALL=C 是为了去除所有本地化的设置,让命令能正确执行, 但是不可以修改~/.bashrc,会导致终端内中文显示为数字(应该是对应的编码)
jack-server问题
jack server交互命令:
1 | jack-admin start-server |
问题一:多用户同时编译时报错
错误信息:
1 | FAILED: setup-jack-server |
解决方案:同时修改HOME/.jack-server/config.properties中的端口号(比如都改为8386/8387,端口号值为0~65535,1024下的值不要用),方可支持多用户同时编译。
查看端口是否一致:cat ~/.jack-server/config.properties|grep -i port && cat ~/.jack|grep -i port|grep -v LOG &&cat ~/.jack-settings|grep -i port
- $HOME/.jack-settings
1 | SERVER_PORT_SERVICE=8386 |
- $HOME/.jack-server/config.properties
1 | jack.server.service.port=8386 |
- $HOME/.jack
1 | SERVER_PORT_SERVICE=8288 |
问题二: No Jack server running. Try ‘jack-admin start-server’
错误信息
1 | com.android.jack.server.api.v01.ServerException: './config.properties' musthave permission rw------- but have rwx------ |
解决方案:通过查看文件 HOME/.jack-server/config.properties的权限由rwx改为rw即可解决问题。
问题三:未配置变量信息导致问题
错误信息:
1 | ERROR: Communication error with Jack server (52) make: *** [out/target/common/obj/JAVA_LIBRARIES/libutil_intermediates/classes.jack] Error |
这种情况多半属于jack-admin缺少变量JACK_JAR而导致的。
解决方案:
工程根目录内执行以下三句,再进行编译。
1 | export JACK_JAR=./out/host/linux-x86/framework/jack.jar |
问题四:TLSv1, TLSv1.1 禁用
报错信息:
1 | Ensuring Jack server is installed and started |
解决方式:
1 | sudo vim /etc/java-8-openjdk/security/java.security |
vim里面输入/搜索jdk.tls.disabledAlgorithms= 将TLSv1, TLSv1.1 光标选中输入x删除掉取消禁用.然后wq保存.
修改后:
1 | jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, \ |
aosp/prebuilts/sdk/tools/ 目录下执行./jack-admin kill-server && ./jack-admin start-server 成功。
xmllint的问题
报错信息:/bin/bash: xmllint: command not found
解决方案:
1 | sudo apt-get install libxml2-utils |
编译内存不足
报错信息
1 | Try increasing heap size with java option '-Xmx<size>'错误 |
解决方案:
1 | export JACK_SERVER_VM_ARGUMENTS="-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4g" |
1 | jack-admin kill-server |
运行模拟器
启动模拟器
在编译完成之后,就可以通过以下命令运行Android虚拟机了,由于之前已经执行过source和lunch命令了,可以直接运行:
1 | source build/envsetup.sh |
启动模拟器失败
libncurses.so.5缺少
1 | aosp error while loading shared libraries: libncurses.so.5 |
解决方案
1 | 解决方法: |
缺少文件userdata-qemu.img
1 | cannot addlibrary /root/aosp/prebuilts/android-emulator/linux- |
解决方案
1 | 编译“aosp_car_x86_64-userdebug”,完成后执行emulator无法正常进入模拟器 |
模拟器启动后界面一直处于phone is starting
解决方案
1 | 使用emulator命令和emulator -partition-size 200来回重试 |
AOSP源码编译某个单独的模块
上面的编译我们都是对整个Android系统进行编译的.如果我们要编译系统的Settings应用模块,这就属于源码单编某一个模块.
在AOSP根目录执行:
1 | source build/envsetup.sh |
进入Settings的目录:
1 | cd packages/apps/Settings |
通过mm编译当前目录下的模块,不编译依赖模块。
1 | mm |
编译成功后会有提示生成文件的存放路径。除了Settings.odex文件,还会在out/target/product/generic_x86/system/priv-app/Settings目录下生成Settings.apk。
此外还有以下命令可以进行单编:
- mmm:编译指定目录下的模块,不编译它所依赖的其它模块。
- mma:编译当前目录下的模块及其依赖项。
- mmma:编译指定路径下所有模块,并且包含依赖。
如果对系统模块的源码进行修改,查看生成的APK文件,有两种方式:
- 通过adb push或者adb install 来安装APK。
- 使用make snod命令,重新生成 system.img,运行模拟器查看。
导入源码到AndroidStudio
编译idegen模块,生成IDE项目文件
在源码中,存在idegen模块,该模块专门用来为idea工具生成系统源码的project.默认情况下aosp编译并不会生成该文件。
在开始编译该模块之前,首先确保你已经编译过Android源码了,如果没有,先要进行AOSP编译.和编译普通的模块一样,我们用mmm命令编译idegen.
在开始编译之前,检查out/host/linux-x86/framework/目录下是否存在idegen.jar文件,存在则说明你已经编译过该模块,否者,则需要编译.执行如下命令即可:
1 | source build/envsetup.sh 将脚本添加到系统内 |
其中mmm development/tools/idegen/执行完成后会生成idegen.jar,而sodo ./development/tools/idegen/idegen.sh则会在源码目录下生成IEDA工程配置文件:android.ipr,android.iml及android.iws.
简单的说明一下这三个文件的作用:
- android.ipr:通常是保存工程相关的设置,比如编译器配置,入口,相关的libraries等
- android.iml:则是主要是描述了modules,比如modules的路径,依赖关系等.
- android.iws:则主要是包含了一些个人工作区的设置.
“android.iml”和”android.ipr”一般是”只读”的属性,我们这里建议大家,把这两个文件改成可读可写,否则,在更改一些项目配置的时候可能会出现无法保存的情况,执行如下两条命令即可。
1 | sudo chmod 777 android.iml |
导入源码到AndroidStudio
配置AS
IDE内存优化
因为源码数量非常多,所以导入时IDEA/AS会需要大量内存。所以我们需要编辑IDE的VM选项。配置文件为
IDEA的是IDEA_HOME/bin/idea.vmoptions
AS的是AS_HOME/bin/studio.vmoptions
注意,AS有一个64位版本的配置文件studio64.vmoptions最好一并修改了。
找到上面的配置文件,将对应的内容修改为
1 | -Xms748m -Xmx748m |
即将VM的堆内存最小和最大都设置为748m。官方要求至少在748m以上,根据实际情况进行配置即可
导入源码
接下来,我们导入源码:打开Android Studio,点击File->Open,选择刚才生成的android.ipr文件即可,然后就是漫长的等待,注意此时是将源码完全导入到AS中了。
如果AS运行比较慢我们就需要排除一些不需要导入的模块。
排除模块
很多情况下,我们希望不导入某些模块,那么就可以在导入前修改android.iml文件,通过添加配置的方式告诉AS不导入某些模块,比如现在我不想导入art模块,那么就在android.iml文件中添加:
1 | <excludeFloder url="file://$MODULE_DIR$"/abi> |
不难发现,其格式为:<excludeFloder url="file://$MODULE_DIR$"/模块名>
注:编译生成的android.iml文件中已经默认排除了一些模块,通过搜索excludeFolder关键字可找到.
如果比较关心framworks和packages模块,则保留framworks和packages模块,将其他模块全部排除,在android.iml中添加了以下配置:
1 | <excludeFolder url="file://$MODULE_DIR$/.repo" /> |
完成之后,按照上面说的步骤,使用Android Studio选中”android.ipr”打开项目即可。
等项目加载完成后,我们还可以通过Android Studio对Exclude的Module进行调整,所以也不用害怕这里Exclude掉了有用的代码,或少Exclude了一部分代码,在项目加载完以后再进行调整就行了。此处和在android.iml文件中添加excludeFolder 的功能是一样的;
打开”Project Structure”,中间的窗口选择”android”,在弹出的窗口中左边栏中选择”Modules”,而后在右边的窗口中选择”Sources”。
在这里我们可以看到项目的所有代码目录,我们可以选中不需要的module,并点击上面的”Excluded”按钮,当被选中的目录变为橙色,即表示完成Exclude操作;
如果想要取消对某代码目录的Exclude操作,选中该目录,再次点击”Excluded”按钮,等待目录变为蓝色即可。
配置源码正确跳转
当我们导入完源码后,就可以查看整个系统的源码,但是有个问题,打开的Java代码,查看集成关系或者调用关系的时候,还是会跳转到.class文件中,而不是相应的Java类,
比如PhoneWindow.java继承了Window.java,但是我们跳转的时候却跳到了Window.class,并没有跳转到frameworks目录下对应的源码类,而是jar包中的类。
我们需要让其跳转到相应的类中。我们就需要新建一个没有任何jar库的SDK给到系统源码项目的依赖, 这里的配置JDK/SDK,是用于解决在分析和调试源码的过程,能正确地跳转到目标源码,
而非SDK中的代码。
- 新建JDK
Project Structure -> SDKs, 新建 JDK, 其中JDK目录可选择跟原本JDK一致即可,任意取一个名字,这里取empty_jdk 然后删除这里取empty_jdk其classpath和SourcePath的内容,确保使用Android系统源码文件
- 配置SDK
Project Structure -> SDKs, 选中与自己编译的AOSP对应的SDk版本(如果没有对应的就到SDKmanager里面取下载一个对应的版本) Android API 28 Platform, 然后选择其Java SDK为前面新建的empty_jdk
- 选择SDK
Project Structure -> Project -> 选中Project SDK, 选择前面的Android API 28 Platform
- 建立依赖
Project Structure -> Modules -> android -> Dependencies: Module选择我们上面编辑过的SDK。然后点击下图绿色的+号来选择Jars or directories,将 aosp/frameworks 目录添加进来,再按照同样的步骤将aosp/external 目录, 也可添加其他所关注的源码;
然后选中其他所有的依赖,点击右边的下移箭头将其他依赖移动到我们添加的目录下面。(或者将其他的所有依赖删除)
注意,一般我们大部分人不在ubuntu下开发app ,为了能在Windows或Mac系统下也能使用Android Studio查看源码,
可以按照上面的步骤,那样直接拷贝ubuntu下的android.iml和android.ipr文件到Windows或Mac系统下的android源码根目录下,
然后导入Adnroid Studio中,这样就可以在这两个平台上进行查看源码了。
通过AS调试源码
打开模拟器
要调试代码,首先要打开模拟器,注意不是Android Studio自带的模拟器,而是通过编译后的代码启动的模拟器,否则可能出现代码不对应的问题。
直接运行emulator命令是无法启动的,执行方法如下:
1 | source build/envsteup.sh |
接下来通过Run->Attache debugger to Android process,在弹出的Choose Process框内必须选择Show all processes,否则看不到相关的进程:然后选择system_process,就可以进行调试了。
Android刷机知识
BootLoader
机器首先要启动,CPU 最先执行的一段程序就是 BootLoader,是在操作系统内核运行之前运行的一段小程序。其实Bootloader就相当于电脑的bios。 通过这段小程序,进行硬件初始化,获取内存大小信息等,调整手机到适配状态,从而将系统的软硬件环境带到一个合适状态,以便为最终调用操作系统内核准备好正确的环境。
。很多的手机厂商都会锁住BootLoader,这样你就只能使用官方的系统,想要第三方的ROM能够运行,或者破解官方系统这时候就需要进行bootloader解锁!这是刷机的第一步, 当然也有很多手机没有bootloader锁!我们只需要知道要想刷机就得先bootloader解锁。
FastBoot
fastboot,它是bootloader后期进入的一个特殊阶段。例如小米手机开机同时按音量下建就会进入这个模式.也是一种模式。可以通过数据线与电脑连接,然后在电脑上执行一些命令,如刷系统镜像到手机上。fastboot可以理解为实现了一个简单的通信协议,接收命令并更新镜像文件,其他什么的干不了。
需使用USB数据线连接电脑和手机的一种线刷刷机模式,大部分第三方的Recovery刷入,或者救砖均是在Fastboot模式下进行,所以这种方式称为线刷。 fastboot需要bootloader的支持,所以不是每家手机都会支持这种模式。Fastboot 可以说是一个通信协议,电脑可以通过这个通信协议,直接向手机系统不同分区中写入文件(.img 文件)。
fastboot(bootloader)模式怎么进入?
大多数安卓手机,都可以在关机状态下,然后同时按住【电源键】+【音量+】键,大约2-3s后,就可以进入Fastboot模式。 作为开发者在开机状态下可以用下面的方式进入:
1 | adb reboot bootloader |
fastboot命令
然后就可以执行下面的fastboot命令了:
1 | fastboot flashing unlock #6.0以上设备 设备必须解锁,开始刷机(这个不同的手机厂商不同) |
Recovery
如果没有进入fastboot,bootloader继续执行,如果又发现有特殊的按键组合,比如小米上是音量上键和开机键,则会进入recovery模式。它里面包含了一个kernel以及一个可执行程序recovery,以
及一些初始化文件。Recovery模式指的是一种可以对安卓机内部的数据或系统进行修改的模式,也叫工程模式,像是电脑上的小型winPE系统,winPE可以在电脑上安装操作系统,或者做些删除备份、管理的工作。
官方Recovery用处不大,所以通常会刷入一个第三方的Recovery ,Recovery 更类似于一个小型的管理系统。只不过功能简单,所做的管理有限。在recovery模式下,会加载了部分文件系统,所以才可以读sdcard中的update.zip进行刷机,当然,也可以清除cache和用户数据。
该模式可根据用户的需要进行修改,因此有官方recovery模式以及第三方recovery模式。第三方recovery模式可以识别第三方rom包,因此可以用来刷机。而官方recovery一般不能识别第三方zip文件。好用的第三方RE:TWRP 和 CWM Recovery刷机包是称为Google Update 格式。在用Recovery恢复时,刷机包通常放在SD卡里,所以这里刷机一般称为卡刷。
线刷和卡刷
- 线刷: 直接想手机硬盘写入*.img 文件,我个人觉得这种方法比较快捷,而且省事。但是必须借助电脑和数据线。
- 卡刷:就是利用recovery的从SD卡中更新系统的这个功能,如果你想刷第三方Rom,必须刷入个第三方recovery,只有fastboot模式才能刷recovery.img。卡刷有个限制,必须要把想要更新的ROM(Android系统)拷贝到SD卡上。如果手机已经是砖了。那只能用线刷了。
手机硬件驱动知识
硬件驱动的作用
AOSP是一个由谷歌维护的开源操作系统开发项目,既然是开源项目,也就意味着任何人都可以自由地审查和贡献代码以及修复项目仓库,而谷歌引领着大方向和大部分的开发工作。AOSP会定期为Android加入最新的安全补丁,谷歌每年也会在其I/O开发者大会上公布操作系统的新功能。除了开放贡献代码外,AOSP还可以在开源许可下自由使用和修改。
比如,小米,华为等厂商根据自己的目的自由调整该项目,并开发了自己的衍生产品,包括多用途的emui和miui。需要注意的是,AOSP包含了开发者构建Android所需的一切,但它并不包括成品智能手机所需的一切。
谷歌和AOSP无法为所有硬件配置提供内核设备驱动。所谓设备驱动,是指手机硬件所需的固件,比如处理器或摄像头。手机和SoC制造商,如高通和三星,必须将这些驱动程序纳入他们的Android构建中。
这也是为什么从AOSP到实际设备的系统更新需要一定时间的原因。其次AOSP也不包含谷歌的软件应用套件,如Chrome浏览器、YouTube,甚至谷歌Play商店。
它也不包括谷歌的一些底层技术和API,而这些技术和API可以实现移动支付、语音命令和云存储等功能,这些都是作为谷歌移动服务(GMS)单独授权的。 任何厂商想要在系统中安装GMS,都必须为自己的设备获得GMS授权和移动应用分发协议(MADA),然后通过多项兼容性测试。有Android兼容性测试套件(CTS)来验证软件和硬件以及API。
正因为AOSP开源的特性,许多的硬件厂商的驱动代码并不是开源的,所以AOSP会有一个硬件抽象层 (HAL),来保证驱动程序代码不被泄露。大多数手机厂商都是从高通等芯片厂商那里获得AOSP版本,该AOSP版本为硬件量身定坐了高通驱动程序,所以刷入真机是可以正常的运行。
如何添加硬件驱动
在上面步骤中我们编译好了AOSP可以直接通过模拟器运行.编译aosp时也会生成system.img文件,这个文件是最终刷机用的,但是system.img文件必须依赖驱动文件生成,
如果没有放入对应的驱动就编译,那么生成的镜像也是无法正常刷机的。通过上文我们知道aosp 仅是一套源码,真机运行需要厂商的驱动,厂商的驱动是不包含在AOSP中的,
第三方ROM(如CM等)的厂家驱动是自行提取的。但是google也开源了nexus和pixel对应的AOSP版本的硬件驱动代码.如果我们有nexus或者是pixel设备就可以下载相应的驱动进行编译,
然后将编译好的系统输入到设备中去.
下载对应的驱动
生成驱动
将驱动文件下载后,解压到AOSP根目录,得到几个.sh文件,执行后,会在AOSP下创建vendor目录,里面包含了驱动。
编译带有驱动的AOSP
再次make -j4
,此次编译的结果就包含了驱动,编译出新的系统.
ROM编译及烧录
一般定制ROM其实就是对手机内存里的system/app文件夹的内容进行自定义,系统所有的程序都在这个文件夹里,比如浏览器、拨号器、联系人等。自己安装的软件\data\文件夹中。
真机驱动下载
在上文中可以了解到厂商的驱动是不包含在AOSP中的.因此编译出来的AOSP系统源码要在真机上运行,还需要加上厂商驱动进行编译才能烧录到真机上使用.
Google提供了Nexus和Pixel这两个太子机的驱动,我们可以在驱动页面下载合适的驱动。
Driver Binaries for Nexus and Pixel Devices
配置真机驱动到AOSP
- 在上面链接里面,两个文件都进行下载,一个是google vendor,一个qcom。
- 解压得到
extract-google_devices-blueline.sh
,extract-qcom-blueline.sh
- 将这两个脚本放到aosp代码目录下,进行提取
sh extract-google_devices-blueline.sh
1 | vendor/ |
第2个 高通驱动
sh extract-qcom-blueline.sh
1 | vendor/ |
执行后,会在AOSP下创建vendor目录,里面包含了驱动。编译完成后,执行make fastboot adb
单独编译fastboot和adb。
编译Rom
重新对AOSP进行编译.此次编译的结果就包含了驱动,编译完成后,执行make fastboot adb 单独编译fastboot和adb。
烧录Rom到手机
- 手机启用开发者模式,打开 USB 调试 adb shell 能进入。
- 开机键 + 音量- 进入 bootloader 模式。
- 电脑上能识别出来手机并装上了驱动。
- fastboot devices 能看到设备。
- 再次执行./fastboot -w flashall将开始刷机,刷完会自动重启,over!
参考资料:
Android 镜像使用帮助
MIUI ROM适配之旅第一天——认识Android手机
Android FrameWork 学习之Android 系统源码调试
从CM刷机过程和原理分析Android系统结构
Android ROM移植
android rom移植知识普及
Android系统源码修改
android系统的分区结构
Android ROM的制作与烧录
android系统源码中添加app源码(源码部署移植)
参考资料:
Ubentu编译Android源码(AOSP)
AOSP源码下载/编译/刷机/调试
Android rom移植一
目前通用的Android拼包移植方法均是正向移植
Android驱动开发全过程