1 /*
2  * Copyright (c) 2024 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 #undef LOG_TAG
17 #define LOG_TAG "AVSessionDynamicLoader"
18 
19 #include <dlfcn.h>
20 #include "avsession_log.h"
21 #include "avsession_errors.h"
22 #include "avsession_dynamic_loader.h"
23 #include "directory_ex.h"
24 
25 namespace OHOS {
26 namespace AVSession {
27 using namespace std;
28 
AVSessionDynamicLoader()29 AVSessionDynamicLoader::AVSessionDynamicLoader()
30 {
31     SLOGI("AVSessionDynamicLoader ctor");
32 }
33 
~AVSessionDynamicLoader()34 AVSessionDynamicLoader::~AVSessionDynamicLoader()
35 {
36     SLOGI("AVSessionDynamicLoader dtor");
37     for (auto iterator = dynamicLibHandle_.begin(); iterator != dynamicLibHandle_.end(); ++iterator) {
38 #ifndef TEST_COVERAGE
39         dlclose(iterator->second);
40 #endif
41         SLOGI("close library avsession_dynamic success: %{public}s", iterator->first.c_str());
42     }
43 }
44 
OpenDynamicHandle(std::string dynamicLibrary)45 void* AVSessionDynamicLoader::OpenDynamicHandle(std::string dynamicLibrary)
46 {
47     std::lock_guard loaderLock(libLock_);
48     // if not opened, then open directly
49     // do we need lock?
50     // further optimization:
51     // 1. split all dependencies to separate libraries
52     // 2. just close each library not all
53     char realCachePath[PATH_MAX] = { 0X00 };
54     char *realPathRes = realpath(dynamicLibrary.c_str(), realCachePath);
55     if (realPathRes == nullptr || dynamicLibrary.find(".so") == std::string::npos) {
56         SLOGD("OpenDynamicHandle get dynamicLibrary %{public}s", dynamicLibrary.c_str());
57     }
58     if (dynamicLibHandle_[dynamicLibrary] == nullptr) {
59 #ifndef TEST_COVERAGE
60         void* dynamicLibHandle = dlopen(dynamicLibrary.c_str(), RTLD_NOW);
61         if (dynamicLibHandle == nullptr) {
62             SLOGE("Failed to open %{public}s, reason: %{public}sn", dynamicLibrary.c_str(), dlerror());
63             return nullptr;
64         }
65         SLOGI("open library %{public}s success", dynamicLibrary.c_str());
66         dynamicLibHandle_[dynamicLibrary] = dynamicLibHandle;
67 #else
68         SLOGI("in test coverage state, dlclose/dlopen may conflict with llvm");
69 #endif
70     }
71     return dynamicLibHandle_[dynamicLibrary];
72 }
73 
GetFuntion(std::string dynamicLibrary,std::string function)74 void* AVSessionDynamicLoader::GetFuntion(std::string dynamicLibrary, std::string function)
75 {
76     std::lock_guard loaderLock(libLock_);
77     // if not opened, then open directly
78     if (dynamicLibHandle_[dynamicLibrary] == nullptr) {
79         OpenDynamicHandle(dynamicLibrary);
80     }
81 
82     void* handle = nullptr;
83     if (dynamicLibHandle_[dynamicLibrary] != nullptr) {
84         handle = dlsym(dynamicLibHandle_[dynamicLibrary], function.c_str());
85         if (handle == nullptr) {
86             SLOGE("Failed to load %{public}s, reason: %{public}sn", function.c_str(), dlerror());
87             return nullptr;
88         }
89         SLOGI("GetFuntion %{public}s success", function.c_str());
90     }
91     return handle;
92 }
93 
CloseDynamicHandle(std::string dynamicLibrary)94 void AVSessionDynamicLoader::CloseDynamicHandle(std::string dynamicLibrary)
95 {
96     std::lock_guard loaderLock(libLock_);
97     // if already opened, then close all
98     if (dynamicLibHandle_[dynamicLibrary] != nullptr) {
99 #ifndef TEST_COVERAGE
100         dlclose(dynamicLibHandle_[dynamicLibrary]);
101 #endif
102         dynamicLibHandle_[dynamicLibrary] = nullptr;
103         SLOGI("close library avsession_dynamic success: %{public}s", dynamicLibrary.c_str());
104     }
105 }
106 
107 }  // namespace AVSession
108 }  // namespace OHOS