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