1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <dlfcn.h>
17 #include <dirent.h>
18 #include <iostream>
19 #include <algorithm>
20 #include <fstream>
21 #include <sys/file.h>
22 #include <fcntl.h>
23 #include "iremote_broker.h"
24 #include "ipc_skeleton.h"
25 #include "drm_dfx.h"
26 #include "drm_dfx_utils.h"
27 #include "drm_log.h"
28 #include "drm_error_code.h"
29 #include "napi_param_utils.h"
30 #include "drm_host_manager.h"
31
32 namespace OHOS {
33 namespace DrmStandard {
34 using namespace OHOS::HiviewDFX;
35 std::queue<Message> DrmHostManager::messageQueue;
36 std::mutex DrmHostManager::queueMutex;
37 std::condition_variable DrmHostManager::cv;
38
39 const int32_t LAZY_UNLOAD_TIME_CHECK_IN_MINUTES = 1;
40 const int32_t LAZY_UNLOAD_WAIT_IN_MILMINUTES = 100;
41 const int32_t LAZY_UNLOAD_TIME_IN_MINUTES = 3;
42 const int32_t NOT_LAZY_LOADDED = -65536;
43 const int32_t TIME_IN_MS = 60000;
44
DrmHostDeathRecipient(const sptr<DrmHostManager> & drmHostManager,std::string & name)45 DrmHostManager::DrmHostDeathRecipient::DrmHostDeathRecipient(
46 const sptr<DrmHostManager> &drmHostManager, std::string &name)
47 : drmHostManager_(drmHostManager)
48 {
49 name_ = name;
50 DRM_DEBUG_LOG("DrmHostDeathRecipient");
51 }
52
~DrmHostDeathRecipient()53 DrmHostManager::DrmHostDeathRecipient::~DrmHostDeathRecipient()
54 {
55 DRM_DEBUG_LOG("~DrmHostDeathRecipient");
56 }
OnDrmPluginDied(std::string & name)57 void DrmHostManager::OnDrmPluginDied(std::string &name)
58 {
59 }
OnRemoteDied(const wptr<IRemoteObject> & remote)60 void DrmHostManager::DrmHostDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
61 {
62 DRM_ERR_LOG("Remote service died, do clean works.");
63 drmHostManager_->ClearDeathService(name_);
64 }
65
ClearDeathService(std::string & name)66 void DrmHostManager::ClearDeathService(std::string &name)
67 {
68 DRM_INFO_LOG("ClearDeathService enter.");
69 std::lock_guard<std::recursive_mutex> lock(drmHostMapMutex);
70 if (lazyLoadPluginInfoMap.count(name) <= 0) {
71 DRM_DEBUG_LOG("PluginCountInfo is empty, name:%{public}s",
72 name.c_str());
73 return;
74 }
75 if (lazyLoadPluginCountMap.empty()) {
76 DRM_DEBUG_LOG("PluginCountMap is empty.");
77 return;
78 }
79 if (statusCallback_ != nullptr) {
80 statusCallback_->OnDrmPluginDied(name);
81 }
82 lazyLoadPluginCountMap[name] = NOT_LAZY_LOADDED;
83 lazyLoadPluginTimeoutMap[name] = NOT_LAZY_LOADDED;
84 for (auto it = hdiMediaKeySystemFactoryAndPluginNameMap.begin();
85 it != hdiMediaKeySystemFactoryAndPluginNameMap.end();) {
86 if (it->second == name) {
87 it = hdiMediaKeySystemFactoryAndPluginNameMap.erase(it);
88 } else {
89 ++it;
90 }
91 }
92 }
93
DrmHostManager(StatusCallback * statusCallback)94 DrmHostManager::DrmHostManager(StatusCallback *statusCallback) : statusCallback_(statusCallback)
95 {}
96
~DrmHostManager()97 DrmHostManager::~DrmHostManager()
98 {
99 DRM_INFO_LOG("~DrmHostManager enter.");
100 {
101 std::lock_guard<std::recursive_mutex> lock(drmHostMapMutex);
102 statusCallback_ = nullptr;
103 }
104 StopServiceThread();
105 }
106
StopServiceThread()107 void DrmHostManager::StopServiceThread()
108 {
109 DRM_INFO_LOG("StopServiceThread enter.");
110 if (!serviceThreadRunning) {
111 return;
112 }
113 serviceThreadRunning = false;
114 cv.notify_all();
115 if (serviceThread.joinable()) {
116 serviceThread.join();
117 }
118 if (messageQueueThread.joinable()) {
119 messageQueueThread.join();
120 }
121 std::lock_guard<std::recursive_mutex> lock(drmHostMapMutex);
122 for (auto libHandle : loadedLibs) {
123 StopThreadFuncType StopThread = (StopThreadFuncType)dlsym(libHandle, "StopThread");
124 if (StopThread) {
125 StopThread();
126 }
127 dlclose(libHandle);
128 libHandle = nullptr;
129 }
130 UnloadAllServices();
131 loadedLibs.clear();
132
133 ReportServiceBehaviorEvent("DRM_OEM_SERVICE", "end");
134 }
135
DelayedLazyUnLoad()136 void DrmHostManager::DelayedLazyUnLoad()
137 {
138 DRM_DEBUG_LOG("DelayedLazyUnLoad enter.");
139 sptr<IDeviceManager> deviceMgr = IDeviceManager::Get();
140 std::lock_guard<std::recursive_mutex> drmHostMapLock(drmHostMapMutex);
141 if (deviceMgr == nullptr || lazyLoadPluginInfoMap.empty()) {
142 return;
143 }
144 for (auto pluginInfoIt = lazyLoadPluginInfoMap.begin(); pluginInfoIt != lazyLoadPluginInfoMap.end();
145 pluginInfoIt++) {
146 DRM_DEBUG_LOG("ProcessMessage check lazy unload, name:%{public}s, Count:%{public}d,"
147 "Timeout:%{public}d", pluginInfoIt->second.c_str(), lazyLoadPluginCountMap[pluginInfoIt->first],
148 lazyLoadPluginTimeoutMap[pluginInfoIt->first]);
149 if (lazyLoadPluginCountMap[pluginInfoIt->first] <= NOT_LAZY_LOADDED ||
150 lazyLoadPluginTimeoutMap[pluginInfoIt->first] <= NOT_LAZY_LOADDED) {
151 DRM_DEBUG_LOG("ProcessMessage not need to unload");
152 continue;
153 }
154 if (lazyLoadPluginCountMap[pluginInfoIt->first] <= 0) {
155 if (lazyLoadPluginTimeoutMap[pluginInfoIt->first] <= LAZY_UNLOAD_TIME_CHECK_IN_MINUTES) {
156 deviceMgr->UnloadDevice(pluginInfoIt->second);
157 DRM_INFO_LOG("ProcessMessage UnloadDevice:%{public}s.", pluginInfoIt->second.c_str());
158 lazyLoadPluginCountMap[pluginInfoIt->first] = NOT_LAZY_LOADDED;
159 lazyLoadPluginTimeoutMap[pluginInfoIt->first] = NOT_LAZY_LOADDED;
160 } else {
161 lazyLoadPluginTimeoutMap[pluginInfoIt->first] -= LAZY_UNLOAD_TIME_CHECK_IN_MINUTES;
162 }
163 }
164 }
165 }
166
ProcessMessage()167 void DrmHostManager::ProcessMessage()
168 {
169 DRM_INFO_LOG("ProcessMessage enter.");
170 messageQueueThread = std::thread([this] {
171 int32_t counter = TIME_IN_MS;
172 while (serviceThreadRunning) {
173 std::unique_lock<std::mutex> queueMutexLock(queueMutex);
174 cv.wait_for(queueMutexLock, std::chrono::milliseconds(LAZY_UNLOAD_WAIT_IN_MILMINUTES), [this] {
175 return (!this->messageQueue.empty() || !this->serviceThreadRunning);
176 });
177 std::queue<Message> localQueue;
178 localQueue.swap(messageQueue);
179 queueMutexLock.unlock();
180 while (!localQueue.empty()) {
181 auto message = localQueue.front();
182 localQueue.pop();
183 DRM_DEBUG_LOG("ProcessMessage message type:%{public}d.", message.type);
184 if (message.type == Message::UnLoadOEMCertifaicateService) {
185 std::lock_guard<std::recursive_mutex> lock(drmHostMapMutex);
186 void *libHandle = pluginNameAndHandleMap[message.name];
187 if (libHandle != nullptr) {
188 ReleaseHandleAndKeySystemMap(libHandle);
189 loadedLibs.erase(std::remove(loadedLibs.begin(), loadedLibs.end(), libHandle),
190 loadedLibs.end());
191 DRM_DEBUG_LOG("ProcessMessage UnLoadOEMCertifaicateService success.");
192 }
193 }
194 }
195 if (!serviceThreadRunning) {
196 break;
197 }
198 counter -= LAZY_UNLOAD_WAIT_IN_MILMINUTES;
199 if (counter <= 0) {
200 DRM_DEBUG_LOG("ProcessMessage lazy unload start.");
201 DelayedLazyUnLoad();
202 counter = TIME_IN_MS;
203 }
204 }
205 });
206 }
207
ReleaseHandleAndKeySystemMap(void * handle)208 void DrmHostManager::ReleaseHandleAndKeySystemMap(void *handle)
209 {
210 DRM_INFO_LOG("ReleaseHandleAndKeySystemMap enter.");
211 std::lock_guard<std::recursive_mutex> drmHostMapLock(drmHostMapMutex);
212 sptr<IMediaKeySystem> hdiMediaKeySystem = handleAndKeySystemMap[handle];
213 if (hdiMediaKeySystem != nullptr) {
214 ReleaseMediaKeySystem(hdiMediaKeySystem);
215 hdiMediaKeySystem->Destroy();
216 hdiMediaKeySystem = nullptr;
217 DRM_DEBUG_LOG("ReleaseHandleAndKeySystemMap ReleaseMediaKeySystem end");
218 } else {
219 DRM_INFO_LOG("ReleaseHandleAndKeySystemMap handle not found");
220 }
221 handleAndKeySystemMap.erase(handle);
222
223 if (handle != nullptr) {
224 loadedLibs.erase(std::remove(loadedLibs.begin(), loadedLibs.end(), handle), loadedLibs.end());
225 StopThreadFuncType StopThread = (StopThreadFuncType)dlsym(handle, "StopThread");
226 if (StopThread) {
227 StopThread();
228 }
229 dlclose(handle);
230 handle = nullptr;
231 DRM_DEBUG_LOG("ReleaseHandleAndKeySystemMap handle closed");
232 }
233 }
234
GetOemLibraryPath(std::vector<std::string> & libsToLoad)235 void DrmHostManager::GetOemLibraryPath(std::vector<std::string> &libsToLoad)
236 {
237 DIR *dir = nullptr;
238 struct dirent *entry = nullptr;
239 if ((dir = opendir(OEM_CERTIFICATE_PATH)) != nullptr) {
240 while ((entry = readdir(dir)) != nullptr) {
241 std::string fileName = entry->d_name;
242 DRM_DEBUG_LOG("ServiceThreadMain fileName:%{public}s.", fileName.c_str());
243 if (fileName.find(".so") == std::string::npos) {
244 continue;
245 }
246 std::string fullPath = OEM_CERTIFICATE_PATH + fileName;
247 DRM_DEBUG_LOG("ServiceThreadMain fullPath:%{public}s.", fullPath.c_str());
248 libsToLoad.push_back(fullPath);
249 }
250 closedir(dir);
251 dir = nullptr;
252 }
253 }
254
ServiceThreadMain()255 void DrmHostManager::ServiceThreadMain() __attribute__((no_sanitize("cfi")))
256 {
257 DRM_INFO_LOG("ServiceThreadMain enter.");
258 std::vector<std::string> libsToLoad;
259 GetOemLibraryPath(libsToLoad);
260 for (const auto &libpath : libsToLoad) {
261 void *handle = dlopen(libpath.c_str(), RTLD_LAZY);
262 if (handle == nullptr) {
263 continue;
264 }
265 {
266 std::lock_guard<std::recursive_mutex> drmHostMapLock(drmHostMapMutex);
267 loadedLibs.push_back(handle);
268 }
269 auto QueryMediaKeySystemName = (QueryMediaKeySystemNameFuncType)dlsym(handle, "QueryMediaKeySystemName");
270 auto IsProvisionRequired = (IsProvisionRequiredFuncType)dlsym(handle, "IsProvisionRequired");
271 auto SetMediaKeySystem = (SetMediaKeySystemFuncType)dlsym(handle, "SetMediaKeySystem");
272 auto ThreadExitNotify = (ThreadExitNotifyFuncType)dlsym(handle, "ThreadExitNotify");
273 auto StartThread = (StartThreadFuncType)dlsym(handle, "StartThread");
274 if (QueryMediaKeySystemName && IsProvisionRequired && SetMediaKeySystem && ThreadExitNotify &&
275 StartThread) {
276 std::string pluginName;
277 int32_t ret = QueryMediaKeySystemName(pluginName);
278 if (ret != DRM_OK) {
279 ReleaseHandleAndKeySystemMap(handle);
280 DRM_ERR_LOG("QueryMediaKeySystemName error!");
281 continue;
282 }
283 sptr<IMediaKeySystem> hdiMediaKeySystem = nullptr;
284 ret = CreateMediaKeySystem(pluginName, hdiMediaKeySystem);
285 if (ret != DRM_OK || hdiMediaKeySystem == nullptr) {
286 ReleaseHandleAndKeySystemMap(handle);
287 DRM_ERR_LOG("CreateMediaKeySystem error!");
288 continue;
289 }
290 {
291 std::lock_guard<std::recursive_mutex> drmHostMapLock(drmHostMapMutex);
292 pluginNameAndHandleMap[pluginName] = handle;
293 handleAndKeySystemMap[handle] = hdiMediaKeySystem;
294 }
295 ret = SetMediaKeySystem(hdiMediaKeySystem);
296 if (ret != DRM_OK) {
297 ReleaseHandleAndKeySystemMap(handle);
298 DRM_ERR_LOG("SetMediaKeySystem error!");
299 continue;
300 }
301 if (IsProvisionRequired() == false) {
302 ReleaseHandleAndKeySystemMap(handle);
303 DRM_DEBUG_LOG("Provision not required!");
304 continue;
305 }
306 ret = ThreadExitNotify(DrmHostManager::UnLoadOEMCertifaicateService);
307 if (ret != DRM_OK) {
308 ReleaseHandleAndKeySystemMap(handle);
309 DRM_ERR_LOG("ThreadExitNotify error!");
310 continue;
311 }
312 ret = StartThread();
313 if (ret != DRM_OK) {
314 ReleaseHandleAndKeySystemMap(handle);
315 DRM_ERR_LOG("StartThread error!");
316 }
317 }
318 }
319 ReportServiceBehaviorEvent("DRM_OEM_SERVICE", "start");
320 }
321
UnLoadOEMCertifaicateService(std::string & name,ExtraInfo info)322 void DrmHostManager::UnLoadOEMCertifaicateService(std::string &name, ExtraInfo info)
323 {
324 DRM_INFO_LOG("UnLoadOEMCertifaicateService enter.");
325 std::unique_lock<std::mutex> queueMutexLock(queueMutex);
326 Message message(Message::UnLoadOEMCertifaicateService, name, info);
327 messageQueue.push(message);
328 cv.notify_all();
329 }
330
OemCertificateManager()331 void DrmHostManager::OemCertificateManager()
332 {
333 DRM_INFO_LOG("OemCertificateManager enter.");
334 serviceThreadRunning = true;
335 serviceThread = std::thread([this] {
336 this->ServiceThreadMain();
337 });
338 ProcessMessage();
339 }
340
Init(void)341 int32_t DrmHostManager::Init(void)
342 {
343 DRM_INFO_LOG("Init enter.");
344 LoadPluginInfo(PLUGIN_LAZYLOAD_CONFIG_PATH);
345 InitGetMediaKeySystems();
346 OemCertificateManager();
347 return DRM_OK;
348 }
349
DeInit(void)350 void DrmHostManager::DeInit(void)
351 {
352 DRM_INFO_LOG("DeInit");
353 }
354
OnReceive(const HDI::ServiceManager::V1_0::ServiceStatus & status)355 void DrmHostManager::OnReceive(const HDI::ServiceManager::V1_0::ServiceStatus &status)
356 {}
357
StringTrim(const std::string & str)358 std::string DrmHostManager::StringTrim(const std::string &str)
359 {
360 DRM_DEBUG_LOG("StringTrim enter.");
361 size_t first = str.find_first_not_of(" \t\n\r");
362 if (first == std::string::npos)
363 return "";
364 size_t last = str.find_last_not_of(" \t\n\r");
365 return str.substr(first, (last - first + 1));
366 }
367
parseLazyLoadService(std::ifstream & file,std::map<std::string,std::string> & lazyLoadPluginInfoMap)368 void DrmHostManager::parseLazyLoadService(
369 std::ifstream &file, std::map<std::string, std::string> &lazyLoadPluginInfoMap)
370 {
371 DRM_INFO_LOG("parseLazyLoadService enter.");
372 std::string line;
373 while (getline(file, line)) {
374 line = StringTrim(line);
375 if (line == "]" || line == "],") {
376 break;
377 }
378 if (!line.empty() && line.front() == '"') {
379 /* Remove front quotation marks */
380 line = line.substr(1);
381 if (!line.empty() && (line.back() == '"' || line.back() == ',')) {
382 /* Remove trailing quotation marks or commas */
383 line.pop_back();
384 }
385 }
386 size_t colonPos = line.find(':');
387 if (colonPos != std::string::npos) {
388 std::string key = StringTrim(line.substr(0, colonPos));
389 std::string value = StringTrim(line.substr(colonPos + 1));
390 /* Further StringTrim the value */
391 if (!value.empty() && value.back() == '"') {
392 /* Remove the last closing quotation mark of value */
393 value.pop_back();
394 }
395 lazyLoadPluginInfoMap[key] = value;
396 lazyLoadPluginCountMap[key] = NOT_LAZY_LOADDED;
397 lazyLoadPluginTimeoutMap[key] = NOT_LAZY_LOADDED;
398 }
399 }
400 }
401
LoadPluginInfo(const std::string & filePath)402 int32_t DrmHostManager::LoadPluginInfo(const std::string &filePath)
403 {
404 DRM_INFO_LOG("LoadPluginInfo enter.");
405 std::lock_guard<std::recursive_mutex> drmHostMapLock(drmHostMapMutex);
406 lazyLoadPluginInfoMap.clear();
407 int fd = open(filePath.c_str(), O_RDONLY);
408 if (fd == -1) {
409 DRM_ERR_LOG("LoadPluginInfo unable to open file:%{public}s.", filePath.c_str());
410 return DRM_HOST_ERROR;
411 }
412
413 std::ifstream file(filePath);
414 if (!file.is_open()) {
415 DRM_ERR_LOG("LoadPluginInfo unable to open file:%{public}s.", filePath.c_str());
416 close(fd);
417 return DRM_HOST_ERROR;
418 }
419
420 std::string line;
421 bool inPluginServices = false;
422 while (getline(file, line)) {
423 line = StringTrim(line);
424 if (line == "\"plugin_services\": {") {
425 inPluginServices = true;
426 } else if (inPluginServices) {
427 if (line == "}") {
428 break;
429 } else if (line == "\"lazy_load_service\": [") {
430 parseLazyLoadService(file, lazyLoadPluginInfoMap);
431 /* Exit after parsing lazy_load_service */
432 break;
433 }
434 }
435 }
436 file.close();
437 close(fd);
438 return DRM_OK;
439 }
440
UnloadAllServices()441 void DrmHostManager::UnloadAllServices()
442 {
443 DRM_INFO_LOG("UnloadAllServices enter.");
444 std::lock_guard<std::recursive_mutex> drmHostMapLock(drmHostMapMutex);
445 sptr<IDeviceManager> deviceMgr = IDeviceManager::Get();
446 if (deviceMgr == nullptr) {
447 DRM_ERR_LOG("deviceMgr == nullptr");
448 return;
449 }
450 for (auto pluginInfoIt = lazyLoadPluginInfoMap.begin(); pluginInfoIt != lazyLoadPluginInfoMap.end();
451 pluginInfoIt++) {
452 deviceMgr->UnloadDevice(pluginInfoIt->second);
453 }
454 }
455
ReleaseSevices(sptr<IMediaKeySystemFactory> drmHostServieProxy)456 void DrmHostManager::ReleaseSevices(sptr<IMediaKeySystemFactory> drmHostServieProxy)
457 {
458 DRM_INFO_LOG("ReleaseSevices enter.");
459 std::lock_guard<std::recursive_mutex> drmHostMapLock(drmHostMapMutex);
460 const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IMediaKeySystemFactory>(drmHostServieProxy);
461 if (remote != nullptr && drmHostDeathRecipientMap[drmHostServieProxy] != nullptr) {
462 remote->RemoveDeathRecipient(drmHostDeathRecipientMap[drmHostServieProxy]);
463 drmHostDeathRecipientMap[drmHostServieProxy] = nullptr;
464 }
465 drmHostDeathRecipientMap.erase(drmHostServieProxy);
466 std::string name = hdiMediaKeySystemFactoryAndPluginNameMap[drmHostServieProxy];
467 /* No need to release non lazy loading */
468 if (lazyLoadPluginInfoMap.count(name) <= 0) {
469 DRM_DEBUG_LOG("ReleaseSevices PluginCountInfo is empty, name:%{public}s",
470 name.c_str());
471 return;
472 }
473 if (lazyLoadPluginCountMap.empty()) {
474 DRM_DEBUG_LOG("ReleaseSevices PluginCountMap is empty");
475 return;
476 }
477 lazyLoadPluginCountMap[name]--;
478 DRM_DEBUG_LOG("Lazy unLoad plugin name:%{public}s,count:%{public}d", name.c_str(), lazyLoadPluginCountMap[name]);
479 if (lazyLoadPluginCountMap[name] == 0) {
480 lazyLoadPluginTimeoutMap[name] = LAZY_UNLOAD_TIME_IN_MINUTES;
481 DRM_DEBUG_LOG(
482 "ReleaseSevices device need to unload: %{public}s.", lazyLoadPluginInfoMap[name].c_str());
483 }
484 hdiMediaKeySystemFactoryAndPluginNameMap.erase(drmHostServieProxy);
485 }
486
LazyLoadPlugin(std::string & name,std::vector<std::string> & serviceName,sptr<IDeviceManager> & deviceMgr,sptr<IServiceManager> & servmgr)487 int32_t DrmHostManager::LazyLoadPlugin(std::string &name, std::vector<std::string> &serviceName,
488 sptr<IDeviceManager> &deviceMgr, sptr<IServiceManager> &servmgr)
489 {
490 DRM_INFO_LOG("LazyLoadPlugin enter, name:%{public}s.", name.c_str());
491 deviceMgr = IDeviceManager::Get();
492 if (deviceMgr == nullptr) {
493 DRM_ERR_LOG("LazyLoadPlugin deviceMgr == nullptr");
494 return DRM_SERVICE_ERROR;
495 }
496 int32_t ret = deviceMgr->LoadDevice(lazyLoadPluginInfoMap[name]);
497 if (ret != DRM_OK) {
498 DRM_ERR_LOG("LazyLoadPlugin loadDevice failed return Code:%{public}d", ret);
499 ret = servmgr->ListServiceByInterfaceDesc(serviceName, "ohos.hdi.drm.v1_0.IMediaKeySystemFactory");
500 if (ret != DRM_OK) {
501 DRM_ERR_LOG("ListServiceByInterfaceDesc faild, return Code:%{public}d", ret);
502 return DRM_SERVICE_ERROR;
503 }
504 } else {
505 lazyLoadPluginCountMap[name] = 0;
506 DRM_INFO_LOG("LazyLoadPlugin LoadDevice: %{public}s.", lazyLoadPluginInfoMap[name].c_str());
507 serviceName.push_back(lazyLoadPluginInfoMap[name]);
508 }
509 return DRM_OK;
510 }
511
ProcessLazyLoadPlugin(std::string & name,std::vector<std::string> & serviceName,sptr<IDeviceManager> & deviceMgr,sptr<IServiceManager> & servmgr)512 int32_t DrmHostManager::ProcessLazyLoadPlugin(std::string &name, std::vector<std::string> &serviceName,
513 sptr<IDeviceManager> &deviceMgr, sptr<IServiceManager> &servmgr)
514 {
515 DRM_INFO_LOG("ProcessLazyLoadPlugin enter, name:%{public}s.", name.c_str());
516 /*
517 * If the plugin is configured with lazy loading, read the service name from the configuration file.
518 * If lazy loading is not configured, traverse the service bound by the interface descriptor, and obtain
519 * the plugin service instance through the uuid and issuport interfaces
520 */
521 if (lazyLoadPluginInfoMap.count(name) > 0) {
522 auto it = std::find(serviceName.begin(), serviceName.end(), lazyLoadPluginInfoMap[name]);
523 if (it == serviceName.end()) {
524 int32_t ret = LazyLoadPlugin(name, serviceName, deviceMgr, servmgr);
525 if (ret != DRM_OK) {
526 DRM_ERR_LOG("ProcessLazyLoadPlugin LazyLoadPlugin faild, return Code:%{public}d",
527 ret);
528 return DRM_SERVICE_ERROR;
529 }
530 }
531 }
532 if (serviceName.empty()) {
533 DRM_DEBUG_LOG("No DRM driver service named:%{public}s configured.",
534 name.c_str());
535 return DRM_SERVICE_ERROR;
536 }
537 return DRM_OK;
538 }
539
ProcessLazyLoadInfomation(std::string & name,sptr<IMediaKeySystemFactory> & drmHostServieProxy)540 int32_t DrmHostManager::ProcessLazyLoadInfomation(std::string &name, sptr<IMediaKeySystemFactory> &drmHostServieProxy)
541 {
542 DRM_INFO_LOG("ProcessLazyLoadInfomation enter, name:%{public}s.", name.c_str());
543 drmHostDeathRecipientMap[drmHostServieProxy] = new DrmHostDeathRecipient(this, name);
544 const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IMediaKeySystemFactory>(drmHostServieProxy);
545 if (remote != nullptr && drmHostDeathRecipientMap[drmHostServieProxy] != nullptr) {
546 bool result = remote->AddDeathRecipient(drmHostDeathRecipientMap[drmHostServieProxy]);
547 if (!result) {
548 drmHostDeathRecipientMap[drmHostServieProxy] = nullptr;
549 ReleaseSevices(drmHostServieProxy);
550 DRM_ERR_LOG("AddDeathRecipient for drm Host failed.");
551 return DRM_HOST_ERROR;
552 }
553 }
554 if (!lazyLoadPluginCountMap.empty()) {
555 lazyLoadPluginCountMap[name]++;
556 hdiMediaKeySystemFactoryAndPluginNameMap[drmHostServieProxy] = name;
557 DRM_DEBUG_LOG("Lazy load plugin name:%{public}s,count:%{public}d",
558 name.c_str(), lazyLoadPluginCountMap[name]);
559 }
560 return DRM_OK;
561 }
562
GetServices(std::string & name,bool * isSurpported,sptr<IMediaKeySystemFactory> & drmHostServieProxys)563 int32_t DrmHostManager::GetServices(std::string &name, bool *isSurpported,
564 sptr<IMediaKeySystemFactory> &drmHostServieProxys)
565 {
566 DRM_INFO_LOG("GetServices enter, name:%{public}s.", name.c_str());
567 std::lock_guard<std::recursive_mutex> drmHostMapLock(drmHostMapMutex);
568 std::vector<std::string> serviceName;
569 drmHostServieProxys = nullptr;
570 sptr<IServiceManager> servmgr = IServiceManager::Get();
571 if (servmgr == nullptr) {
572 DRM_ERR_LOG("GetServices IServiceManager::Get() failed!");
573 return DRM_HOST_ERROR;
574 }
575 int32_t ret = servmgr->ListServiceByInterfaceDesc(serviceName, "ohos.hdi.drm.v1_0.IMediaKeySystemFactory");
576 if (ret != DRM_OK) {
577 DRM_ERR_LOG("ListServiceByInterfaceDesc faild, return Code:%{public}d", ret);
578 return ret;
579 }
580 sptr<IDeviceManager> deviceMgr = nullptr;
581 ret = ProcessLazyLoadPlugin(name, serviceName, deviceMgr, servmgr);
582 if (ret != DRM_OK) {
583 DRM_ERR_LOG("GetServices ProcessLazyLoadPlugin faild, return Code:%{public}d", ret);
584 return ret;
585 }
586
587 for (auto hdiServiceName : serviceName) {
588 sptr<IMediaKeySystemFactory> drmHostServieProxy =
589 OHOS::HDI::Drm::V1_0::IMediaKeySystemFactory::Get(hdiServiceName, false);
590 if (drmHostServieProxy == nullptr) {
591 DRM_ERR_LOG("GetServices failed.");
592 continue;
593 }
594 ret = drmHostServieProxy->IsMediaKeySystemSupported(name, "", SECURE_UNKNOWN, *isSurpported);
595 if (ret != DRM_OK) {
596 DRM_ERR_LOG("IsMediaKeySystemSupported return Code:%{public}d", ret);
597 continue;
598 } else if (*isSurpported) {
599 ret = ProcessLazyLoadInfomation(name, drmHostServieProxy);
600 if (ret != DRM_OK) {
601 DRM_ERR_LOG("GetServices ProcessLazyLoadInfomation faild, return Code:%{public}d", ret);
602 return ret;
603 }
604 drmHostServieProxys = drmHostServieProxy;
605 break;
606 }
607 }
608
609 if (lazyLoadPluginCountMap[name] == 0 && deviceMgr != nullptr) {
610 lazyLoadPluginTimeoutMap[name] = LAZY_UNLOAD_TIME_IN_MINUTES;
611 DRM_ERR_LOG("GetServices error, serive unsupported, unload device name:%{public}s",
612 name.c_str());
613 return DRM_SERVICE_ERROR;
614 }
615 return DRM_OK;
616 }
617
IsMediaKeySystemSupported(std::string & name,bool * isSurpported)618 int32_t DrmHostManager::IsMediaKeySystemSupported(std::string &name, bool *isSurpported)
619 {
620 DRM_INFO_LOG("IsMediaKeySystemSupported one parameter enter, name:%{public}s.", name.c_str());
621 sptr<IMediaKeySystemFactory> drmHostServieProxys;
622 /* Lock will be released when lock goes out of scope */
623 std::lock_guard<std::recursive_mutex> drmHostMapLock(drmHostMapMutex);
624 int32_t ret = GetServices(name, isSurpported, drmHostServieProxys);
625 if (ret != DRM_OK || drmHostServieProxys == nullptr) {
626 *isSurpported = false;
627 DRM_ERR_LOG("IsMediaKeySystemSupported one parameter GetServices error");
628 return DRM_SERVICE_ERROR;
629 }
630 ReleaseSevices(drmHostServieProxys);
631 return DRM_OK;
632 }
633
IsMediaKeySystemSupported(std::string & name,std::string & mimeType,bool * isSurpported)634 int32_t DrmHostManager::IsMediaKeySystemSupported(std::string &name, std::string &mimeType, bool *isSurpported)
635 {
636 DRM_INFO_LOG(
637 "IsMediaKeySystemSupported two parameters enter, name:%{public}s, mimeType:%{public}s.",
638 name.c_str(),
639 mimeType.c_str());
640 sptr<IMediaKeySystemFactory> drmHostServieProxys;
641 /* Lock will be released when lock goes out of scope */
642 std::lock_guard<std::recursive_mutex> drmHostMapLock(drmHostMapMutex);
643 int32_t ret = GetServices(name, isSurpported, drmHostServieProxys);
644 if (ret != DRM_OK || drmHostServieProxys == nullptr) {
645 *isSurpported = false;
646 DRM_ERR_LOG("IsMediaKeySystemSupported two parameters GetServices error.");
647 return DRM_SERVICE_ERROR;
648 }
649 if (mimeType.length() == 0) {
650 *isSurpported = false;
651 ReleaseSevices(drmHostServieProxys);
652 DRM_ERR_LOG("IsMediaKeySystemSupported mimeType is null!");
653 return DRM_SERVICE_ERROR;
654 }
655 ret = drmHostServieProxys->IsMediaKeySystemSupported(name, mimeType, SECURE_UNKNOWN, *isSurpported);
656 if (ret != 0) {
657 DRM_ERR_LOG("IsMediaKeySystemSupported return Code:%{public}d.", ret);
658 }
659 ReleaseSevices(drmHostServieProxys);
660 return DRM_OK;
661 }
662
IsMediaKeySystemSupported(std::string & name,std::string & mimeType,int32_t securityLevel,bool * isSurpported)663 int32_t DrmHostManager::IsMediaKeySystemSupported(
664 std::string &name, std::string &mimeType, int32_t securityLevel, bool *isSurpported)
665 {
666 DRM_INFO_LOG("IsMediaKeySystemSupported three parameters enter, name:%{public}s, "
667 "mimeType:%{public}s, securityLevel:%{public}d.",
668 name.c_str(),
669 mimeType.c_str(),
670 securityLevel);
671 std::lock_guard<std::recursive_mutex> drmHostMapLock(drmHostMapMutex);
672 sptr<IMediaKeySystemFactory> drmHostServieProxys;
673 /* Lock will be released when lock goes out of scope */
674 int32_t ret = GetServices(name, isSurpported, drmHostServieProxys);
675 if (ret != DRM_OK || drmHostServieProxys == nullptr) {
676 *isSurpported = false;
677 DRM_ERR_LOG("IsMediaKeySystemSupported three parameters GetServices error");
678 return DRM_SERVICE_ERROR;
679 }
680 if (mimeType.length() == 0) {
681 *isSurpported = false;
682 ReleaseSevices(drmHostServieProxys);
683 DRM_ERR_LOG("IsMediaKeySystemSupported mimeType is null!");
684 return DRM_SERVICE_ERROR;
685 }
686 ret = drmHostServieProxys->IsMediaKeySystemSupported(
687 name, mimeType, (OHOS::HDI::Drm::V1_0::ContentProtectionLevel)securityLevel, *isSurpported);
688 if (ret != DRM_OK) {
689 DRM_ERR_LOG("IsMediaKeySystemSupported return Code:%{public}d", ret);
690 }
691 ReleaseSevices(drmHostServieProxys);
692 return DRM_OK;
693 }
694
ReleaseMediaKeySystem(sptr<IMediaKeySystem> & hdiMediaKeySystem)695 void DrmHostManager::ReleaseMediaKeySystem(sptr<IMediaKeySystem> &hdiMediaKeySystem)
696 {
697 DRM_INFO_LOG("ReleaseMediaKeySystem enter.");
698 std::lock_guard<std::recursive_mutex> drmHostMapLock(drmHostMapMutex);
699 sptr<IMediaKeySystemFactory> drmHostServieProxys = hdiMediaKeySystemAndFactoryMap[hdiMediaKeySystem];
700 if (drmHostServieProxys != nullptr) {
701 ReleaseSevices(drmHostServieProxys);
702 } else {
703 DRM_INFO_LOG("ReleaseMediaKeySystem proxys not found.");
704 }
705 hdiMediaKeySystemAndFactoryMap.erase(hdiMediaKeySystem);
706 }
707
CreateMediaKeySystem(std::string & name,sptr<IMediaKeySystem> & hdiMediaKeySystem)708 int32_t DrmHostManager::CreateMediaKeySystem(std::string &name, sptr<IMediaKeySystem> &hdiMediaKeySystem)
709 {
710 DRM_INFO_LOG("CreateMediaKeySystem enter.");
711 /* Lock will be released when lock goes out of scope */
712 std::lock_guard<std::recursive_mutex> drmHostMapLock(drmHostMapMutex);
713 bool isSurpported = false;
714 sptr<IMediaKeySystemFactory> drmHostServieProxys;
715 int32_t ret = GetServices(name, &isSurpported, drmHostServieProxys);
716 if (ret != DRM_OK || drmHostServieProxys == nullptr) {
717 DRM_ERR_LOG("CreateMediaKeySystem faild.");
718 return DRM_HOST_ERROR;
719 }
720
721 ret = drmHostServieProxys->CreateMediaKeySystem(hdiMediaKeySystem);
722 if (ret != DRM_OK) {
723 hdiMediaKeySystem = nullptr;
724 ReleaseSevices(drmHostServieProxys);
725 DRM_ERR_LOG("CreateMediaKeySystem return Code:%{public}d", ret);
726 return DRM_HOST_ERROR;
727 }
728 hdiMediaKeySystemAndFactoryMap[hdiMediaKeySystem] = drmHostServieProxys;
729 return DRM_OK;
730 }
731
GetMediaKeySystemUuid(std::string & name,std::string & uuid)732 int32_t DrmHostManager::GetMediaKeySystemUuid(std::string &name, std::string &uuid)
733 {
734 DRM_INFO_LOG("GetMediaKeySystemUuid enter.");
735 bool isSurpported = false;
736 sptr<IMediaKeySystemFactory> drmHostServieProxys;
737 /* Lock will be released when lock goes out of scope */
738 std::lock_guard<std::recursive_mutex> drmHostMapLock(drmHostMapMutex);
739 int32_t ret = GetServices(name, &isSurpported, drmHostServieProxys);
740 if (ret != DRM_OK || drmHostServieProxys == nullptr) {
741 DRM_INFO_LOG("GetMediaKeySystemUuid faild.");
742 return DRM_HOST_ERROR;
743 }
744 ret = drmHostServieProxys->GetMediaKeySystemDescription(name, uuid);
745 if (ret != DRM_OK) {
746 ReleaseSevices(drmHostServieProxys);
747 DRM_ERR_LOG("GetMediaKeySystemUuid return Code:%{public}d", ret);
748 return DRM_HOST_ERROR;
749 }
750 ReleaseSevices(drmHostServieProxys);
751 return DRM_OK;
752 }
753
GetMediaKeySystems(std::map<std::string,std::string> & mediaKeySystemDescription)754 int32_t DrmHostManager::GetMediaKeySystems(std::map<std::string, std::string> &mediaKeySystemDescription)
755 {
756 DRM_INFO_LOG("GetMediaKeySystems enter.");
757 std::lock_guard<std::recursive_mutex> drmHostMapLock(drmHostMapMutex);
758 mediaKeySystemDescription.clear();
759 mediaKeySystemDescription.insert(mediaKeySystemDescription_.begin(), mediaKeySystemDescription_.end());
760 DRM_DEBUG_LOG("GetMediaKeySystems size:%{public}zu\n", mediaKeySystemDescription.size());
761 return DRM_OK;
762 }
763
InitGetMediaKeySystems()764 int32_t DrmHostManager::InitGetMediaKeySystems()
765 {
766 DRM_INFO_LOG("InitGetMediaKeySystems enter.");
767 std::lock_guard<std::recursive_mutex> drmHostMapLock(drmHostMapMutex);
768 int32_t ret;
769 std::vector<std::string> pluginServiceNames;
770 /*
771 * If the plugin is configured with lazy loading, read the service name from the configuration file.
772 * If lazy loading is not configured, traverse the service bound by the interface descriptor, and obtain
773 * the plugin service instance through the uuid and issuport interfaces
774 */
775 sptr<IDeviceManager> deviceMgr = IDeviceManager::Get();
776 if (deviceMgr == nullptr) {
777 DRM_ERR_LOG("InitGetMediaKeySystems deviceMgr == nullptr");
778 return DRM_HOST_ERROR;
779 }
780
781 for (auto pluginInfoIt = lazyLoadPluginInfoMap.begin(); pluginInfoIt != lazyLoadPluginInfoMap.end();
782 pluginInfoIt++) {
783 ret = deviceMgr->LoadDevice(pluginInfoIt->second);
784 if (ret != DRM_OK) {
785 DRM_ERR_LOG("InitGetMediaKeySystems LoadDevice return Code:%{public}d", ret);
786 continue;
787 }
788 }
789
790 auto servmgr = IServiceManager::Get();
791 if (servmgr == nullptr) {
792 DRM_ERR_LOG("InitGetMediaKeySystems IServiceManager::Get() failed!");
793 return DRM_HOST_ERROR;
794 }
795 ret = servmgr->ListServiceByInterfaceDesc(pluginServiceNames, "ohos.hdi.drm.v1_0.IMediaKeySystemFactory");
796 if (ret != DRM_OK) {
797 DRM_ERR_LOG("InitGetMediaKeySystems ListServiceByInterfaceDesc faild, return Code:%{public}d", ret);
798 return ret;
799 }
800 for (auto hdiServiceName : pluginServiceNames) {
801 std::string pluginName = "";
802 std::string pluginUuid = "";
803 sptr<IMediaKeySystemFactory> drmHostServieProxy =
804 OHOS::HDI::Drm::V1_0::IMediaKeySystemFactory::Get(hdiServiceName, false);
805 if (drmHostServieProxy == nullptr) {
806 continue;
807 }
808 ret = drmHostServieProxy->GetMediaKeySystemDescription(pluginName, pluginUuid);
809 if (ret != DRM_OK) {
810 continue;
811 }
812 mediaKeySystemDescription_.insert(std::pair<std::string, std::string>(pluginName, pluginUuid));
813 }
814 for (auto pluginInfoIt = lazyLoadPluginInfoMap.begin(); pluginInfoIt != lazyLoadPluginInfoMap.end();
815 pluginInfoIt++) {
816 ret = deviceMgr->UnloadDevice(pluginInfoIt->second);
817 if (ret != DRM_OK) {
818 DRM_ERR_LOG("UnloadDevice return Code:%{public}d", ret);
819 continue;
820 }
821 }
822 return DRM_OK;
823 }
824 } // namespace DrmStandard
825 } // namespace OHOS