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