4 * Copyright (c) 2014 Samsung Electronics Co. Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
27 #include <dd-display.h>
36 #include <co_context.h>
38 #include <co_network.h>
42 #include "s_indi_main.h"
43 #include "s_indi_util.h"
44 #include "s_indi_log.h"
46 #define S_INDI_UPDATE_INTERVAL 1
47 #define S_INDI_NO_RX_PKT_TIMEOUT 60
48 #define S_INDI_PROC_FILE "/proc/net/dev"
50 #define S_INDI_DB_STORAGE_NAME "database"
51 #define S_INDI_DB_STORAGE_PATH "/opt/dbspace/.dnet.db"
52 #define S_INDI_VCONF_STORAGE_NAME "vconf"
54 #define S_INDI_ALLOC_USER_DATA(data, plugin, cp) \
56 data = s_indi_malloc0(sizeof(__s_indi_cb_user_data)); \
57 data->indi_plugin = plugin; \
61 #define S_INDI_FREE_USER_DATA(data) \
63 s_indi_free(data->cp_name); \
68 TcorePlugin *indi_plugin;
70 } __s_indi_cb_user_data;
73 struct global_data msg_id;
76 GHashTable *state_info; /* HashTable of s_indi_cp_state_info_type with key = cp_name */
78 GHashTable *vconf_info; /* Mapping of enum tcore_storage_key to cp_name */
79 } s_indi_private_info;
81 /***************** HOOKS *****************/
82 static enum tcore_hook_return s_indi_on_hook_modem_plugin_removed(Server *server, CoreObject *source,
83 enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data);
84 static enum tcore_hook_return s_indi_on_hook_modem_plugin_added(Server *server, CoreObject *source,
85 enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data);
86 static enum tcore_hook_return s_indi_on_hook_voice_call_status(Server *server, CoreObject *source,
87 enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data);
88 static enum tcore_hook_return s_indi_on_hook_sim_init(Server *server, CoreObject *source,
89 enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data);
90 static enum tcore_hook_return s_indi_on_hook_net_register(Server *server, CoreObject *source,
91 enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data);
92 static enum tcore_hook_return s_indi_on_hook_ps_call_status(Server *server, CoreObject *source,
93 enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data);
94 static enum tcore_hook_return s_indi_on_hook_modem_power(Server *server, CoreObject *source,
95 enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data);
97 /***************** VCONF Callbacks *****************/
98 static void s_indi_storage_key_callback(enum tcore_storage_key key, void *value, void *user_data);
100 /***************** Utilities: GDestroyNotifications *****************/
101 static void __s_indi_state_info_value_destroy_notification(gpointer data);
102 static void __s_indi_dev_info_value_destroy_notification(gpointer data);
104 /***************** Utilities: Indicator Plugin *****************/
105 static inline s_indi_private_info *__s_indi_get_priv_info(TcorePlugin *plugin);
106 static gboolean __s_indi_start_updater(TcorePlugin *indi_plugin, gchar *cp_name);
107 static gboolean __s_indi_update_callback(__s_indi_cb_user_data *data);
108 static void __s_indi_set_dormancy_value(Server *server, s_indi_dormancy_info_type *dormancy_info, enum tcore_storage_key key_fd);
109 static void __s_indi_refresh_modems(TcorePlugin *indi_plugin);
110 static s_indi_cp_state_info_type *__s_indi_alloc_state_info(CoreObject *co_ps);
111 static s_indi_dev_state_info_type *__s_indi_alloc_device_state(CoreObject *ps_context, s_indi_cp_state_info_type *parent);
112 static CoreObject *__s_indi_fetch_ps_co(TcorePlugin *plugin);
114 static void __s_indi_add_modem_plugin(TcorePlugin *indi_plugin, TcorePlugin *modem_plugin);
115 static void __s_indi_remove_modem_plugin(TcorePlugin *indi_plugin, TcorePlugin *modem_plugin);
116 static void __s_indi_register_vconf_key(enum tcore_storage_key key, TcorePlugin *indi_plugin, const char *cp_name);
117 static void __s_indi_unregister_vconf_key(enum tcore_storage_key key, TcorePlugin *indi_plugin, const char *cp_name);
118 static void __s_indi_process_fast_dormancy(s_indi_cp_state_info_type *state_info, GVariant *value);
119 static gboolean __s_indi_cancel_pm_lock(gboolean b_pm_lock);
120 static gboolean __s_indi_handle_voice_call_status(Server *server, CoreObject *source,
121 enum tcore_notification_command command, const char *cp_name,
122 s_indi_cp_state_info_type *state_info);
124 static void __s_indi_deactivate_ps_context (gpointer key, gpointer value, gpointer user_data);
125 static gboolean __s_indi_check_fast_dormancy(TcorePlugin *indi_plugin, CoreObject *co_ps, s_indi_dormancy_info_type *dormancy_info, gboolean b_pm_lock);
127 void __s_indi_process_fast_dormancy(s_indi_cp_state_info_type *state_info, GVariant *value)
129 gboolean fd_set = FALSE;
130 int on_timeout = S_INDI_ZERO;
131 int off_timeout = S_INDI_ZERO;
133 if (!g_variant_is_of_type(value, G_VARIANT_TYPE_INT32)) {
134 err("wrong variant data type");
138 state_info->dormant_info.b_vconf_checker = TRUE;
140 fd_set = g_variant_get_int32(value);
141 dbg("fast dormancy set (%s)", fd_set ? "TRUE" : "FALSE");
144 on_timeout = S_INDI_FIVE;
145 off_timeout = S_INDI_FIVE;
147 on_timeout = S_INDI_MINUS_ONE;
148 off_timeout = S_INDI_MINUS_ONE;
150 state_info->dormant_info.lcd_on_timeout = on_timeout;
151 state_info->dormant_info.lcd_off_timeout = off_timeout;
152 state_info->dormant_info.is_dormant_set = fd_set;
155 void __s_indi_register_vconf_key(enum tcore_storage_key key, TcorePlugin *indi_plugin, const char *cp_name)
157 s_indi_private_info *priv_info = __s_indi_get_priv_info(indi_plugin);
158 Storage *strg_vconf = tcore_server_find_storage(tcore_plugin_ref_server(indi_plugin), S_INDI_VCONF_STORAGE_NAME);
159 s_indi_assert(NULL != strg_vconf);
161 /** NULL cp_name: subscription independent vconf key */
162 if (tcore_storage_set_key_callback(strg_vconf, key, s_indi_storage_key_callback, indi_plugin)
163 && (NULL != cp_name))
164 g_hash_table_insert(priv_info->vconf_info, GUINT_TO_POINTER(key), s_indi_strdup(cp_name));
167 void __s_indi_unregister_vconf_key(enum tcore_storage_key key, TcorePlugin *indi_plugin, const char *cp_name)
169 s_indi_private_info *priv_info = __s_indi_get_priv_info(indi_plugin);
170 Storage *strg_vconf = tcore_server_find_storage(tcore_plugin_ref_server(indi_plugin), S_INDI_VCONF_STORAGE_NAME);
171 s_indi_assert(NULL != strg_vconf);
173 /** NULL cp_name: subscription independent vconf key */
174 if (tcore_storage_remove_key_callback(strg_vconf, key, s_indi_storage_key_callback)
175 && (NULL != cp_name))
176 g_hash_table_remove(priv_info->vconf_info, GUINT_TO_POINTER(key));
179 void __s_indi_add_modem_plugin(TcorePlugin *indi_plugin, TcorePlugin *modem_plugin)
181 gchar *cp_name = NULL;
182 enum tcore_storage_key vconf_key;
183 s_indi_private_info *priv_info = __s_indi_get_priv_info(indi_plugin);
185 /** @todo: It may be possible to use cp_name without duping as well */
186 cp_name = s_indi_strdup(tcore_server_get_cp_name_by_plugin(modem_plugin));
187 s_indi_assert(NULL != cp_name);
188 s_indi_log_ex(cp_name, "Added");
190 /** @todo: Check if key-value replacement is the intended behavior */
191 g_hash_table_insert(priv_info->state_info, cp_name, __s_indi_alloc_state_info(__s_indi_fetch_ps_co(modem_plugin)));
193 if (s_indi_str_has_suffix(cp_name, "0")) {
194 vconf_key = STORAGE_KEY_TESTMODE_FAST_DORMANCY;
195 } else if (s_indi_str_has_suffix(cp_name, "1")) {
196 vconf_key = STORAGE_KEY_TESTMODE_FAST_DORMANCY2;
198 s_indi_assert_not_reached();
201 __s_indi_register_vconf_key(vconf_key, indi_plugin, cp_name);
204 void __s_indi_remove_modem_plugin(TcorePlugin *indi_plugin, TcorePlugin *modem_plugin)
206 const char *cp_name = NULL;
207 enum tcore_storage_key vconf_key;
208 s_indi_private_info *priv_info = __s_indi_get_priv_info(indi_plugin);
210 cp_name = tcore_server_get_cp_name_by_plugin(modem_plugin);
211 s_indi_assert(NULL != cp_name);
212 s_indi_assert(NULL != priv_info->state_info);
214 if (g_hash_table_remove(priv_info->state_info, cp_name))
215 s_indi_log_ex(cp_name, "Removed");
217 if (s_indi_str_has_suffix(cp_name, "0")) {
218 vconf_key = STORAGE_KEY_TESTMODE_FAST_DORMANCY;
219 } else if (s_indi_str_has_suffix(cp_name, "1")) {
220 vconf_key = STORAGE_KEY_TESTMODE_FAST_DORMANCY2;
222 s_indi_assert_not_reached();
225 __s_indi_unregister_vconf_key(vconf_key, indi_plugin, cp_name);
228 CoreObject *__s_indi_fetch_ps_co(TcorePlugin *plugin)
230 CoreObject *co_ps = NULL;
231 GSList *co_list = tcore_plugin_get_core_objects_bytype(plugin, CORE_OBJECT_TYPE_PS);
232 s_indi_assert(co_list != NULL);
233 s_indi_assert(g_slist_length(co_list) == S_INDI_ONE);
235 co_ps = g_slist_nth_data(co_list, S_INDI_ZERO);
236 s_indi_assert(co_ps != NULL);
237 g_slist_free(co_list);
242 s_indi_cp_state_info_type *__s_indi_alloc_state_info(CoreObject *co_ps)
244 s_indi_cp_state_info_type *state_info = s_indi_malloc0(sizeof(s_indi_cp_state_info_type));
245 state_info->co_ps = co_ps;
246 state_info->ps_state = S_INDI_CELLULAR_UNKNOWN;
247 state_info->cp_trans_state = S_INDI_TRANSFER_UNKNOWN;
248 state_info->dormant_info.lcd_state = S_INDI_LCD_UNKNOWN;
249 state_info->dormant_info.lcd_on_timeout = S_INDI_MINUS_ONE;
250 state_info->dormant_info.lcd_off_timeout = S_INDI_MINUS_ONE;
251 state_info->rx_total = S_INDI_ZERO;
252 state_info->tx_total = S_INDI_ZERO;
253 state_info->dormant_info.parent = state_info;
255 /* tcore_context_get_ipv4_devname uses glib allocator so key should be freed using g_free() */
256 state_info->device_info = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, __s_indi_dev_info_value_destroy_notification);
260 s_indi_dev_state_info_type *__s_indi_alloc_device_state(CoreObject *ps_context, s_indi_cp_state_info_type *parent)
262 s_indi_dev_state_info_type *dev_state = s_indi_malloc0(sizeof(s_indi_dev_state_info_type));
263 dev_state->ps_context = ps_context;
264 dev_state->parent = parent;
268 s_indi_private_info *__s_indi_get_priv_info(TcorePlugin *plugin)
270 s_indi_private_info *priv_info = tcore_plugin_ref_user_data(plugin);
271 s_indi_assert(NULL != priv_info);
275 gboolean __s_indi_start_updater(TcorePlugin *indi_plugin, gchar *cp_name)
277 __s_indi_cb_user_data *cb_data = NULL;
278 s_indi_cp_state_info_type *state_info = NULL;
279 s_indi_private_info *priv_info = __s_indi_get_priv_info(indi_plugin);
281 if ((state_info = g_hash_table_lookup(priv_info->state_info, cp_name)) == NULL) {
282 warn("CP [%s] Not Present", cp_name);
283 s_indi_free(cp_name);
287 if (state_info->src != NULL) {
288 dbg("Another one is in progress");
289 s_indi_free(cp_name);
293 S_INDI_ALLOC_USER_DATA(cb_data, indi_plugin, cp_name);
295 dbg("indicator is starting");
296 state_info->src = g_timeout_source_new_seconds(S_INDI_UPDATE_INTERVAL);
297 g_source_set_callback(state_info->src, (GSourceFunc)__s_indi_update_callback, cb_data, NULL);
298 g_source_set_priority(state_info->src, G_PRIORITY_HIGH);
299 g_source_attach(state_info->src, NULL);
300 g_source_unref(state_info->src);
304 gboolean __s_indi_cancel_pm_lock(gboolean b_pm_lock)
306 /* Cancel power lock */
308 int rv = S_INDI_ZERO;
309 rv = display_unlock_state(LCD_OFF, PM_RESET_TIMER);
310 dbg("display_unlock_state: rv(%d)", rv);
316 gboolean __s_indi_update_callback(__s_indi_cb_user_data *data)
318 #define INDICATOR_BUFF_SIZE 4096
319 gchar buff[INDICATOR_BUFF_SIZE];
320 s_indi_cp_state_info_type *state_info = NULL;
321 s_indi_dev_state_info_type *dev_state = NULL;
322 TcorePlugin *indi_plugin = data->indi_plugin;
323 const char *cp_name = data->cp_name;
324 unsigned int modem_id;
327 unsigned long long rx_curr_total = S_INDI_ZERO, tx_curr_total = S_INDI_ZERO, rx_prev_total = S_INDI_ZERO, tx_prev_total = S_INDI_ZERO;
328 unsigned long rx_changes_total = S_INDI_ZERO, tx_changes_total = S_INDI_ZERO;
329 s_indi_transfer_state cp_state = S_INDI_TRANSFER_NORMAL; /* Assume no activity */
330 enum tcore_storage_key key_last_rcv, key_last_snt, key_total_rcv, key_total_snt, key_service_state;
331 s_indi_private_info *priv_info = __s_indi_get_priv_info(indi_plugin);
332 Storage *strg_vconf = NULL;
335 if (s_indi_str_has_suffix(cp_name, "0")) {
336 key_last_rcv = STORAGE_KEY_CELLULAR_PKT_LAST_RCV;
337 key_last_snt = STORAGE_KEY_CELLULAR_PKT_LAST_SNT;
338 key_total_rcv = STORAGE_KEY_CELLULAR_PKT_TOTAL_RCV;
339 key_total_snt = STORAGE_KEY_CELLULAR_PKT_TOTAL_SNT;
340 key_service_state = STORAGE_KEY_PACKET_SERVICE_STATE;
341 modem_id = MODEM_ID_PRIMARY;
342 } else if (s_indi_str_has_suffix(cp_name, "1")) {
343 key_last_rcv = STORAGE_KEY_CELLULAR_PKT_LAST_RCV2;
344 key_last_snt = STORAGE_KEY_CELLULAR_PKT_LAST_SNT2;
345 key_total_rcv = STORAGE_KEY_CELLULAR_PKT_TOTAL_RCV2;
346 key_total_snt = STORAGE_KEY_CELLULAR_PKT_TOTAL_SNT2;
347 key_service_state = STORAGE_KEY_PACKET_SERVICE_STATE2;
348 modem_id = MODEM_ID_SECONDARY;
350 err("Unhandled CP Name %s", cp_name);
351 s_indi_assert_not_reached();
352 S_INDI_FREE_USER_DATA(data);
353 return G_SOURCE_REMOVE;
356 /* Check CP Name presence */
357 if ((state_info = g_hash_table_lookup(priv_info->state_info, cp_name)) == NULL) {
358 warn("%s CP is not present", cp_name);
362 /* Check dev_state presence */
363 if (g_hash_table_size(state_info->device_info) == S_INDI_ZERO) {
364 msg("Nothing to update, aborting timer");
368 /** @todo: Check if needs to be read atomically */
369 pf = fopen(S_INDI_PROC_FILE, "r");
371 err("indicator fail to open file(%s), errno(%d)", S_INDI_PROC_FILE, errno);
375 /* Skip first line */
376 rv = fgets(buff, sizeof(buff), pf);
378 err("fail to read file or reach EOF, plz check %s", S_INDI_PROC_FILE);
382 /* Skip second line */
383 rv = fgets(buff, sizeof(buff), pf);
385 err("fail to read file or reach EOF, plz check %s", S_INDI_PROC_FILE);
389 /* Update all devices of state_info */
390 while (fgets(buff, sizeof(buff), pf)) {
391 gchar *ifname = buff, *entry = NULL;
393 /* Skip whitespaces */
394 while (*ifname == ' ')
397 /* Terminate to read ifname */
398 entry = strrchr(ifname, ':');
401 /* Read device_info */
402 /* Takes care of the fix: Fix the PLM p131003-03182. Sha-ID: 65544f0be8e60ae3f964921755a1e83fa8e71441*/
403 if ((dev_state = g_hash_table_lookup(state_info->device_info, ifname)) != NULL) {
404 gint result = S_INDI_ZERO;
405 unsigned long rx_pkt = S_INDI_ZERO, tx_pkt = S_INDI_ZERO;
406 /************************************************************************
407 Sample Input of S_INDI_PROC_FILE
408 ************************************************************************
409 Inter-| Receive | Transmit
410 face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
411 lo: 114955545 88409 0 0 0 0 0 0 114955545 88409 0 0 0 0 0 0
412 eth0: 2714004148 6475059 0 0 0 0 0 0 72595891 8726308 0 0 0 0 0 0
413 ************************************************************************/
414 s_indi_log_v("Reading stats of interface %s", ifname);
415 result = sscanf(entry, "%lu %*s %*s %*s %*s %*s %*s %*s %lu %*s %*s %*s %*s %*s %*s %*s", &rx_pkt, &tx_pkt);
416 if (result <= S_INDI_ZERO) {
417 err("stats fail to get proc field => %d", result);
418 goto EXIT; /** @todo: REMOVE or CONTINUE ? */
421 /* Save per device */
422 dev_state->prev_rx = dev_state->curr_rx;
423 dev_state->prev_tx = dev_state->curr_tx;
424 dev_state->curr_rx = rx_pkt;
425 dev_state->curr_tx = tx_pkt;
427 /* Compute CP totals */
428 rx_curr_total += rx_pkt;
429 tx_curr_total += tx_pkt;
430 rx_prev_total += dev_state->prev_rx;
431 tx_prev_total += dev_state->prev_tx;
435 rx_changes_total = rx_curr_total - rx_prev_total;
436 tx_changes_total = tx_curr_total - tx_prev_total;
438 if (rx_changes_total) {
439 cp_state |= S_INDI_TRANSFER_RX;
441 if (tx_changes_total) {
442 cp_state |= S_INDI_TRANSFER_TX;
445 /* todo: reduce the number of conditions */
446 if (cp_state == S_INDI_TRANSFER_TX) {
447 state_info->no_rx_pckt++;
449 else if (cp_state == S_INDI_TRANSFER_NORMAL) {
450 /* todo: why check against 5 */
451 if (state_info->no_rx_pckt > 5) {
452 state_info->no_rx_pckt++;
454 state_info->dormant_info.dormant_cnt++;
456 state_info->dormant_info.dormant_cnt = 0;
457 state_info->dormant_info.is_dormant = FALSE;
461 s_indi_log_txrx(modem_id, "Transfer State:[%d] rx_cnt:[%d] RX: [%10lu] TX: [%10lu]", cp_state, state_info->no_rx_pckt, rx_changes_total, tx_changes_total);
464 if (state_info->dormant_info.lcd_state < S_INDI_LCD_OFF) {
465 if (state_info->cp_trans_state != cp_state) { /* New Transfer State */
466 strg_vconf = tcore_server_find_storage(tcore_plugin_ref_server(indi_plugin), S_INDI_VCONF_STORAGE_NAME);
467 s_indi_assert(NULL != strg_vconf);
469 state_info->cp_trans_state = cp_state;
470 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, cp_state);
471 if (cp_state != S_INDI_TRANSFER_NORMAL) { /* Data activity */
472 s_indi_log_txrx(modem_id, "pkt_state[%d] rx_changes [%lu] tx_changes [%lu]",
473 cp_state, rx_changes_total, tx_changes_total);
474 tcore_storage_set_int(strg_vconf, key_last_rcv, rx_curr_total/1000);
475 tcore_storage_set_int(strg_vconf, key_last_snt, tx_curr_total/1000);
480 if (state_info->no_rx_pckt >= S_INDI_NO_RX_PKT_TIMEOUT) {
481 state_info->no_rx_pckt = S_INDI_ZERO;
482 dbg("request to disconnect all ps context");
483 g_hash_table_foreach(state_info->device_info, __s_indi_deactivate_ps_context, state_info->co_ps);
486 priv_info->b_pm_lock = __s_indi_check_fast_dormancy(indi_plugin, state_info->co_ps, &state_info->dormant_info, priv_info->b_pm_lock);
488 return G_SOURCE_CONTINUE; /* Revisit after S_INDI_UPDATE_INTERVAL */
491 dbg("indicator is stopped");
494 strg_vconf = tcore_server_find_storage(tcore_plugin_ref_server(indi_plugin), S_INDI_VCONF_STORAGE_NAME);
495 s_indi_assert(NULL != strg_vconf);
497 /* Update PS Call and indicator states */
498 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, S_INDI_TRANSFER_NORMAL);
499 tcore_storage_set_int(strg_vconf, key_service_state, S_INDI_CELLULAR_OFF);
500 dbg("PS Call status (%s) - [DISCONNECTED]", cp_name);
503 state_info->src = NULL;
504 state_info->cp_trans_state = S_INDI_TRANSFER_NORMAL;
505 state_info->ps_state = S_INDI_CELLULAR_OFF;
507 /* Update total VCONF before dying updator */
508 tcore_storage_set_int(strg_vconf, key_total_rcv, tcore_storage_get_int(strg_vconf, key_total_rcv) + state_info->rx_total);
509 tcore_storage_set_int(strg_vconf, key_total_snt, tcore_storage_get_int(strg_vconf, key_total_snt) + state_info->tx_total);
511 /** @todo: VCONF needs upgrade to support llu */
512 s_indi_log_txrx(modem_id, "RX-TOTAL[%d] TX-TOTAL[%d]",
513 tcore_storage_get_int(strg_vconf, key_total_rcv), tcore_storage_get_int(strg_vconf, key_total_snt));
514 state_info->rx_total = S_INDI_ZERO;
515 state_info->tx_total = S_INDI_ZERO;
518 S_INDI_FREE_USER_DATA(data);
519 return G_SOURCE_REMOVE;
522 static void __s_indi_deactivate_ps_context (gpointer key, gpointer value, gpointer user_data)
525 dbg("Temp Fix: stopping deactivation from indicator ");
528 user_data = user_data;
531 s_indi_dev_state_info_type *dev_state = value;
533 if(dev_state->ps_context && user_data){
534 dbg("Deactivating PS context [%p] which is associated with interface %s", dev_state->ps_context, ifname);
535 tcore_ps_deactivate_context(user_data, dev_state->ps_context, NULL);
541 void __s_indi_state_info_value_destroy_notification(gpointer data)
543 s_indi_cp_state_info_type *state_info = data;
544 const char *cp_name = NULL;
545 Storage *strg_vconf = NULL;
546 enum tcore_storage_key key_total_rcv, key_total_snt;
547 s_indi_assert(NULL != state_info);
548 s_indi_assert(NULL != state_info->co_ps);
550 cp_name = tcore_server_get_cp_name_by_plugin(tcore_object_ref_plugin(state_info->co_ps));
551 s_indi_assert(NULL != cp_name);
552 dbg("CP Name: [%s]", cp_name);
555 if (s_indi_str_has_suffix(cp_name, "0")) {
556 key_total_rcv = STORAGE_KEY_CELLULAR_PKT_TOTAL_RCV;
557 key_total_snt = STORAGE_KEY_CELLULAR_PKT_TOTAL_SNT;
558 } else if (s_indi_str_has_suffix(cp_name, "1")) {
559 key_total_rcv = STORAGE_KEY_CELLULAR_PKT_TOTAL_RCV2;
560 key_total_snt = STORAGE_KEY_CELLULAR_PKT_TOTAL_SNT2;
562 err("Unhandled CP Name %s", cp_name);
563 s_indi_assert_not_reached();
567 /* Free device nodes */
568 g_hash_table_destroy(state_info->device_info);
569 strg_vconf = tcore_server_find_storage(tcore_plugin_ref_server(tcore_object_ref_plugin(state_info->co_ps)), S_INDI_VCONF_STORAGE_NAME);
570 s_indi_assert(NULL != strg_vconf);
572 /* Update VCONF before dying */
573 tcore_storage_set_int(strg_vconf, key_total_rcv, tcore_storage_get_int(strg_vconf, key_total_rcv) + state_info->rx_total);
574 tcore_storage_set_int(strg_vconf, key_total_snt, tcore_storage_get_int(strg_vconf, key_total_snt) + state_info->tx_total);
575 dbg("CP[%s] RX-TOTAL[%10llu] TX-TOTAL[%10llu]", cp_name,
576 tcore_storage_get_int(strg_vconf, key_total_rcv), tcore_storage_get_int(strg_vconf, key_total_snt));
579 s_indi_free(state_info->dormant_info.mccmnc);
583 void __s_indi_dev_info_value_destroy_notification(gpointer data)
585 s_indi_dev_state_info_type *dev_state = data;
586 s_indi_cp_state_info_type *state_info = NULL;
587 s_indi_assert(NULL != dev_state);
588 state_info = dev_state->parent;
589 s_indi_assert(NULL != state_info);
591 /* Update parent before dying */
592 state_info->rx_total += dev_state->curr_rx/1000;
593 state_info->tx_total += dev_state->curr_tx/1000;
595 s_indi_log_v("DYING after contributing [RX: %lu][TX: %lu] OUT OF [RX: %llu][TX: %llu]",
596 dev_state->curr_rx/1000, dev_state->curr_tx/1000,
597 state_info->rx_total, state_info->tx_total);
602 void __s_indi_refresh_modems(TcorePlugin *indi_plugin)
604 GSList *mp_list = tcore_server_get_modem_plugin_list(tcore_plugin_ref_server(indi_plugin));
605 s_indi_log_v("Processing %u present modems", g_slist_length(mp_list));
608 __s_indi_add_modem_plugin(indi_plugin, mp_list->data);
609 mp_list = mp_list->next;
612 g_slist_free(mp_list);
615 void __s_indi_set_dormancy_value(Server *server, s_indi_dormancy_info_type *dormancy_info, enum tcore_storage_key key_fd)
617 if (dormancy_info->b_vconf_checker) {
618 Storage *strg_vconf = tcore_server_find_storage(server, S_INDI_VCONF_STORAGE_NAME);
619 gboolean b_fd_force = tcore_storage_get_bool(strg_vconf, key_fd);
621 s_indi_assert(NULL != strg_vconf);
624 dbg("forcely enable fast dormancy ");
625 dormancy_info->lcd_on_timeout = S_INDI_FIVE;
626 dormancy_info->lcd_off_timeout = S_INDI_FIVE;
628 dbg("forcely disable fast dormancy ");
629 dormancy_info->lcd_on_timeout = S_INDI_MINUS_ONE;
630 dormancy_info->lcd_off_timeout = S_INDI_MINUS_ONE;
634 if (!dormancy_info->mccmnc) {
635 dbg("mccmnc is null");
639 /** @todo: Make List of blocked mccmnc and use that */
641 * Fast dormancy values are updated currently only for SKT and KT operators in DB.Revisit.
644 if ((g_strcmp0((const char *)dormancy_info->mccmnc, "00101") == S_INDI_ZERO)
645 || (g_strcmp0((const char *)dormancy_info->mccmnc, "99999") == S_INDI_ZERO)) {
646 dormancy_info->lcd_on_timeout = S_INDI_ZERO;
647 dormancy_info->lcd_off_timeout = S_INDI_ZERO;
648 dbg("FD does not work in testsim");
651 #define szQUERY_SIZE 5000
654 char szQuery[szQUERY_SIZE];
657 GHashTable *in_param, *out_param;
660 /* Initialize Storage */
661 strg_db = tcore_server_find_storage(server, S_INDI_DB_STORAGE_NAME);
662 db_handle = tcore_storage_create_handle(strg_db, S_INDI_DB_STORAGE_PATH);
663 if (db_handle == NULL) {
664 err("Failed to get Storage handle");
668 /* Initialize parameters */
669 in_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
670 g_hash_table_insert(in_param, "1", g_strdup(dormancy_info->mccmnc));
672 out_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify)g_hash_table_destroy);
674 memset(szQuery, '\0', szQUERY_SIZE);
675 strcpy(szQuery, "select");
676 strcat(szQuery, " a.dormant_id, a.network_info_id, a.lcd_on_timeout, a.lcd_off_timeout"); //0,1,2,3
677 strcat(szQuery, " from fast_dormancy a, network_info b");
678 strcat(szQuery, " where b.mccmnc= ? and a.network_info_id = b.network_info_id ");
680 tcore_storage_read_query_database(strg_db, db_handle, szQuery, in_param, out_param, 4);
682 dbg("Get dormancy value");
683 g_hash_table_iter_init(&iter, out_param);
684 while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
685 GHashTableIter iter2;
686 gpointer key2, value2;
689 g_hash_table_iter_init(&iter2, (GHashTable *)value);
690 while (g_hash_table_iter_next(&iter2, &key2, &value2) == TRUE) {
691 if (g_str_equal(key2, "2") == TRUE) {
692 dormancy_info->lcd_on_timeout = atoi((const char*)value2);
693 dbg("lcd on timeout(%d)", dormancy_info->lcd_on_timeout);
695 else if (g_str_equal(key2, "3") == TRUE) {
696 dormancy_info->lcd_off_timeout = atoi((const char*)value2);
697 dbg("lcd off timeout(%d)", dormancy_info->lcd_off_timeout);
705 g_hash_table_destroy(in_param);
706 g_hash_table_destroy(out_param);
708 if(dormancy_info->lcd_on_timeout > 0 || dormancy_info->lcd_off_timeout > 0) {
709 dormancy_info->is_dormant_set = TRUE;
712 /* De-initialize Storage */
713 tcore_storage_remove_handle(strg_db, db_handle);
717 static gboolean __s_indi_check_fast_dormancy(TcorePlugin *indi_plugin, CoreObject *co_ps, s_indi_dormancy_info_type *dormancy_info, gboolean b_pm_lock)
721 S_INDI_NOT_USED(indi_plugin);
722 S_INDI_NOT_USED(co_ps);
724 if(!dormancy_info->is_dormant_set){
725 dormancy_info->dormant_cnt = 0;
726 dormancy_info->is_dormant = FALSE;
729 b_pm_lock = __s_indi_cancel_pm_lock(b_pm_lock);
733 if(dormancy_info->is_dormant){
734 dormancy_info->dormant_cnt = 0;
738 if(dormancy_info->lcd_state < 3 && dormancy_info->lcd_on_timeout > 0){ //on 1 && dim 2
740 //satisfy with fd condition, set fd and cancle the pm lock
741 if(dormancy_info->dormant_cnt >= dormancy_info->lcd_on_timeout){
742 dbg("set lcd on fast dormancy");
743 dormancy_info->dormant_cnt = 0;
744 dormancy_info->is_dormant = TRUE;
748 else if(dormancy_info->lcd_state < 3 && dormancy_info->lcd_on_timeout <= 0){
749 dormancy_info->dormant_cnt = 0;
751 else if(dormancy_info->lcd_state == 3 && dormancy_info->lcd_off_timeout > 0){ //off 3
753 //call the pm lock state if pkt exist and not dormant state
754 if(dormancy_info->dormant_cnt < dormancy_info->lcd_off_timeout){
755 b_pm_lock = __s_indi_cancel_pm_lock(b_pm_lock);
758 else if(dormancy_info->dormant_cnt >= dormancy_info->lcd_off_timeout){
759 dbg("set lcd off fast dormancy");
760 dormancy_info->dormant_cnt = 0;
761 dormancy_info->is_dormant = TRUE;
764 else if(dormancy_info->lcd_state == 3 && dormancy_info->lcd_off_timeout <= 0){ //off 3
765 dormancy_info->dormant_cnt = 0;
770 rv = display_unlock_state(LCD_OFF, PM_RESET_TIMER);
772 dbg("display_unlock_state: rv(%d)", rv);
778 void s_indi_storage_key_callback(enum tcore_storage_key key, void *value, void *user_data)
780 s_indi_cp_state_info_type *state_info = NULL;
781 GVariant *tmp = value;
782 s_indi_private_info *priv_info = __s_indi_get_priv_info(user_data);
784 s_indi_assert(NULL != tmp);
787 case STORAGE_KEY_TESTMODE_FAST_DORMANCY: /* Fall Through */
788 case STORAGE_KEY_TESTMODE_FAST_DORMANCY2:
790 const gchar *cp_name = NULL;
791 if ((cp_name = g_hash_table_lookup(priv_info->vconf_info, GUINT_TO_POINTER(key))) != NULL)
792 if ((state_info = g_hash_table_lookup(priv_info->state_info, cp_name)) != NULL) {
793 s_indi_log_ex(cp_name, "Processing Fast Dormancy");
795 /*TODO: Currently testmodem fast dormancy is not enabled.so process fast dormancy will not happen */
797 __s_indi_process_fast_dormancy(state_info, tmp);
801 case STORAGE_KEY_PM_STATE:
805 gint pm_state = S_INDI_ZERO;
807 if (!g_variant_is_of_type(tmp, G_VARIANT_TYPE_INT32)) {
808 err("Wrong variant data type");
812 pm_state = g_variant_get_int32(tmp);
814 dbg("PM state Value:[%d]", pm_state);
816 g_hash_table_iter_init(&iter, priv_info->state_info);
817 while (g_hash_table_iter_next (&iter, &key, &value)) {
819 state_info->dormant_info.lcd_state = pm_state;
824 s_indi_assert_not_reached();
828 enum tcore_hook_return s_indi_on_hook_modem_power(Server *server, CoreObject *source,
829 enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data)
831 struct tnoti_modem_power *modem_power = data;
832 s_indi_assert(modem_power != NULL);
834 S_INDI_NOT_USED(server);
835 S_INDI_NOT_USED(command);
836 S_INDI_NOT_USED(data_len);
838 CORE_OBJECT_CHECK_RETURN(source, CORE_OBJECT_TYPE_MODEM, TCORE_HOOK_RETURN_CONTINUE);
840 if (modem_power->state == MODEM_STATE_ERROR) { /* CP reset */
841 TcorePlugin *indi_plugin = user_data;
842 const char *cp_name = NULL;
843 s_indi_cp_state_info_type *state_info = NULL;
844 s_indi_private_info *priv_info = __s_indi_get_priv_info(indi_plugin);
846 cp_name = tcore_server_get_cp_name_by_plugin(tcore_object_ref_plugin(source));
847 s_indi_assert(NULL != cp_name);
848 s_indi_log_ex(cp_name, "MODEM_STATE_ERROR");
850 if ((state_info = g_hash_table_lookup(priv_info->state_info, cp_name)) == NULL) {
851 warn("BAILING OUT: [%s] not found", cp_name);
852 return TCORE_HOOK_RETURN_CONTINUE;
855 /* Remove all device states since PS releasing all contexts */
856 g_hash_table_remove_all(state_info->device_info);
858 /* Free MCC/MNC. It will be received again */
859 s_indi_free(state_info->dormant_info.mccmnc);
860 state_info->dormant_info.mccmnc = NULL;
862 /* Reset Dormant Information @todo: Why is this required? */
863 state_info->dormant_info.lcd_on_timeout = S_INDI_ZERO;
864 state_info->dormant_info.lcd_off_timeout = S_INDI_ZERO;
865 priv_info->b_pm_lock = __s_indi_cancel_pm_lock(priv_info->b_pm_lock);
868 return TCORE_HOOK_RETURN_CONTINUE;
871 enum tcore_hook_return s_indi_on_hook_ps_call_status(Server *server, CoreObject *source,
872 enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data)
874 struct tnoti_ps_call_status *cstatus = data;
875 TcorePlugin *indi_plugin = user_data;
876 const char *cp_name = NULL;
877 s_indi_cp_state_info_type *state_info = NULL;
879 gpointer cp_name_key, cp_state = NULL;
880 unsigned char active_pdp_count = S_INDI_ZERO;
881 s_indi_private_info *priv_info = __s_indi_get_priv_info(indi_plugin);
883 s_indi_assert(cstatus != NULL);
885 S_INDI_NOT_USED(command);
886 S_INDI_NOT_USED(data_len);
888 CORE_OBJECT_CHECK_RETURN(source, CORE_OBJECT_TYPE_PS, TCORE_HOOK_RETURN_CONTINUE);
890 cp_name = tcore_server_get_cp_name_by_plugin(tcore_object_ref_plugin(source));
891 s_indi_assert(NULL != cp_name);
893 s_indi_log_ex(cp_name, "cid(%d) state(%d) reason(%d)",
894 cstatus->context_id, cstatus->state, cstatus->result);
896 if (cstatus->state == S_INDI_PS_CALL_OK)
897 return TCORE_HOOK_RETURN_CONTINUE;
899 if ((state_info = g_hash_table_lookup(priv_info->state_info, cp_name)) == NULL) {
900 warn("BAILING OUT: [%s] not found", cp_name);
901 return TCORE_HOOK_RETURN_CONTINUE;
904 s_indi_assert(source == state_info->co_ps);
906 if (cstatus->state == S_INDI_PS_CALL_CONNECT) {
907 GSList *l_context = NULL;
908 CoreObject *co_context = NULL;
909 gchar *dev_name = NULL;
910 s_indi_dev_state_info_type *dev_state = NULL;
911 enum tcore_storage_key key_service_state, key_fd;
912 Storage *strg_vconf = NULL;
913 int role = CONTEXT_ROLE_UNKNOWN;
914 gboolean data_allowed = FALSE;
915 gboolean roaming_allowed = FALSE;
917 /* Fetch context with internet/tethering role */
918 l_context = tcore_ps_ref_context_by_id(source, cstatus->context_id);
920 role = tcore_context_get_role(l_context->data);
921 if (role == CONTEXT_ROLE_INTERNET || role == CONTEXT_ROLE_TETHERING || role == CONTEXT_ROLE_MMS) {
922 co_context = l_context->data;
926 l_context = l_context->next;
930 err("INTERNET/TETHERING/MMS role not found");
931 return TCORE_HOOK_RETURN_CONTINUE;
934 dev_name = tcore_context_get_ipv4_devname(co_context); /* glib allocator */
935 s_indi_assert(NULL != dev_name);
937 /* Check if dev_name already exists */
938 if (g_hash_table_lookup(state_info->device_info, dev_name)) {
939 dbg("default connection is already connected");
941 return TCORE_HOOK_RETURN_CONTINUE;
944 /* Update Cellular State */
945 if (s_indi_str_has_suffix(cp_name, "0")) {
946 key_service_state = STORAGE_KEY_PACKET_SERVICE_STATE;
947 key_fd = STORAGE_KEY_TESTMODE_FAST_DORMANCY;
948 } else if (s_indi_str_has_suffix(cp_name, "1")) {
949 key_service_state = STORAGE_KEY_PACKET_SERVICE_STATE2;
950 key_fd = STORAGE_KEY_TESTMODE_FAST_DORMANCY2;
952 err("Un-handled CP");
954 s_indi_assert_not_reached();
955 return TCORE_HOOK_RETURN_CONTINUE;
959 strg_vconf = tcore_server_find_storage(server, S_INDI_VCONF_STORAGE_NAME);
960 s_indi_assert(NULL != strg_vconf);
962 data_allowed = tcore_storage_get_bool(strg_vconf, STORAGE_KEY_3G_ENABLE);
963 roaming_allowed = tcore_storage_get_bool(strg_vconf, STORAGE_KEY_SETAPPL_STATE_DATA_ROAMING_BOOL);
966 return TCORE_HOOK_RETURN_CONTINUE;
967 else if (state_info->roaming_status && !roaming_allowed)
968 return TCORE_HOOK_RETURN_CONTINUE;
970 /* Set Cellular state connected */
971 if (role == CONTEXT_ROLE_INTERNET || role == CONTEXT_ROLE_TETHERING) {
972 state_info->ps_state = S_INDI_CELLULAR_CONNECTED;
973 tcore_storage_set_int(strg_vconf, key_service_state, S_INDI_CELLULAR_CONNECTED);
974 }else if(role == CONTEXT_ROLE_MMS){
975 state_info->ps_state = S_INDI_CELLULAR_MMS_CONNECTED;
976 tcore_storage_set_int(strg_vconf, key_service_state, S_INDI_CELLULAR_MMS_CONNECTED);
979 /* Initialize Packet indicator to Normal */
980 tcore_storage_set_int(strg_vconf, STORAGE_KEY_PACKET_INDICATOR_STATE, S_INDI_TRANSFER_NORMAL);
981 state_info->cp_trans_state = S_INDI_TRANSFER_NORMAL;
983 s_indi_log_ex(cp_name, "PS Call status - [CONNECTED]");
985 /* Create new dev state */
986 dev_state = __s_indi_alloc_device_state(co_context, state_info);
987 g_hash_table_insert(state_info->device_info, dev_name, dev_state);
991 /* Read & Update dormancy values */
992 __s_indi_set_dormancy_value(server, &state_info->dormant_info, key_fd);
995 __s_indi_start_updater(indi_plugin, s_indi_strdup(cp_name));
998 else if (cstatus->state == S_INDI_PS_CALL_NO_CARRIER) {
999 gchar *dev_name = NULL;
1000 GSList *l_context = tcore_ps_ref_context_by_id(source, cstatus->context_id);
1002 /* Remove all related contexts */
1004 dev_name = tcore_context_get_ipv4_devname(l_context->data);
1005 if (dev_name != NULL) {
1006 g_hash_table_remove(state_info->device_info, dev_name);
1009 l_context = l_context->next;
1012 g_hash_table_iter_init(&iter, (GHashTable *)priv_info->state_info);
1013 while (g_hash_table_iter_next(&iter, &cp_name_key, &cp_state) == TRUE) {
1014 s_indi_log_ex(cp_name_key, "State: [0x%x]", cp_state);
1015 if (g_hash_table_size(((s_indi_cp_state_info_type *)cp_state)->device_info) != S_INDI_ZERO) {
1021 /* Cancel PM Lock if there doens't exist any active PDP connection */
1022 if (active_pdp_count == S_INDI_ZERO) {
1023 dbg("No Active PDP context. Resetting 'PM Lock' status");
1024 priv_info->b_pm_lock = __s_indi_cancel_pm_lock(priv_info->b_pm_lock);
1028 return TCORE_HOOK_RETURN_CONTINUE;
1031 enum tcore_hook_return s_indi_on_hook_net_register(Server *server, CoreObject *source,
1032 enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data)
1034 TcorePlugin *indi_plugin = user_data;
1035 const char *cp_name = NULL;
1036 s_indi_cp_state_info_type *state_info = NULL;
1037 gboolean active = FALSE;
1038 s_indi_private_info *priv_info = __s_indi_get_priv_info(indi_plugin);
1039 gboolean gsm_dtm_support = FALSE;
1040 struct tnoti_network_registration_status *regist_status = data;
1041 int roaming_status = S_INDI_ZERO;
1043 S_INDI_NOT_USED(command);
1044 S_INDI_NOT_USED(data_len);
1045 CORE_OBJECT_CHECK_RETURN(source, CORE_OBJECT_TYPE_NETWORK, TCORE_HOOK_RETURN_CONTINUE);
1047 cp_name = tcore_server_get_cp_name_by_plugin(tcore_object_ref_plugin(source));
1048 s_indi_assert(NULL != cp_name);
1049 s_indi_assert(NULL != regist_status);
1051 if ((state_info = g_hash_table_lookup(priv_info->state_info, cp_name)) == NULL) {
1052 warn("BAILING OUT: [%s] not found", cp_name);
1053 return TCORE_HOOK_RETURN_CONTINUE;
1056 roaming_status = state_info->roaming_status = regist_status->roaming_status;
1057 gsm_dtm_support = tcore_network_get_gsm_dtm_support(source);
1059 s_indi_log_ex(cp_name, "roam_status: [0x%x] dtm_support: [0x%x]",
1060 roaming_status, gsm_dtm_support);
1062 if (gsm_dtm_support)
1063 return TCORE_HOOK_RETURN_CONTINUE;
1065 active = (g_hash_table_size(state_info->device_info) >= S_INDI_ONE) ? TRUE : FALSE;
1068 Storage *strg_vconf = NULL;
1069 GSList *co_list = NULL;
1070 CoreObject *co_call = NULL;
1071 unsigned int total_call_cnt = S_INDI_ZERO;
1072 enum telephony_network_service_type svc_type;
1073 enum tcore_storage_key key_service_state;
1074 gboolean roaming_allowed = FALSE;
1077 if (s_indi_str_has_suffix(cp_name, "0")) {
1078 key_service_state = STORAGE_KEY_PACKET_SERVICE_STATE;
1079 } else if (s_indi_str_has_suffix(cp_name, "1")) {
1080 key_service_state = STORAGE_KEY_PACKET_SERVICE_STATE2;
1082 err("Un-handled CP");
1083 s_indi_assert_not_reached();
1084 return TCORE_HOOK_RETURN_CONTINUE;
1087 strg_vconf = tcore_server_find_storage(server, S_INDI_VCONF_STORAGE_NAME);
1088 roaming_allowed = tcore_storage_get_bool(strg_vconf, STORAGE_KEY_SETAPPL_STATE_DATA_ROAMING_BOOL);
1090 svc_type = regist_status->service_type;
1091 s_indi_log_ex(cp_name, "srvc_type(%d), roaming_allowed(%d)",
1092 svc_type, roaming_allowed);
1095 * If Roaming is NOT allowed and indication provides Roaming
1096 * status Available, there is a mismatch.
1097 * Set Cellular state OFF.
1099 if (state_info->ps_state != S_INDI_CELLULAR_OFF && !roaming_allowed && roaming_status) {
1100 tcore_storage_set_int(strg_vconf, key_service_state, S_INDI_CELLULAR_OFF); /* Set Cellular State OFF */
1102 /* Indicator need not know worry about roaming status. packet service plugin should take care of de-activating the contexts
1103 when roaming is enabled and network enters roaming. When all the contexts associated with that network is de-activated. Indicator
1104 plugin will automatically ps status for that CP to S_INDI_CELLULAR_OFF
1106 state_info->ps_state = S_INDI_CELLULAR_OFF; /* Update cache */
1108 s_indi_log_ex(cp_name, "PS Call status - [DISCONNECTED]");
1109 return TCORE_HOOK_RETURN_CONTINUE;
1112 if (svc_type < NETWORK_SERVICE_TYPE_2G || svc_type > NETWORK_SERVICE_TYPE_2_5G_EDGE)
1113 return TCORE_HOOK_RETURN_CONTINUE;
1115 co_list = tcore_plugin_get_core_objects_bytype(tcore_object_ref_plugin(source), CORE_OBJECT_TYPE_CALL);
1117 err("[ error ] co_list : NULL");
1118 return TCORE_HOOK_RETURN_CONTINUE;
1120 s_indi_assert(g_slist_length(co_list) == S_INDI_ONE);
1122 co_call = (CoreObject *)co_list->data;
1123 g_slist_free(co_list);
1125 total_call_cnt = tcore_call_object_total_length(co_call);
1126 s_indi_log_ex(cp_name, "totall call cnt (%d)", total_call_cnt);
1128 if (total_call_cnt > S_INDI_ONE) {
1129 s_indi_cellular_state pkg_state = S_INDI_CELLULAR_UNKNOWN;
1130 pkg_state = tcore_storage_get_int(strg_vconf, key_service_state);
1131 if (pkg_state != S_INDI_CELLULAR_OFF) {
1132 tcore_storage_set_int(strg_vconf, key_service_state, S_INDI_CELLULAR_OFF);
1133 state_info->ps_state = S_INDI_CELLULAR_OFF; /* Update cache */
1138 return TCORE_HOOK_RETURN_CONTINUE;
1141 enum tcore_hook_return s_indi_on_hook_sim_init(Server *server, CoreObject *source,
1142 enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data)
1144 struct tnoti_sim_status *sim_data = data;
1145 enum tcore_storage_key fd_key;
1146 s_indi_assert(NULL != sim_data);
1148 S_INDI_NOT_USED(command);
1149 S_INDI_NOT_USED(data_len);
1151 CORE_OBJECT_CHECK_RETURN(source, CORE_OBJECT_TYPE_SIM, TCORE_HOOK_RETURN_CONTINUE);
1153 if (sim_data->sim_status == SIM_STATUS_INIT_COMPLETED) {
1154 struct tel_sim_imsi *sim_imsi = NULL;
1155 const char *cp_name = NULL;
1156 s_indi_cp_state_info_type *state_info = NULL;
1157 TcorePlugin *indi_plugin = user_data;
1158 s_indi_private_info *priv_info = __s_indi_get_priv_info(indi_plugin);
1160 cp_name = tcore_server_get_cp_name_by_plugin(tcore_object_ref_plugin(source));
1161 s_indi_assert(NULL != cp_name);
1162 s_indi_log_ex(cp_name, "SIM_STATUS_INIT_COMPLETED");
1164 if ((state_info = g_hash_table_lookup(priv_info->state_info, cp_name)) == NULL) {
1165 warn("BAILING OUT: [%s] not found", cp_name);
1166 return TCORE_HOOK_RETURN_CONTINUE;
1169 sim_imsi = tcore_sim_get_imsi(source);
1170 s_indi_assert(NULL != sim_imsi);
1171 state_info->dormant_info.mccmnc = s_indi_strdup((gchar *)sim_imsi->plmn);
1172 free(sim_imsi); /* libc allocator */
1174 /* Update Cellular State */
1175 if (s_indi_str_has_suffix(cp_name, "0")) {
1176 fd_key = STORAGE_KEY_TESTMODE_FAST_DORMANCY;
1177 } else if (s_indi_str_has_suffix(cp_name, "1")) {
1178 fd_key = STORAGE_KEY_TESTMODE_FAST_DORMANCY2;
1180 err("Un-handled CP");
1181 return TCORE_HOOK_RETURN_CONTINUE;
1184 /* Caching the lcdontimer and lcdofftimer dormant values for different network from db */
1185 __s_indi_set_dormancy_value(server, &(state_info->dormant_info), fd_key);
1188 return TCORE_HOOK_RETURN_CONTINUE;
1191 gboolean __s_indi_handle_voice_call_status(Server *server, CoreObject *source,
1192 enum tcore_notification_command command, const char *cp_name,
1193 s_indi_cp_state_info_type *state_info)
1195 CoreObject *co_network = NULL;
1196 enum tcore_storage_key vconf_key;
1197 Storage *strg_vconf;
1198 enum telephony_network_service_type svc_type;
1199 gboolean show_icon = TRUE;
1201 if (g_hash_table_size(state_info->device_info) == S_INDI_ZERO) {
1202 s_indi_log_ex(cp_name, "PS state is already OFF");
1206 co_network = tcore_plugin_ref_core_object(tcore_object_ref_plugin(state_info->co_ps),
1207 CORE_OBJECT_TYPE_NETWORK);
1210 gboolean gsm_dtm_support = FALSE;
1211 gsm_dtm_support = tcore_network_get_gsm_dtm_support(co_network);
1212 if (gsm_dtm_support) {
1213 s_indi_log_ex(cp_name, "GSM DTM supported! UI need not be synchronized");
1218 /* Mapping VCONF keys */
1219 if (s_indi_str_has_suffix(cp_name, "0")) {
1220 vconf_key = STORAGE_KEY_PACKET_SERVICE_STATE;
1221 } else if (s_indi_str_has_suffix(cp_name, "1")) {
1222 vconf_key = STORAGE_KEY_PACKET_SERVICE_STATE2;
1224 s_indi_assert_not_reached();
1228 tcore_network_get_service_type(co_network, &svc_type);
1231 case NETWORK_SERVICE_TYPE_2G:
1232 case NETWORK_SERVICE_TYPE_2_5G:
1233 case NETWORK_SERVICE_TYPE_2_5G_EDGE:
1237 case NETWORK_SERVICE_TYPE_3G:
1238 case NETWORK_SERVICE_TYPE_HSDPA:
1239 if (tcore_object_ref_plugin(co_network) != tcore_object_ref_plugin(source))
1247 s_indi_log_ex(cp_name, "RAT: [0x%x], ps_state: [0x%x], show_icon[%d]",
1248 svc_type, state_info->ps_state, show_icon);
1250 if (show_icon == TRUE) {
1251 if (state_info->ps_state == S_INDI_CELLULAR_OFF) {
1252 state_info->ps_state = S_INDI_CELLULAR_CONNECTED;
1259 case TNOTI_CALL_STATUS_IDLE: {
1260 int total_call_cnt = S_INDI_ZERO;
1261 total_call_cnt = tcore_call_object_total_length(source);
1262 if (total_call_cnt > S_INDI_ONE) {
1263 s_indi_log_ex(cp_name, "Call is still connected");
1266 state_info->ps_state = S_INDI_CELLULAR_CONNECTED;
1269 case TNOTI_CALL_STATUS_DIALING:
1270 case TNOTI_CALL_STATUS_INCOMING:
1271 case TNOTI_CALL_STATUS_ACTIVE: {
1272 state_info->ps_state = S_INDI_CELLULAR_OFF;
1276 s_indi_log_ex(cp_name, "Unexpected command: [0x%x]", command);
1277 s_indi_assert_not_reached();
1283 /* Update PS Call state */
1284 strg_vconf = tcore_server_find_storage(server, S_INDI_VCONF_STORAGE_NAME);
1285 if (state_info->ps_state != tcore_storage_get_int(strg_vconf, vconf_key)) {
1286 tcore_storage_set_int(strg_vconf, vconf_key, state_info->ps_state);
1287 s_indi_log_ex(cp_name, "PS Call status - [%s]", (state_info->ps_state == S_INDI_CELLULAR_CONNECTED ? "CONNECTED"
1288 : (state_info->ps_state == S_INDI_CELLULAR_OFF ? "DISCONNECTED"
1289 : (state_info->ps_state == S_INDI_CELLULAR_USING ? "IN USE" : "UNKNOWN"))));
1295 enum tcore_hook_return s_indi_on_hook_voice_call_status(Server *server, CoreObject *source,
1296 enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data)
1298 TcorePlugin *indi_plugin = user_data;
1299 s_indi_private_info *priv_info = __s_indi_get_priv_info(indi_plugin);
1300 const char *cp_name = NULL;
1301 s_indi_cp_state_info_type *state_info = NULL;
1303 GHashTableIter iter;
1304 gpointer key, value;
1306 S_INDI_NOT_USED(data_len);
1307 S_INDI_NOT_USED(data);
1309 CORE_OBJECT_CHECK_RETURN(source, CORE_OBJECT_TYPE_CALL, TCORE_HOOK_RETURN_CONTINUE);
1311 /* Update all modem states */
1312 g_hash_table_iter_init(&iter, priv_info->state_info);
1313 while (g_hash_table_iter_next (&iter, &key, &value)) {
1317 (void)__s_indi_handle_voice_call_status(server, source, command,
1318 cp_name, state_info);
1321 return TCORE_HOOK_RETURN_CONTINUE;
1324 enum tcore_hook_return s_indi_on_hook_modem_plugin_added(Server *server, CoreObject *source,
1325 enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data)
1327 s_indi_assert(NULL != data);
1328 s_indi_assert(NULL != user_data);
1330 S_INDI_NOT_USED(server);
1331 S_INDI_NOT_USED(source);
1332 S_INDI_NOT_USED(command);
1333 S_INDI_NOT_USED(data_len);
1335 __s_indi_add_modem_plugin(user_data, data);
1337 return TCORE_HOOK_RETURN_CONTINUE;
1340 enum tcore_hook_return s_indi_on_hook_modem_plugin_removed(Server *server, CoreObject *source,
1341 enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data)
1343 s_indi_assert(NULL != data);
1344 s_indi_assert(NULL != user_data);
1346 S_INDI_NOT_USED(server);
1347 S_INDI_NOT_USED(source);
1348 S_INDI_NOT_USED(command);
1349 S_INDI_NOT_USED(data_len);
1351 __s_indi_remove_modem_plugin(user_data, data);
1353 return TCORE_HOOK_RETURN_CONTINUE;
1356 gboolean s_indi_init(TcorePlugin *plugin)
1358 Server *server = NULL;
1359 s_indi_private_info *priv_info = NULL;
1361 priv_info = s_indi_malloc0(sizeof(*priv_info));
1362 if (tcore_plugin_link_user_data(plugin, priv_info) != TCORE_RETURN_SUCCESS) {
1363 err("Failed to link private data");
1364 s_indi_free(priv_info);
1368 server = tcore_plugin_ref_server(plugin);
1370 /* Initialize SIPC counter */
1371 priv_info->msg_id.id_current = S_INDI_SIPC_ITER_START - S_INDI_ONE;
1372 priv_info->msg_id.id_start = S_INDI_SIPC_ITER_START;
1373 priv_info->msg_id.id_end = S_INDI_SIPC_ITER_END;
1375 /* Initialize VCONF => CP_NAME mapping */
1376 priv_info->vconf_info = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, s_indi_free_func);
1378 /* Initialize State Information */
1379 priv_info->state_info = g_hash_table_new_full(g_str_hash, g_str_equal, s_indi_free_func, __s_indi_state_info_value_destroy_notification);
1381 if (priv_info->state_info == NULL
1382 || priv_info->vconf_info == NULL) {
1383 err("Memory allocation problem! Bailing Out");
1387 priv_info->b_pm_lock = FALSE;
1389 /* Register vconf key callbacks */
1390 __s_indi_register_vconf_key(STORAGE_KEY_PM_STATE, plugin, NULL);
1393 tcore_server_add_notification_hook(server, TNOTI_MODEM_POWER, s_indi_on_hook_modem_power, plugin);
1394 tcore_server_add_notification_hook(server, TNOTI_PS_CALL_STATUS, s_indi_on_hook_ps_call_status, plugin);
1395 tcore_server_add_notification_hook(server, TNOTI_NETWORK_REGISTRATION_STATUS, s_indi_on_hook_net_register, plugin);
1396 tcore_server_add_notification_hook(server, TNOTI_SIM_STATUS, s_indi_on_hook_sim_init, plugin);
1398 /* For 2G PS suspend/resume */
1399 tcore_server_add_notification_hook(server, TNOTI_CALL_STATUS_IDLE, s_indi_on_hook_voice_call_status, plugin);
1400 tcore_server_add_notification_hook(server, TNOTI_CALL_STATUS_DIALING, s_indi_on_hook_voice_call_status, plugin);
1401 tcore_server_add_notification_hook(server, TNOTI_CALL_STATUS_INCOMING, s_indi_on_hook_voice_call_status, plugin);
1402 tcore_server_add_notification_hook(server, TNOTI_CALL_STATUS_ACTIVE, s_indi_on_hook_voice_call_status, plugin);
1404 /* For new Modems */
1405 tcore_server_add_notification_hook(server, TNOTI_SERVER_ADDED_MODEM_PLUGIN, s_indi_on_hook_modem_plugin_added, plugin);
1406 tcore_server_add_notification_hook(server, TNOTI_SERVER_REMOVED_MODEM_PLUGIN, s_indi_on_hook_modem_plugin_removed, plugin);
1408 /* Add existing Modems */
1409 __s_indi_refresh_modems(plugin);
1414 s_indi_deinit(plugin);
1418 void s_indi_deinit(TcorePlugin *plugin)
1420 Server *server = NULL;
1422 s_indi_cp_state_info_type *state_info = NULL;
1423 TcorePlugin *modem_plugin = NULL;
1424 s_indi_private_info *priv_info = __s_indi_get_priv_info(plugin);
1427 server = tcore_plugin_ref_server(plugin);
1428 tcore_server_remove_notification_hook(server, s_indi_on_hook_modem_power);
1429 tcore_server_remove_notification_hook(server, s_indi_on_hook_ps_call_status);
1430 tcore_server_remove_notification_hook(server, s_indi_on_hook_net_register);
1431 tcore_server_remove_notification_hook(server, s_indi_on_hook_sim_init);
1432 tcore_server_remove_notification_hook(server, s_indi_on_hook_voice_call_status);
1433 tcore_server_remove_notification_hook(server, s_indi_on_hook_modem_plugin_added);
1434 tcore_server_remove_notification_hook(server, s_indi_on_hook_modem_plugin_removed);
1436 /* Remove key callback */
1437 __s_indi_unregister_vconf_key(STORAGE_KEY_PM_STATE, plugin, NULL);
1439 /* Destroy all watched modems */
1440 iter = g_hash_table_get_values(priv_info->state_info);
1442 state_info = iter->data;
1443 modem_plugin = tcore_object_ref_plugin(state_info->co_ps);
1444 __s_indi_remove_modem_plugin(plugin, modem_plugin);
1446 iter = g_list_delete_link(iter, iter);
1449 /* Decrement hash table reference */
1450 g_hash_table_destroy(priv_info->state_info);
1451 g_hash_table_destroy(priv_info->vconf_info);
1454 s_indi_free(priv_info);
1455 tcore_plugin_link_user_data(plugin, NULL);