1 /*
2 * Copyright (c) 2025 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 "rdb_dlopen_manager.h"
17
18 #include <cerrno>
19 #include <dlfcn.h>
20
21 #include "access_token_error.h"
22 #include "accesstoken_common_log.h"
23
24 namespace OHOS {
25 namespace Security {
26 namespace AccessToken {
27 namespace {
28 constexpr const char* RDB_SYMBOL_CREATE = "Create";
29 constexpr const char* RDB_SYMBOL_DESTROY = "Destroy";
30 constexpr const char* DELAY_DLCLOSE_TASK_NAME = "DelayDlclose";
31 constexpr int64_t DELAY_DLCLOSE_TIME_MILLISECONDS = 180 * 1000;
32
33 using CreateFunc = void* (*)(void);
34 using DestroyFunc = void (*)(void*);
35 }
36
RdbDlopenManager()37 RdbDlopenManager::RdbDlopenManager()
38 {
39 LOGI(ATM_DOMAIN, ATM_TAG, "RdbDlopenManager");
40 }
41
42 #ifdef EVENTHANDLER_ENABLE
InitEventHandler()43 void RdbDlopenManager::InitEventHandler()
44 {
45 eventRunner_ = AppExecFwk::EventRunner::Create(true, AppExecFwk::ThreadMode::FFRT);
46 if (eventRunner_ == nullptr) {
47 LOGE(ATM_DOMAIN, ATM_TAG, "Failed to create a eventRunner.");
48 return;
49 }
50 eventHandler_ = std::make_shared<AccessEventHandler>(eventRunner_);
51 }
52
GetEventHandler()53 std::shared_ptr<AccessEventHandler> RdbDlopenManager::GetEventHandler()
54 {
55 std::lock_guard<std::mutex> lock(eventHandlerLock_);
56 if (eventHandler_ == nullptr) {
57 InitEventHandler();
58 }
59 return eventHandler_;
60 }
61 #endif
62
Init()63 void RdbDlopenManager::Init()
64 {
65 if (instance_ == nullptr) {
66 return;
67 }
68
69 instance_->InitRdbHelper();
70 }
71
Create(void * handle)72 void RdbDlopenManager::Create(void* handle)
73 {
74 if (handle == nullptr) {
75 LOGE(ATM_DOMAIN, ATM_TAG, "Dynamic open handle is nullptr.");
76 return;
77 }
78
79 CreateFunc create = reinterpret_cast<CreateFunc>(dlsym(handle, RDB_SYMBOL_CREATE));
80 if (create == nullptr) {
81 LOGE(ATM_DOMAIN, ATM_TAG,
82 "Find symbol %{public}s from %{public}s failed, errno is %{public}d, errMsg is %{public}s.",
83 RDB_SYMBOL_CREATE, RDB_ADAPTER_LIBPATH, errno, dlerror());
84 return;
85 }
86 instance_ = reinterpret_cast<AccessTokenDbLoaderInterface*>(create());
87
88 Init();
89 }
90
Destroy(void * handle)91 void RdbDlopenManager::Destroy(void* handle)
92 {
93 if (handle == nullptr) {
94 LOGE(ATM_DOMAIN, ATM_TAG, "Dynamic open handle is nullptr.");
95 return;
96 }
97
98 DestroyFunc destroy = reinterpret_cast<DestroyFunc>(dlsym(handle, RDB_SYMBOL_DESTROY));
99 if (destroy == nullptr) {
100 LOGE(ATM_DOMAIN, ATM_TAG,
101 "Find symbol %{public}s from %{public}s failed, errno is %{public}d, errMsg is %{public}s.",
102 RDB_SYMBOL_DESTROY, RDB_ADAPTER_LIBPATH, errno, dlerror());
103 return;
104 }
105
106 if (instance_ == nullptr) {
107 return;
108 }
109
110 destroy(instance_);
111 instance_ = nullptr;
112 }
113
CleanUp()114 bool RdbDlopenManager::CleanUp()
115 {
116 // if DestroyRdbHelper return false after 10 attempts, don't dlclose otherwise this may cause cppcrash
117 return (instance_ != nullptr) ? instance_->DestroyRdbHelper() : true;
118 }
119
DelayDlcloseHandle(int64_t delayTime)120 void RdbDlopenManager::DelayDlcloseHandle(int64_t delayTime)
121 {
122 #ifdef EVENTHANDLER_ENABLE
123 auto eventHandler = GetEventHandler();
124 if (eventHandler == nullptr) {
125 LOGE(ATM_DOMAIN, ATM_TAG, "Fail to get EventHandler.");
126 return;
127 }
128
129 eventHandler->ProxyRemoveTask(std::string(DELAY_DLCLOSE_TASK_NAME));
130
131 std::function<void()> delayed = ([delayTime, this]() {
132 LOGI(ATM_DOMAIN, ATM_TAG, "Delay dlclose rdb handle.");
133 std::lock_guard<std::mutex> lock(handleMutex_);
134 if (handle_ == nullptr) {
135 return;
136 }
137
138 if (taskNum_ > 0) {
139 LOGI(ATM_DOMAIN, ATM_TAG, "There is still %{public}d database call remain, wait for next task.",
140 taskNum_.load());
141 return;
142 }
143 LOGI(ATM_DOMAIN, ATM_TAG, "There is no database call remain, clean up resource.");
144
145 if (!CleanUp()) {
146 return;
147 }
148
149 Destroy(handle_);
150 dlclose(handle_);
151 handle_ = nullptr;
152 });
153 eventHandler->ProxyPostTask(delayed, std::string(DELAY_DLCLOSE_TASK_NAME), delayTime);
154 #else
155 LOGW(ATM_DOMAIN, ATM_TAG, "Eventhandler is not support!");
156 #endif
157 }
158
GetDbInstance()159 AccessTokenDbLoaderInterface* RdbDlopenManager::GetDbInstance()
160 {
161 {
162 std::lock_guard<std::mutex> lock(handleMutex_);
163 if (handle_ == nullptr) {
164 handle_ = dlopen(RDB_ADAPTER_LIBPATH, RTLD_LAZY);
165 if (handle_ == nullptr) {
166 LOGE(ATM_DOMAIN, ATM_TAG, "Dlopen %{public}s failed, errno is %{public}d, errMsg is %{public}s.",
167 RDB_ADAPTER_LIBPATH, errno, dlerror());
168 return nullptr;
169 }
170 }
171
172 if (instance_ == nullptr) {
173 Create(handle_);
174 }
175 }
176
177 DelayDlcloseHandle(DELAY_DLCLOSE_TIME_MILLISECONDS);
178 return instance_;
179 }
180
Modify(const AtmDataType type,const GenericValues & modifyValue,const GenericValues & conditionValue)181 int32_t RdbDlopenManager::Modify(const AtmDataType type, const GenericValues& modifyValue,
182 const GenericValues& conditionValue)
183 {
184 auto instance = GetDbInstance();
185 if (instance == nullptr) {
186 return AccessTokenError::ERR_LOAD_SO_FAILED;
187 }
188
189 ++taskNum_;
190 int32_t res = instance->Modify(type, modifyValue, conditionValue);
191 --taskNum_;
192 return res;
193 }
194
Find(AtmDataType type,const GenericValues & conditionValue,std::vector<GenericValues> & results)195 int32_t RdbDlopenManager::Find(AtmDataType type, const GenericValues& conditionValue,
196 std::vector<GenericValues>& results)
197 {
198 auto instance = GetDbInstance();
199 if (instance == nullptr) {
200 return AccessTokenError::ERR_LOAD_SO_FAILED;
201 }
202
203 ++taskNum_;
204 int32_t res = instance->Find(type, conditionValue, results);
205 --taskNum_;
206 return res;
207 }
208
DeleteAndInsertValues(const std::vector<DelInfo> & delInfoVec,const std::vector<AddInfo> & addInfoVec)209 int32_t RdbDlopenManager::DeleteAndInsertValues(const std::vector<DelInfo>& delInfoVec,
210 const std::vector<AddInfo>& addInfoVec)
211 {
212 auto instance = GetDbInstance();
213 if (instance == nullptr) {
214 return AccessTokenError::ERR_LOAD_SO_FAILED;
215 }
216
217 ++taskNum_;
218 int32_t res = instance->DeleteAndInsertValues(delInfoVec, addInfoVec);
219 --taskNum_;
220 return res;
221 }
222 } // namespace AccessToken
223 } // namespace Security
224 } // namespace OHOS
225