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