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