• 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 #ifndef COMPONENT_MANAGER_H
17 #define COMPONENT_MANAGER_H
18 
19 #include <memory>
20 #include <dlfcn.h>
21 #include <nocopyable.h>
22 
23 #include "define_multimodal.h"
24 #include "i_context.h"
25 
26 #undef MMI_LOG_DOMAIN
27 #define MMI_LOG_DOMAIN MMI_LOG_SERVER
28 #undef MMI_LOG_TAG
29 #define MMI_LOG_TAG "ComponentManager"
30 
31 namespace OHOS {
32 namespace MMI {
33 
34 // Loading、unloading and bookkeeping of modules.
35 class ComponentManager final {
36 private:
37     template<typename IComponent>
38     using CreateComponent = IComponent* (*)(IContext *context);
39 
40     template<typename IComponent>
41     using DestroyComponent = void (*)(IComponent *);
42 
43 public:
44     template<typename IComponent>
45     class Component final {
46     public:
47         Component(IContext *context, void *handle);
48         Component(Component &&other);
49         ~Component();
50         DISALLOW_COPY(Component);
51 
52         Component<IComponent>& operator=(Component<IComponent> &&other);
53         void operator()(IComponent *instance);
54         IComponent* GetInstance();
55 
56     private:
57         void DeleteInstance(IComponent *instance);
58         void Unload();
59 
60         IContext *context_ { nullptr };
61         void *handle_ { nullptr };
62         IComponent *instance_ { nullptr };
63     };
64 
65     ComponentManager() = default;
66     ~ComponentManager() = default;
67     DISALLOW_COPY_AND_MOVE(ComponentManager);
68 
69     template<typename IComponent>
70     static std::unique_ptr<IComponent, Component<IComponent>> LoadLibrary(IContext *context, const char *libPath);
71 };
72 
73 template<typename IComponent>
Component(IContext * context,void * handle)74 ComponentManager::Component<IComponent>::Component(IContext *context, void *handle)
75     : context_(context), handle_(handle)
76 {}
77 
78 template<typename IComponent>
~Component()79 ComponentManager::Component<IComponent>::~Component()
80 {
81     Unload();
82 }
83 
84 template<typename IComponent>
Component(ComponentManager::Component<IComponent> && other)85 ComponentManager::Component<IComponent>::Component(ComponentManager::Component<IComponent> &&other)
86     : context_(other.context_), handle_(other.handle_), instance_(other.instance_)
87 {
88     other.context_ = nullptr;
89     other.handle_ = nullptr;
90     other.instance_ = nullptr;
91 }
92 
93 template<typename IComponent>
94 ComponentManager::Component<IComponent>& ComponentManager::Component<IComponent>::operator=(
95     Component<IComponent> &&other)
96 {
97     if (&other == this) {
98         return *this;
99     }
100     Unload();
101     context_ = other.context_;
102     handle_ = other.handle_;
103     instance_ = other.instance_;
104     other.context_ = nullptr;
105     other.handle_ = nullptr;
106     other.instance_ = nullptr;
107     return *this;
108 }
109 
110 template<typename IComponent>
operator()111 void ComponentManager::Component<IComponent>::operator()(IComponent *instance)
112 {
113     DeleteInstance(instance);
114 }
115 
116 template<typename IComponent>
GetInstance()117 IComponent* ComponentManager::Component<IComponent>::GetInstance()
118 {
119     if (instance_ != nullptr) {
120         return instance_;
121     }
122     ::dlerror();
123     CreateComponent<IComponent> create =
124         reinterpret_cast<CreateComponent<IComponent>>(::dlsym(handle_, "CreateInstance"));
125     if (auto err = ::dlerror(); err != nullptr) {
126         MMI_HILOGE("dlsym('CreateInstance') fail: %{public}s", err);
127         return nullptr;
128     }
129     instance_ = create(context_);
130     return instance_;
131 }
132 
133 template<typename IComponent>
DeleteInstance(IComponent * instance)134 void ComponentManager::Component<IComponent>::DeleteInstance(IComponent *instance)
135 {
136     if ((handle_ == nullptr) || (instance_ == nullptr) || (instance_ != instance)) {
137         return;
138     }
139     ::dlerror();
140     DestroyComponent<IComponent> destroy =
141         reinterpret_cast<DestroyComponent<IComponent>>(::dlsym(handle_, "DestroyInstance"));
142     if (auto err = ::dlerror(); err != nullptr) {
143         MMI_HILOGE("dlsym('DestroyInstance') fail: %{public}s", err);
144         return;
145     }
146     destroy(instance_);
147     instance_ = nullptr;
148 }
149 
150 template<typename IComponent>
Unload()151 void ComponentManager::Component<IComponent>::Unload()
152 {
153     if (handle_ != nullptr) {
154         DeleteInstance(instance_);
155         if (::dlclose(handle_) != RET_OK) {
156             MMI_HILOGE("dlclose fail: %{public}s", ::dlerror());
157         }
158         handle_ = nullptr;
159     }
160 }
161 
162 template<typename IComponent>
LoadLibrary(IContext * context,const char * libPath)163 std::unique_ptr<IComponent, ComponentManager::Component<IComponent>> ComponentManager::LoadLibrary(
164     IContext *context, const char *libPath)
165 {
166     if (libPath == nullptr) {
167         MMI_HILOGE("libPath is null");
168         return { nullptr, ComponentManager::Component<IComponent>(nullptr, nullptr) };
169     }
170     void *handle = ::dlopen(libPath, RTLD_NOW);
171     if (handle == nullptr) {
172         if (auto err = ::dlerror(); err != nullptr) {
173             MMI_HILOGE("dlopen fail for %{public}s: %{public}s", libPath, err);
174         } else {
175             MMI_HILOGE("dlopen fail for %{public}s", libPath);
176         }
177         return { nullptr, ComponentManager::Component<IComponent>(nullptr, nullptr) };
178     }
179     Component<IComponent> plugin(context, handle);
180     return { plugin.GetInstance(), std::move(plugin) };
181 }
182 } // namespace MMI
183 } // namespace OHOS
184 #endif // COMPONENT_MANAGER_H
185