• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# DRM解决方案开发指导
2
3DRM 解决方案插件实现 DRM HDI 接口(链接),DRM Kit的DRM框架将通过HDI接口加载DRM解决方案插件。
4
5插件由DRM解决方案集成方开发,放置在设备的 /vendor 分区中。
6
7OpenHarmony HDI 插件驱动服务开发流程参考[HDF驱动开发流程](../../../device-dev/driver/driver-hdf-manage.md),DRM HDI API 的 IDL 在 ohos/drivers/interface/drm/v1_0 目录中定义,其中 v1_0 对应不同版本的 HDI API 版本号,需根据实际调用的 HDI API 版本进行修改。
8
9DRM HDI API 的 IDL 构建完成后,可以在`//ohos/out/产品型号/gen/drivers/interface/drm/v1_0/`中找到生成的相应版本的 .h 和 .cpp文件。
10实现 DRM 解决方案插件的步骤如下(以clearplay为例):
11
121. [开发插件](#开发插件)
13    - 模块添加
14    - 驱动入口实现
15    - HDI接口实现
16    - 编译配置
17    - 部件配置
18    - 部件编译入口配置
19    - 服务代码编译
20
212. [DRM解决方案插件服务配置](#drm解决方案插件服务配置)
22    - hcs配置
23    - host用户与组配置
24    - 动态加载
25
263. [添加SELinux权限](#添加selinux权限)
27
28## 开发插件
29
30### 模块添加
31
32创建插件目录,参考如下:
33```
34//drivers/peripheral/clearplay
35.
36├── BUILD.gn     # 模块编译BUILD.gn37├── bundle.json  # 部件配置。
38├── hdi_service  # DRM解决方案HDI服务代码。
39│   ├── BUILD.gn # DRM解决方案HDI服务代码编译BUILD.gn40│   ├── common   # DRM解决方案HDI服务依赖的工具类代码,包含json解析、base64编解码。
41│   ├── include  # RM解决方案HDI服务实现头文件。
42│   └── src      # DRM解决方案HDI服务实现代码。
43├── interfaces   # DRM解决方案HDI服务能力接口。
44│   ├── BUILD.gn # DRM解决方案HDI服务能力接口编译BUILD.gn45│   ├── include  # DRM解决方案HDI服务能力接口文件。
46│   └── src      # DRM解决方案HDI服务能力接口实现。
47└── README_zh.md # DRM解决方案HDI服务组件说明。
48```
49
50### 驱动入口实现
51
52驱动入口实现可以参考`//ohos/out/产品型号/gen/drivers/interface/drm/v1_0/media_key_system_factory_driver.cpp`,需要驱动入口实现中修改以下几点,并手动配置编译:
53
54```
55using namespace OHOS::HDI::Drm::V1_0; // 1. 本文中 V1_0 为 HDI API 版本号,需根据不同版本进行变更。
56
57struct HdfMediaKeySystemFactoryHost {
58    struct IDeviceIoService ioService;
59    OHOS::sptr<OHOS::IRemoteObject> stub;
60};
61static int HdfMediaKeySystemFactoryDriverBind(struct HdfDeviceObject *deviceObject)
62{
63    auto *hdfMediaKeySystemFactoryHost = new (std::nothrow) HdfMediaKeySystemFactoryHost;
64    if (hdfMediaKeySystemFactoryHost == nullptr) {
65        HDF_LOGE("%{public}s: failed to create create HdfMediaKeySystemFactoryHost object", __func__);
66        return HDF_FAILURE;
67    }
68    int ret = HdfDeviceObjectSetInterfaceDesc(deviceObject, "ohos.hdi.drm.v1_0.IMediaKeySystemFactory"); // 2. 服务绑定接口描述符,便于DRM框架服务通过接口描述符获取到DRM解决方案HDI服务,根据不同的HDI API版本号调整。
69    if (ret != HDF_SUCCESS) {
70        HDF_LOGE("%{public}s: failed to HdfDeviceObjectSetInterfaceDesc", __func__);
71    }
72
73    hdfMediaKeySystemFactoryHost->ioService.Dispatch = MediaKeySystemFactoryDriverDispatch;
74    hdfMediaKeySystemFactoryHost->ioService.Open = NULL;
75    hdfMediaKeySystemFactoryHost->ioService.Release = NULL;
76
77    auto serviceImpl = OHOS::HDI::Drm::V1_0::IMediaKeySystemFactory::Get("clearplay_service", true); // 3. 获取DRM解决方案HDI服务实例。
78    if (serviceImpl == nullptr) {
79        HDF_LOGE("%{public}s: failed to get of implement service", __func__);
80        delete hdfMediaKeySystemFactoryHost;
81        return HDF_FAILURE;
82    }
83
84    hdfMediaKeySystemFactoryHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl,
85        OHOS::HDI::Drm::V1_0::IMediaKeySystemFactory::GetDescriptor()); // 4. 获取DRM解决方案HDI服务实现对应的Stub对象。
86    if (hdfMediaKeySystemFactoryHost->stub == nullptr) {
87        HDF_LOGE("%{public}s: failed to get stub object", __func__);
88        delete hdfMediaKeySystemFactoryHost;
89        return HDF_FAILURE;
90    }
91
92    deviceObject->service = &hdfMediaKeySystemFactoryHost->ioService;
93    return HDF_SUCCESS;
94}
95
96static int32_t MediaKeySystemFactoryDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data,
97    struct HdfSBuf *reply)
98{
99    auto *hdfMediaKeySystemFactoryHost =
100        CONTAINER_OF(client->device->service, struct HdfMediaKeySystemFactoryHost, ioService);
101
102    OHOS::MessageParcel *dataParcel = nullptr;
103    OHOS::MessageParcel *replyParcel = nullptr;
104    OHOS::MessageOption option;
105
106    if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) {
107        HDF_LOGE("%{public}s: invalid data sbuf object to dispatch", __func__);
108        return HDF_ERR_INVALID_PARAM;
109    }
110    if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) {
111        HDF_LOGE("%{public}s: invalid reply sbuf object to dispatch", __func__);
112        return HDF_ERR_INVALID_PARAM;
113    }
114
115    return hdfMediaKeySystemFactoryHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option);
116}
117```
118
119### HDI接口实现
120
121实现可以参考`//ohos/out/产品型号/gen/drivers/interface/drm/v1_0/`中自动生成的.cpp文件,可以按照业务需要进行定制化修改或新增文件,如`media_key_system_factory_service.cpp`:
122
123```
124extern "C" IMediaKeySystemFactory *MediaKeySystemFactoryImplGetInstance(void)
125{
126    // 请新增实现。
127    return new (std::nothrow) MediaKeySystemFactoryService();
128}
129
130int32_t MediaKeySystemFactoryService::IsMediaKeySystemSupported(const std::string& name, const std::string& mimeType,
131     OHOS::HDI::Drm::V1_0::ContentProtectionLevel level, bool& isSupported)
132{
133    // 请新增实现。
134    return HDF_SUCCESS;
135}
136
137int32_t MediaKeySystemFactoryService::CreateMediaKeySystem(sptr<OHOS::HDI::Drm::V1_0::IMediaKeySystem>& mediaKeySystem)
138{
139    // 请新增实现。
140    return HDF_SUCCESS;
141}
142
143int32_t MediaKeySystemFactoryService::GetMediaKeySystemDescription(std::string& name, std::string& uuid)
144{
145    // 请新增实现。
146    return HDF_SUCCESS;
147}
148
149```
150
151### 编译配置
152//drivers/peripheral/clearplay/BUILD.gn
153
154```
155if (defined(ohos_lite)) {
156  group("clearplay_entry") {
157    deps = []
158  }
159} else {
160  group("clearplay_entry") {
161    deps = [
162      "./hdi_service:hdf_clearplay_service",
163      "./interfaces:hdf_clearplay_interfaces",
164    ]
165  }
166}
167```
168
169//drivers/peripheral/clearplay/hdi_service/BUILD.gn
170```
171import("//build/ohos.gni")
172
173ohos_shared_library("libmedia_key_system_factory_clearplay_service_1.0") {
174  include_dirs = [
175    "./include",
176    "./include/drm/v1_0",
177    "./include/drm",
178    "./../interfaces/include",
179    "./../interfaces/include/drm/v1_0",
180    "./../interfaces/include/drm",
181    "./common",
182  ]
183  sources = [
184    "./common/base64_utils.cpp",
185    "./src/media_decrypt_module_service.cpp",
186    "./src/media_key_session_callback_service.cpp",
187    "./src/media_key_session_service.cpp",
188    "./src/media_key_system_callback_service.cpp",
189    "./src/media_key_system_factory_service.cpp",
190    "./src/media_key_system_service.cpp",
191    "./src/oem_certificate_service.cpp",
192  ]
193
194  deps = [ ]
195
196  cflags = [
197    "-Wall",
198    "-Wextra",
199    "-Werror",
200    "-fsigned-char",
201    "-fno-common",
202    "-fno-strict-aliasing",
203  ]
204
205  external_deps = [
206    "c_utils:utils",
207    "hdf_core:libhdf_utils",
208    "hilog:libhilog",
209    "ipc:ipc_single",
210  ]
211
212  install_images = [ chipset_base_dir ]
213  subsystem_name = "hdf"
214  part_name = "drivers_peripheral_clearplay"
215}
216
217group("hdf_clearplay_service") {
218  deps = [ ":libmedia_key_system_factory_clearplay_service_1.0" ]
219}
220```
221
222//drivers/peripheral/clearplay/interfaces/BUILD.gn
223
224```
225import("//build/ohos.gni")
226
227ohos_shared_library("libclearplay_driver") {
228  include_dirs = [
229    "./include",
230    "./include/drm",
231  ]
232
233  public_configs = [ ":clearplay_imp_external_library_config" ]
234  sources = [ "./src/media_key_system_factory_driver.cpp" ]
235
236  external_deps = [
237    "c_utils:utils",
238    "drivers_interface_drm:libdrm_stub_1.0",
239    "hdf_core:libhdf_host",
240    "hdf_core:libhdf_ipc_adapter",
241    "hdf_core:libhdf_utils",
242    "hdf_core:libhdi",
243    "hilog:libhilog",
244    "ipc:ipc_single",
245  ]
246  cflags = [
247    "-Wall",
248    "-Wextra",
249    "-Werror",
250    "-fsigned-char",
251    "-fno-common",
252    "-fno-strict-aliasing",
253  ]
254  shlib_type = "hdi"
255  install_images = [ chipset_base_dir ]
256  subsystem_name = "hdf"
257  part_name = "drivers_peripheral_clearplay"
258}
259
260config("clearplay_imp_external_library_config") {
261  include_dirs =
262      [ "//drivers/peripheral/clearplay/interfaces/include/drm/v1_0" ]
263}
264group("hdf_clearplay_interfaces") {
265  deps = [ ":libclearplay_driver" ]
266}
267```
268
269### 部件配置
270
271新建drivers/peripheral/clearplay/build.json用于定义新增的drivers_peripheral_clearplay部件:
272
273```
274{
275  "name": "@ohos/drivers_peripheral_clearplay",
276  "description": "clearplay drm device driver",
277  "version": "4.0",
278  "license": "Apache License 2.0",
279  "publishAs": "code-segment",
280  "segment": {
281    "destPath": "drivers/peripheral/clearplay"
282  },
283  "dirs": {},
284  "scripts": {},
285  "component": {
286    "name": "drivers_peripheral_clearplay",
287    "subsystem": "hdf",
288    "syscap": [],
289    "adapted_system_type": ["standard"],
290    "rom": "",
291    "ram": "",
292    "deps": {
293      "components": [
294        "bounds_checking_function",
295        "drivers_interface_drm",
296        "c_utils",
297        "hdf_core",
298        "hilog",
299        "ipc"
300      ],
301      "third_party": []
302    },
303    "build": {
304      "sub_component": [
305        "//drivers/peripheral/clearplay:clearplay_entry"
306      ],
307      "inner_kits": [
308        {
309          "type":"so",
310          "name": "//drivers/peripheral/clearplay/hdi_service:libmedia_key_system_factory_clearplay_service_1.0",
311            "header": {
312              "header_files": [
313                "imedia_decrypt_module.h",
314                "imedia_key_session_callback.h",
315                "imedia_key_session.h",
316                "imedia_key_system_callback.h",
317                "imedia_key_system_factory.h",
318                "imedia_key_system.h",
319                "ioem_certificate.h",
320                "media_decrypt_module_proxy.h",
321                "media_decrypt_module_stub.h",
322                "media_key_session_callback_proxy.h",
323                "media_key_session_callback_stub.h",
324                "media_key_session_proxy.h",
325                "media_key_session_stub.h",
326                "media_key_system_callback_proxy.h",
327                "media_key_system_callback_stub.h",
328                "media_key_system_factory_proxy.h",
329                "media_key_system_factory_stub.h",
330                "media_key_system_proxy.h",
331                "media_key_system_stub.h",
332                "media_key_system_types.h",
333                "oem_certificate_proxy.h",
334                "oem_certificate_stub.h"
335              ],
336              "header_base": "//drivers/peripheral/clearplay/interfaces/include/drm/v1_0"
337          }
338        },
339        {
340          "type":"so",
341          "name": "//drivers/peripheral/clearplay/interfaces:libclearplay_driver",
342            "header": {
343              "header_files": [],
344              "header_base": "//drivers/peripheral/clearplay/interfaces/include/drm/v1_0"
345          }
346        }
347      ]
348    }
349  }
350}
351```
352### 部件编译入口配置
353
354以rk3568产品为例:`//productdefine/common/inherit/chipset_common.json`
355
356```
357{
358  "component": "drivers_peripheral_clearplay",
359  "features": []
360}
361```
362
363### 服务代码编译
364
365与编译系统部件编译类似:
366`./build.sh --product-name rk3568 --ccache --build-target drivers_peripheral_clearplay`
367编译生成的二进制文件如下:
368//ohos/out/rk3568/hdf/drivers_peripheral_clearplay/libclearplay_driver.z.so
369//ohos/out/rk3568/hdf/drivers_peripheral_clearplay/libmedia_key_system_factory_clearplay_service_1.0.z.so
370
371## DRM解决方案插件服务配置
372
373### hcs配置
374
375以rk3568产品为例,在`vendor/hihope/rk3568/hdf_config/uhdf/device_info.hcs`添加驱动服务配置
376
377```
378clearplay :: host {
379    hostName = "clearplay_host";   // 进程名。
380    priority = 50;
381    uid = ""; // 用户态进程uid,缺省为空,会被配置为hostName的定义值,即普通用户。
382    gid = ""; // 用户态进程gid,缺省为空,会被配置为hostName的定义值,即普通用户组。
383    caps = ["DAC_OVERRIDE", "DAC_READ_SEARCH"]; // 用户态进程Linux capabilities配置,缺省为空,需要业务模块按照业务需要进行配置。
384    clearplay_device :: device {
385        device0 :: deviceNode {
386            policy = 2;
387            priority = 100;
388            moduleName = "libclearplay_driver.z.so";  // 驱动加载入口。
389            serviceName = "clearplay_service";        // 服务名称。
390        }
391    }
392}
393```
394
395### host用户与组配置
396
397对于在hcs中新增加的host节点,需要新增配置对应进程的uid(用户ID)和gid(组ID)
398passwd文件为系统用户配置文件,存储了系统中所有用户的基本信息,这里以此为例:
399
400```
401//base/startup/init/services/etc/passwd
402clearplay_host:x:1089:1089:::/bin/false
403```
404
405`//base/startup/init/services/etc/passwd`中每行用户信息使用“:”作为分隔符,划分为7个字段,每个字段所表示的含义如下:
406用户名:密码:UID(用户ID):GID(组ID):描述信息:主目录:默认shell
407
408group为用户组配置文件,存储了所有用户组的信息,以下为例:
409
410```
411base/startup/init/services/etc/group
412clearplay_host:x:1089:
413```
414
415base/startup/init/services/etc/group中每行代表一个用户组,用户组中以“:”作为分隔符,分为4个字段,每个字段的含义如下:
416组名:密码:GID(组ID):该用户组中的用户列表
417注意:
418- passwd中clearplay_host对应device_info.hcs中的uid,若device_info.hcs中uid缺省,则默认为hostName
419- group中clearplay_host对应device_info.hcs中的gid,若device_info.hcs中gid缺省,则默认为hostName
420
421### 动态加载
422
423为节约 RAM 内存占用,DRM 框架服务支持动态加载 DRM 解决方案插件,DRM 框架服务调用完解决方案插件后,及时卸载 DRM 解决方案插件,释放 RAM 内存占用,插件需通过修改服务启动属性将自身服务配置成懒加载,并加入到设备上的 DRM 框架服务懒加载列表配置文件中;HDI服务提供动态加载能力,系统启动过程中默认不加载,支持动态加载,以下为示例:
424`device_info.hcs`配置preload为2
425```
426clearplay :: host {
427    hostName = "clearplay_host";
428    priority = 50;
429    clearplay_device :: device {
430        device0 :: deviceNode {
431            policy = 2;
432            priority = 100;
433            preload = 2; // 设置preload为2,则系统启动过程中默认不加载,后续可手动加载。
434            moduleName = "libclearplay_driver.z.so";
435            serviceName = "clearplay_service";
436        }
437    }
438}
439```
440设备上`/etc/drm/drm_plugin_lazyloding.cfg`为 DRM 框架服务懒加载列表配置文件,键值对形式,DRM 解决方案插件解决方案名为键,DRM解决方案服务名为值:
441```
442{
443    "plugin_services": {
444        "lazy_load_service": [
445            "com.clearplay.drm:clearplay_service"
446        ]
447    }
448}
449```
450
451## 添加SELinux权限
452
453selinux用于限制服务进程可访问的资源,以下给定基础的selinux配置,在此基础上按业务添加所需规则。
454
455注意:以下示例中,clearplay_host表示hcs中的hostName值,clearplay_service表示服务名称
456//base/security/selinux_adapter/sepolicy/ohos_policy/drivers/adapter/public/hdf_service_contexts
457`clearplay_service                             u:object_r:hdf_clearplay_service:s0`
458
459//base/security/selinux_adapter/sepolicy/ohos_policy/drivers/adapter/public/hdf_service.te
460`type hdf_clearplay_service, hdf_service_attr;`
461
462//base/security/selinux_adapter/sepolicy/ohos_policy/startup/init/public/chipset_init.te
463`allow init clearplay_host:process { rlimitinh siginh transition };`
464
465//base/security/selinux_adapter/sepolicy/ohos_policy/drivers/peripheral/clearplay/vendor/hdf_devmgr.te
466```
467allow hdf_devmgr clearplay_host:binder { call transfer };
468allow hdf_devmgr clearplay_host:dir { search };
469allow hdf_devmgr clearplay_host:file { open read };
470allow hdf_devmgr clearplay_host:process { getattr };
471```
472
473//base/security/selinux_adapter/sepolicy/ohos_policy/drivers/adapter/public/type.te
474`type clearplay_host, hdfdomain, domain;`
475
476//base/security/selinux_adapter/sepolicy/ohos_policy/drivers/peripheral/clearplay/vendor/clearplay_host.te(新建此目录)
477```
478allow clearplay_host chip_prod_file:dir { search };
479allow clearplay_host dev_console_file:chr_file { read write };
480allow clearplay_host dev_hdf_kevent:chr_file { open read write ioctl getattr };
481allow clearplay_host dev_unix_socket:dir { search };
482allow clearplay_host hdf_device_manager:hdf_devmgr_class { get };
483allow clearplay_host hdf_devmgr:binder { call transfer };
484allow clearplay_host hdf_clearplay_service:hdf_devmgr_class { add };
485allow clearplay_host hilog_param:file { open read map };
486allow clearplay_host musl_param:file { open read map };
487allow clearplay_host sa_device_service_manager:samgr_class { get };
488allow clearplay_host samgr:binder { call };
489allow clearplay_host sh:binder { call };
490allow clearplay_host vendor_etc_file:dir { open read getattr search };
491allow clearplay_host vendor_etc_file:file { open read getattr };
492allowxperm clearplay_host dev_hdf_kevent:chr_file ioctl { 0x6202 0x6203 };
493```