數位版權管理

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 硬體抽象層
Android DRM HAL (R 版後)
圖 1b. 從 Android 11 開始適用的 DRM 硬體抽象層

行動裝置使用者對於豐富的數位內容相當重視,為了讓內容廣為流通,Android 開發人員和數位內容發布商需要在整個 Android 生態系統中,實作一致的 DRM 實作。為了讓數位內容可在 Android 裝置上使用,並確保所有裝置至少有一個一致的 DRM,Google 會在相容的 Android 裝置上提供 DRM,且不收取授權費。DRM 外掛程式已與 Android DRM 架構整合,可使用硬體支援保護功能,保護付費內容與使用者憑證。

DRM 外掛程式提供的內容保護功能取決於基礎硬體平台的安全性和內容防護功能。裝置的硬體功能應包括硬體安全啟動功能,以建立對加密編譯金鑰安全性和保護的信任鏈。裝置的內容保護功能應包括保護裝置中已解密的影格,以及透過可信的輸出保護機制保護內容。並非所有硬體平台都支援上述所有安全性和內容保護功能。安全性從未在單一堆疊中實作,而是須整合硬體、軟體與服務。硬體安全功能、信任的開機機制,以及用於處理安全性功能的隔離安全作業系統,這三者相輔相成,對於提供安全裝置至關重要。

建築

DRM 架構的設計不受實作方式影響,並在特定 DRM 配置的 DRM 外掛程式中,抽象化特定 DRM 配置的實作細節。DRM 架構包含簡單的 API,可處理複雜的 DRM 作業、取得授權、佈建裝置、關聯 DRM 內容及其授權,並最後解密 DRM 內容。

Android DRM 架構會在兩個架構層中實作:

  • DRM 架構 API,可透過 Android 應用程式架構公開給應用程式。
  • 原生程式碼 DRM 架構,可為 DRM 外掛程式 (代理程式) 公開介面,以便處理各種 DRM 方案的權利管理和解密作業。
Android DRM 架構
圖 2a. Android 11 之前的 DRM 架構
Android DRM 架構
圖 2b. 從 Android 11 開始的 DRM 架構

詳情請參閱「Android Media DRM」和「 Android 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);

判斷外掛程式工廠是否能夠建構 DRM 外掛程式,以支援 mimeType 指定的特定媒體容器格式。

::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 檔案。