2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <vconf/vconf.h>
18 #include <openssl/sha.h>
20 #include "stc-monitor.h"
21 #include "stc-manager-gdbus.h"
22 #include "stc-default-connection.h"
24 /* connman service dbus details */
25 #define CONNMAN_SERVICE "net.connman"
26 #define CONNMAN_PATH "/net/connman"
28 #define CONNMAN_MANAGER_PATH "/"
29 #define CONNMAN_MANAGER_INTERFACE CONNMAN_SERVICE ".Manager"
30 #define CONNMAN_SERVICE_INTERFACE CONNMAN_SERVICE ".Service"
32 #define CONNMAN_CELLULAR_SERVICE_PROFILE_PREFIX CONNMAN_PATH "/service/cellular_"
33 #define CONNMAN_WIFI_SERVICE_PROFILE_PREFIX CONNMAN_PATH "/service/wifi_"
34 #define CONNMAN_ETHERNET_SERVICE_PROFILE_PREFIX CONNMAN_PATH "/service/ethernet_"
35 #define CONNMAN_BLUETOOTH_SERVICE_PROFILE_PREFIX CONNMAN_PATH "/service/bluetooth_"
37 #define CONNMAN_SIGNAL_PROPERTY_CHANGED "PropertyChanged"
39 /* telephony service dbus details */
40 #define TELEPHONY_SERVICE "org.tizen.telephony"
41 #define TELEPHONY_DEFAULT_PATH "/org/tizen/telephony"
43 #define TELEPHONY_SERVICE_MANAGER TELEPHONY_SERVICE".Manager"
44 #define TELEPHONY_SIM_INTERFACE TELEPHONY_SERVICE".Sim"
46 #define TELEPHONY_GET_MODEMS "GetModems"
47 #define TELEPHONY_GET_IMSI "GetIMSI"
49 #define SIM_SLOT_SINGLE 1
51 #define VCONF_TELEPHONY_DEFAULT_DATA_SERVICE "db/telephony/dualsim/default_data_service"
53 default_connection_s g_default_connection;
54 guint g_default_connection_sub_id = 0;
56 static int __telephony_get_current_sim(void)
58 int sim_slot_count = 0;
61 if (vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT_COUNT, &sim_slot_count) != 0) {
62 STC_LOGD("failed to get sim slot count"); //LCOV_EXCL_LINE
63 return -1; //LCOV_EXCL_LINE
66 if (sim_slot_count == SIM_SLOT_SINGLE) {
67 STC_LOGD("It's single sim model"); //LCOV_EXCL_LINE
68 return current_sim; //LCOV_EXCL_LINE
71 if (vconf_get_int(VCONF_TELEPHONY_DEFAULT_DATA_SERVICE, ¤t_sim) != 0) {
72 STC_LOGD("failed to get default data service = %d\n", //LCOV_EXCL_LINE
74 return -1; //LCOV_EXCL_LINE
80 static void __make_imsi_to_subscriber_id(char *imsi)
84 unsigned char md[SHA256_DIGEST_LENGTH];
87 SHA256_Update(&ctx, imsi, strlen(imsi));
88 SHA256_Final(md, &ctx);
90 for (i = 0; i < SHA256_DIGEST_LENGTH; ++i)
91 snprintf(g_default_connection.subscriber_id + (i * 2), 3, "%02x", md[i]);
94 static void __telephony_get_modem_subscriber_id(GDBusConnection *connection,
95 const char *default_modem_name)
97 GVariant *message = NULL;
98 char tel_path[MAX_PATH_LENGTH];
99 char imsi[IMSI_LENGTH];
100 const char *plmn = NULL;
102 const char *msin = NULL;
105 snprintf(tel_path, sizeof(tel_path), "%s/%s", TELEPHONY_DEFAULT_PATH,
107 message = stc_manager_gdbus_call_sync(connection,
110 TELEPHONY_SIM_INTERFACE,
113 if (message == NULL) {
114 STC_LOGE("Failed to get services informations"); //LCOV_EXCL_LINE
115 goto done; //LCOV_EXCL_LINE
118 DEBUG_PARAMS(message);
119 DEBUG_PARAM_TYPE(message);
120 g_variant_get(message, "(&s&s)", &plmn, &msin);
121 plmn_len = strlen(plmn);
122 msin_len = strlen(msin);
124 if (msin_len + plmn_len >= IMSI_LENGTH) {
125 STC_LOGD("Incorrect length of mobile subscriber identifier + net id"); //LCOV_EXCL_LINE
126 goto done; //LCOV_EXCL_LINE
129 snprintf(imsi, IMSI_LENGTH, "%s%s", plmn, msin);
130 __make_imsi_to_subscriber_id(imsi);
133 g_variant_unref(message);
137 static void __telephony_update_default_modem_subscriber_id(GDBusConnection *connection)
139 GVariant *message = NULL;
140 GVariantIter *iter = NULL;
141 gchar *default_modem_name = NULL;
142 gchar *modem_name = NULL;
143 int current_sim = __telephony_get_current_sim();
145 if (current_sim < 0) {
146 STC_LOGI("Sim not found"); //LCOV_EXCL_LINE
147 return; //LCOV_EXCL_LINE
150 message = stc_manager_gdbus_call_sync(connection,
152 TELEPHONY_DEFAULT_PATH,
153 TELEPHONY_SERVICE_MANAGER,
154 TELEPHONY_GET_MODEMS,
156 if (message == NULL) {
157 STC_LOGE("Failed to get services informations"); //LCOV_EXCL_LINE
158 return; //LCOV_EXCL_LINE
161 g_variant_get(message, "(as)", &iter);
162 DEBUG_PARAMS(message);
163 DEBUG_PARAM_TYPE(message);
164 while (g_variant_iter_loop(iter, "s", &modem_name)) {
165 if (current_sim == 0) {
166 default_modem_name = g_strdup(modem_name);
170 current_sim--; //LCOV_EXCL_LINE
173 __telephony_get_modem_subscriber_id(connection, default_modem_name);
175 FREE(default_modem_name);
176 g_variant_iter_free(iter);
177 g_variant_unref(message);
181 static void __print_default_connection_info(void)
183 STC_LOGI("============= default connection info ============");
184 STC_LOGI("path [%s]", g_default_connection.path);
185 STC_LOGI("type [%d]", g_default_connection.type);
186 STC_LOGI("ifname [%s]", g_default_connection.ifname);
187 STC_LOGI("roaming [%u]", g_default_connection.roaming ? TRUE : FALSE);
188 if (g_default_connection.type == STC_IFACE_DATACALL)
189 STC_LOGI("sub_id [%s]", g_default_connection.subscriber_id);
190 STC_LOGI("==================================================");
193 static void __reset_default_connection_data(void)
195 FREE(g_default_connection.path);
196 FREE(g_default_connection.ifname);
197 g_default_connection.type = STC_IFACE_UNKNOWN;
198 g_default_connection.roaming = FALSE;
201 static gboolean __is_cellular_internet_profile(const char *profile)
203 const char internet_suffix[] = "_1";
208 if (g_str_has_prefix(profile, CONNMAN_CELLULAR_SERVICE_PROFILE_PREFIX)
210 char *suffix = strrchr(profile, '_');
211 if (g_strcmp0(suffix, internet_suffix) == 0)
218 static gboolean __is_cellular_profile(const char *profile)
223 return g_str_has_prefix(profile, //LCOV_EXCL_LINE
224 CONNMAN_CELLULAR_SERVICE_PROFILE_PREFIX);
227 static gboolean __is_wifi_profile(const char *profile)
232 return g_str_has_prefix(profile, //LCOV_EXCL_LINE
233 CONNMAN_WIFI_SERVICE_PROFILE_PREFIX);
236 static gboolean __is_ethernet_profile(const char *profile)
241 return g_str_has_prefix(profile, //LCOV_EXCL_LINE
242 CONNMAN_ETHERNET_SERVICE_PROFILE_PREFIX);
245 static gboolean __is_bluetooth_profile(const char *profile)
250 return g_str_has_prefix(profile, //LCOV_EXCL_LINE
251 CONNMAN_BLUETOOTH_SERVICE_PROFILE_PREFIX);
254 static gboolean __is_connected(GVariantIter *array)
256 gboolean is_connected = FALSE;
257 GVariant *variant = NULL;
260 while (g_variant_iter_loop(array, "{sv}", &key, &variant)) {
261 if (g_strcmp0(key, "State") != 0)
264 if (g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) {
265 const gchar *state = NULL;
267 state = g_variant_get_string(variant, NULL);
268 if (g_strcmp0(state, "ready") == 0 ||
269 g_strcmp0(state, "online") == 0)
274 g_variant_unref(variant);
281 static void __get_default_connection_info(GDBusConnection *connection,
282 const char *object_path)
284 GVariant *message = NULL;
285 GVariantIter *iter = NULL;
286 GVariant *variant = NULL;
289 if (object_path == NULL) {
290 STC_LOGI("Object path is NULL, so information not available.");
294 message = stc_manager_gdbus_call_sync(connection,
297 CONNMAN_SERVICE_INTERFACE,
298 "GetProperties", NULL);
299 if (message == NULL) {
300 STC_LOGE("Failed to get services informations"); //LCOV_EXCL_LINE
301 goto done; //LCOV_EXCL_LINE
304 g_variant_get(message, "(a{sv})", &iter);
306 STC_LOGE("Profile %s doesn't exist", object_path); //LCOV_EXCL_LINE
307 goto done; //LCOV_EXCL_LINE
310 while (g_variant_iter_loop(iter, "{sv}", &key, &variant)) {
311 if (g_strcmp0(key, "Ethernet") == 0) {
312 GVariantIter *iter1 = NULL;
313 GVariant *variant1 = NULL;
316 g_variant_get(variant, "a{sv}", &iter1);
318 continue; //LCOV_EXCL_LINE
320 while (g_variant_iter_loop(iter1, "{sv}", &key1,
322 if (g_strcmp0(key1, "Interface") == 0) {
324 g_variant_get_string(variant1,
326 g_default_connection.ifname =
331 g_variant_iter_free(iter1);
333 } else if (g_strcmp0(key, "Roaming") == 0) {
334 gboolean roaming = 0;
336 if (g_variant_is_of_type(variant,
337 G_VARIANT_TYPE_BOOLEAN)) {
338 roaming = g_variant_get_boolean(variant);
339 g_default_connection.roaming = roaming;
346 g_variant_iter_free(iter);
349 g_variant_unref(message);
354 static stc_error_e __get_default_profile(GDBusConnection *connection)
356 GVariant *message = NULL;
357 GVariantIter *iter = NULL;
361 message = stc_manager_gdbus_call_sync(connection,
363 CONNMAN_MANAGER_PATH,
364 CONNMAN_MANAGER_INTERFACE,
365 "GetServices", NULL);
366 if (message == NULL) {
367 STC_LOGE("Failed to get profiles"); //LCOV_EXCL_LINE
368 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
371 g_variant_get(message, "(a(oa{sv}))", &iter);
372 while (g_variant_iter_loop(iter, "(oa{sv})", &object_path, &next)) {
373 if (object_path == NULL)
374 continue; //LCOV_EXCL_LINE
376 if (__is_cellular_profile(object_path) &&
377 !__is_cellular_internet_profile(object_path))
380 if (__is_connected(next) == TRUE) {
381 /* reset old default connection data */
382 FREE(g_default_connection.path);
383 FREE(g_default_connection.ifname);
384 g_default_connection.type = STC_IFACE_UNKNOWN;
385 g_default_connection.roaming = FALSE;
387 g_default_connection.path = g_strdup(object_path);
389 g_variant_iter_free(next);
394 g_variant_iter_free(iter);
395 g_variant_unref(message);
397 if (__is_cellular_profile(g_default_connection.path)) {
398 g_default_connection.type = STC_IFACE_DATACALL; //LCOV_EXCL_LINE
399 __telephony_update_default_modem_subscriber_id(connection); //LCOV_EXCL_LINE
400 } else if (__is_wifi_profile(g_default_connection.path)) {
401 g_default_connection.type = STC_IFACE_WIFI; //LCOV_EXCL_LINE
402 } else if (__is_ethernet_profile(g_default_connection.path)) {
403 g_default_connection.type = STC_IFACE_WIRED; //LCOV_EXCL_LINE
404 } else if (__is_bluetooth_profile(g_default_connection.path)) {
405 g_default_connection.type = STC_IFACE_BLUETOOTH; //LCOV_EXCL_LINE
407 g_default_connection.type = STC_IFACE_UNKNOWN; //LCOV_EXCL_LINE
410 __get_default_connection_info(connection, g_default_connection.path);
412 __print_default_connection_info();
414 stc_monitor_update_rstn_by_default_connection(&g_default_connection);
416 return STC_ERROR_NONE;
419 static void _service_signal_cb(GDBusConnection *conn,
420 const gchar *name, const gchar *path,
421 const gchar *interface, const gchar *sig,
422 GVariant *param, gpointer user_data)
424 gchar *sigvalue = NULL;
425 GVariant *variant = NULL;
426 stc_s *stc = (stc_s *)stc_get_manager();
427 ret_msg_if(stc == NULL, "failed to get stc data");
429 if (path == NULL || param == NULL)
432 g_variant_get(param, "(sv)", &sigvalue, &variant);
433 if (sigvalue == NULL)
436 if (g_strcmp0(sig, CONNMAN_SIGNAL_PROPERTY_CHANGED) != 0)
439 if (g_strcmp0(sigvalue, "State") == 0 &&
440 g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) {
441 const gchar *state = NULL;
443 state = g_variant_get_string(variant, NULL);
444 if (g_strcmp0(state, "ready") == 0 ||
445 g_strcmp0(state, "online") == 0) {
446 if (g_strcmp0(g_default_connection.path, path)) {
447 __reset_default_connection_data();
448 __get_default_profile(stc->connection);
451 if (g_strcmp0(g_default_connection.path, path) == 0) {
452 __reset_default_connection_data(); //LCOV_EXCL_LINE
453 __get_default_profile(stc->connection); //LCOV_EXCL_LINE
456 } else if (g_strcmp0(sigvalue, "Roaming") == 0) {
458 if (g_strcmp0(g_default_connection.path, path) == 0) {
459 gboolean roaming = 0;
461 if (g_variant_is_of_type(variant,
462 G_VARIANT_TYPE_BOOLEAN)) {
463 roaming = g_variant_get_boolean(variant);
464 g_default_connection.roaming = roaming;
476 g_variant_unref(variant);
481 stc_error_e stc_default_connection_monitor_init(stc_s *stc)
483 ret_value_msg_if(stc == NULL, STC_ERROR_INVALID_PARAMETER, "failed to get stc data");
485 __get_default_profile(stc->connection);
486 g_default_connection_sub_id =
487 stc_manager_gdbus_subscribe_signal(stc->connection,
489 CONNMAN_SERVICE_INTERFACE,
490 CONNMAN_SIGNAL_PROPERTY_CHANGED,
492 G_DBUS_SIGNAL_FLAGS_NONE,
496 STC_LOGI("Successfully subscribed connman [%s] signal", CONNMAN_SIGNAL_PROPERTY_CHANGED);
497 return STC_ERROR_NONE;
500 stc_error_e stc_default_connection_monitor_deinit(stc_s *stc)
502 ret_value_msg_if(stc == NULL, STC_ERROR_INVALID_PARAMETER, "failed to get stc data");
504 stc_manager_gdbus_unsubscribe_signal(stc->connection,
505 g_default_connection_sub_id);
506 FREE(g_default_connection.path);
507 FREE(g_default_connection.ifname);
508 return STC_ERROR_NONE;
511 gchar *stc_default_connection_get_ifname(void)
513 return g_strdup(g_default_connection.ifname);
516 default_connection_s *stc_get_default_connection(void)
518 return &g_default_connection;