3、系统服务开发环境搭建:IDE配置、源码索引、调试工具准备

说实话,很多刚接触AOSP的朋友,第一步就栽在环境搭建上。

不是IDE卡死,就是源码索引半天出不来,更别提调试了。我当年第一次搭AOSP开发环境,光等源码编译就等了整整一个通宵,结果第二天发现JDK版本不对,又重来一遍……嗯,这些坑咱们今天一次性填平。

3.1 IDE选择与配置:别在编辑器上纠结

我个人习惯用IntelliJ IDEA,社区版就够用。为什么不用Eclipse?说白了,AOSP的源码结构太庞大了,Eclipse的索引引擎扛不住。你想想看,几万个Java文件同时加载,IDE直接卡成PPT。

我建议你直接上IntelliJ IDEA 2023.2以上版本,对AOSP的支持更友好。具体配置步骤如下:

  1. 安装JDK:必须用OpenJDK 11或17,Oracle JDK在AOSP里会有兼容性问题。我在项目中遇到过因为JDK版本不对,导致编译出来的系统服务在真机上跑不起来的情况。
  2. 导入源码:不要直接Open整个AOSP目录,那样IDE会崩溃。正确做法是只导入 frameworks/basepackages/services 这两个核心模块。
  3. 调整内存:在 idea64.exe.vmoptions 里把 -Xms 设为2048m,-Xmx 设为8192m。别心疼内存,AOSP源码就是吃内存大户。
小技巧:在导入源码前,先执行 source build/envsetup.sh && lunch 生成 out/soong/.bootstrap 目录,这样IDE能识别AOSP的模块依赖关系。

3.2 源码索引:让IDE认识AOSP

源码索引是环境搭建里最磨人的一步。我记得第一次索引AOSP,等了快两个小时,结果中途断电……那种绝望感,懂的都懂。

这里我分享一个加速索引的方法:

  • 排除无用目录:在IDE里右键Mark Directory as Excluded,把 out/prebuilts/external/ 这些目录排除掉。这些目录占了源码体积的60%以上,但对我们写系统服务来说基本用不上。
  • 使用模块化索引:只索引你当前开发的模块。比如你写系统服务,就只索引 frameworks/base/servicesframeworks/base/core。其他模块等需要时再手动添加。
  • 开启省电模式:索引期间把笔记本插上电源,关闭其他应用。我见过有人开着Chrome的50个标签页跑索引,结果IDE直接OOM崩溃。
注意:索引完成后,第一次打开某个Java文件可能会很慢,因为IDE在构建符号表。别急,等个一两分钟就好了。千万不要中途强制关闭IDE,否则索引会损坏,又得重来。

3.3 调试工具准备:三板斧

调试系统服务,光靠Logcat是不够的。你需要三样东西:

工具 用途 我的经验
adb logcat 查看运行时日志 配合 logcat -b events 看系统事件,比看普通日志更高效
gdb/lldb 调试Native代码 系统服务里如果用了JNI,必须用这个。我曾经用gdb定位过一个内存泄漏,花了三天
Android Studio Profiler 性能分析 看CPU、内存、网络,比你自己加时间戳靠谱一百倍

具体怎么配?我建议你这样做:

  • Logcat配置:在 ~/.bashrc 里加个别名 alias al='adb logcat -v threadtime',这样每次敲 al 就能看到带线程和时间的日志,排查问题快很多。
  • gdb配置:AOSP自带了一个 development/scripts/gdbclient.py 脚本,直接 source 它就能连上模拟器或真机。别自己手写gdb命令,太容易出错了。
  • Profiler连接:用Android Studio的Profiler时,记得先 adb rootadb remount,否则有些系统进程的权限不够,看不到完整数据。

避坑指南:我曾经在调试一个系统服务时,发现Logcat里死活看不到我的日志。折腾了半天,才发现是 android:debuggable 没设为 true。记住,系统服务默认是不输出调试日志的,你需要在AndroidManifest里显式开启。

3.4 实战:验证环境是否搭好

环境搭没搭好,跑个简单的例子就知道了。我建议你写一个最小的系统服务,打印一行日志:

// 在 frameworks/base/services/core/java/com/android/server/ 下新建一个 TestService.java
public class TestService extends SystemService {
    public TestService(Context context) {
        super(context);
    }

    @Override
    public void onStart() {
        Slog.i("TestService", "环境搭建成功!");
    }
}

然后编译、刷机、看Logcat。如果能看到这行日志,恭喜你,环境搭好了。如果看不到……嗯,回头检查一下前三步,大概率是索引没配好或者JDK版本不对。

好了,环境搭建就这些。下一章咱们开始写第一个真正的系统服务,到时候你会感谢今天把环境搭得这么稳的自己。