• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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