Fix ps-plugin not initialized issue
[platform/core/telephony/tel-plugin-packetservice.git] / src / ps_master.c
1 /*
2  * tel-plugin-packetservice
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: DongHoo Park <donghoo.park@samsung.com>
7  *          Arun Shukla <arun.shukla@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */
22
23 #include <unistd.h>
24
25 #include "ps_common.h"
26 #include "ps_context.h"
27 #include "ps_master.h"
28 #include "ps_modem.h"
29 #include "ps_service.h"
30 #include "ps_master_interface.h"
31
32 #include <server.h>
33 #include <plugin.h>
34 #include <storage.h>
35 #include <co_context.h>
36
37 #include "ps_log.h"
38
39 /* [Wearable][sap-stack] SAPInterface.h */
40 #define SAP_CONN_TYPE_ALL       0x00
41 #define SAP_CONN_TYPE_BT        0x01
42 #define SAP_CONN_TYPE_MOBILE    0x10 /* scs */
43
44 #define _PS_CHECK_STRG(master) { \
45                 if (G_UNLIKELY(!master->strg)) { \
46                         warn("Updating strg"); \
47                         master->strg = tcore_server_find_storage(tcore_plugin_ref_server(master->plg), "vconf"); \
48                 } \
49 } \
50
51 static void __ps_master_storage_key_callback(enum tcore_storage_key key, void *value, void *user_data);
52
53 static void __ps_master_handle_ups_mode(ps_modem_t *modem, gchar *request)
54 {
55         GSList *contexts = NULL;
56         unsigned int index;
57
58         if (G_UNLIKELY(!modem))
59                 return;
60
61         info("send dbus %s requeset", request);
62         contexts = modem->contexts;
63         if (!contexts) {
64                 err("no profiles");
65                 return;
66         }
67
68         for (index = 0; index < g_slist_length(contexts); index++) {
69                 ps_context_t *context = g_slist_nth_data(contexts, index);
70                 CoreObject *co_context = _ps_context_ref_co_context(context);
71                 int role = tcore_context_get_role(co_context);
72
73                 dbg("context(%p), path(%s), role(%d)", context, _ps_context_ref_path(context), role);
74
75                 if (role == CONTEXT_ROLE_INTERNET && context->is_default) {
76                         if (!g_strcmp0(request, "IfaceDown"))
77                                 _ps_context_handle_ifacedown(context);
78                         else if (!g_strcmp0(request, "IfaceUp"))
79                                 _ps_context_handle_ifaceup(context);
80                 } else if (role == CONTEXT_ROLE_UNKNOWN || role == CONTEXT_ROLE_USER_DEFINED) {
81                         warn("Not supported profile type: %d", role);
82                         continue;
83                 } else {
84                         if (CONTEXT_STATE_ACTIVATED != tcore_context_get_state(co_context))
85                                 continue;
86
87                         if (!g_strcmp0(request, "InterfaceDown")) {
88                                 warn("disconnect context request.");
89                                 _ps_service_deactivate_context(_ps_context_ref_service(context), context);
90                         }
91                 }
92         }
93 }
94
95 static void __ps_master_register_key_callback(ps_master_t *master, enum tcore_storage_key key)
96 {
97         _PS_CHECK_STRG(master);
98         tcore_storage_set_key_callback(master->strg, key, __ps_master_storage_key_callback, master);
99 }
100
101 static void __ps_master_deregister_key_callback(ps_master_t *master, enum tcore_storage_key key)
102 {
103         _PS_CHECK_STRG(master);
104         tcore_storage_remove_key_callback(master->strg, key, __ps_master_storage_key_callback);
105 }
106
107 void __remove_master(gpointer data, gpointer user_data)
108 {
109         ps_master_t *master = data;
110         Server *s;
111
112         info("master:[%p]", master);
113
114         /*Deinit alarm*/
115         alarmmgr_fini();
116
117         /*Registering the key callbacks for values in storage settings */
118         __ps_master_deregister_key_callback(master, KEY_TELEPHONY_READY);
119         __ps_master_deregister_key_callback(master, KEY_3G_ENABLE);
120         __ps_master_deregister_key_callback(master, KEY_DATA_ROAMING_SETTING);
121 #if defined(TIZEN_UPS_ENABLED)
122         __ps_master_deregister_key_callback(master, KEY_POWER_SAVING_MODE);
123         __ps_master_deregister_key_callback(master, KEY_PM_STATE);
124 #endif
125
126         s = tcore_plugin_ref_server(master->plg);
127
128         tcore_server_remove_notification_hook(s, __on_hook_modem_added);
129         tcore_server_remove_notification_hook(s, __on_hook_modem_removed);
130
131         /*Need to remove the compelete hash table*/
132         g_hash_table_remove_all(master->modems);
133
134         /*Need to UNexport and Unref the master Object */
135         g_dbus_interface_skeleton_unexport(G_DBUS_INTERFACE_SKELETON(master->if_obj));
136
137         g_object_unref(master->if_obj);
138
139         /*Need to free the memory allocated for the members of the master*/
140         g_free(master);
141         master = NULL;
142
143         dbg("Exiting");
144 }
145
146 static void __ps_master_storage_key_callback(enum tcore_storage_key key, void *value, void *user_data)
147 {
148         GVariant *tmp = NULL;
149         GHashTableIter iter;
150         gpointer h_key, h_value;
151         gboolean type_check = FALSE;
152         ps_master_t *master = (ps_master_t *)user_data;
153
154         g_return_if_fail(master != NULL);
155
156         tmp = (GVariant *)value;
157         if (G_UNLIKELY(!tmp)) {
158                 err("value is null");
159                 return;
160         }
161
162         switch (key) {
163         case KEY_3G_ENABLE:
164         case KEY_DATA_ROAMING_SETTING:
165         case KEY_NETWORK_RESTRICT_MODE:
166         case KEY_TELEPHONY_READY:
167                 type_check = g_variant_is_of_type(tmp, G_VARIANT_TYPE_BOOLEAN);
168                 if (!type_check) {
169                         err("wrong variant data type");
170                         g_variant_unref(tmp);
171                         return;
172                 }
173                 break;
174
175         case KEY_POWER_SAVING_MODE:
176         case KEY_PM_STATE:
177                 type_check = g_variant_is_of_type(tmp, G_VARIANT_TYPE_INT32);
178                 if (!type_check) {
179                         err("wrong variant data type");
180                         g_variant_unref(tmp);
181                         return;
182                 }
183                 break;
184
185         default:
186                 warn("unknown key (0x%x)", key);
187                 return;
188         }
189
190         g_hash_table_iter_init(&iter, master->modems);
191         while (g_hash_table_iter_next(&iter, &h_key, &h_value) == TRUE) {
192                 if (key == KEY_3G_ENABLE) {
193                         gboolean data_allowed = g_variant_get_boolean(tmp);
194                         msg("[PSINFO] data_allowed [%d] changed", data_allowed);
195                         _ps_modem_set_data_allowed(h_value, data_allowed);
196                 } else if (key == KEY_DATA_ROAMING_SETTING) {
197                         gboolean roaming_allowed = g_variant_get_boolean(tmp);
198                         msg("[PSINFO] roaming_allowed [%d] changed.", roaming_allowed);
199                         _ps_modem_set_data_roaming_allowed(h_value, roaming_allowed);
200                 } else if (key == KEY_POWER_SAVING_MODE) {
201                         gint new_ps_mode = g_variant_get_int32(tmp);
202                         gint curr_ps_mode = _ps_modem_get_psmode(h_value);
203
204                         if (curr_ps_mode & POWER_SAVING_MODE_DATA_ALLOWED)
205                                 new_ps_mode |= POWER_SAVING_MODE_DATA_ALLOWED;
206
207                         info("[PSINFO] curr_ps_mode [0X%x] new_ps_mode[0X%x]", curr_ps_mode, new_ps_mode);
208                         _ps_modem_set_psmode(h_value, new_ps_mode);
209                 } else if (key == KEY_PM_STATE) {
210                         gint pm_state = g_variant_get_int32(tmp);
211                         gint ps_mode = _ps_modem_get_psmode(h_value);
212
213                         if (ps_mode != POWER_SAVING_MODE_NORMAL)
214                                 dbg("current power saving mode: %d, pm_state: %d", ps_mode, pm_state);
215
216                         if (ps_mode & POWER_SAVING_MODE_DATA_ALLOWED) {
217                                 warn("UPS by FMM: Do not change data network state.");
218                                 return;
219                         }
220                         if (pm_state == 3) { /* LCD Off */
221                                 if (ps_mode > POWER_SAVING_MODE_NORMAL && ps_mode < POWER_SAVING_MODE_WEARABLE) {
222                                         msg("[PSINFO] LCD OFF. Start Deactivate with power saving [%d]", ps_mode);
223                                         /* send dbus request pdp context deactivation. */
224                                         __ps_master_handle_ups_mode(h_value, "IfaceDown");
225                                 } else {
226                                         _ps_modem_set_pm_state(h_value, pm_state);
227                                 }
228                         } else { /* LCD On or dimming */
229                                 if (ps_mode > POWER_SAVING_MODE_NORMAL && ps_mode < POWER_SAVING_MODE_WEARABLE) {
230                                         msg("[PSINFO] pm_state(%d) changed. Start activate with power saving [%d]", pm_state, ps_mode);
231                                         /* send dbus request pdp context activation. */
232                                         __ps_master_handle_ups_mode(h_value, "IfaceUp");
233                                 } else {
234                                         _ps_modem_set_pm_state(h_value, pm_state);
235                                 }
236                         }
237                 } else if (key == KEY_NETWORK_RESTRICT_MODE) {
238                         gboolean b_network_restrict = g_variant_get_boolean(tmp);
239                         if (b_network_restrict) {
240                                 msg("[PSINFO] network restricted mode on");
241                                 _ps_modem_set_data_allowed(h_value, FALSE);
242                         } else {
243                                 gboolean key_3g_enable = FALSE;
244                                 msg("[PSINFO] network restricted mode off");
245                                 key_3g_enable = _ps_master_get_storage_value_bool(master, KEY_3G_ENABLE);
246                                 _ps_modem_set_data_allowed(h_value, key_3g_enable);
247                         }
248 #ifdef STORAGE_KEY_WECONN_ALL_CONNECTED
249                 } else if (key == KEY_WECONN_ALL_CONNECTED) {
250                         int b_wms_connected = g_variant_get_int32(tmp);
251                         if (b_wms_connected) {
252                                 int sap_conn_type = SAP_CONN_TYPE_ALL;
253                                 sap_conn_type = _ps_master_get_storage_value_int(master, KEY_SAP_CONNECTION_TYPE);
254                                 if (sap_conn_type == SAP_CONN_TYPE_BT) {
255                                         msg("[PSINFO][Wearable] Companinon mode. set data allowed FALSE");
256                                         _ps_modem_set_data_allowed(h_value, FALSE);
257                                 }
258                         } else {
259                                 gboolean key_3g_enable = FALSE;
260                                 key_3g_enable = _ps_master_get_storage_value_bool(master, KEY_3G_ENABLE);
261                                 msg("[PSINFO][Wearable] Standalone mode. set data allowed (%d)", key_3g_enable);
262                                 _ps_modem_set_data_allowed(h_value, key_3g_enable);
263                         }
264 #endif
265                 } else if (key == KEY_TELEPHONY_READY) {
266                         gboolean b_telephony_ready = _ps_master_get_storage_value_bool(master, KEY_TELEPHONY_READY);
267                         if (b_telephony_ready)
268                                 ps_master_emit_modem_added_signal(master, h_value);
269                 }
270         }
271
272 }
273
274 static gboolean __ps_master_create_modem(ps_master_t *master, TcorePlugin *modem_plg)
275 {
276         ps_modem_t *modem = NULL, *tmp = NULL;
277         gchar *modem_name = NULL;
278         gchar *cp_name = NULL;
279         CoreObject *co_modem = NULL;
280         gboolean key_telephony_ready;
281
282         g_return_val_if_fail(master != NULL, FALSE);
283
284         cp_name = (gchar *)tcore_server_get_cp_name_by_plugin(modem_plg);
285         modem_name = g_strdup_printf("/%s", cp_name);
286         tmp = g_hash_table_lookup(master->modems, modem_name);
287         if (tmp != NULL) {
288                 dbg("modem (%p) already existed", tmp);
289                 g_free(modem_name);
290                 return FALSE;
291         }
292
293         dbg("create modem(%s) objects", modem_name);
294         co_modem = tcore_plugin_ref_core_object(modem_plg, CORE_OBJECT_TYPE_MODEM);
295         modem = _ps_modem_create_modem(master->conn, master->plg, master, modem_name, co_modem, cp_name);
296         if (!modem) {
297                 err("fail to create modem");
298                 g_free(modem_name);
299                 return FALSE;
300         }
301
302         g_hash_table_insert(master->modems, g_strdup(modem_name), modem);
303         info("modem (%p) created at path %s", modem, modem_name);
304         key_telephony_ready = _ps_master_get_storage_value_bool(master, KEY_TELEPHONY_READY);
305         if (key_telephony_ready)
306                 ps_master_emit_modem_added_signal(master, modem);
307         else
308                 warn("Wait for telephony ready");
309
310         g_free(modem_name);
311         return TRUE;
312 }
313
314 ps_master_t *_ps_master_create_master(GDBusConnection *conn, TcorePlugin *p)
315 {
316         ps_master_t *new_master = NULL;
317
318         dbg("master object create");
319         g_return_val_if_fail(conn != NULL, NULL);
320
321         /*Initializing the master list for internal referencing*/
322         new_master = g_try_malloc0(sizeof(ps_master_t));
323         if (G_UNLIKELY(!new_master)) {
324                 err("Unable to allocate memory for master");
325                 return NULL;
326         }
327
328         new_master->conn = conn;
329         new_master->plg = p;
330         new_master->modems = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, __remove_modem_handler);
331         new_master->strg = tcore_server_find_storage(tcore_plugin_ref_server(p), "vconf");
332
333         /*Setting Up the call backs for the interface*/
334         if (!ps_master_setup_interface(new_master)) {
335                 g_free(new_master);
336                 return NULL;
337         }
338
339
340         /*Registering the key callbacks for values in storage settings */
341         __ps_master_register_key_callback(new_master, KEY_TELEPHONY_READY);
342         __ps_master_register_key_callback(new_master, KEY_3G_ENABLE);
343         __ps_master_register_key_callback(new_master, KEY_DATA_ROAMING_SETTING);
344 #if defined(TIZEN_UPS_ENABLED)
345         __ps_master_register_key_callback(new_master, KEY_POWER_SAVING_MODE);
346         __ps_master_register_key_callback(new_master, KEY_PM_STATE);
347 #endif
348         /* __ps_master_register_key_callback(new_master, KEY_PM_STATE); */
349
350         /*Alarm manager init*/
351         dbg("init alarm manager.");
352         if (alarmmgr_init("packetservice") != ALARMMGR_RESULT_SUCCESS) {
353                 err("Failed to init alarm manager");
354                 g_free(new_master);
355                 return NULL;
356         }
357         /*Adding Hook for modem addition laters*/
358         tcore_server_add_notification_hook(tcore_plugin_ref_server(p),
359                                            TNOTI_SERVER_ADDED_MODEM_PLUGIN, __on_hook_modem_added, new_master);
360
361         /*Adding Hook for modem removal laters*/
362         tcore_server_add_notification_hook(tcore_plugin_ref_server(p),
363                                            TNOTI_SERVER_REMOVED_MODEM_PLUGIN, __on_hook_modem_removed, new_master);
364
365         info("Successfully created the master");
366         return new_master;
367 }
368
369 gboolean _ps_master_create_modems(ps_master_t *master, TcorePlugin *modem_plg)
370 {
371         g_return_val_if_fail(master != NULL, FALSE);
372
373         if (!modem_plg) {
374                 GSList *modem_list, *iter;
375                 Server *s = tcore_plugin_ref_server(master->plg);
376                 gboolean ret = TRUE;
377                 modem_list = tcore_server_get_modem_plugin_list(s);
378                 for (iter = modem_list; iter != NULL; iter = iter->next) {
379                         TcorePlugin *modem_p = iter->data;
380                         ret = __ps_master_create_modem(master, modem_p);
381                 }
382                 g_slist_free(modem_list);
383                 return ret;
384         } else
385                 return __ps_master_create_modem(master, modem_plg);
386 }
387
388 gboolean _ps_master_destroy_modem(ps_master_t *master, TcorePlugin *plugin)
389 {
390         gchar *modem_name;
391         ps_modem_t *modem;
392
393         dbg("destroy modem object");
394         modem_name = g_strdup_printf("/%s", tcore_server_get_cp_name_by_plugin(plugin));
395         modem = g_hash_table_lookup(master->modems, modem_name);
396         if (modem == NULL) {
397                 warn("modem '%s' doesn't exists", modem_name);
398                 g_free(modem_name);
399                 return FALSE;
400         }
401
402         /*  Destroy Modem */
403         info("Destroying modem object for '%s' modem[%p]", modem_name, modem);
404         _ps_modem_destroy_modem(master->conn, modem);
405
406         if (g_hash_table_remove(master->modems, modem_name) == TRUE)
407                 info("Removed modem '%s'", modem_name);
408
409         g_free(modem_name);
410
411         return TRUE;
412 }
413
414 gboolean _ps_master_get_storage_value_bool(ps_master_t *master, enum tcore_storage_key key)
415 {
416         g_return_val_if_fail(master != NULL, FALSE);
417         _PS_CHECK_STRG(master);
418         return tcore_storage_get_bool(master->strg, key);
419 }
420
421 gint _ps_master_get_storage_value_int(ps_master_t *master, enum tcore_storage_key key)
422 {
423         g_return_val_if_fail(master != NULL, FALSE);
424         _PS_CHECK_STRG(master);
425         return tcore_storage_get_int(master->strg, key);
426 }
427
428 char *_ps_master_get_storage_value_string(ps_master_t *master, enum tcore_storage_key key)
429 {
430         g_return_val_if_fail(master != NULL, FALSE);
431         _PS_CHECK_STRG(master);
432         return tcore_storage_get_string(master->strg, key);
433 }
434
435 gboolean _ps_master_set_storage_value_bool(ps_master_t *master, enum tcore_storage_key key, gboolean value)
436 {
437         g_return_val_if_fail(master != NULL, FALSE);
438         _PS_CHECK_STRG(master);
439         return tcore_storage_set_bool(master->strg, key, value);
440 }
441
442 gboolean _ps_master_set_storage_value_int(ps_master_t *master, enum tcore_storage_key key, gint value)
443 {
444         g_return_val_if_fail(master != NULL, FALSE);
445         _PS_CHECK_STRG(master);
446         return tcore_storage_set_int(master->strg, key, value);
447 }
448
449 gboolean _ps_master_set_storage_value_string(ps_master_t *master, enum tcore_storage_key key, char *value)
450 {
451         g_return_val_if_fail(master != NULL, FALSE);
452         _PS_CHECK_STRG(master);
453         return tcore_storage_set_string(master->strg, key, value);
454 }
455
456 gboolean _ps_master_set_always_on_control(ps_master_t *master, gboolean enable)
457 {
458         GHashTableIter iter;
459         gpointer key, value;
460
461         g_return_val_if_fail(master != NULL, FALSE);
462         g_return_val_if_fail(master->modems != NULL, FALSE);
463
464         g_hash_table_iter_init(&iter, master->modems);
465         while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
466                 unsigned int i;
467                 ps_modem_t *modem = value;
468
469                 if (!modem || !modem->contexts)
470                         continue;
471
472                 for (i = 0; i < g_slist_length(modem->contexts); i++) {
473                         ps_context_t *context = (ps_context_t *)g_slist_nth_data(modem->contexts, i);
474                         gchar *path = _ps_context_ref_path(context);
475                         if (path) {
476                                 dbg("context(%s)", path);
477                                 _ps_context_set_alwayson_enable(context, enable);
478                         }
479                 }
480         }
481         return TRUE;
482 }
483