• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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