• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "camera_dynamic_loader.h"
17 
18 #include <cstddef>
19 #include <cstdint>
20 #include <dlfcn.h>
21 #include <map>
22 #include <memory>
23 #include <mutex>
24 #include <thread>
25 #include <utility>
26 
27 #include "camera_log.h"
28 
29 namespace OHOS {
30 namespace CameraStandard {
31 using namespace std;
32 
33 enum AsyncLoadingState : int32_t { NONE, PREPARE, LOADING };
34 
35 static const uint32_t HANDLE_MASK = 0xffffffff;
36 static mutex g_libMutex;
37 static map<const string, shared_ptr<Dynamiclib>> g_dynamiclibMap = {};
38 static map<const string, weak_ptr<Dynamiclib>> g_weakDynamiclibMap = {};
39 
40 static mutex g_asyncLoadingMutex;
41 static condition_variable g_asyncLiblockCondition;
42 static AsyncLoadingState g_isAsyncLoading = AsyncLoadingState::NONE;
43 
Dynamiclib(const string & libName)44 Dynamiclib::Dynamiclib(const string& libName) : libName_(libName)
45 {
46     CAMERA_SYNC_TRACE;
47     MEDIA_INFO_LOG("Dynamiclib::Dynamiclib dlopen %{public}s", libName_.c_str());
48     libHandle_ = dlopen(libName_.c_str(), RTLD_NOW);
49     CHECK_ERROR_RETURN_LOG(
50         libHandle_ == nullptr, "Dynamiclib::Dynamiclib dlopen name:%{public}s return null", libName_.c_str());
51     MEDIA_INFO_LOG("Dynamiclib::Dynamiclib dlopen %{public}s success handle:%{public}u", libName_.c_str(),
52         static_cast<uint32_t>(HANDLE_MASK & reinterpret_cast<uintptr_t>(libHandle_)));
53 }
54 
~Dynamiclib()55 Dynamiclib::~Dynamiclib()
56 {
57     CAMERA_SYNC_TRACE;
58     if (libHandle_ != nullptr) {
59         int ret = dlclose(libHandle_);
60         MEDIA_INFO_LOG("Dynamiclib::~Dynamiclib dlclose name:%{public}s handle:%{public}u result:%{public}d",
61             libName_.c_str(), static_cast<uint32_t>(HANDLE_MASK & reinterpret_cast<uintptr_t>(libHandle_)), ret);
62         libHandle_ = nullptr;
63     }
64 }
65 
IsLoaded()66 bool Dynamiclib::IsLoaded()
67 {
68     return libHandle_ != nullptr;
69 }
70 
GetFunction(const string & functionName)71 void* Dynamiclib::GetFunction(const string& functionName)
72 {
73     CAMERA_SYNC_TRACE;
74     CHECK_ERROR_RETURN_RET_LOG(
75         !IsLoaded(), nullptr, "Dynamiclib::GetFunction fail libname:%{public}s not loaded", libName_.c_str());
76 
77     void* handle = dlsym(libHandle_, functionName.c_str());
78     CHECK_ERROR_RETURN_RET_LOG(
79         handle == nullptr, nullptr, "Dynamiclib::GetFunction fail function:%{public}s not find", functionName.c_str());
80     MEDIA_INFO_LOG("Dynamiclib::GetFunction %{public}s success", functionName.c_str());
81     return handle;
82 }
GetDynamiclibNoLock(const string & libName)83 shared_ptr<Dynamiclib> CameraDynamicLoader::GetDynamiclibNoLock(const string& libName)
84 {
85     auto loadedIterator = g_dynamiclibMap.find(libName);
86     if (loadedIterator != g_dynamiclibMap.end()) {
87         MEDIA_INFO_LOG("Dynamiclib::GetDynamiclib %{public}s by cache", libName.c_str());
88         return loadedIterator->second;
89     }
90 
91     shared_ptr<Dynamiclib> dynamiclib = nullptr;
92     auto loadedWeakIterator = g_weakDynamiclibMap.find(libName);
93     if (loadedWeakIterator != g_weakDynamiclibMap.end()) {
94         dynamiclib = loadedWeakIterator->second.lock();
95     }
96     if (dynamiclib != nullptr) {
97         MEDIA_INFO_LOG("Dynamiclib::GetDynamiclib %{public}s by weak cache", libName.c_str());
98     } else {
99         dynamiclib = make_shared<Dynamiclib>(libName);
100     }
101     CHECK_ERROR_RETURN_RET_LOG(
102         !dynamiclib->IsLoaded(), nullptr, "CameraDynamicLoader::GetDynamiclib name:%{public}s fail", libName.c_str());
103     g_dynamiclibMap.emplace(pair<const string, shared_ptr<Dynamiclib>>(libName, dynamiclib));
104     MEDIA_INFO_LOG("Dynamiclib::GetDynamiclib %{public}s load first", libName.c_str());
105     return dynamiclib;
106 }
107 
GetDynamiclib(const string & libName)108 shared_ptr<Dynamiclib> CameraDynamicLoader::GetDynamiclib(const string& libName)
109 {
110     CAMERA_SYNC_TRACE;
111     lock_guard<mutex> lock(g_libMutex);
112     return GetDynamiclibNoLock(libName);
113 }
114 
LoadDynamiclibAsync(const std::string & libName)115 void CameraDynamicLoader::LoadDynamiclibAsync(const std::string& libName)
116 {
117     CAMERA_SYNC_TRACE;
118     unique_lock<mutex> asyncLock(g_asyncLoadingMutex);
119     MEDIA_INFO_LOG("CameraDynamicLoader::LoadDynamiclibAsync %{public}s", libName.c_str());
120     if (g_isAsyncLoading != AsyncLoadingState::NONE) {
121         MEDIA_INFO_LOG("CameraDynamicLoader::LoadDynamiclibAsync %{public}s is loading", libName.c_str());
122         return;
123     }
124     g_isAsyncLoading = AsyncLoadingState::PREPARE;
125     thread asyncThread = thread([libName]() {
126         unique_lock<mutex> lock(g_libMutex);
127         {
128             unique_lock<mutex> asyncLock(g_asyncLoadingMutex);
129             g_isAsyncLoading = AsyncLoadingState::LOADING;
130             g_asyncLiblockCondition.notify_all();
131         }
132         GetDynamiclibNoLock(libName);
133         {
134             unique_lock<mutex> asyncLock(g_asyncLoadingMutex);
135             g_isAsyncLoading = AsyncLoadingState::NONE;
136         }
137         MEDIA_INFO_LOG("CameraDynamicLoader::LoadDynamiclibAsync %{public}s finish", libName.c_str());
138     });
139     asyncThread.detach();
140     g_asyncLiblockCondition.wait(asyncLock, []() { return g_isAsyncLoading != AsyncLoadingState::PREPARE; });
141 }
142 
FreeDynamiclib(const string & libName)143 void CameraDynamicLoader::FreeDynamiclib(const string& libName)
144 {
145     CAMERA_SYNC_TRACE;
146     lock_guard<mutex> lock(g_libMutex);
147     auto loadedIterator = g_dynamiclibMap.find(libName);
148     CHECK_ERROR_RETURN(loadedIterator == g_dynamiclibMap.end());
149     MEDIA_INFO_LOG("Dynamiclib::FreeDynamiclib %{public}s lib use count is:%{public}d", libName.c_str(),
150         static_cast<int32_t>(loadedIterator->second.use_count()));
151 
152     weak_ptr<Dynamiclib> weaklib = loadedIterator->second;
153     g_weakDynamiclibMap[libName] = weaklib;
154     g_dynamiclibMap.erase(loadedIterator);
155 }
156 } // namespace CameraStandard
157 } // namespace OHOS