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 31namespace OHOS { 32namespace EDM { 33std::shared_ptr<PluginManager> PluginManager::instance_; 34std::mutex PluginManager::mutexLock_; 35 36PluginManager::PluginManager() 37{ 38 EDMLOGD("PluginManager::PluginManager."); 39} 40 41PluginManager::~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 52std::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 65std::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 81std::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 90std::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 101std::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 112bool 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 154bool 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 173void 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 195void 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 205void 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 EDMLOGI("PluginManager::UnloadPlugin finish."); 236} 237 238void PluginManager::DumpPlugin() 239{ 240 for (auto it = pluginsCode_.begin(); it != pluginsCode_.end(); it++) { 241 std::string setTagPermissions; 242 std::string getTagPermissions; 243 IPlugin::PolicyPermissionConfig setConfig = it->second->GetAllPermission(FuncOperateType::SET); 244 IPlugin::PolicyPermissionConfig getConfig = it->second->GetAllPermission(FuncOperateType::GET); 245 for (auto &item : setConfig.tagPermissions) { 246 setTagPermissions.append(item.second); 247 } 248 for (auto &item : getConfig.tagPermissions) { 249 getTagPermissions.append(item.second); 250 } 251 EDMLOGD("PluginManager::Dump plugins_code.code:%{public}u,name:%{public}s,get permission:%{public}s, " 252 "set permission:%{public}s,get tagPermissions:%{public}s,set tagPermissions:%{public}s", 253 it->first, it->second->GetPolicyName().c_str(), 254 it->second->GetPermission(FuncOperateType::GET).c_str(), 255 it->second->GetPermission(FuncOperateType::SET).c_str(), 256 getTagPermissions.c_str(), setTagPermissions.c_str()); 257 } 258 for (auto it = pluginsName_.begin(); it != pluginsName_.end(); it++) { 259 std::string setTagPermissions; 260 std::string getTagPermissions; 261 IPlugin::PolicyPermissionConfig setConfig = it->second->GetAllPermission(FuncOperateType::SET); 262 IPlugin::PolicyPermissionConfig getConfig = it->second->GetAllPermission(FuncOperateType::GET); 263 for (auto &item : setConfig.tagPermissions) { 264 setTagPermissions.append(item.second); 265 } 266 for (auto &item : getConfig.tagPermissions) { 267 getTagPermissions.append(item.second); 268 } 269 EDMLOGD("PluginManager::Dump plugins_name.name:%{public}s,code:%{public}u,get permission type:%{public}s, " 270 "set permission type:%{public}s,get tagPermissions:%{public}s,set tagPermissions:%{public}s", 271 it->first.c_str(), it->second->GetCode(), 272 it->second->GetPermission(FuncOperateType::GET).c_str(), 273 it->second->GetPermission(FuncOperateType::SET).c_str(), 274 getTagPermissions.c_str(), setTagPermissions.c_str()); 275 } 276} 277} // namespace EDM 278} // namespace OHOS 279