DRM在Android中(2)——HAL

相关原创文章:
数字版权管理DRM
DRM在Android中
DRM-widevine 总结
DRM-Playready总结
ExoPlayer+Shaka-packager播放自制DRM视频

1. Android HIDL

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的其他详细内容,有许多资料可以查阅。

  • HIDL
  • HAL
    DRM在Android中(2)——HAL_第1张图片
    DRM在Android中(2)——HAL_第2张图片
    在AndroidO版本以前,DRM架构是直接通过dlopen调用DRM插件,而不是使用HAL的方式,相关代码在:frameworks/av/drm/libmediadrm。在AndroidO版本后也兼容之前的非HAL的插件,除了上图的DrmManager方式外,也可以通过DrmHal调用drm hal1.0的passthrough方式来调用legacy plugins,详细代码:/hardware/interfaces/drm/1.0/default

2. DRM HAL

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> &registered) {
                    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> &registered) {
                    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> &registered) {
                    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

2.1 passthrough

passthrough直通模式: HIDL 的一种模式,使用这种模式时,服务器是共享库,由客户端进行 dlopen 处理。在直通模式下,客户端和服务器是相同的进程,但代码库不同。此模式仅用于将旧版代码库并入 HIDL 模型。

要将运行早期版本的 Android 的设备更新为使用 Android O,可以将惯用的(和旧版)HAL 封装在一个新 HIDL 接口中,该接口将在绑定式模式和同进程(直通)模式提供 HAL。这种封装对于 HAL 和 Android 框架来说都是透明的。

详细代码,可参照/hardware/interfaces/drm/1.0/default
DRM在Android中(2)——HAL_第3张图片

2.2 HAL 1.0

AndroidO版本开始,使用DRM HAL方式来加载DRM插件,AndroidO的DRM HAL对应的版本为HAL 1.0。对应的widevine版本是v13。
DRM在Android中(2)——HAL_第4张图片

2.3 HAL 1.1

AndroidP版本的DRM HAL为HAL1.1。对应的widevine版本是v14。此版本继承了HAL1.0,同时修改了一些接口。

2.3 HAL 1.2

AndroidQ版本的DRM HAL为HAL1.2,并且增加了LAZY HAL概念,以支持低性能的Android设备。对应的widevine版本是v15。

  1. 1.2 HAL 继承HAL1.0, HAL1.1,修改了一些接口。
  2. LAZY HAL

androidP已引入lazy hal概念,但并没有在drm hal中使用,drm lazy hal在AndroidQ上开始应用。

Lazy hal可以使hal服务在使用的时候开启,而当不使用时,所有client都注销服务时,就关闭hal服务,因此,这个可以有效地提高Android设备的性能和降低功耗。

在DRM 插件对接时,需要在每个插件中编写相应的Lazy hal service。

3. DRM HAL 实现

AndroidQ DRM HAL1.2为例说明:

相关代码:

  • libmediadrm: frameworks/av/drm/libmediadrm
  • mediadrmservice: frameworks/av/services/mediadrm
  • drm hidl: hardware/interfaces/drm/1.2
  • clearkey plugin:frameworks/av/drm/mediadrm/plugins/clearkey
  • widevine plugin: …(厂商自行移植)

  • 在目录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

4. 插件的实现

在系统启动时,DRM 框架会扫描 HAL 实例/服务(如 .rc文件中所述),并通过 HIDL 注册表发现插件。媒体 DRM 服务器 (mediadrmserver) 创建 CryptoHalDrmHal 对象。 然后,CryptoHalDrmHal 使用供应商专用实现来调用发现的插件。

插件应实现绑定式 HAL。绑定式 HAL 使用 HAL 接口定义语言 (HIDL),HIDL 支持在不重新构建 HAL 的情况下替换框架。

插件由供应商或 SOC 制造商构建,放置在设备的 /vendor 分区中。所有在上市时即搭载了 Android 8.0 或更高版本的设备都必须支持使用 HIDL 语言编写的绑定式 HAL。

大致步骤:

  1. 在插件服务的 service.cpp 中实现 main() 入口点。
  2. 实现 CryptoFactoryDrmFactory
  3. 实现 DRM 插件。
  4. 新的 API 在 IDrmPlugin.halICryptoPlugin.hal 中定义。
  5. 在插件中实现新的 API。

DrmHal 类会搜索已注册的 DRM 插件服务,并通过 DrmFactory 类构建支持给定加密方案的相应插件。

CryptoHal 类会搜索已注册的 DRM 插件服务,并通过 CryptoFactory 类构建支持给定加密方案的相应插件。

DRM在Android中(2)——HAL_第5张图片
博文为ganqiuye原创,转载请附上原文出处链接和本声明。

相关资料:

DRM

MediaDrm

MediaCrypto

HIDL

HAL

你可能感兴趣的:(数字版权DRM)