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