sensord: use LIBDIR macro for finding library path
[platform/core/system/sensord.git] / src / shared / sensor_plugin_loader.cpp
1 /*
2  * libsensord-share
3  *
4  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <sensor_plugin_loader.h>
21 #include <libxml/xmlmemory.h>
22 #include <libxml/parser.h>
23 #include <sensor_hal.h>
24 #include <sensor_base.h>
25 #include <dlfcn.h>
26 #include <dirent.h>
27 #include <common.h>
28 #include <unordered_set>
29 #include <algorithm>
30
31 using std::make_pair;
32 using std::equal;
33 using std::unordered_set;
34
35 #define ROOT_ELEMENT "PLUGIN"
36 #define TEXT_ELEMENT "text"
37 #define PATH_ATTR "path"
38 #define HAL_ELEMENT "HAL"
39 #define SENSOR_ELEMENT "SENSOR"
40
41 #define PLUGINS_CONFIG_PATH "/usr/etc/sensor_plugins.xml"
42 #define PLUGINS_DIR_PATH "/sensord"
43
44 #define SENSOR_INDEX_SHIFT 16
45
46 sensor_plugin_loader::sensor_plugin_loader()
47 {
48 }
49
50 sensor_plugin_loader& sensor_plugin_loader::get_instance()
51 {
52         static sensor_plugin_loader inst;
53         return inst;
54 }
55
56 bool sensor_plugin_loader::load_module(const string &path, void** module, void** handle)
57 {
58         void *_handle = dlopen(path.c_str(), RTLD_NOW);
59
60         if (!_handle) {
61                 ERR("Failed with dlopen(%s), dlerror : %s", path.c_str(), dlerror());
62                 return false;
63         }
64
65         dlerror();
66
67         typedef void* create_t(void);
68         typedef void destroy_t(void *);
69
70         create_t* init_module = (create_t*) dlsym(_handle, "create");
71
72         if (!init_module) {
73                 ERR("Failed to find \"create\" symbol");
74                 dlclose(_handle);
75                 return false;
76         }
77
78         destroy_t* exit_module = (destroy_t*) dlsym(_handle, "destroy");
79
80         if (!exit_module) {
81                 ERR("Failed to find \"destroy\" symbol");
82                 dlclose(_handle);
83                 return false;
84         }
85
86         void *_module = init_module();
87
88         if (!_module) {
89                 ERR("Failed to init the module, Target file is %s\n", path.c_str());
90                 exit_module(_module);
91                 dlclose(_handle);
92                 return false;
93         }
94
95         *module = _module;
96         *handle = _handle;
97
98         return true;
99 }
100
101 bool sensor_plugin_loader::insert_module(plugin_type type, const string &path)
102 {
103         if (type == PLUGIN_TYPE_HAL) {
104                 DBG("insert sensor plugin [%s]", path.c_str());
105                 sensor_hal *module;
106                 void *handle;
107
108                 if (!load_module(path, (void **)&module, &handle))
109                         return false;
110
111                 sensor_type_t sensor_type = module->get_type();
112                 m_sensor_hals.insert(make_pair(sensor_type, module));
113         } else if (type == PLUGIN_TYPE_SENSOR) {
114                 DBG("insert sensor plugin [%s]", path.c_str());
115                 sensor_base *module;
116                 void *handle;
117
118                 if (!load_module(path, (void**)&module, &handle))
119                         return false;
120
121                 if (!module->init()) {
122                         ERR("Failed to init [%s] module\n", module->get_name());
123                         delete module;
124                         dlclose(handle);
125                         return false;
126                 }
127                 DBG("init [%s] module", module->get_name());
128
129                 sensor_type_t sensor_type = module->get_type();
130
131                 int idx;
132                 idx = m_sensors.count(sensor_type);
133                 module->set_id(idx << SENSOR_INDEX_SHIFT | sensor_type);
134                 m_sensors.insert(make_pair(sensor_type, module));
135         }else {
136                 ERR("Not supported type: %d", type);
137                 return false;
138         }
139
140         return true;
141 }
142
143 bool sensor_plugin_loader::load_plugins(void)
144 {
145         vector<string> hal_paths, sensor_paths;
146         vector<string> unique_hal_paths, unique_sensor_paths;
147
148         get_paths_from_config(string(PLUGINS_CONFIG_PATH), hal_paths, sensor_paths);
149         get_paths_from_dir(string(LIBDIR) + string(PLUGINS_DIR_PATH), hal_paths, sensor_paths);
150
151         //remove duplicates while keeping the original ordering => unique_*_paths
152         unordered_set<string> s;
153         auto unique = [&s](vector<string> &paths, const string &path) {
154                 if (s.insert(path).second)
155                         paths.push_back(path);
156         };
157
158         for_each(hal_paths.begin(), hal_paths.end(),
159                 [&](const string &path) {
160                         unique(unique_hal_paths, path);
161                 }
162         );
163
164         for_each(sensor_paths.begin(), sensor_paths.end(),
165                 [&](const string &path) {
166                         unique(unique_sensor_paths, path);
167                 }
168         );
169
170         //load plugins specified by unique_*_paths
171         auto insert = [&](plugin_type type, const string &path) {
172                         insert_module(type, path);
173         };
174
175         for_each(unique_hal_paths.begin(), unique_hal_paths.end(),
176                 [&](const string &path) {
177                         insert(PLUGIN_TYPE_HAL, path);
178                 }
179         );
180
181         for_each(unique_sensor_paths.begin(), unique_sensor_paths.end(),
182                 [&](const string &path) {
183                         insert(PLUGIN_TYPE_SENSOR, path);
184                 }
185         );
186
187         show_sensor_info();
188         return true;
189 }
190
191 void sensor_plugin_loader::show_sensor_info(void)
192 {
193         INFO("========== Loaded sensor information ==========\n");
194
195         int index = 0;
196
197         auto it = m_sensors.begin();
198
199         while (it != m_sensors.end()) {
200                 sensor_base* sensor = it->second;
201
202                 sensor_info info;
203                 sensor->get_sensor_info(info);
204                 INFO("No:%d [%s]\n", ++index, sensor->get_name());
205                 info.show();
206                 it++;
207         }
208
209         INFO("===============================================\n");
210 }
211
212
213 bool sensor_plugin_loader::get_paths_from_dir(const string &dir_path, vector<string> &hal_paths, vector<string> &sensor_paths)
214 {
215         const string PLUGIN_POSTFIX = ".so";
216         const string HAL_POSTFIX = "_hal.so";
217
218         DIR *dir = NULL;
219         struct dirent *dir_entry = NULL;
220
221         dir = opendir(dir_path.c_str());
222
223         if (!dir) {
224                 ERR("Failed to open dir: %s", dir_path.c_str());
225                 return false;
226         }
227
228         string name;
229
230         while ((dir_entry = readdir(dir))) {
231                 name = string(dir_entry->d_name);
232
233                 if (equal(PLUGIN_POSTFIX.rbegin(), PLUGIN_POSTFIX.rend(), name.rbegin())) {
234                         if (equal(HAL_POSTFIX.rbegin(), HAL_POSTFIX.rend(), name.rbegin()))
235                                 hal_paths.push_back(dir_path + "/" + name);
236                         else
237                                 sensor_paths.push_back(dir_path + "/" + name);
238                 }
239         }
240
241         closedir(dir);
242         return true;
243 }
244
245 bool sensor_plugin_loader::get_paths_from_config(const string &config_path, vector<string> &hal_paths, vector<string> &sensor_paths)
246 {
247         xmlDocPtr doc;
248         xmlNodePtr cur;
249
250         doc = xmlParseFile(config_path.c_str());
251
252         if (doc == NULL) {
253                 ERR("There is no %s\n", config_path.c_str());
254                 return false;
255         }
256
257         cur = xmlDocGetRootElement(doc);
258
259         if (cur == NULL) {
260                 ERR("There is no root element in %s\n", config_path.c_str());
261                 xmlFreeDoc(doc);
262                 return false;
263         }
264
265         if (xmlStrcmp(cur->name, (const xmlChar *)ROOT_ELEMENT)) {
266                 ERR("Wrong type document: there is no [%s] root element in %s\n", ROOT_ELEMENT, config_path.c_str());
267                 xmlFreeDoc(doc);
268                 return false;
269         }
270
271         xmlNodePtr plugin_list_node_ptr;
272         xmlNodePtr module_node_ptr;
273         char* prop = NULL;
274         string path, category;
275
276         plugin_list_node_ptr = cur->xmlChildrenNode;
277
278         while (plugin_list_node_ptr != NULL) {
279                 //skip garbage element, [text]
280                 if (!xmlStrcmp(plugin_list_node_ptr->name, (const xmlChar *)TEXT_ELEMENT)) {
281                         plugin_list_node_ptr = plugin_list_node_ptr->next;
282                         continue;
283                 }
284
285                 DBG("<%s>\n", (const char*)plugin_list_node_ptr->name);
286
287                 module_node_ptr = plugin_list_node_ptr->xmlChildrenNode;
288                 while (module_node_ptr != NULL) {
289                         if (!xmlStrcmp(module_node_ptr->name, (const xmlChar *)TEXT_ELEMENT)) {
290                                 module_node_ptr = module_node_ptr->next;
291                                 continue;
292                         }
293
294                         prop = (char*)xmlGetProp(module_node_ptr, (const xmlChar*)PATH_ATTR);
295                         path = prop;
296                         free(prop);
297
298                         DBG("<%s path=\"%s\">\n", (const char*) module_node_ptr->name, path.c_str());
299
300                         category = (const char*) plugin_list_node_ptr->name;
301
302                         if (category == string(HAL_ELEMENT))
303                                 hal_paths.push_back(path);
304                         else if (category == string(SENSOR_ELEMENT))
305                                 sensor_paths.push_back(path);
306
307                         DBG("\n");
308                         module_node_ptr = module_node_ptr->next;
309                 }
310
311                 DBG("\n");
312                 plugin_list_node_ptr = plugin_list_node_ptr->next;
313         }
314
315         xmlFreeDoc(doc);
316
317         return true;
318
319 }
320
321 sensor_hal* sensor_plugin_loader::get_sensor_hal(sensor_type_t type)
322 {
323         auto it_plugins = m_sensor_hals.find(type);
324
325         if (it_plugins == m_sensor_hals.end())
326                 return NULL;
327
328         return it_plugins->second;
329 }
330
331 vector<sensor_hal *> sensor_plugin_loader::get_sensor_hals(sensor_type_t type)
332 {
333         vector<sensor_hal *> sensor_hal_list;
334         pair<sensor_hal_plugins::iterator, sensor_hal_plugins::iterator> ret;
335         ret = m_sensor_hals.equal_range(type);
336
337         for (auto it = ret.first; it != ret.second; ++it)
338                 sensor_hal_list.push_back(it->second);
339
340         return sensor_hal_list;
341 }
342
343 sensor_base* sensor_plugin_loader::get_sensor(sensor_type_t type)
344 {
345         auto it_plugins = m_sensors.find(type);
346
347         if (it_plugins == m_sensors.end())
348                 return NULL;
349
350         return it_plugins->second;
351 }
352
353 vector<sensor_base *> sensor_plugin_loader::get_sensors(sensor_type_t type)
354 {
355         vector<sensor_base *> sensor_list;
356         pair<sensor_plugins::iterator, sensor_plugins::iterator> ret;
357
358         if (type == ALL_SENSOR)
359                 ret = std::make_pair(m_sensors.begin(), m_sensors.end());
360         else
361                 ret = m_sensors.equal_range(type);
362
363         for (auto it = ret.first; it != ret.second; ++it)
364                 sensor_list.push_back(it->second);
365
366         return sensor_list;
367 }
368
369
370 sensor_base* sensor_plugin_loader::get_sensor(sensor_id_t id)
371 {
372         const int SENSOR_TYPE_MASK = 0x0000FFFF;
373         vector<sensor_base *> sensors;
374
375         sensor_type_t type = (sensor_type_t) (id & SENSOR_TYPE_MASK);
376         unsigned int index = id >> SENSOR_INDEX_SHIFT;
377
378         sensors = get_sensors(type);
379
380         if (sensors.size() <= index)
381                 return NULL;
382
383         return sensors[index];
384 }
385
386
387 vector<sensor_base *> sensor_plugin_loader::get_virtual_sensors(void)
388 {
389         vector<sensor_base *> virtual_list;
390         sensor_base* module;
391
392         for (auto sensor_it = m_sensors.begin(); sensor_it != m_sensors.end(); ++sensor_it) {
393                 module = sensor_it->second;
394
395                 if (module && module->is_virtual() == true) {
396                         virtual_list.push_back(module);
397                 }
398         }
399
400         return virtual_list;
401 }
402
403 bool sensor_plugin_loader::destroy()
404 {
405         sensor_base* sensor;
406
407         for (auto sensor_it = m_sensors.begin(); sensor_it != m_sensors.end(); ++sensor_it) {
408                 sensor = sensor_it->second;
409
410                 //need to dlclose
411                 //unregister_module(module);
412
413                 delete sensor;
414         }
415
416         sensor_hal* sensor_hal;
417
418         for (auto sensor_hal_it = m_sensor_hals.begin(); sensor_hal_it != m_sensor_hals.end(); ++sensor_hal_it) {
419                 sensor_hal = sensor_hal_it->second;
420
421                 // need to dlclose
422                 //unregister_module(module);
423
424                 delete sensor_hal;
425         }
426
427         m_sensors.clear();
428         m_sensor_hals.clear();
429
430         return true;
431 }
432