1 /*
2 * Copyright (c) 2022-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 "plugin_manager.h"
17
18 #include <cstring>
19 #include <dirent.h>
20 #include <dlfcn.h>
21 #include <iostream>
22 #include <mutex>
23 #include <string_ex.h>
24 #include <unistd.h>
25
26 #include "edm_ipc_interface_code.h"
27 #include "edm_log.h"
28 #include "func_code_utils.h"
29 #include "permission_manager.h"
30
31 namespace OHOS {
32 namespace EDM {
33 std::shared_ptr<PluginManager> PluginManager::instance_;
34 std::mutex PluginManager::mutexLock_;
35
PluginManager()36 PluginManager::PluginManager()
37 {
38 EDMLOGD("PluginManager::PluginManager.");
39 }
40
~PluginManager()41 PluginManager::~PluginManager()
42 {
43 EDMLOGD("PluginManager::~PluginManager.");
44 pluginsCode_.clear();
45 pluginsName_.clear();
46 for (auto handle : pluginHandles_) {
47 dlclose(handle);
48 }
49 pluginHandles_.clear();
50 }
51
GetInstance()52 std::shared_ptr<PluginManager> PluginManager::GetInstance()
53 {
54 if (instance_ == nullptr) {
55 std::lock_guard<std::mutex> autoLock(mutexLock_);
56 if (instance_ == nullptr) {
57 instance_.reset(new (std::nothrow) PluginManager());
58 }
59 }
60
61 IPluginManager::pluginManagerInstance_ = instance_.get();
62 return instance_;
63 }
64
GetPluginByFuncCode(std::uint32_t funcCode)65 std::shared_ptr<IPlugin> PluginManager::GetPluginByFuncCode(std::uint32_t funcCode)
66 {
67 FuncCodeUtils::PrintFuncCode(funcCode);
68 FuncFlag flag = FuncCodeUtils::GetSystemFlag(funcCode);
69 if (flag == FuncFlag::POLICY_FLAG) {
70 std::uint32_t code = FuncCodeUtils::GetPolicyCode(funcCode);
71 EDMLOGD("PluginManager::code %{public}u", code);
72 auto it = pluginsCode_.find(code);
73 if (it != pluginsCode_.end()) {
74 return it->second;
75 }
76 }
77 EDMLOGD("GetPluginByFuncCode::return nullptr");
78 return nullptr;
79 }
80
GetPluginByPolicyName(const std::string & policyName)81 std::shared_ptr<IPlugin> PluginManager::GetPluginByPolicyName(const std::string &policyName)
82 {
83 auto it = pluginsName_.find(policyName);
84 if (it != pluginsName_.end()) {
85 return it->second;
86 }
87 return nullptr;
88 }
89
GetPluginByCode(std::uint32_t code)90 std::shared_ptr<IPlugin> PluginManager::GetPluginByCode(std::uint32_t code)
91 {
92 EDMLOGD("PluginManager::code %{public}u", code);
93 auto it = pluginsCode_.find(code);
94 if (it != pluginsCode_.end()) {
95 return it->second;
96 }
97 EDMLOGD("GetPluginByCode::return nullptr");
98 return nullptr;
99 }
100
CreateExecuteStrategy(ExecuteStrategy strategy)101 std::shared_ptr<IPluginExecuteStrategy> PluginManager::CreateExecuteStrategy(ExecuteStrategy strategy)
102 {
103 if (strategy == ExecuteStrategy::ENHANCE) {
104 return enhanceStrategy_;
105 }
106 if (strategy == ExecuteStrategy::REPLACE) {
107 return replaceStrategy_;
108 }
109 return singleStrategy_;
110 }
111
AddPlugin(std::shared_ptr<IPlugin> plugin)112 bool PluginManager::AddPlugin(std::shared_ptr<IPlugin> plugin)
113 {
114 if (plugin == nullptr) {
115 return false;
116 }
117 EDMLOGD("AddPlugin %{public}d", plugin->GetCode());
118 IPlugin::PolicyPermissionConfig setConfig = plugin->GetAllPermission(FuncOperateType::SET);
119 IPlugin::PolicyPermissionConfig getConfig = plugin->GetAllPermission(FuncOperateType::GET);
120 IPlugin::PermissionType setType = plugin->GetPermissionType(FuncOperateType::SET);
121 IPlugin::PermissionType getType = plugin->GetPermissionType(FuncOperateType::GET);
122 ErrCode result = PermissionManager::GetInstance()->AddPermission(setConfig.permission, setType);
123 if (result == ERR_OK && getConfig.permission != setConfig.permission) {
124 result = PermissionManager::GetInstance()->AddPermission(getConfig.permission, getType);
125 }
126 if (result == ERR_OK) {
127 for (auto &item : setConfig.tagPermissions) {
128 if (PermissionManager::GetInstance()->AddPermission(item.second, setType) != ERR_OK) {
129 return false;
130 }
131 }
132 for (auto &item : getConfig.tagPermissions) {
133 if (PermissionManager::GetInstance()->AddPermission(item.second, getType) != ERR_OK) {
134 return false;
135 }
136 }
137 pluginsCode_.insert(std::make_pair(plugin->GetCode(), plugin));
138 pluginsName_.insert(std::make_pair(plugin->GetPolicyName(), plugin));
139 if (extensionPluginMap_.count(plugin->GetCode()) > 0) {
140 EDMLOGD("PluginManager::AddPlugin %{public}d add extension plugin %{public}d", plugin->GetCode(),
141 extensionPluginMap_[plugin->GetCode()]);
142 plugin->SetExtensionPlugin(GetPluginByCode(extensionPluginMap_[plugin->GetCode()]));
143 }
144 if (executeStrategyMap_.count(plugin->GetCode()) > 0) {
145 plugin->SetExecuteStrategy(CreateExecuteStrategy(executeStrategyMap_[plugin->GetCode()]));
146 } else {
147 plugin->SetExecuteStrategy(CreateExecuteStrategy(ExecuteStrategy::SINGLE));
148 }
149 return true;
150 }
151 return false;
152 }
153
AddExtensionPlugin(std::shared_ptr<IPlugin> extensionPlugin,uint32_t basicPluginCode,ExecuteStrategy strategy)154 bool PluginManager::AddExtensionPlugin(std::shared_ptr<IPlugin> extensionPlugin, uint32_t basicPluginCode,
155 ExecuteStrategy strategy)
156 {
157 if (AddPlugin(extensionPlugin)) {
158 auto basicPlugin = GetPluginByCode(basicPluginCode);
159 if (basicPlugin != nullptr) {
160 EDMLOGD("PluginManager::AddExtensionPlugin %{public}d add extension plugin %{public}d", basicPluginCode,
161 extensionPlugin->GetCode());
162 basicPlugin->SetExtensionPlugin(extensionPlugin);
163 basicPlugin->SetExecuteStrategy(CreateExecuteStrategy(strategy));
164 }
165 extensionPlugin->SetPluginType(IPlugin::PluginType::EXTENSION);
166 extensionPluginMap_.insert(std::make_pair(basicPluginCode, extensionPlugin->GetCode()));
167 executeStrategyMap_.insert(std::make_pair(basicPluginCode, strategy));
168 return true;
169 }
170 return false;
171 }
172
LoadPlugin()173 void PluginManager::LoadPlugin()
174 {
175 std::lock_guard<std::mutex> autoLock(mutexLock_);
176 #if defined(_ARM64_) || defined(_X86_64_)
177 std::string pluginDir = "/system/lib64/edm_plugin/";
178 #else
179 std::string pluginDir = "/system/lib/edm_plugin/";
180 #endif
181 DIR *dir = opendir(pluginDir.c_str());
182 if (dir == nullptr) {
183 EDMLOGE("PluginManager::LoadPlugin open edm_plugin dir fail.");
184 return;
185 }
186 struct dirent *entry;
187 while ((entry = readdir(dir)) != nullptr) {
188 if (entry->d_type == DT_REG && strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
189 LoadPlugin(pluginDir + entry->d_name);
190 }
191 }
192 closedir(dir);
193 }
194
LoadPlugin(const std::string & pluginPath)195 void PluginManager::LoadPlugin(const std::string &pluginPath)
196 {
197 void *handle = dlopen(pluginPath.c_str(), RTLD_LAZY);
198 if (!handle) {
199 EDMLOGE("PluginManager::open plugin so fail. %{public}s.", dlerror());
200 return;
201 }
202 pluginHandles_.push_back(handle);
203 }
204
UnloadPlugin()205 void PluginManager::UnloadPlugin()
206 {
207 std::lock_guard<std::mutex> autoLock(mutexLock_);
208 for (auto codeIter = pluginsCode_.begin(); codeIter != pluginsCode_.end();) {
209 if (codeIter->second != nullptr) {
210 codeIter->second->ResetExtensionPlugin();
211 }
212 if (codeIter->second == nullptr || codeIter->first > static_cast<uint32_t>(EdmInterfaceCode::POLICY_CODE_END)) {
213 codeIter = pluginsCode_.erase(codeIter);
214 } else {
215 ++codeIter;
216 }
217 }
218 for (auto nameIter = pluginsName_.begin(); nameIter != pluginsName_.end();) {
219 if (nameIter->second == nullptr ||
220 nameIter->second->GetCode() > static_cast<uint32_t>(EdmInterfaceCode::POLICY_CODE_END)) {
221 nameIter = pluginsName_.erase(nameIter);
222 } else {
223 ++nameIter;
224 }
225 }
226 for (auto handleIter = pluginHandles_.begin(); handleIter != pluginHandles_.end();) {
227 auto handle = *handleIter;
228 if (handle == nullptr || dlclose(handle) == 0) {
229 handleIter = pluginHandles_.erase(handleIter);
230 } else {
231 EDMLOGE("PluginManager::UnloadPlugin close handle failed.");
232 ++handleIter;
233 }
234 }
235 }
236
DumpPlugin()237 void PluginManager::DumpPlugin()
238 {
239 for (auto it = pluginsCode_.begin(); it != pluginsCode_.end(); it++) {
240 std::string setTagPermissions;
241 std::string getTagPermissions;
242 IPlugin::PolicyPermissionConfig setConfig = it->second->GetAllPermission(FuncOperateType::SET);
243 IPlugin::PolicyPermissionConfig getConfig = it->second->GetAllPermission(FuncOperateType::GET);
244 for (auto &item : setConfig.tagPermissions) {
245 setTagPermissions.append(item.second);
246 }
247 for (auto &item : getConfig.tagPermissions) {
248 getTagPermissions.append(item.second);
249 }
250 EDMLOGD("PluginManager::Dump plugins_code.code:%{public}u,name:%{public}s,get permission:%{public}s, "
251 "set permission:%{public}s,get tagPermissions:%{public}s,set tagPermissions:%{public}s",
252 it->first, it->second->GetPolicyName().c_str(),
253 it->second->GetPermission(FuncOperateType::GET).c_str(),
254 it->second->GetPermission(FuncOperateType::SET).c_str(),
255 getTagPermissions.c_str(), setTagPermissions.c_str());
256 }
257 for (auto it = pluginsName_.begin(); it != pluginsName_.end(); it++) {
258 std::string setTagPermissions;
259 std::string getTagPermissions;
260 IPlugin::PolicyPermissionConfig setConfig = it->second->GetAllPermission(FuncOperateType::SET);
261 IPlugin::PolicyPermissionConfig getConfig = it->second->GetAllPermission(FuncOperateType::GET);
262 for (auto &item : setConfig.tagPermissions) {
263 setTagPermissions.append(item.second);
264 }
265 for (auto &item : getConfig.tagPermissions) {
266 getTagPermissions.append(item.second);
267 }
268 EDMLOGD("PluginManager::Dump plugins_name.name:%{public}s,code:%{public}u,get permission type:%{public}s, "
269 "set permission type:%{public}s,get tagPermissions:%{public}s,set tagPermissions:%{public}s",
270 it->first.c_str(), it->second->GetCode(),
271 it->second->GetPermission(FuncOperateType::GET).c_str(),
272 it->second->GetPermission(FuncOperateType::SET).c_str(),
273 getTagPermissions.c_str(), setTagPermissions.c_str());
274 }
275 }
276 } // namespace EDM
277 } // namespace OHOS
278