Native App 与 SurfaceFinger 建立 Binder 通信过程分析

154 阅读3分钟

以通俗易懂的语言,结合Android源码关键片段,为您解析Native App与SurfaceFlinger建立Binder通信的全过程。我们可以把这个过程想象成“跨城快递系统”,其中SurfaceFlinger是总部,Native App是分部,Binder驱动是物流网络,而ServiceManager则是快递目录。

一、通信前的准备:搭建物流网络(Binder驱动)

就像现实中的物流需要公路、铁路一样,Binder通信需要底层基础设施——Binder驱动。这个驱动在Android内核中实现,负责:

  1. 维护进程间通信的“高速公路”
  2. 记录服务地址簿(类似快递公司的网点目录)
  3. 传递带有跟踪号的包裹(事务)

在SurfaceFlinger启动时,会执行以下关键操作(源码位置:frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp):

cpp
	int main(int, char**) {

	    sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();

	    sp<IServiceManager> sm = defaultServiceManager();

	    

	    // 向ServiceManager注册两个核心服务

	    sm->addService(String16("SurfaceFlinger"), flinger, false, 

	                  IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);

	    

	    sp<SurfaceComposerAIDL> composerAIDL = sp<SurfaceComposerAIDL>::make(flinger);

	    sm->addService(String16("SurfaceFlingerAIDL"), composerAIDL, false,

	                  IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);

	    

	    // 进入消息循环

	    IPCThreadState::self()->joinThreadPool();

	}

二、建立通信的三种方式解析

方式1:传统Binder接口(ISurfaceComposer)

这是比较底层的通信方式,就像使用物流公司的“专线运输”:

  1. 服务端暴露:SurfaceFlinger实现ISurfaceComposer接口
  2. 客户端获取:通过ISurfaceComposer::asInterface()获取代理
  3. 典型操作setTransactionState(更新显示状态)

方式2:AIDL接口(推荐方式)

这是现代Android推荐的方式,类似使用标准化的“快递单”:

  1. AIDL定义frameworks/native/libs/gui/aidl/android/gui/ISurfaceComposer.aidl

  2. 核心方法

    • createDisplay() 创建虚拟显示屏
    • createDisplayEventConnection() 监听VSYNC信号
  3. 通信优势:自动生成类型安全的代理类,支持异步调用

方式3:Legacy接口(已废弃)

类似过时的“电报通信”,仅保留用于兼容旧系统。

三、完整通信流程示例

以创建虚拟显示屏为例,演示完整通信链路:

  1. 服务端注册(SurfaceFlinger启动时)

    • 通过addService向ServiceManager注册服务
    • 相当于在快递目录登记“Android显示中心”
  2. 客户端查询(Native App)

    cpp
    	sp<IServiceManager> sm = defaultServiceManager();
    
    	sp<IBinder> binder = sm->getService(String16("SurfaceFlingerAIDL"));
    
    	sp<ISurfaceComposer> composer = interface_cast<ISurfaceComposer>(binder);
    
    • 相当于查快递目录找到“Android显示中心”的联系方式
  3. 方法调用(创建显示屏)

    cpp
    	sp<IBinder> displayBinder;
    
    	composer->createDisplay("VirtualDisplay", false, 60.0f, &displayBinder);
    
    • 相当于发送快递单,请求创建虚拟显示屏
  4. 服务端处理(SurfaceFlinger进程)

    • 通过onTransact接收请求
    • 验证权限(需要android.permission.ACCESS_SURFACE_FLINGER
    • 创建DisplayDevice对象
    • 返回操作结果
  5. 结果返回(同步/异步)

    • 同步调用:直接返回显示ID
    • 异步调用:通过@OneWay注解实现

四、关键安全机制

  1. 权限验证

    cpp
    	// 在SurfaceFlinger的onTransact中
    
    	if (!checkPermission(android.Manifest.permission.ACCESS_SURFACE_FLINGER)) {
    
    	    return PERMISSION_DENIED;
    
    	}
    
  2. 死亡通知

    • 客户端注册IBinder::DeathRecipient
    • 服务端崩溃时自动收到通知
  3. 引用计数

    • Binder驱动自动管理服务生命周期
    • 最后一个客户端断开时释放资源

五、调试技巧

  1. 查看注册服务:

    bash
    	adb shell service list | grep SurfaceFlinger
    
  2. 跟踪Binder调用:

    bash
    	adb shell binder_state_dump | grep SurfaceFlinger
    
  3. 调试日志:

    • 启用SurfaceFlinger调试日志:adb shell setprop debug.sf.showupdates 1
    • 跟踪Binder事务:adb shell setprop log.tag.SurfaceFlinger DEBUG

六、系统演进趋势

从Android 10开始,显示系统逐步向以下方向发展:

  1. AIDL标准化:完全替代传统Binder接口
  2. 安全增强:新增android.permission.WAKEUP_SURFACE_FLINGER权限
  3. 性能优化:支持Binder调用链跟踪(atrace

通过理解这个“跨城快递系统”的工作原理,您可以:

  • 优化显示相关的Native代码性能
  • 调试画面不更新、卡顿等显示问题
  • 开发需要直接操作显示系统的底层功能(如VR/AR应用)