近来研究了下Android emulator,就是Android Studio中用于调试App的虚拟机AVD(Android Virtualized Device)。本来是件挺平淡无奇的事情,但非要给生活比个””耶…..”(^-^)V 需求是,在Linux OS中,使用自定义的Android Kernel! 由于烂樱桃本人只略懂一丢虚拟化技术,对于Android算是一窍不通,所以,本文主要记录步骤为主,木有原理性的东西。
0. 准备 安装Android Studio
到Android Studio 官网下载最新Android for Linux 64-bit 基本上解压缩之后就能用,如果安装有问题参考官方安装文档
注:安装过程需要访问Android的一些服务器,下载文件。所以,需要保证上网方式科学有效,还是那句话,不要问如何上网。
1. 安装AVD
Android Studio中AVD的安装很方便,第一次创建虚拟机的时候,需要先点击那个’Download’按钮,在线下载虚拟机镜像。
需要注意的两点:
- 需要下载不带有’google play’图标的镜像,因为带有Google play log的镜像中有很多限制,比如无法使用adb root等。
- Android Q内含Android Kernel 4.14, Android R是最新版的Android,内含Android Kernel 5.4. 硬盘空间允许的话,Android Q 和 R 都安装了,下面会分别讲述kernel 4.14 和5.4的不同玩法。
直接上图一看便知
2 命令行启动Android模拟器
为了方便启动模拟器,在安装好AVD之后,我们可以退出Android Studio,正常情况后面的步骤都不在需要用到Android Studio了。
Android Studio在安装过程中,会下载Android SDK,默认路径是~/Android/SDK
这就是Android的开发包了,其中~/Android/SDK/emulator
包含了启动模拟器所需要的脚本。
所以,只要进入到emulator的目录内,或者把emulator加到PATH环境变量中,就可以运行模拟器了1
DISPLAY=:0 ./emulator -avd Pixel_2_v54 -verbose -show-kernel -shell -memory 8192 -no-snapshot-load -gpu guest #-qemu -enable-kvm
具体的参数含义参考官方文档 emulator-commandline
3. 更换模拟器的Kernel
这是本文的主要目的,在Android Q(Android Kernel 4.14)以及之前的版本的Android,是吧所有的kernel driver全都built-in到一个内核镜像中(bzImage),但在Android R(Kernel 5.4)开始,为了适应硬件的需求,开始将部分驱动编译成内核模块(kernel module)放在系统镜像中。更详细的故事可以参考Google outlines plans for mainline Linux kernel support in Android –Google wants less forking, more modularization for Android’s Linux kernel
3.1 Android Q with Kernel 4.14
此时的事情很简单,仅需要简单的几步: 1. 下载内核镜像; 2. 下载编译工具; 3. 编译内核
1 | git clone https://android.googlesource.com/kernel/goldfish/ -b android-goldfish-4.14-dev.150 |
注意,两个repo的branch得是搭配的,不可以随意换。
Building Kernels Manually这里列出了各种相关的kernel repo。
编译成功之后,这样启动Android模拟器:1
DISPLAY=:0 ./emulator -avd Pixel_2_v54 -verbose -show-kernel -shell -memory 8192 -no-snapshot-load -gpu guest -kernel /path/to/repo/goldfish/arch/x86/boot/bzImage #-qemu -enable-kvm
方法参考: Run Android Emulator with a Custom Kernel
3.2 Android R with Kernel 5.4
因为需要重新打包system.img,更新其中的kernel module,所以,除了上面两个repo之外,还需要Android完整的源码,并且编译完整的Android image。
3.2.1 编译Kernel 5.4
首先使用跟4.14类似的编译方法。尽管容易理解,但并不推荐,这样还需要手动打包,制作ramdisk.img。1
2
3git clone https://android.googlesource.com/kernel/goldfish/ -b android-5.4
或者如果已经clone过goldfish kenrel,执行:
cd goldfish && git checkout android-5.4
1 | git clone https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9 -b master |
下载clang编译器,并且使用特别版本clang-r377782c来编译Android-R1
2git clone git clone https://android.googlesource.com/platform/prebuilts/clang/host/linux-x86 -b android-r-preview-4
export PATH=$PATH:/path/to/linux-x86/clang-r377782c/bin:/path/to/x86_64-linux-android-4.9/
一切准备就绪之后,编译kernel-5.41
2make O=out ARCH=x86_64 CC=clang CLANG_TRIPLE=x86_64-linux-gnu x86_64_defconfig
make O=out ARCH=x86_64 CC=clang CLANG_TRIPLE=x86_64-linux-gnu- CROSS_COMPILE=x86_64-linux-androidkernel- LD=ld.lld
3.2.1’ 编译Kernel 5.4
使用repo下载Android Kernel 5.4 以及编译工具(x86_64-linux-android-4.9) 和 编译器Clang1
2
3
4
5
6
7mkdir goldfish-kernel-54
cd goldfish-kernel-54/
repo init -u https://android.googlesource.com/kernel/manifest -b common-android-5.4
repo sync
BUILD_CONFIG=goldfish-modules/build.config.goldfish.x86_64 build/build.sh
#grep '=m' ./out/android-5.4/common/.config
#vim ./goldfish-modules/goldfish_defconfig.fragment
所有生成的二进制文件(包含bzImage, *.ko)都在 out/android-5.4/dist/
里面了。
3.2.2 编译Android镜像
1 | apt install libncurses5-dev |
注: 初始化仓库的时候,这里使用master branch,如果想编译其他分支参考Android manifest
各个branch的含义以及支持情况,可以参考Codenames, Tags, and Build Numbers
编译Android源码的更详细介绍,可以参考Building Android
所有生成的镜像文件都在文件夹out/target/product/generic_x86/
中
Andriod源码中包含了模拟器,一旦Android镜像编译完成之后,可以直接启动Android虚拟机1
emulator
并且可以基于这个虚拟机,创建一个可以用于Android studio的AVD,详细参见Using Android Emulator Virtual Devices
3.2.3 替换Kernel,重做system.img
1 | rm /path/to/android-src/prebuilts/qemu-kernel/x86_64/5.4/ko/* |
重新make 之后,会生成包含customized过的kernel以及module,这是我们想起来准备工作中下载的Android-R镜像
默认位置这里~/Android/Sdk/system-images/android-R/google-apis/x86_64/
替换掉kernel 和 ramdisk.img:
1 | cp /path/to/android-src/out/target/product/generic_x86_64/kernel-ranchu-64 ~/Android/Sdk/system-images/android-R/google-apis/x86_64/ |
Android源码库中并不包含内核,android-src/out/target/product/generic_x86/kernel-ranchu-64仅仅是上一步生产的内核改了个名字。
另外,注意generic_x86_64文件夹中同时还有一个文件’ramdisk.img’,不要混淆,我们需要的是ramdisk-qemu.img
然后启动Android虚拟机:1
DISPLAY=:0 ./emulator -avd Pixel_2_v54 -verbose -show-kernel -shell -memory 8192 -no-snapshot-load -gpu guest #-sysdir /path/to/adroid-R/google-apis/x86_64/ #-qemu -enable-kvm
-sysdir
参数是说,如果不想直接替换Sdk中的源文件,可以copy一下文件夹x86_64,然后替换kernel 和 ramdisk.img,但同时需要指定sysdir的路径
3.2.3’ 替换Kernel,重做system.img
1 | export ANDROID_PRODUCT_OUT=/path/to/android_src/out/target/product/generic_x86/ |
启动Android虚拟机:1
DISPLAY=:0 ./emulator -avd Pixel_2_v54 -verbose -show-kernel -shell -memory 8192 -no-snapshot-load -gpu guest -sysdir $MYPACKEDIMG/img
参考链接:
如何下载Android源码
Android相关源码仓库目录
关于Android 源码编译的问题,文章android-kernel-clang以及作者Nathan Chancellor帮了不少的忙!
Android Emulator Linux DevelopmentAndroid 源码中的一个文章,或多或少参考了了一丢丢。