1c29fa5a6Sopenharmony_ci/*
2c29fa5a6Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3c29fa5a6Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4c29fa5a6Sopenharmony_ci * you may not use this file except in compliance with the License.
5c29fa5a6Sopenharmony_ci * You may obtain a copy of the License at
6c29fa5a6Sopenharmony_ci *
7c29fa5a6Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8c29fa5a6Sopenharmony_ci *
9c29fa5a6Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10c29fa5a6Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11c29fa5a6Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12c29fa5a6Sopenharmony_ci * See the License for the specific language governing permissions and
13c29fa5a6Sopenharmony_ci * limitations under the License.
14c29fa5a6Sopenharmony_ci */
15c29fa5a6Sopenharmony_ci
16c29fa5a6Sopenharmony_ci#ifndef PLUGIN_MANAGER_H
17c29fa5a6Sopenharmony_ci#define PLUGIN_MANAGER_H
18c29fa5a6Sopenharmony_ci
19c29fa5a6Sopenharmony_ci#include <memory>
20c29fa5a6Sopenharmony_ci#include <mutex>
21c29fa5a6Sopenharmony_ci
22c29fa5a6Sopenharmony_ci#include <dlfcn.h>
23c29fa5a6Sopenharmony_ci
24c29fa5a6Sopenharmony_ci#include "nocopyable.h"
25c29fa5a6Sopenharmony_ci
26c29fa5a6Sopenharmony_ci#include "i_context.h"
27c29fa5a6Sopenharmony_ci#include "i_plugin_manager.h"
28c29fa5a6Sopenharmony_ci
29c29fa5a6Sopenharmony_cinamespace OHOS {
30c29fa5a6Sopenharmony_cinamespace Msdp {
31c29fa5a6Sopenharmony_cinamespace DeviceStatus {
32c29fa5a6Sopenharmony_ci
33c29fa5a6Sopenharmony_ci// Loading、unloading and bookkeeping of modules.
34c29fa5a6Sopenharmony_ciclass PluginManager final : public IPluginManager {
35c29fa5a6Sopenharmony_ci    template<typename IPlugin>
36c29fa5a6Sopenharmony_ci    class Plugin final {
37c29fa5a6Sopenharmony_ci    public:
38c29fa5a6Sopenharmony_ci        Plugin(IContext *context, void *handle);
39c29fa5a6Sopenharmony_ci        ~Plugin();
40c29fa5a6Sopenharmony_ci        DISALLOW_COPY_AND_MOVE(Plugin);
41c29fa5a6Sopenharmony_ci
42c29fa5a6Sopenharmony_ci        IPlugin* GetInstance();
43c29fa5a6Sopenharmony_ci
44c29fa5a6Sopenharmony_ci    private:
45c29fa5a6Sopenharmony_ci        IContext *context_ { nullptr };
46c29fa5a6Sopenharmony_ci        void *handle_ { nullptr };
47c29fa5a6Sopenharmony_ci        IPlugin *instance_ { nullptr };
48c29fa5a6Sopenharmony_ci    };
49c29fa5a6Sopenharmony_ci
50c29fa5a6Sopenharmony_ci    template<typename IPlugin>
51c29fa5a6Sopenharmony_ci    using CreatePlugin = IPlugin* (*)(IContext *context);
52c29fa5a6Sopenharmony_ci
53c29fa5a6Sopenharmony_ci    template<typename IPlugin>
54c29fa5a6Sopenharmony_ci    using DestroyPlugin = void (*)(IPlugin *);
55c29fa5a6Sopenharmony_ci
56c29fa5a6Sopenharmony_cipublic:
57c29fa5a6Sopenharmony_ci    PluginManager(IContext *context) : context_(context) {}
58c29fa5a6Sopenharmony_ci    ~PluginManager() = default;
59c29fa5a6Sopenharmony_ci    DISALLOW_COPY_AND_MOVE(PluginManager);
60c29fa5a6Sopenharmony_ci
61c29fa5a6Sopenharmony_ci    ICooperate* LoadCooperate() override;
62c29fa5a6Sopenharmony_ci    void UnloadCooperate() override;
63c29fa5a6Sopenharmony_ci
64c29fa5a6Sopenharmony_ciprivate:
65c29fa5a6Sopenharmony_ci    template<typename IPlugin>
66c29fa5a6Sopenharmony_ci    std::unique_ptr<Plugin<IPlugin>> LoadLibrary(IContext *context, const char *libPath);
67c29fa5a6Sopenharmony_ci
68c29fa5a6Sopenharmony_ciprivate:
69c29fa5a6Sopenharmony_ci    std::mutex lock_;
70c29fa5a6Sopenharmony_ci    IContext *context_ { nullptr };
71c29fa5a6Sopenharmony_ci    std::unique_ptr<Plugin<ICooperate>> cooperate_ { nullptr };
72c29fa5a6Sopenharmony_ci};
73c29fa5a6Sopenharmony_ci
74c29fa5a6Sopenharmony_citemplate<typename IPlugin>
75c29fa5a6Sopenharmony_ciPluginManager::Plugin<IPlugin>::Plugin(IContext *context, void *handle)
76c29fa5a6Sopenharmony_ci    : context_(context), handle_(handle)
77c29fa5a6Sopenharmony_ci{}
78c29fa5a6Sopenharmony_ci
79c29fa5a6Sopenharmony_citemplate<typename IPlugin>
80c29fa5a6Sopenharmony_ciPluginManager::Plugin<IPlugin>::~Plugin()
81c29fa5a6Sopenharmony_ci{
82c29fa5a6Sopenharmony_ci    if (instance_ != nullptr) {
83c29fa5a6Sopenharmony_ci        DestroyPlugin<IPlugin> destroy =
84c29fa5a6Sopenharmony_ci            reinterpret_cast<DestroyPlugin<IPlugin>>(::dlsym(handle_, "DestroyInstance"));
85c29fa5a6Sopenharmony_ci        if (destroy != nullptr) {
86c29fa5a6Sopenharmony_ci            destroy(instance_);
87c29fa5a6Sopenharmony_ci        }
88c29fa5a6Sopenharmony_ci    }
89c29fa5a6Sopenharmony_ci    ::dlclose(handle_);
90c29fa5a6Sopenharmony_ci}
91c29fa5a6Sopenharmony_ci
92c29fa5a6Sopenharmony_citemplate<typename IPlugin>
93c29fa5a6Sopenharmony_ciIPlugin* PluginManager::Plugin<IPlugin>::GetInstance()
94c29fa5a6Sopenharmony_ci{
95c29fa5a6Sopenharmony_ci    if (instance_ != nullptr) {
96c29fa5a6Sopenharmony_ci        return instance_;
97c29fa5a6Sopenharmony_ci    }
98c29fa5a6Sopenharmony_ci    CreatePlugin<IPlugin> create = reinterpret_cast<CreatePlugin<IPlugin>>(::dlsym(handle_, "CreateInstance"));
99c29fa5a6Sopenharmony_ci    if (create != nullptr) {
100c29fa5a6Sopenharmony_ci        instance_ = create(context_);
101c29fa5a6Sopenharmony_ci    }
102c29fa5a6Sopenharmony_ci    return instance_;
103c29fa5a6Sopenharmony_ci}
104c29fa5a6Sopenharmony_ci
105c29fa5a6Sopenharmony_citemplate<typename IPlugin>
106c29fa5a6Sopenharmony_cistd::unique_ptr<PluginManager::Plugin<IPlugin>> PluginManager::LoadLibrary(IContext *context, const char *libPath)
107c29fa5a6Sopenharmony_ci{
108c29fa5a6Sopenharmony_ci    char realPath[PATH_MAX] = { 0 };
109c29fa5a6Sopenharmony_ci    if (realpath(libPath, realPath) == nullptr) {
110c29fa5a6Sopenharmony_ci        FI_HILOGE("Path is error, path is %{public}s", libPath);
111c29fa5a6Sopenharmony_ci        return nullptr;
112c29fa5a6Sopenharmony_ci    }
113c29fa5a6Sopenharmony_ci    void *handle = ::dlopen(libPath, RTLD_NOW);
114c29fa5a6Sopenharmony_ci    return (handle != nullptr ? std::make_unique<Plugin<IPlugin>>(context, handle) : nullptr);
115c29fa5a6Sopenharmony_ci}
116c29fa5a6Sopenharmony_ci} // namespace DeviceStatus
117c29fa5a6Sopenharmony_ci} // namespace Msdp
118c29fa5a6Sopenharmony_ci} // namespace OHOS
119c29fa5a6Sopenharmony_ci#endif // PLUGIN_MANAGER_H