Android系统开发--8.AndroidStudio导入系统源码(上)

目前流行的阅读 android 系统源码的工具主要有以下几种: source insight, understand, vscode, vim 等。也有同学不用导工程直接 find + grep + 文本编辑器的, 这些工具我也都用过很长一段时间, 但总有不满意的地方。

后来 android-studio 发布了 3.0 版本, 开始支持 NDK 开发了,体验了一下之后,就觉得这功能不就是我想要的嘛,同时写 java 和 c++ 代码。于是开始各种折腾,折腾了几个星期后,终于找到一种将 android系统源码导入到 android-studio 的方法,使用 gradle + cmake + NDK 支持同时解析 java 和 c++ 代码。理论上来说支持任何 java, c++ 工程或者混合工程。

下面就以导入 Android framework 代码为例, 演示一下导入的过程。

0. 准备工作

如果需要解析C/C++代码的话,则需要安装 cmake, ndk。
打开 SDKManager 选择 SDK Tools, 勾选 cmake 和 NDK 然后 install 即可。
SDKManager

1. 手动创建 gradle 工程文件

我们把工程文件创建在 device/qiushao 目录下, 这样可以避免工程文件创建在 Android 根目录下时 AndroidStudio 会扫描整个 Android 源码文件,导致导入速度非常慢的问题。
新建 device/qiushao/build.gradle 文件,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
}
}

allprojects {
repositories {
google()
jcenter()
}
}

apply plugin: 'com.android.application'

android {
compileSdkVersion 26
defaultConfig {
applicationId "net.qiushao.androidtest"
minSdkVersion 17
targetSdkVersion 26
versionCode 1
versionName "1.0"
}

//java 代码路径设置,把 java 代码路径添加到 main.java.srcDirs 即可
sourceSets {
main.java.srcDirs += '../../frameworks/base/core/java'
main.java.srcDirs += '../../frameworks/base/services/core/java'
}
}

其实关键配置就最后几行, 其他都是模板代码。

2. 创建 AndroidManifest.xml 文件

由于是 Android 工程,所以必须创建一个 AndroidManifest.xml 文件,而且路径还必须是 src/main/AndroidManifest.xml:

1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.qiushao.androidtest">

</manifest>

如果只是要看 java 代码的话,这样就已经配置完成了。
使用 AndroidStudio –> File –> Open 打开 build.gradle 文件, open as a project。
然后等几分钟就导入完成啦。
随便打开个 java 文件看看,是不是已经可以代码跳转了。

3. 导入 c/c++ 代码

我们做系统层开发的,经常要接触到 native service, 都是 C++ 的代码, 所以必须要有个顺手的 IDE 支持才行。
AndroidStudio 自然是支持的, 只要在前面的基础上,再加点配置就行了。
build.gradle 增加以下配置:

1
2
3
4
5
6
7
8
9
android {
...
//c/c++ 代码通过 NDK 来解析, 解析规则在 CMakeLists.txt 里配置
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}

增加 device/qiushao/CMakeLists.txt 文件,内容如下:

1
2
3
4
5
6
7
8
9
cmake_minimum_required(VERSION 2.6)
project(pure)
set(CMAKE_CXX_STANDARD 11)

FILE(GLOB_RECURSE pure_cpp_list "./*.cpp")
FILE(GLOB_RECURSE pure_c_list "./*.c")

add_library(pure ${pure_cpp_list} ${pure_c_list})
set_target_properties(pure PROPERTIES LINKER_LANGUAGE CXX)

添加完后,点击一下 sync project with gradle files, 即可重新解析工程文件。
打开之前我们写的 hello.c 文件, 发现已经有语法着色,代码提示功能了。

最终的目录结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
qiushao
├── build.gradle
├── CMakeLists.txt
├── common
│   └── hello
│   ├── Android.mk
│   └── hello.c
├── generic_pure
│   ├── Android.mk
│   ├── AndroidProducts.mk
│   ├── BoardConfig.mk
│   ├── generic_pure.mk
│   └── vendorsetup.sh
└── src
└── main
└── AndroidManifest.xml

其中 build.gradle, CMakeLists.txt, AndroidManifest.xml 是我们新增加的文件。

4. 局限

这种方法有个局限: CMakeLists.txt 中只能配置 device/qiushao 目录下的 C++ 源码。
如果尝试增加 Android 源码根目录下的其他源码, 比如 bootable/recovery :

1
2
3
4
5
FILE(GLOB_RECURSE recovery_cpp_list "../../bootable/recovery/*.cpp")
FILE(GLOB_RECURSE pure_cpp_list "./*.cpp")
FILE(GLOB_RECURSE pure_c_list "./*.c")

add_library(pure ${pure_cpp_list} ${pure_c_list} ${recovery_cpp_list})

这样就会导致 AndroidStudio 会在整个 Android 源码目录下去搜索 cpp 文件, 工程加载的速度就会变得非常慢,可能得花上几个小时以上。
当然这个问题也有解决的方法, 欲知方法如何,请听下回分解。