本文讨论的不是“怎样让 Codex 记住更多文字”,而是怎样把一棵 AOSP 整机源码树布置成一个可操作、可约束、可验证的工程环境。示例目标是 AOSP 17、Cuttlefish
aosp_cf_x86_64_phone和dev-sidebarfeature;可运行代码位于仓库的codex/目录,入口见 README。当前仓库仅包含占位源码;离线测试验证 Harness 脚本行为,不代表 AOSP 已构建或功能已通过设备验收。
本文基于 android10_r41 版本分析。
死亡通知的基本流程
死亡通知是为了让 Bp 端(客户端进程)能知晓 Bn 端(服务端进程)的生死情况,当 Bn 端进程死亡后能通知到 Bp 端。
分析源码之前,我们需要明确"死亡通知"实际是一个回调过程:
- 客户端,构造并保存好“死亡回调对象”,接着把“死亡回调对象”发送给驱动
- 驱动保存好“死亡回调对象”,同时记录好“死亡回调对象”对应的客户端和服务端
- 当服务端进程“挂掉”了,会执行进程的清理函数,清理函数会调用到 binder 驱动的清理函数,驱动清理函数会找到使用了服务端服务的客户端,把服务端死亡消息发送给客户端,客户端调用死亡通知回调
Server 端的处理
如果Binder 程序示例之 Java 篇中的 sayHello 服务端方法在执行过程中抛出异常会怎么样?
涉及其他基础内容,推迟到基础组件篇部分内容讲解完成后再讲
在 Android 11 之前的版本里,SM 是面向 Binder 驱动编程,直接使用 open、mmap、ioctl 等 API 与 Binder 驱动交互。而从 Android 11 开始,SM 放弃使用这些较底层的接口,转向 libbinder 库和 AIDL。
今天我们就以 android12_r28 的源码来看看主要的变化。
ServiceManager 的启动过程
int main(int argc, char** argv) {
if (argc > 2) {
LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
}
const char* driver = argc == 2 ? argv[1] : "/dev/binder";
// binder 驱动的初始化
sp<ProcessState> ps = ProcessState::initWithDriver(driver);
ps->setThreadPoolMaxThreadCount(0);
ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
//实例化 ServiceManager,传入 Access 类用于鉴权
// ServiceManager 的父类是 BnServiceManager,是一个 binder 本地类
sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());
// 注册自己
if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
LOG(ERROR) << "Could not self register servicemanager";
}
//注册到驱动,成为 Binder 管理员,handle 是 0
IPCThreadState::self()->setTheContextObject(manager);
ps->becomeContextManager();
//准备 looper
sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);
//通知驱动 BC_ENTER_LOOPER ,监听驱动 fd ,有消息时回调到 handleEvent 处理 binder 调用
BinderCallback::setupTo(looper);
ClientCallbackCallback::setupTo(looper, manager);
//无限循环等消息
while(true) {
looper->pollAll(-1);
}
// should not be reached
return EXIT_FAILURE;
}
问原理
- 什么是 Android Binder?
- Android Binder 是如何实现进程间通信的?
- Android 为什么采用 Binder 作为主要的的 IPC 机制?
- Binder 是如何实现仅通过一次拷贝将数据从 A 进程传递给 B 进程的?
- Binder 的优势是什么?
这些都是问 Binder 的基本原理,回答都大同小异。对于应用层开发,99% 止步于此,再问就不礼貌了。
如果是应聘 Framework 岗位,可能还需要熟悉下面的问题。
接下来我们仿造振动器写一个简单的 AIDL HAL 模块。
AIDL 文件编写
首先,在 hardware/interfaces/ 路径下创建 aidl hal 项目目录:
cd hardware/interfaces
mkdir hello_aidl_hal
cd hello_aidl_hal
mkdir -p android/hardware/hello
本文说明 Claude Code 版 AOSP Harness 的上下文选择、构建部署流程和功能验收。实现位于仓库的 claude-code/,示例目标为 AOSP 17、Cuttlefish 和
dev-sidebar。当前仓库仅包含占位源码;离线测试证明脚本行为,不代表系统已编译或功能已通过真机验证。
****--- title: 001.AOSP 极速上手 author: 阿豪 date: 2023-07-03 order: 1 redirectFrom:
- /pages/af6995/ categories:
- Framework
- 玩转AOSP篇 tags:
本文基于 aosp android-16.0.0_r4 版本分析。
很久很久以前,没有 AI 辅助,为了降低源码阅读难度,一直把整个显示系统进行拆解(app gui/hwui wms sf)分析,但是拆解后,总是有一种盲人摸象的感觉。要融汇贯通,掌握整体的架构思维,还是得的基于实际上层场景进行全流程分析!
这个系列会很长很长,通过上层不同的窗口操作场景(窗口显示移除,窗口动画,StartingWindow,分屏,小窗等等),贯穿 app gui/hwui wms sf 每个细节,梳理出 Framework 中,显示系统的整个流程,为成为一名 Android 显示全栈工程师打好基础。
1. 显示基本流程
分析显示问题需要了解显示的基本流程:
- 绘制过程(DrawFrame)
- 申请 Buffer
- 绘制(HWUI Opengl/Vulkan 视频解码等方式绘制)
- 提交 buffer
- 合成 (Compose):
- 一个 Vsycn 周期内收集到多个 Buffer
- 多个 Buffer 叠合成到一个 Buffer(Device/Clent 合成)
- 送到 panel 显示
- 显示完成,release buffer