重点:核心关注MediaExtractorService 是需要自己实现的 其它的都是aidl 自动生成的。

在 Android 媒体框架的 Binder 跨进程通信体系中,BpMediaExtractorService、BnMediaExtractorService、IMediaExtractorService、MediaExtractorService 是围绕media.extractor服务形成的接口定义 - 跨进程代理 - 跨进程服务端 - 实际业务实现四层核心关系,且该关系遵循 Android Binder 开发的标准设计规范(AIDL 自动生成 + 手动实现业务逻辑)。结合你关注的 Android 9/10 + 版本、media.extractor服务场景,以下从核心定义、层级关系、代码生成 / 实现、调用链路四个维度讲透,同时明确版本差异细节:

一、先明确核心前提(Binder 开发通用规则)

这四个类的关系建立在Android AIDL 跨进程通信基础上,核心规则:

  1. 开发者编写AIDL 接口文件,编译工具会自动生成 3 个核心类:
    • 基接口类(如IMediaExtractorService):定义跨进程通信的方法规范;
    • BnXXX(如BnMediaExtractorService):Binder服务端基类(Binder Native),运行在服务提供进程(media.extractor进程),需子类实现抽象方法;
    • BpXXX(如BpMediaExtractorService):Binder客户端代理类(Binder Proxy),运行在服务调用进程(如 MediaServer、应用进程),负责将方法调用转发给服务端;
  2. 开发者需手动实现一个业务类(如MediaExtractorService),继承 BnXXX 并实现抽象方法,作为跨进程服务的实际业务逻辑载体

二、四个类的核心定义与层级关系(从顶层到实现)

四层关系呈 **「接口定义→服务端基类→实际业务实现」「接口定义→客户端代理」** 分支结构,核心是IMediaExtractorService 为所有类的根接口,Bn/Bp 为 AIDL 自动生成的跨进程通信骨架,MediaExtractorService 为手动实现的实际业务类。

1. 根接口:IMediaExtractorService(AIDL 生成,方法规范)
  • 生成来源:由 AIDL 文件 frameworks/av/media/libmedia/IMediaExtractorService.aidl 编译自动生成,对应头文件IMediaExtractorService.h
  • 核心作用:定义media.extractor服务的跨进程通信方法规范,所有 Bn/Bp/MediaExtractorService 都需遵循该规范,核心方法如:

    cpp

    运行

    // 核心跨进程方法:创建MediaExtractor实例(NuPlayer/GenericSource核心调用)
    virtual sp<IMediaExtractor> createExtractor(
            const String16& path, const ParcelFileDescriptor& fd, const String16& mime) = 0;
    // 获取服务支持的媒体格式列表
    virtual Vector<String16> getSupportedTypes() = 0;
    
  • 关键特性:纯虚接口类,无任何实现代码,仅作为所有相关类的方法约定
2. Binder 服务端基类:BnMediaExtractorService(AIDL 生成,通信骨架)
  • 生成来源:同上述 AIDL 文件编译自动生成,继承自IMediaExtractorService和 Android Binder 核心类BBinder
  • 核心作用:作为media.extractor服务端的Binder 通信骨架,运行在 **media.extractor独立进程 **(Android 10+)/MediaServer 进程(Android 9),核心能力:
    1. 实现 Binder 跨进程通信的底层逻辑(数据序列化 / 反序列化、进程间方法转发);
    2. 暴露纯虚抽象方法(与IMediaExtractorService的方法一一对应),要求子类必须实现;
    3. 作为服务端的 “入口”,接收客户端(Bp)的跨进程调用请求。
  • 关键特性:仅提供通信骨架,无任何媒体业务逻辑,无法直接实例化(含纯虚方法)。
3. 实际业务实现:MediaExtractorService(手动实现,业务核心)
  • 实现来源:由 Android 系统开发人员手动编写,源码位置frameworks/av/media/extractors/MediaExtractorService.cpp
  • 核心作用:作为media.extractor服务的实际业务逻辑载体,是createExtractor等方法的真实实现者,核心能力:
    1. 继承BnMediaExtractorService,实现其所有纯虚抽象方法;
    2. 完成媒体解封装的核心业务:创建MediaExtractor实例、适配 TS/MP4/FLV 等格式、校验权限、返回IMediaExtractor接口给客户端;
    3. media.extractor服务的核心价值体现,所有跨进程调用最终都会落到此类的方法实现上。
  • 关键特性可实例化,是media.extractor服务注册到 ServiceManager 的实际对象
4. Binder 客户端代理:BpMediaExtractorService(AIDL 生成,请求转发)
  • 生成来源:同上述 AIDL 文件编译自动生成,继承自IMediaExtractorService和 Android Binder 核心类BpRefBase
  • 核心作用:作为media.extractor客户端的跨进程代理,运行在服务调用进程(如 NuPlayer 所在的 MediaServer 进程、应用进程),核心能力:
    1. 持有服务端的 Binder 对象(通过defaultServiceManager()->getService("media.extractor")获取);
    2. 将客户端的本地方法调用(如createExtractor序列化为 Binder 数据,转发给服务端(BnMediaExtractorService/MediaExtractorService);
    3. 接收服务端的返回数据,反序列化为本地对象(如IMediaExtractor)并返回给客户端调用者(如 NuPlayer::GenericSource)。
  • 关键特性:客户端无需关心跨进程细节,调用此类方法与调用本地方法完全一致,由其自动完成 “本地→跨进程→服务端” 的转发。

三、四层关系总览(一张图讲清)

plaintext

┌─────────────────────────────────────────────────────────┐
│ 根接口:IMediaExtractorService(AIDL生成,纯虚方法规范) │
├─────────────────────┬─────────────────────────────────┤
│ 继承                 │ 继承                             │
├─────────────────────▼─────────────────────────────────┤
│ BnMediaExtractorService(AIDL生成,服务端Binder骨架)  │
├─────────────────────┤                                  │
│ 继承                 │                                  │
├─────────────────────▼─────────────────────────────────┤
│ MediaExtractorService(手动实现,实际业务逻辑)        │
│ (运行在media.extractor进程,注册到ServiceManager)    │
├─────────────────────────────────────────────────────────┤
│ BpMediaExtractorService(AIDL生成,客户端Binder代理)  │
│ (运行在调用进程,持有服务端Binder对象,转发调用)    │
└─────────────────────────────────────────────────────────┘

核心关联一句话IMediaExtractorService是所有类的方法标准Bn/BpMediaExtractorService是 AIDL 自动生成的跨进程通信骨架(服务端 / 客户端),MediaExtractorService继承 Bn 并实现实际业务的最终服务类,也是media.extractor服务的实际载体。

四、代码层面的生成与实现(关键文件)

结合 Android AOSP 源码,明确四个类的生成文件、实现文件、版本差异,贴合你关注的 Android 9/10+:

类名 生成 / 实现方式 核心文件路径(Android 10+) Android 9 版本差异
IMediaExtractorService AIDL 自动生成 frameworks/av/media/libmedia/IMediaExtractorService.h 路径一致,方法稍少
BnMediaExtractorService AIDL 自动生成 frameworks/av/media/libmedia/IMediaExtractorService.cpp 路径一致,内嵌在 IMediaExtractorService.cpp
BpMediaExtractorService AIDL 自动生成 frameworks/av/media/libmedia/IMediaExtractorService.cpp 路径一致,内嵌在 IMediaExtractorService.cpp
MediaExtractorService 手动实现 frameworks/av/media/extractors/MediaExtractorService.cpp 路径一致,未独立为 media.extractor 进程,运行在 MediaServer

关键版本细节

  • Android 10+:MediaExtractorService运行在独立的media.extractor进程(由main_extractor_service.cpp启动并注册服务);
  • Android 9:无独立media.extractor进程,MediaExtractorService运行在MediaServer 进程,但类的关系、实现逻辑与高版本完全一致。

五、实际跨进程调用链路(与你的代码关联)

结合你之前的代码 sp<IBinder> binder = defaultServiceManager()->getService(String16("media.extractor"));,完整的跨进程调用链路如下(以 NuPlayer 调用createExtractor创建 MediaExtractor 为例):

plaintext

【客户端:MediaServer进程(NuPlayer/GenericSource)】
1. 客户端通过ServiceManager获取`media.extractor`的Binder对象(IBinder);
2. 将IBinder对象封装为`BpMediaExtractorService`实例(客户端代理);
3. 客户端调用`bpService->createExtractor(...)`(本地方法);
4. `BpMediaExtractorService`将方法参数**序列化为Parcel数据**,通过Binder驱动转发给服务端;

【Binder驱动:进程间数据转发】
- 负责将客户端的Parcel数据转发到`media.extractor`进程,同时转发服务端的返回数据;

【服务端:media.extractor进程(Android 10+)】
1. `BnMediaExtractorService`接收Binder驱动的Parcel数据,**反序列化为原始参数**;
2. `BnMediaExtractorService`将请求转发给子类`MediaExtractorService`的`createExtractor`方法;
3. `MediaExtractorService`执行实际业务:创建MediaExtractor实例、设置数据源、返回IMediaExtractor接口;
4. `BnMediaExtractorService`将返回结果**序列化为Parcel数据**,通过Binder驱动返回给客户端;

【客户端:MediaServer进程】
1. `BpMediaExtractorService`接收返回的Parcel数据,**反序列化为IMediaExtractor实例**;
2. 将IMediaExtractor返回给NuPlayer/GenericSource,完成跨进程调用;

核心亮点:客户端(NuPlayer)全程无需关心跨进程细节,调用BpMediaExtractorService的方法与调用本地类完全一致,所有底层通信由 Binder 框架和 AIDL 生成的类自动完成。

六、与你之前关注的BnMediaSource的关联(补充)

你之前在 Android 9 中接触的BnMediaSource,与本次的BnMediaExtractorService遵循完全相同的 Binder 设计规则

  • BnMediaSourceIMediaSource.aidl自动生成,是IMediaSource接口的 Binder 服务端基类;
  • Android 9 中 GenericSource 内嵌的匿名子类,本质是继承BnMediaSource并实现实际业务的自定义类(与MediaExtractorService继承BnMediaExtractorService的逻辑一致);
  • 简单说:BnMediaSource音视频数据源的服务端基类,BnMediaExtractorService解封装服务的服务端基类,二者都是 AIDL 生成的 Binder 服务端骨架。

核心总结

  1. 根接口IMediaExtractorService(AIDL 生成),定义media.extractor服务的跨进程方法,是所有类的方法标准;
  2. 通信骨架Bn/BpMediaExtractorService(AIDL 生成),分别为 Binder 服务端 / 客户端基类,提供跨进程通信的底层骨架,无业务逻辑;
  3. 实际实现MediaExtractorService(手动实现),继承BnMediaExtractorService,实现所有抽象方法,是media.extractor服务的实际业务核心,也是注册到 ServiceManager 的真实服务对象;
  4. 进程分布:Android 10 + 中Bn/MediaExtractorService运行在media.extractor进程,Bp运行在调用进程;Android 9 中均运行在 MediaServer 进程,关系不变;
  5. 设计规范:该四层关系是 Android Binder 跨进程通信的标准设计,所有系统服务(如 media.player、audio)均遵循此规范。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐