• 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     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