Ahao's Technical Blog Ahao's Technical Blog
首页
  • 001.基础篇
  • 002.玩转AOSP篇
  • 003.学穿Binder篇
  • 004.基础组件篇
  • 005.系统启动过程分析
  • 006.Hal开发入门与实践
  • 007.显示系统
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

阿豪讲Framework

不积跬步无以至千里
首页
  • 001.基础篇
  • 002.玩转AOSP篇
  • 003.学穿Binder篇
  • 004.基础组件篇
  • 005.系统启动过程分析
  • 006.Hal开发入门与实践
  • 007.显示系统
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 基础篇

  • 玩转AOSP篇

    • 001.AOSP 极速上手
    • 002.Android 系统开发工具推荐
    • 003.添加 Product
    • 004.添加可执行程序
    • 005.添加 C/C++、Java 库
    • 006.添加配置文件与删除已有模块
    • 007.玩转 AOSP 之系统 App 源码添加
    • 008.使用 Android Studio 开发系统 App
    • 009.SeAndroid 使用极速上手
    • 010.添加开机自启动 Shell 脚本
    • 011.如何阅读 Android 系统源码 —— C/C++ 篇
      • 1. 工具篇
      • 2. 手段篇
    • 012.如何阅读 Android 系统源码 —— Java 篇
    • 013.系统开发专用版 Android Studio 上手指南
    • 014.Repo 使用入门
    • 015.Android14 Native 图形化调试上手
    • 016.2025 Android Studio For Platform 上手指南
  • 学穿Binder篇

  • 基础组件篇

  • 系统启动过程分析

  • Hal开发入门与实践

  • 显示系统

  • Framework
  • 玩转AOSP篇
阿豪
2023-07-05
目录

011.如何阅读 Android 系统源码 —— C/C++ 篇

# 1. 工具篇

对于 Android 系统源码中的 C/C++ 代码,CLion 是一个不错的工具。

较新版本的 Android 源码支持使用 AIDEgen 调用 Clion 查看 C/C++ 代码。但是,对于我们学习使用的 Android10 是不支持的。不过我们可以通过其他办法实现 Clion 查看 C/C++ 代码:

# 准备工作
source build/envsetup.sh
lunch aosp_x86_64-eng #选择一个合适的 Product
export SOONG_GEN_CMAKEFILES=1
export SOONG_GEN_CMAKEFILES_DEBUG=1
make -j16
1
2
3
4
5
6

接着我们就可以使用 Clion 打开我们的代码了。

假设我们需要看 SurfaceFlinger 相关代码:

#系统源码目录下搜索
find . -name "SurfaceFlinger*"
./frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
./frameworks/native/services/surfaceflinger/SurfaceFlingerProperties.cpp
./frameworks/native/services/surfaceflinger/SurfaceFlinger.h
./frameworks/native/services/surfaceflinger/SurfaceFlingerProperties.h
./frameworks/native/services/surfaceflinger/SurfaceFlingerFactory.h
.......
1
2
3
4
5
6
7
8

这里我们知道 SurfaceFlinger 定义在 frameworks/native/services 目录:

接着我们打开 Clion,点击 Open:

选择 out/development/ide/clion/frameworks/native 目录

这样我们就可以使用 CLion 查看系统源码了,需要注意的是我们的源码需要在 External Libraries 中查看:

我们也可以通过点击 Change Project Root 按钮调整目录结构:

# 2. 手段篇

阅读源码主要两个手段:

  • 打印 Log + 打印调用堆栈
  • 使用 CLion 调试

这里我们修改 SurfaceFlinger 的主函数 main_surfaceflinger.cpp 来演示打印 Log 和打印调用堆栈:

//log的头文件
#include "log/log.h"
//直接 define LOG_TAG 会报已定义错误,因为 SurFaceFlinger 模块的 Android.bp 已经定义了 LOG_Tag
//下面这样定义就不会出错了
#ifdef LOG_TAG
#undef LOG_TAG
#define LOG_TAG "yuandaima_sf"
#endif

//打印堆栈的头文件
#include <utils/CallStack.h>

//在 main 函数中打印信息

int main(int, char**) {

    //打印日志
    ALOGD("surfaceflinger is starting");

    //打印堆栈
    android::CallStack callStack(LOG_TAG, 1);

    //省略后面的代码
    //......
}
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

修改 /frameworks/native/services/surfaceflinger/Android.bp,添加 CallStack 的库依赖:

cc_binary {
    name: "surfaceflinger",
    defaults: ["libsurfaceflinger_binary"],
    init_rc: ["surfaceflinger.rc"],
    srcs: [
        ":surfaceflinger_binary_sources",
        // Note: SurfaceFlingerFactory is not in the filegroup so that it
        // can be easily replaced.
        "SurfaceFlingerFactory.cpp",
    ],
    shared_libs: [
        "libSurfaceFlingerProp",
        "libutilscallstack",
    ],

    logtags: ["surfaceflinger.logtags"],
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

接着我们重新编译代码,启动模拟器,进入 adb shell,查看 log:

rice14:/ # logcat | grep yuandaima_sf
05-11 09:54:10.291  1531  1531 D yuandaima_sf: surfaceflinger is starting

05-11 09:54:10.296  1531  1531 D yuandaima_sf: #00 pc 00000000000030a1  /system/bin/surfaceflinger (main+65)
05-11 09:54:10.296  1531  1531 D yuandaima_sf: #01 pc 000000000008a985  /apex/com.android.runtime/lib64/bionic/libc.so (__libc_init+117)
1
2
3
4
5

通过 log 信息我们可以知道程序的运行状态和运行过程中的关键参数。通过调用栈我们可以知道函数的执行流程。

我们还可以通过 Clion 来调试 C/C++ 代码:

这里以调试 service_manager.c 为例:

我们在如下位置打印好断点:

接着配置远程调试:

这样我们的 Clion 就配置好了。

接着我们查看 servicemanage 进程的 pid:

adb shell ps -A | grep servicemanager 
system        1406     1   14116   5532 binder_ioctl        0 S servicemanager
system        1407     1   21764   9772 SyS_epoll_wait      0 S hwservicemanager
system        1408     1   14816   2584 binder_ioctl        0 S vndservicemanage
1
2
3
4

servicemanager 的 pid 为 1406,接着在模拟器上开启 gdbserver:

adb forward tcp:1235 tcp:1235
adb shell gdbserver64 :1235 --attach 1406
1
2

接着点击 Clion 右上角的 debug 按钮就进入 debug 环境了:

这样我们就可以开始调试 C/C++ 代码了。

010.添加开机自启动 Shell 脚本
012.如何阅读 Android 系统源码 —— Java 篇

← 010.添加开机自启动 Shell 脚本 012.如何阅读 Android 系统源码 —— Java 篇→

最近更新
01
如何调试 SurfaceFlinger
10-05
02
SurfaceFlinger 概述
10-05
03
HWC 接口分析
10-05
更多文章>
Theme by Vdoing | Copyright © 2020-2025 AHao Framework | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式