halapi: Add configuration feature
[platform/hal/api/common.git] / src / hal-api-conf.c
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdlib.h>
18
19 #include <gio/gio.h>
20 #include <glib-object.h>
21 #include <json-glib/json-glib.h>
22
23 #include "hal-common.h"
24 #include "hal-common-interface.h"
25
26 #include "hal-api-conf.h"
27
28 #include "common.h"
29
30 static enum hal_abi_version _platform_abi_version = HAL_ABI_VERSION_END;
31
32 static JsonParser *_parser = NULL;
33 static JsonObject *_root_object = NULL;
34
35 static GHashTable *_module_hash = NULL;
36
37 static bool _initialized = false;
38
39 void __attribute__ ((destructor)) _destroy_configuration(void);
40
41 void _destroy_configuration(void)
42 {
43         if (_parser)
44                 g_object_unref(_parser);
45
46         if (_module_hash) {
47                 g_hash_table_remove_all(_module_hash);
48                 g_hash_table_unref(_module_hash);
49         }
50
51         _initialized = false;
52 }
53
54 static const char *__get_group_string_name(enum hal_module module)
55 {
56         if (HAL_MODULE_TBM <= module && module <= HAL_MODULE_INPUT)
57                 return hal_group_string[HAL_GROUP_GRAPHICS];
58
59         if (HAL_MODULE_AUDIO <= module && module <= HAL_MODULE_ALSAUCM)
60                 return hal_group_string[HAL_GROUP_MULTIMEDIA];
61
62         if (HAL_MODULE_BLUETOOTH <= module && module <= HAL_MODULE_MTP)
63                 return hal_group_string[HAL_GROUP_CONNECTIVITY];
64
65         if (HAL_MODULE_TELEPHONY == module)
66                 return hal_group_string[HAL_GROUP_TELEPHONY];
67
68         if (HAL_MODULE_LOCATION == module)
69                 return hal_group_string[HAL_GROUP_LOCATION];
70
71         if (HAL_MODULE_COMMON <= module && module <= HAL_MODULE_DEVICE_HAPTIC)
72                 return hal_group_string[HAL_GROUP_SYSTEM];
73
74         return NULL;
75 }
76
77 static enum hal_group __get_group_enum_name_by_module(enum hal_module module)
78 {
79         if (HAL_MODULE_TBM <= module && module <= HAL_MODULE_INPUT)
80                 return HAL_GROUP_GRAPHICS;
81
82         if (HAL_MODULE_AUDIO <= module && module <= HAL_MODULE_ALSAUCM)
83                 return HAL_GROUP_MULTIMEDIA;
84
85         if (HAL_MODULE_BLUETOOTH <= module && module <= HAL_MODULE_MTP)
86                 return HAL_GROUP_CONNECTIVITY;
87
88         if (HAL_MODULE_TELEPHONY == module)
89                 return HAL_GROUP_TELEPHONY;
90
91         if (HAL_MODULE_LOCATION == module)
92                 return HAL_GROUP_LOCATION;
93
94         if (HAL_MODULE_COMMON <= module && module <= HAL_MODULE_DEVICE_HAPTIC)
95                 return HAL_GROUP_SYSTEM;
96
97         return HAL_GROUP_UNKNOWN;
98 }
99
100 static enum hal_abi_version __convert_abi_version_str_to_enum(const char *abi_version) {
101         int version;
102         for (version = HAL_ABI_VERSION_UNKNOWN + 1; version < HAL_ABI_VERSION_END; version++){
103                 if (g_strcmp0(abi_version, hal_abi_version_str[version]) == 0)
104                         return (enum hal_abi_version)version;
105         }
106
107         return HAL_ABI_VERSION_UNKNOWN;
108 }
109
110 static const char *__convert_module_to_string(enum hal_module module)
111 {
112         return hal_module_string[module];
113 }
114
115 static enum hal_license __convert_license_str_to_enum(const char *license)
116 {
117         if (g_strcmp0(license, "APACHE_2_0") == 0)
118                 return HAL_LICENSE_APACHE_2_0;
119
120         if (g_strcmp0(license, "FLORA") == 0)
121                 return HAL_LICENSE_FLORA;
122
123         if (g_strcmp0(license, "MIT") == 0)
124                 return HAL_LICENSE_MIT;
125
126         return HAL_LICENSE_UNKNOWN;
127 }
128
129 __attribute__ ((visibility("default")))
130 void _destroy_module_info(gpointer data)
131 {
132 #define SAFE_FREE_AND_NULL(x) \
133 do { \
134         if (x) { \
135                 free(x); \
136                 x = NULL; \
137         } \
138 } while (0);
139
140         struct __hal_module_info *info = (struct __hal_module_info *)data;
141         gboolean is_contained = false;
142
143         if (info) {
144                 is_contained = g_hash_table_contains(_module_hash, GINT_TO_POINTER(info->module));
145                 if (is_contained)
146                         g_hash_table_steal(_module_hash, GINT_TO_POINTER(info->module));
147
148                 SAFE_FREE_AND_NULL(info->module_name);
149                 SAFE_FREE_AND_NULL(info->library_name);
150                 SAFE_FREE_AND_NULL(info->library_name_64bit);
151                 SAFE_FREE_AND_NULL(info->symbol_name);
152                 SAFE_FREE_AND_NULL(info->abi_versions);
153                 SAFE_FREE_AND_NULL(info);
154         }
155 }
156
157 static bool __init_configuration(void)
158 {
159         JsonNode *root_node = NULL;
160         GError *error = NULL;
161         gboolean result;
162
163         if (_initialized)
164                 return _initialized;
165
166         _parser = json_parser_new();
167         result = json_parser_load_from_file(_parser, HAL_CONFIGURATION_PATH, &error);
168         if (result == FALSE) {
169                 _E("Failed to parsing json configuration file : %s\n", error->message);
170                 goto err;
171         }
172
173         root_node = json_parser_get_root(_parser);
174         if (JSON_NODE_HOLDS_OBJECT(root_node) == FALSE) {
175                 _E("There is no object in root node\n");
176                 goto err;
177         }
178
179         _root_object = json_node_get_object(root_node);
180         _module_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, _destroy_module_info);
181
182         _initialized = true;
183
184         return _initialized;
185
186 err:
187         if (error)
188                 g_error_free(error);
189         _destroy_configuration();
190
191         return _initialized;
192 }
193
194 static struct __hal_module_info *__create_hal_module_info(enum hal_module module, JsonObject *object)
195 {
196         struct __hal_module_info *info;
197         JsonArray *abi_versions_array = NULL;
198         GList *abi_list = NULL;
199         GList *iter_list = NULL;
200         int list_index = 0;
201         const char *tmp;
202
203         info = (struct __hal_module_info *)calloc(1, sizeof(struct __hal_module_info));
204         if (info == NULL) {
205                 _E("Out of Memory\n");
206                 return NULL;
207         }
208
209         info->module = module;
210         info->module_name = g_strdup(__convert_module_to_string(module));
211         info->group = __get_group_enum_name_by_module(module);
212
213         tmp = json_object_get_string_member(object, "license");
214         info->license = __convert_license_str_to_enum(tmp);
215
216         info->library_name = g_strdup(json_object_get_string_member(object, "library_name"));
217         info->library_name_64bit = g_strdup(json_object_get_string_member(object, "library_name_64bit"));
218         info->symbol_name = g_strdup(json_object_get_string_member(object, "symbol_name"));
219
220         if (info->library_name && info->library_name_64bit && info->symbol_name)
221                 info->hal_api = true;
222
223         abi_versions_array = json_object_get_array_member(object, "abi_versions");
224         if (abi_versions_array == NULL)
225                 return info;
226
227         abi_list = json_array_get_elements(abi_versions_array);
228         info->num_abi_versions = g_list_length(abi_list);
229         if (info->num_abi_versions > 0) {
230                 info->abi_versions = (struct hal_abi_version_match*)calloc(info->num_abi_versions,
231                                 sizeof(struct hal_abi_version_match));
232                 if (info->abi_versions == NULL) {
233                         _E("Out of Memory\n");
234                         _destroy_module_info(info);
235                         g_list_free(abi_list);
236                         return NULL;
237                 }
238
239                 for (iter_list = abi_list; iter_list != NULL; iter_list = iter_list->next) {
240                         JsonObject *tmp_object = json_node_get_object(iter_list->data);
241
242                         tmp = json_object_get_string_member(tmp_object, "platform_abi_version");
243                         info->abi_versions[list_index].platform_abi_version =
244                                 __convert_abi_version_str_to_enum(tmp);
245
246                         tmp = json_object_get_string_member(tmp_object, "backend_min_abi_version");
247                         info->abi_versions[list_index].backend_min_abi_version =
248                                 __convert_abi_version_str_to_enum(tmp);
249                         list_index++;
250                 }
251         }
252
253         if (abi_list)
254                 g_list_free(abi_list);
255
256         return info;
257 }
258
259 __attribute__ ((visibility("default")))
260 struct __hal_module_info* _hal_api_conf_get_module_info(enum hal_module module)
261 {
262         struct __hal_module_info *info = NULL;
263         JsonObject *module_object = NULL;
264         JsonArray *module_array = NULL;
265         GList *module_list = NULL;
266         GList *iter_list;
267         const char *group_name = NULL;
268         const char *module_name = NULL;
269         bool ret_initialized;
270
271         ret_initialized = __init_configuration();
272         if (ret_initialized == false) {
273                 _E("Failed to parse json information\n");
274                 goto ret;
275         }
276
277         info = (struct __hal_module_info*)g_hash_table_lookup(_module_hash, GINT_TO_POINTER(module));
278         if (info != NULL)
279                 return info;
280
281         group_name = __get_group_string_name(module);
282         if (group_name == NULL) {
283                 _E("There is wrong module\n");
284                 goto ret;
285         }
286
287         module_object = json_object_get_object_member(_root_object, "MODULE_INFO");
288         module_array = json_object_get_array_member(module_object, group_name);
289         module_list = json_array_get_elements(module_array);
290         module_name = __convert_module_to_string(module);
291
292         for (iter_list = module_list; iter_list != NULL; iter_list = iter_list->next) {
293                 JsonObject *tmp_object = json_node_get_object(iter_list->data);
294                 const char *value = json_object_get_string_member(tmp_object, "module");
295                 if (g_strcmp0(value, module_name) == 0) {
296                         info = __create_hal_module_info(module, tmp_object);
297                         if (info == NULL)
298                                 _E("Failed to create hal module info\n");
299                         else
300                                 g_hash_table_insert(_module_hash, GINT_TO_POINTER(module), info);
301                         break;
302                 }
303         }
304
305 ret:
306         if (module_list)
307                 g_list_free(module_list);
308
309         return info;
310 }
311
312 enum hal_abi_version _hal_api_conf_get_platform_abi_version(void)
313 {
314         const char *abi_version = NULL;
315         bool ret_initialized;
316
317         if (_platform_abi_version != HAL_ABI_VERSION_END)
318                 return _platform_abi_version;
319
320         ret_initialized = __init_configuration();
321         if (ret_initialized == false) {
322                 _E("Failed to parser json file\n");
323                 return HAL_ABI_VERSION_UNKNOWN;
324         }
325
326         abi_version = json_object_get_string_member(_root_object, "PLATFORM_ABI_VERSION");
327         _platform_abi_version = __convert_abi_version_str_to_enum(abi_version);
328
329         return _platform_abi_version;
330 }