背景:
这几天有学员问了一个怎么在安卓高版本编译一个模拟器运行的kernel,因为平时都是实体机小米,pixel等开发kernel没有模拟器来搞kernel,原本以为这个会比较简单,网络应该很多文章。但是学员一直反馈不成功,我这边也按他的给链接(其实就是参考水文章的锅)等进行了尝试确实不行,而且这块模拟器kernel文章说实话都是些老版本,基本上网络找一了一遍没有一篇是新版本而且可以成功。所以基本上靠网络那些blog文章是不太可能成功的,最后还是在网友等提醒支持下搞定了,所以记录一下弥补网络这块的空白。
官方权威参考链接:
https://source.android.google.cn/docs/setup/build/building-kernels?hl=en#running
下载源码(非常重要):
(注意这里非常非常重要,因为很多学员朋友说国内没办法访问google,所以百度到其他的git clone方式导致仓库不全等,走进了坑...)
创建单独kernel目录:
mkdir android-kernel && cd android-kernel
进行repo代码:
bash
repo init -u https://android.googlesource.com/kernel/manifest -b BRANCH
注意这里很多同学不可以翻墙的,那么就只能选择国内一些镜像这里一定要选着中科大的镜像方法如下:
bash
repo init -u https://mirrors.ustc.edu.cn/aosp/kernel/manifest -b common-android14-6.1
这里的BRANCH大家可能不知道搞啥,不知道为啥写common-android14-6.1,这里可以根据我们模拟器手机设备上的来进行确定:
这里是6.1的kernel,那么就知道我们应该选着6.1的版本
具体的版本可以查看如下链接
https://source.android.google.cn/docs/setup/reference/bazel-support?hl=en
repo init成功后应该显示如下:
然后再进行repo sync,成功后显示如下:
到这里如果你可以和我的一样了,那说明你已经成功了一半了。
(很多同学就是没有下载正确kernel源码仓库,可能只有这里面的common仓库导致需要到aosp源码环境来帮忙编译才可以,但是也只能编译出来kernel,还有很多ko等没有编译出来,所以根本无法正确运行)
启动编译:
直接在repo代码根目录进行bazel编译:
编译kernel部分
编译kernel使用如下命令,注意这里的myout就是编译输出路径
bash
tools/bazel run //common:kernel_x86_64_dist -- --dist_dir=myout
一切顺利就展示如下:
可以去myout路径看看:
可以看到有bzImage和一堆的ko等文件,这里的 bzImage其实就是我们的kernel,难道直接就可以拿这个bzImage去运行了么
bash
test@test:~/disk2/aosp14$ emulator -kernel ~/disk2/kernel-aosp14/myout/bzImage -show-kernel
-show-kernel主要放开kernel日志方便调试
执行后变成下面这样
bash
[ 1.645554] init: Loading module /lib/modules/virtio_blk.ko with args ''
[ 1.645826] virtio_blk: disagrees about version of symbol module_layout
[ 1.646051] init: Failed to insmod '/lib/modules/virtio_blk.ko' with args '': Exec format error
[ 1.646344] init: LoadWithAliases was unable to load virtio_blk
[ 1.646585] init: Copied ramdisk prop to /second_stage_resources/system/etc/ramdisk/build.prop
[ 1.646946] init: [libfs_mgr] ReadFstabFromDt(): failed to read fstab from dt
[ 1.647401] init: Using Android DT directory /proc/device-tree/firmware/android/
[ 1.655634] init: bool android::init::BlockDevInitializer::InitDevices(std::set<std::string>): partition(s) not found in /sys, waiting for their uevent(s): metadata, super, vbmeta
[ 11.666385] init: Wait for partitions returned after 10010ms
[ 11.667437] init: bool android::init::BlockDevInitializer::InitDevices(std::set<std::string>): partition(s) not found after polling timeout: metadata, super, vbmeta
[ 11.670056] init: Failed to mount required partitions early ...
[ 11.671599] init: InitFatalReboot: signal 6
[ 11.683528] init: #00 pc 0000000000323cd1 /init (unwindstack::AndroidLocalUnwinder::InternalUnwind(std::__1::optional<int>, unwindstack::AndroidUnwinderData&)+97) (BuildId: 65c73120e092a845c594ec841c61406c)
[ 11.684854] init: #01 pc 0000000000317b5b /init (android::init::InitFatalReboot(int)+251) (BuildId: 65c73120e092a845c594ec841c61406c)
[ 11.685577] init: #02 pc 0000000000318243 /init (android::init::InstallRebootSignalHandlers()::$_0::__invoke(int)+19) (BuildId: 65c73120e092a845c594ec841c61406c)
[ 11.686345] init: #03 pc 00000000004f4eb0 /init (__restore_rt) (BuildId: 65c73120e092a845c594ec841c61406c)
[ 11.686816] init: #04 pc 00000000004e81ef /init (abort+191) (BuildId: 65c73120e092a845c594ec841c61406c)
[ 11.687239] init: #05 pc 000000000031db3b /init (android::init::InitAborter(char const*)+27) (BuildId: 65c73120e092a845c594ec841c61406c)
[ 11.687739] init: #06 pc 00000000004a301d /init (android::base::SetAborter(std::__1::function<void (char const*)>&&)::$_0::__invoke(char const*)+61) (BuildId: 65c73120e092a845c594ec841c61406c)
[ 11.688371] init: #07 pc 00000000004a27c2 /init (android::base::LogMessage::~LogMessage()+354) (BuildId: 65c73120e092a845c594ec841c61406c)
[ 11.688808] init: #08 pc 000000000030d281 /init (android::init::FirstStageMain(int, char**)+10209) (BuildId: 65c73120e092a845c594ec841c61406c)
[ 11.689252] init: #09 pc 00000000004de2f2 /init (__real_libc_init(void*, void (*)(), int (*)(int, char**, char**), structors_array_t const*, bionic_tcb*)+738) (BuildId: 65c73120e092a845c594ec841c61406c)
明显看到分区无法加载等,这个就是只编译kernel想只替换kernel既可以的情况,就是virtio_blk.ko的报错,无法进入android,主要原因还是模拟器自带的virtio_blk与我们编译kernel是不兼容的,这个接下来还需要编译相关Virtual的ko。
编译vendor块相关对于模拟器
执行如下命令:
bash
tools/bazel run //common-modules/virtual-device:virtual_device_x86_64_dist -- --dist_dir=myout
编译完成后可以看到myout下面多了很多的virtio的ko
到这里整个编译过程就结束了,接下来就要考虑编译出来这些怎么运行。
运行编译的kernel和ko
理解模拟器的kernel来自哪里
aosp源码根路径:kernel/prebuilts/6.1/x86_64
所以就可以可以采用把上面myout路径下东西都暴力覆盖拷贝到这里
拷贝kernel相关文件
bash
cp ./* ~/disk2/aosp14/kernel/prebuilts/6.1/x86_64/
mv ~/disk2/aosp14/kernel/prebuilts/6.1/x86_64/bzImage ~/disk2/aosp14/kernel/prebuilts/6.1/x86_64/kernel-6.1
第二个只是把bzImage重命名kernel-6.1
拷贝virtual-device相关文件
执行如下拷贝命令
bash
test@test:~/disk2/kernel-aosp14/myout$ cp ./* ~/disk2/aosp14/kernel/prebuilts/common-modules/virtual-device/6.1/x86-64/
注意这里拷贝目标和上面不一样,这次是common-modules/virtual-device目录
aosp进行整体编译运行:
这里比较简单就是正常的
bash
make
emulator
运行起来后看看相关的版本号:
可以看看上面编译输出目录myout下面bzImage文件的版本
更多framework详细代码和资料参考如下链接
hal+perfetto+surfaceflinger
https://mp.weixin.qq.com/s/LbVLnu1udqExHVKxd74ILg
其他课程七件套专题:
点击这里
https://mp.weixin.qq.com/s/Qv8zjgQ0CkalKmvi8tMGaw
视频试看:
https://www.bilibili.com/video/BV1wc41117L4/
更多framework假威风耗:androidframework007