news 2026/1/12 2:52:55

AOSP 客制化内功心法(三):

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AOSP 客制化内功心法(三):

“没人调用的代码”是怎么跑起来的?——彻底搞懂系统组件的启动与调用链

发布日期:2025年12月28日
核心标签:AOSP架构、系统服务启动、Binder调用链、Framework API、HAL交互、客制化实战


引言:你是不是也这样困惑过?

你在 AOSP 源码里翻来覆去地看:

“这个WindowManagerService.java里全是方法,比如openWindow()addWindow()……
可我搜遍整个项目,都找不到谁在调用它!
难道这些代码是‘死代码’?那 Android 的窗口是怎么弹出来的?”

别急——不是没人调用,而是调用者藏得太深
就像你家的电灯开关,你按一下就亮,但你不知道背后是电网、变压器、继电器、电线在协同工作。

AOSP 也一样:表面是“函数定义”,背后是一整套“操作系统级调度机制”

今天,我们就用“拆解一台智能冰箱”的方式,把 AOSP 的系统组件、中间件、调用链,从上到下、从里到外讲得明明白白。


第一章:AOSP 不是 App,它是“操作系统工厂”

🏭 比喻:AOSP 是一座四层自动化工厂

楼层名称谁在这里工作?产出什么?
4楼应用层(App)用户、第三方开发者微信、抖音、你的 Launcher
3楼框架层(Framework)系统工程师ActivityManager,LocationManager(给 App 用的接口)
2楼系统服务层(SystemService)核心守护者ActivityManagerService,WindowManagerService(真正干活的)
1楼硬件抽象层(HAL + Kernel)厂商驱动工程师控制摄像头、LED、电池的底层代码

✅ 关键理解:

  • App 在 4 楼按按钮(调用 API)
  • 3 楼的“前台接待”(Framework API)接单
  • 单子通过“内部对讲机”(Binder)传到 2 楼
  • 2 楼的“老师傅”(SystemService)干活
  • 如果需要硬件,就打电话给 1 楼(HAL/Kernel)

所以,你看到的WindowManagerService.addWindow(),就是 2 楼老师傅的“手艺”,不是没人用,而是用它的人在 4 楼,通过 3 楼转达


第二章:三大“神秘组件”揭秘——它们到底怎么被调用的?

🔍 组件类型 1:系统服务(SystemService)

代表ActivityManagerService,PackageManagerService,BatteryService

❓ 问题:谁在 new 它?谁在调用它的方法?
✅ 答案:SystemServer 是“总调度员”
  • 启动时刻:手机开机后,init进程拉起zygotezygote拉起system_server
  • 关键代码SystemServer.java):
    // frameworks/base/services/java/com/android/server/SystemServer.java private void startBootstrapServices() { mActivityManagerService = new ActivityManagerService(...); ServiceManager.addService("activity", mActivityManagerService); // 注册! }
  • 注册后,这个服务就进入了“全局电话簿”(ServiceManager),任何人都能查到。
📞 调用过程(以 startActivity 为例):
[微信 App] └─ 调用 startActivity() ↓ [Framework 层:Activity.java] └─ 转发给 IActivityManager.Stub.Proxy ↓ (通过 Binder 驱动跨进程) [SystemServer 进程] └─ IActivityManager.Stub.onTransact() ↓ ActivityManagerService.startActivity() ← 真正执行!

💡 所以你在ActivityManagerService里看不到“谁调用了我”——
因为任何 App 都可以通过字符串 "activity" 找到你!这是动态查找,不是硬编码调用。


🔍 组件类型 2:Framework API(给 App 用的接口)

代表Context.getSystemService(),SensorManager,CameraManager

❓ 问题:LocationManager.getLastKnownLocation()是怎么连到后台服务的?
✅ 答案:AIDL 自动生成“代理对讲机”
  1. 你写 AIDL:

    // ILocationManager.aidl interface ILocationManager { Location getLastKnownLocation(); }
  2. 编译时,AOSP 自动生成两个类:

    • ILocationManager.Stub→ 服务端存根(在 SystemServer 中)
    • ILocationManager.Stub.Proxy→ 客户端代理(在 App 中)
  3. App 调用时:

    LocationManager lm = (LocationManager) context.getSystemService(LOCATION_SERVICE); lm.getLastKnownLocation(); // 实际调用 Proxy

    → Proxy 把参数打包,通过 Binder 发给 Stub → Stub 调用LocationManagerService

🌟这就是“中间件”:AIDL 自动生成的 Stub/Proxy,是连接 App 和 SystemService 的“翻译官+对讲机”。


🔍 组件类型 3:HAL / Native / Kernel(硬件控制层)

代表hardware/interfaces/light/,libcamera,/sys/class/backlight/

❓ 问题:Java 代码怎么控制 LED 灯?
✅ 答案:JNI + HAL + sysfs 三级跳

假设你想加一个“健康指示灯”:

[HealthService.java] (Java) ↓ [health_jni.cpp] (JNI 层,C++) ↓ dlopen("libhealth_vendor.so") → 调用 vendor 提供的 HAL 函数 ↓ HAL 写入 /sys/class/leds/health/brightness = "255" ↓ Linux Kernel 驱动点亮 LED

💡 关键点:

  • Framework不直接操作硬件
  • 通过HAL 接口(由芯片厂商实现)间接控制;
  • Google 用 HAL 实现“软硬解耦”——你换高通 or 联发科,Framework 代码不用改!

第三章:为什么你看不到“调用代码”?——因为 AOSP 用的是“注册制”,不是“点名制”

🧩 传统编程 vs AOSP 编程

方式传统 AppAOSP 系统
调用方式myService.doSomething()(硬编码)ServiceManager.getService("myservice")(动态查找)
启动方式main() 函数入口init.rc → zygote → SystemServer(逐层孵化)
通信方式直接函数调用Binder 跨进程 + AIDL 代理

✅ 所以你在源码里搜addWindow(,可能只找到定义,找不到调用——
因为调用是通过Binder 字符串名 + 反射 + 动态代理完成的!


第四章:客制化实战——你应该改哪里?

场景:我想让 App 能查询“设备是否过热”

步骤 1:定义服务接口(AIDL)
// frameworks/base/core/java/android/os/IThermalService.aidl interface IThermalService { boolean isDeviceOverheated(); }
步骤 2:实现服务(SystemService)
// frameworks/base/services/core/java/com/android/server/ThermalService.java public class ThermalService extends IThermalService.Stub { @Override public boolean isDeviceOverheated() { // 读取 /sys/class/thermal/thermal_zone0/temp return readTemp() > 60000; // 单位:毫摄氏度 } }
步骤 3:在 SystemServer 中注册
// SystemServer.java ThermalService thermal = new ThermalService(context); ServiceManager.addService("thermal", thermal);
步骤 4:给 App 提供 API(Framework 层)
// ContextImpl.java registerService(THERMAL_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { IBinder b = ServiceManager.getService("thermal"); return IThermalService.Stub.asInterface(b); } });
步骤 5:App 就可以这样用
ITherermalService ts = IThermalService.Stub.asInterface( ServiceManager.getService("thermal") ); if (ts.isDeviceOverheated()) { ... }

✅ 全流程打通!而你不需要改任何“调用者”代码——因为所有调用都是动态的。


第五章:调试技巧——如何追踪“看不见的调用”?

1. 加日志,看执行路径

Slog.i("ThermalService", "isDeviceOverheated() called by " + mContext.getPackageManager().getNameForUid(Binder.getCallingUid()));

2. 用adb shell dumpsys

adb shell dumpsys activity # 查看 AMS 状态 adb shell dumpsys window # 查看 WMS 窗口列表

3. 搜索“注册点”

grep -r "addService.*thermal" frameworks/ # 找到谁注册了 thermal 服务

4. 画调用链图(强烈推荐!)

用纸笔或工具画出:

App → Context.getSystemService("thermal") → ServiceManager.getService("thermal") → Binder IPC → ThermalService.isDeviceOverheated() → read /sys/...

总结:一张图看懂 AOSP 调用全景

[App] │ ├── 调用 getSystemService("xxx") 或直接 ServiceManager.getService("xxx") │ ▼ [Framework API] ← 自动生成的 AIDL Proxy(客户端代理) │ ▼ (Binder IPC) [SystemServer 进程] │ ├── ServiceManager:根据字符串名找到对应服务 │ ▼ [SystemService] ← AIDL Stub(服务端存根)→ 真正业务逻辑 │ ▼ (JNI / HAL) [Native / HAL / Kernel] ← 控制硬件

终极心法:如何高效学习 AOSP?

  1. 不要从头读代码,从“入口”切入

    • 想看服务?从SystemServer.java开始;
    • 想看 API?从ContextImpl.java开始。
  2. 理解“注册-查找-调用”模型

    • AOSP 90% 的组件都是靠ServiceManager.addService()+getService()驱动的。
  3. 善用“动态视角”

    • 代码不是静态的,它在系统启动时被“激活”,在运行时被“查找”。
  4. 客制化 = 插件化思维

    • 你不是重写系统,而是把自己的模块,正确注册进系统插槽

结语
AOSP 的美,在于它的架构设计——
表面是“一堆函数定义”,
背后是“一套精密的操作系统引擎”。

当你不再问“谁在调用它”,
而是说“我要把它注册到哪里”,
你就真正入门了 AOSP 客制化。

下一篇,我们将动手从零定制一个 HAL 模块,让 App 控制一块 RGB LED 灯——
从 Java 到 Kernel,打通全链路!


下一篇预告:《AOSP 客制化内功心法(四):从 App 到 LED——HAL 层深度定制实战》

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/30 20:33:25

CUDA安装后无法识别?教你正确配置Miniconda中的PyTorch环境

CUDA安装后无法识别?教你正确配置Miniconda中的PyTorch环境 在深度学习项目开发中,你是否曾遇到这样的尴尬场景:明明已经装好了NVIDIA驱动和CUDA Toolkit,系统里nvidia-smi也能正常输出,但一运行Python代码&#xff0c…

作者头像 李华
网站建设 2026/1/12 1:54:07

Python安装完成后未生效?Miniconda-Python3.10刷新PATH路径方法

Python安装完成后未生效?Miniconda-Python3.10刷新PATH路径方法 在人工智能和数据科学项目中,一个常见的“低级但致命”的问题往往是:明明已经安装了 Miniconda 和 Python 3.10,可终端里敲 python 还是提示“命令未找到”。这种看…

作者头像 李华
网站建设 2026/1/11 22:43:51

HTML语义化标签应用:Miniconda-Python3.10提升SEO友好度

HTML语义化标签与Miniconda-Python3.10:构建可复现、高可见的技术内容体系 在人工智能和数据科学项目日益复杂化的今天,一个常被忽视的问题浮出水面:我们能否确保别人不仅“能运行代码”,还能“轻松找到并理解它”?这…

作者头像 李华
网站建设 2025/12/30 20:30:40

Anaconda下载缓慢?改用Miniconda-Python3.10镜像极速体验

Miniconda-Python3.10 镜像:告别 Anaconda 下载慢,开启轻量高效开发 在数据科学和人工智能项目中,你是否曾经历过这样的场景:深夜赶工搭建实验环境,打开浏览器点击 Anaconda 安装包下载链接,进度条却以“每…

作者头像 李华
网站建设 2026/1/8 0:22:06

[HNCTF 2022 WEEK3]CM2

得到文件看起来是一个安装程序粗略的查看一下没什么东西,应该就是正常的安装执行安装主程序随便输测试一下IDA 分析主函数里没找到相关信息查找字符串引用一下上面有两条获取输入的函数,分别赋给 v2,v3有一条判断 v2 ! admin查看验证 v3 的函…

作者头像 李华
网站建设 2026/1/10 17:10:34

Anaconda图形界面劣势:Miniconda命令行更适合服务器部署

Anaconda图形界面劣势:Miniconda命令行更适合服务器部署 在高性能计算集群、云服务器或远程科研环境中,你是否遇到过这样的场景?团队成员提交的训练脚本因为“包版本不一致”而失败;新同事花了整整两天才配好能跑通代码的环境&…

作者头像 李华