相关原创文章:
数字版权管理DRM
DRM在Android中
DRM-widevine 总结
DRM-Playready总结
ExoPlayer+Shaka-packager播放自制DRM视频
HIDL 读作 hide-l,全称是 Hardware Interface Definition Language。它在 Android Project Treble 中被起草,在 Android 8.0 中被全面使用。其诞生目的是,框架可以在无需重新构建 HAL 的情况下进行替换。HAL将由供应商或SOC 制造商构建,放置在设备的 /vendor
分区中,这样一来,框架就可以在其自己的分区中通过 OTA 进行替换,而无需重新编译 HAL。
HAL(Hardware Abstract Layer)硬件抽象层。主要目的在于将硬件抽象化。硬件抽象化可以隐藏特定平台的硬件接口细节,为上面一层提供固定统一的接口,使其具有硬件无关性。HAL层位于kernel和framework层之间,各厂商在Android的硬件抽象层实现特定硬件的操作细节,并编译成so库,以库的形式提供给用户使用。
关于Android HAL的其他详细内容,有许多资料可以查阅。
frameworks/av/drm/libmediadrm
。在AndroidO版本后也兼容之前的非HAL的插件,除了上图的DrmManager方式外,也可以通过DrmHal调用drm hal1.0的passthrough方式来调用legacy plugins,详细代码:/hardware/interfaces/drm/1.0/default
DRM框架在AndroidO开始后引入了HAL的概念。直至当前的AndroidQ发展到了HAL1.2版本。下面基于AndroidQ版本来讲述。详细的实现方式可以参照DRM
HAL的加载入口frameworks/av/drm/libmediadrm/DrmHal.cpp
Vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {
Vector<sp<IDrmFactory>> factories;
auto manager = hardware::defaultServiceManager1_2();
if (manager != NULL) {
manager->listManifestByInterface(drm::V1_0::IDrmFactory::descriptor,
[&factories](const hidl_vec<hidl_string> ®istered) {
for (const auto &instance : registered) {
auto factory = drm::V1_0::IDrmFactory::getService(instance);
if (factory != NULL) {
factories.push_back(factory);
}
}
}
);
manager->listManifestByInterface(drm::V1_1::IDrmFactory::descriptor,
[&factories](const hidl_vec<hidl_string> ®istered) {
for (const auto &instance : registered) {
auto factory = drm::V1_1::IDrmFactory::getService(instance);
if (factory != NULL) {
factories.push_back(factory);
}
}
}
);
manager->listByInterface(drm::V1_2::IDrmFactory::descriptor,
[&factories](const hidl_vec<hidl_string> ®istered) {
for (const auto &instance : registered) {
auto factory = drm::V1_2::IDrmFactory::getService(instance);
if (factory != NULL) {
factories.push_back(factory);
}
}
}
);
}
if (factories.size() == 0) {
// must be in passthrough mode, load the default passthrough service
auto passthrough = IDrmFactory::getService();
if (passthrough != NULL) {
ALOGI("makeDrmFactories: using default passthrough drm instance");
factories.push_back(passthrough);
} else {
ALOGE("Failed to find any drm factories");
}
}
return factories;
}
HIDL的相关代码位于:android/hardware/interfaces/drm
passthrough直通模式: HIDL 的一种模式,使用这种模式时,服务器是共享库,由客户端进行 dlopen
处理。在直通模式下,客户端和服务器是相同的进程,但代码库不同。此模式仅用于将旧版代码库并入 HIDL 模型。
要将运行早期版本的 Android 的设备更新为使用 Android O,可以将惯用的(和旧版)HAL 封装在一个新 HIDL 接口中,该接口将在绑定式模式和同进程(直通)模式提供 HAL。这种封装对于 HAL 和 Android 框架来说都是透明的。
详细代码,可参照/hardware/interfaces/drm/1.0/default
。
AndroidO版本开始,使用DRM HAL方式来加载DRM插件,AndroidO的DRM HAL对应的版本为HAL 1.0。对应的widevine版本是v13。
AndroidP版本的DRM HAL为HAL1.1。对应的widevine版本是v14。此版本继承了HAL1.0,同时修改了一些接口。
AndroidQ版本的DRM HAL为HAL1.2,并且增加了LAZY HAL概念,以支持低性能的Android设备。对应的widevine版本是v15。
androidP已引入lazy hal概念,但并没有在drm hal中使用,drm lazy hal在AndroidQ上开始应用。
Lazy hal可以使hal服务在使用的时候开启,而当不使用时,所有client都注销服务时,就关闭hal服务,因此,这个可以有效地提高Android设备的性能和降低功耗。
在DRM 插件对接时,需要在每个插件中编写相应的Lazy hal service。
以AndroidQ DRM HAL1.2为例说明:
相关代码:
frameworks/av/drm/libmediadrm
frameworks/av/services/mediadrm
hardware/interfaces/drm/1.2
frameworks/av/drm/mediadrm/plugins/clearkey
hardware/interfaces/drm/1.2
根据HIDL语法实现相关的HIDL文件,然后编译时通过hidl_gen
工具生成相关的的头文件及接口源码以供具体的插件调用。生成路径:out/soong/.intermediates/hardware/interfaces/drm/1.2/
├── [email protected]
├── [email protected]_genc++
└── [email protected]_genc++_headers
其中headers就是生成相应的头文件[email protected]_genc++_headers/gen/android/hardware/drm/1.2
:
├── BnHwCryptoFactory.h
├── BnHwCryptoPlugin.h
├── BnHwDrmFactory.h
├── BnHwDrmPlugin.h
├── BnHwDrmPluginListener.h
├── BpHwCryptoFactory.h
├── BpHwCryptoPlugin.h
├── BpHwDrmFactory.h
├── BpHwDrmPlugin.h
├── BpHwDrmPluginListener.h
├── BsCryptoFactory.h
├── BsCryptoPlugin.h
├── BsDrmFactory.h
├── BsDrmPlugin.h
├── BsDrmPluginListener.h
├── hwtypes.h
├── ICryptoFactory.h
├── ICryptoFactory.h.d
├── ICryptoPlugin.h
├── IDrmFactory.h
├── IDrmPlugin.h
├── IDrmPluginListener.h
├── IHwCryptoFactory.h
├── IHwCryptoPlugin.h
├── IHwDrmFactory.h
├── IHwDrmPlugin.h
├── IHwDrmPluginListener.h
└── types.h
对于hidl的serviec manager调用,在system/libhidl/transport
在系统启动时,DRM 框架会扫描 HAL 实例/服务(如 .rc
文件中所述),并通过 HIDL 注册表发现插件。媒体 DRM 服务器 (mediadrmserver
) 创建 CryptoHal
和 DrmHal
对象。 然后,CryptoHal
和 DrmHal
使用供应商专用实现来调用发现的插件。
插件应实现绑定式 HAL。绑定式 HAL 使用 HAL 接口定义语言 (HIDL),HIDL 支持在不重新构建 HAL 的情况下替换框架。
插件由供应商或 SOC 制造商构建,放置在设备的 /vendor
分区中。所有在上市时即搭载了 Android 8.0 或更高版本的设备都必须支持使用 HIDL 语言编写的绑定式 HAL。
大致步骤:
service.cpp
中实现 main()
入口点。CryptoFactory
和 DrmFactory
。IDrmPlugin.hal
和 ICryptoPlugin.hal
中定义。DrmHal
类会搜索已注册的 DRM 插件服务,并通过 DrmFactory
类构建支持给定加密方案的相应插件。
CryptoHal
类会搜索已注册的 DRM 插件服务,并通过 CryptoFactory
类构建支持给定加密方案的相应插件。
博文为ganqiuye原创,转载请附上原文出处链接和本声明。
DRM
MediaDrm
MediaCrypto
HIDL
HAL