在 Android sudio 中,想要查看一个 Android 系统的源代码,仅仅需要 Ctrl+鼠标左键 点击该目标类和方法名,即可在开发软件Android studio里查看到相应的源码。当前前提是你已经在 Android sdk 中下载了对应版本的源码。
这是查看 Android 源码最简单的方法,也是最有用的方法。但是这种方式也有弊端,那就是有些代码,特别是 native 代码是无法看到的。但是如果下载所有 Android 代码到本地不仅是网络上有难度,占用磁盘也很大。
所以此处分享两个查看 Android 源代码的在线网站。
Android 源代码官方查看网站:https://cs.android.com/
这个是官方的源代码查看网站,分了四个项目,查看 Android 的话只需要找第一个第一个项目。
非常推荐官方的网站,不仅可以方便的查看、搜索源代码,可以切换分支标记等,还能在整个代码库之间进行交叉引用的代码跳转。更重要的是作为官方的网站,其全局搜索功能是真的好用。强烈推荐。
AOSPXRef 在线查看源代码:http://aospxref.com/
如果官方的网站不方便使用的话,那么就推荐这个网站了,速度非常快,而且包含了最新的代码。
在此处可以进行一些源代码的搜索,不过其搜索体验就完全没有官方的网站好了。图中的各个搜索框对应功能如下:
字段 | 作用 |
---|---|
Full Search | 全文搜索,搜索索引中的所有文本标记(单词,字符串,标识符,数字)。搜索符号:覆盖符号的定义及使用,包括注释出现该符号 |
Definition | 仅查找符号定义。例如搜索xx函数在哪些类中有定义 |
Symbol | 仅查找符号。包括该符号的定义及使用位置 |
File Path | 源文件的路径。搜索源码文件名中包含给定字符串的文件。(类级别)支持输入类名等。方法名通过前三种方式搜索 |
History | 历史记录日志注释 |
AndroidXRef 在线查找源代码:http://androidxref.com/
这个网站最开始比较常用,不过后续只更新到 Android 9。其使用方式与上面的 AOSPXRef 使用方式一样,就不再赘述。
Android 各个版本的源码目录结构基本上是大同小异,此处用最新的源代码来表示其源码目录结构。
注意看左侧目录,其结构对应如下:
art | Android Runtime,一种App运行模式,区别于传统的Dalvik虚拟机,旨在提高Android系统的流畅性 |
bionic | 基础C库源代码,Android改造的C/C++库 |
bootable | Android程序启动导引,适合各种bootloader的通用代码,包括一个recovery目录 |
build | 存放系统编译规则及generic等基础开发包配置 |
compatibility | Android兼容性计划 |
cts | Android兼容性测试套件标准 |
dalvik | Android Dalvik虚拟机相关内容 |
developers | Android开发者参考文档 |
development | Android应用开发基础设施相关 |
device | Android支持的各种设备及相关配置 |
external | Android中使用的外部开源库 |
frameworks | 应用程序框架,Android系统核心部分,由Java和C++编写 |
hardware | 硬件适配接口 |
kernel | Linux Kernel,不过Android默认不提供,需要单独下载,只有一个tests目录 |
libcore | Android Java核心类库 |
libnativehelper | Android动态库,实现JNI库的基础 |
packages | 应用程序包 |
pdk | Plug Development Kit 的缩写,本地开发套件 |
platform_testing | Android平台测试程序 |
prebuilts | x86和arm架构下预编译的一些资源 |
sdk | Android的Java层sdk |
system | Android底层文件系统库、应用和组件 |
test | Android Vendor测试框架 |
toolchain | Android工具链文件 |
tools | Android工具文件 |
Android.bp | Android7.0开始代替Android.mk文件,它是告诉ndk将jni代码编译成动态库的一个脚本 |
Makefile | 全局Makefile文件,用来定义编译规则 |
应用层位于整个Android系统的最上层,开发者开发的应用程序以及系统内置的应用程序都是在应用层。其中目录结构如下:
apps | 核心应用程序 |
inputmethods | 输入法目录 |
providers | 内容提供者目录 |
screensavers | 屏幕保护 |
services | 通信服务 |
wallpapers | 墙纸 |
应用框架层是系统的核心部分,一方面向上提供接口给应用层调用,另一方面向下与C/C++程序库以及硬件抽象层等进行衔接。其中目录结构如下:
av | 多媒体框架 |
base | Android源码的主要核心目录 |
compile | 编译相关 |
ex | 文件解析器 |
hardware | 硬件适配接口 |
layoutlib | 布局相关 |
minikin | Android原生字体,连体字效果 |
ml | 机器学习 |
multidex | 多dex加载器 |
native | native实现 |
opt | 一些软件 |
rs | Render Script,可创建3D接口 |
support | framework支持文件 |
wilhelm | 基于Khronos的OpenSL ES/OpenMAX AL的audio/multimedia实现 |
在 frameworks 中的 base 目录是应用框架层的主要核心代码,其子目录也比较多,我就不贴图了。其部分目录结构如下:
apct-tests | 性能优化测试 |
api | android应用框架层声明类、属性和资源 |
cmds | android系统启动时用到的commands |
core | framework的核心框架组件 |
data | android下的资源(字体、声音、视频、软盘等) |
docs | android项目说明 |
drm | 实现权限管理,数字内容解密等模块的工作 |
graphics | 图像渲染模块 |
keystore | 秘钥库 |
libs | 库信息(界面、存储、USB) |
location | 位置信息 |
media | 手机媒体管理(音频、视频等) |
native | 本地方法实现(传感器、输入、界面、窗体) |
nfc-extras | 近场通讯 |
obex | 蓝牙 |
opengl | 2D和3D图形绘制 |
packages | 框架层的实现(界面、服务、存储) |
proto | 协议框架 |
rs | 资源框架 |
samples | 例子程序 |
sax | xml解析器 |
services | 各种服务程序 |
telecomm | telecomm通信框架 |
telephony | 电话通讯框架 |
tests | 各种测试 |
wifi | wifi模块 |
之所以说这个目录重要,我举几个例子你就明白了:
View
类在 /frameworks/base/core/java/android/view/View.java
Activity
类在 /frameworks/base/core/java/android/app/Activity
Bitmap
类在 /frameworks/base/graphics/java/android/graphics/
这几个类在 Android 开发中非常常用,它们都是在 /frameworks/base/
目录下的。
现在已经知道了可以从哪里找到源代码,也知道了源代码的目录结构,于是就可以小试一下,通过源代码找到我们想找的 native 代码。这些代码在 Android sdk 中的是没有的。
此处以 Bitmap 类来举例。Bitmap 类在 Android 开发中非常常用,也可以在 Android Studio 中点进去查看源码,不过当点进去之后我们会发现不少地方都是报红线的,这些地方都是 sdk 中没有的代码的引用。不过我们可以通过上面分享的三个网站找到这些代码。
比如说在查看创建 Bitmap 的代码时,在 Android Studio 中只能查看到 Bitmap.createBitmap 的 Java 方法:
在这段代码中,创建图片的核心代码就是红色框中的那段 nativeCreate
方法。但是这段代码是 native 代码,在 Android Studio 中无法查看的,这个时候就可以在 Android 源码里面找了。这里使用官方源码查看网站作为例子,另外的两个网站大同小异。
首先在 Android 源码中找到 Bitmap.java 文件,再点击 nativeCreate
,此时能看到这个方法在 Bitmap 类中的引用,但是找不到方法内容:
这个时候就需要用到 JNI 的相关知识了,既然方法名是 nativeCreate
,那么根据 jni 的映射规则,此方法在 native 的方法名应该是 Java_android_graphics_Bitmap_nativeCreate
。搜索一下:
没有搜索结果,那么这个方法既然不是用 jni 命名映射的方式,那么就应该是使用的动态注册了。动态注册方法会在 JNI_OnLoad
方法中使用 JavaVM->RegisterNatives
的方法将两边的方法绑定到一起。其中需要提供 Java 中的方法名和该方法的签名,以及对应的 native 的方法的指针。
这样的话,我们只需要全局搜索 nativeCreate
字符串,或者搜索这个方法的签名 ([IIIIIIZJ)Landroid/graphics/Bitmap;
,如果你下载了源代码到本地的话,这个方法会非常好用。一般情况下,对应于一个 Java 的文件,会有其同名的 cpp 文件来处理其 native 部分,此处就先搜索 Bitmap.cpp 这个文件:
看起来第一个比较像是想要找的,点击去会发现文件中会有这么一段映射:
也就是说 nativeCreate
方法在这个 C++ 文件中对应到了 Bitmap_creator
方法,点击跳转,这样就找到了对应的 native 代码了:
观察此方法的对应参数,能够与 Java 声明的 native 对应的上,确定这就是 Bitmap.nativeCreate 的具体实现代码了。查找源代码,还是要熟悉源代码结构才行啊。
另外注意一下这个目录名 hwui
,这个 hwui
是 Android 用于2d硬件绘图而加入的一个模块。在hwui
之前,Android 主要是用skia
来进行软件绘制,后由于绘制性能等问题,现在 Android 的绘图几乎都是使用了hwui
硬件加速绘图。hwui
主要则是使用 OpenGL ES 来进行 GPU 硬件绘图,以提升整个系统的绘制性能。