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