DRM

Android DRM HAL icon

本文档概述了 Android 数字版权管理 (DRM) 框架,并介绍了 DRM 插件必须实现的接口。本文档未介绍 DRM 方案可能定义的稳健性规则或合规性规则。

框架

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

Android DRM HAL
图 1a. Android 11 之前的 DRM 硬件抽象层
Android DRM HAL post R
图 1b. Android 11 及更高版本中的 DRM 硬件抽象层

对于移动设备用户而言,丰富的数字内容的可用性非常重要。为了使其内容得到广泛使用,Android 开发者和数字内容发布商需要一个在整个 Android 生态系统中受支持的一致 DRM 实现。为了使数字内容在 Android 设备上可用,并确保所有设备上至少有一个一致的 DRM 可用,Google 在兼容的 Android 设备上免费提供 DRM 许可。DRM 插件与 Android DRM 框架集成,可以使用硬件支持的保护来保护优质内容和用户凭据。

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

架构

DRM 框架旨在实现不可知的实现,并抽象出特定 DRM 方案实现的详细信息,使其成为特定于方案的 DRM 插件。DRM 框架包含简单的 API,用于处理复杂的 DRM 操作、获取许可、配置设备、关联 DRM 内容及其许可,以及最终解密 DRM 内容。

Android DRM 框架在两个架构层中实现

  • DRM 框架 API,通过 Android 应用框架向应用公开。
  • 原生代码 DRM 框架,它公开了一个 DRM 插件(代理)接口,用于处理各种 DRM 方案的版权管理和解密。
Android DRM Framework
图 2a. Android 11 之前的 DRM 框架
Android DRM Framework
图 2b. Android 11 及更高版本中的 DRM 框架

如需了解详情,请参阅 Android Media DRMAndroid Media Crypto

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. 将插件服务添加到设备的构建文件。
  2. 更新设备清单。
  3. 添加 SELinux 权限。
  4. /vendor 下创建 .rc 文件。
  5. 实现插件。

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

aidl/PLATFORM_ROOT/hardware/interfaces/drm/

将插件服务添加到设备构建文件

例如,要添加 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 Language

实现插件

  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);

确定插件工厂是否能够构造支持给定加密方案的 DRM 插件,该加密方案由 UUID 指定。

::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 中定义。相应的 IDrmPlugin.h 文件可以在构建后的 out/Soong 中找到。