DRM

Android DRM HAL 图标

本文档概要介绍了 Android 数字版权管理 (DRM) 框架,并介绍了 DRM 插件必须实现的接口。本文档不提供可由 DRM 方案定义的稳健性规则或合规性规则的相关说明。

框架

Android 平台提供了一个可扩展的 DRM 框架,支持应用根据与受版权保护的内容关联的许可限制条件来管理这些内容。DRM 框架支持多种 DRM 方案;设备具体支持哪些 DRM 方案由设备制造商决定。DRM 框架为应用开发者提供了一个统一接口,并隐藏了 DRM 操作的复杂性。DRM 框架为受保护和不受保护的内容提供了一致的操作模式。DRM 方案可以定义复杂的许可元数据使用模型。DRM 框架提供了 DRM 内容与许可之间的关联,并处理权限管理。这样可以将媒体播放器从受 DRM 保护或不受保护的内容中提取出来。请参阅 MediaDrm,了解如何使用该类来获取用于解密受保护的媒体流的密钥。

Android DRM HAL
图 1a. Android 11 之前的 DRM 硬件抽象层
R 之后的 Android DRM HAL
图 1b. 从 Android 11 开始的 DRM 硬件抽象层

能否提供丰富的数字内容对移动设备用户来说非常重要。为保证广泛的内容覆盖面,Android 开发者和数字内容发布者需要实现一种受整个 Android 生态系统支持的一致数字版权管理。为了能够在 Android 设备上提供这类数字内容,并确保至少有一项一致的 DRM 可用于所有设备,Google 为兼容的 Android 设备提供免许可费用的 DRM。DRM 插件会与 Android DRM 框架集成在一起,并可使用受硬件支持的保护功能来确保付费内容和用户凭据的安全。

DRM 插件提供的内容保护功能取决于底层硬件平台的安全和内容保护功能。设备的硬件功能应包括硬件安全启动,可建立加密密钥的安全和保护功能的信任链。设备的内容保护功能应包括设备内加密帧的保护和通过可信输出保护机制实现的内容保护。并非所有硬件平台都支持上述所有的安全和内容保护功能。安全功能绝不会在堆栈的单个位置实现,而是依赖于硬件、软件和服务的集成。将硬件安全功能、可信启动机制以及用于处理安全功能的隔离安全操作系统组合使用是保障安全设备的关键。

架构

DRM 框架与实现无关,可在方案特定的 DRM 插件中提取特定 DRM 方案实现的详情。DRM 框架包括可执行以下操作的简单 API:处理复杂的 DRM 操作,获取许可,配置设备,将 DRM 内容与其许可相关联,以及最终解密 DRM 内容。

Android DRM 是在以下两个架构层中实现的:

  • DRM framework API:通过 Android 应用框架提供给应用。
  • 原生代码 DRM 框架:为 DRM 插件(代理)提供接口,以便处理各种 DRM 方案的版权管理和解密操作。
Android DRM 框架
图 2a. Android 11 之前的 DRM 框架
Android DRM 框架
图 2b. 从 Android 11 开始的 DRM 框架

如需了解详情,请参阅 Android 媒体 DRMAndroid 媒体加密

DRM 插件

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

插件应实现绑定式 HAL。绑定式 HAL 使用 Android 接口定义语言 (AIDL),无需重新构建 HAL 即可替换框架。

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

实现

适用于 Android 13 的 GMS 和 AOSP 设备版本必须使用 AIDL 接口。

如需通过插件实现新的 DRM 框架 API,请执行以下操作:

  1. 将插件服务添加到设备的 build 文件中。
  2. 更新设备清单。
  3. 添加 SELinux 权限。
  4. /vendor 下创建一个 .rc 文件。
  5. 实现插件。

API 在各个版本的 IDrmPlugin.aidlICryptoPlugin.aidlIDrmFactory.aidlICryptoFactory.aidl 中定义。

aidl/PLATFORM_ROOT/hardware/interfaces/drm/

将插件服务添加到设备的 build 文件中

例如,如需添加 AIDL 接口支持,VENDOR DEVICE/device.mk 文件必须包含 android.hardware.drm-service.* 软件包:


  PRODUCT_PACKAGES += \
    android.hardware.drm-service.clearkey \
    android.hardware.drm-service.widevine

更新设备清单

设备的 vendor manifest.xml 文件必须包含以下条目:

  <hal format="aidl">
    <name>android.hardware.drm</name>
    <version>STABLE AIDL VERSION</version>
      <fqname>ICryptoFactory/clearkey</fqname>
      <fqname>IDrmFactory/clearkey</fqname>
      <fqname>ICryptoFactory/widevine</fqname>
      <fqname>IDrmFactory/widevine</fqname>
  </hal>

STABLE AIDL VERSION 是每个 AIDL API 版本的版本号(例如 1、2)。或者,我们建议您使用 vintf_fragments

添加 SELinux 权限

  1. 添加到 VENDOR DEVICE/sepolicy/vendor/file.te
    type mediadrm_vendor_data_file, file_type, data_file_type;
  2. 添加到 VENDOR DEVICE/sepolicy/vendor/file_contexts
        /vendor/bin/hw/android\.hardware\.drm-service\.clearkey  u:object_r:hal_drm_clearkey_exec:s0
    /data/vendor/mediadrm(/.*)? u:object_r:mediadrm_vendor_data_file:s0
  3. 添加到 device/sepolicy/vendor/hal_drm_clearkey.te
        vndbinder_use(hal_drm_clearkey)
        allow hal_drm_clearkey servicemanager:binder { call transfer };
        allow hal_drm_clearkey hal_drm_service:service_manager add;
        allow hal_drm_clearkey { appdomain -isolated_app }:fd use;
        get_prop(ramdump, public_vendor_default_prop)
        

在 /vendor 下创建 RC 文件

.rc 文件指定服务启动时要采取的操作。

如需了解详情,请参阅 Android Init 语言

实现插件

  1. 在插件服务的 service.cpp 中实现 main() 入口点。
  2. 实现 ICryptoPluginIDrmPluginICryptoFactoryIDrmFactory
  3. 在插件中实现新的 API。

DRM 插件详情

DRM 插件供应商实现了 DrmFactoryCryptoFactory 和 DRM 插件。

DrmFactory

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

IDrmFactory 是通过 createPlugin API 与供应商的 DRM HAL 交互的主入口点。createPlugin API 用于创建 IDrmPlugin 实例。

::ndk::ScopedAStatus getSupportedCryptoSchemes(
    std::vector<::aidl::android::hardware::drm::Uuid>* _aidl_return);

getSupportedCryptoSchemes 会返回 AIDL DRM HAL 实例的受支持加密方案列表。

::ndk::ScopedAStatus isCryptoSchemeSupported(
    const ::aidl::android::hardware::drm::Uuid& in_uuid,
    const std::string& in_mimeType,
    ::aidl::android::hardware::drm::SecurityLevel in_securityLevel,
    bool* _aidl_return);

确定插件工厂能否构建支持给定加密方案(由 UUID 指定)的 DRM 插件。

::ndk::ScopedAStatus isContentTypeSupported(const std::string& in_mimeType,
    bool* _aidl_return);

确定插件工厂能否构建支持给定媒体容器格式(由 mimeType 指定)的 DRM 插件。

::ndk::ScopedAStatus createPlugin(
    const ::aidl::android::hardware::drm::Uuid& in_uuid,
    const std::string& in_appPackageName,
    std::shared_ptr<::aidl::android::hardware::drm::IDrmPlugin>* _aidl_return);

为 UUID 指定的加密方案构建 DRM 插件。

CryptoFactory

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

::ndk::ScopedAStatus isCryptoSchemeSupported(
    const ::aidl::android::hardware::drm::Uuid& in_uuid,
    bool* _aidl_return);

确定加密工厂能否构建支持给定加密方案(由 UUID 指定)的加密插件。

::ndk::ScopedAStatus createPlugin(
    const ::aidl::android::hardware::drm::Uuid& in_uuid,
    const std::vector<uint8_t>& in_initData,
    std::shared_ptr<::aidl::android::hardware::drm::ICryptoPlugin>* _aidl_return);

确定插件工厂能否构建支持给定加密方案(由 UUID 指定)的加密插件。

DRM 插件 API

相关 API 在 hardware/interfaces/drm/aidl/aidl_api/android.hardware.drm/ VERSION/android/hardware/drm/IDrmPlugin.aidl 中定义。构建完成后,可以在 out/Soong 中找到相应的 IDrmPlugin.h 文件。