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