From: sinikang Date: Mon, 17 Apr 2017 07:52:04 +0000 (+0900) Subject: Initial commit X-Git-Tag: submit/tizen/20170424.073428~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f647ddcf16f1fefc1f7ad84868c16c5b4b1a6639;p=platform%2Fcore%2Ftelephony%2Ftel-plugin-syspopup.git Initial commit Change-Id: I9f9fdcf704f0f9ce13d59c9eba0b65f5485857dc --- diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..40ad3b7 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +Ja-young Gu +JunHwan An diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f15d992 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,64 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(ui_notifier-plugin C) + +### Global setting ### +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(EXEC_PREFIX "\${prefix}") +SET(LIBDIR ${LIB_INSTALL_DIR}) +SET(INCLUDEDIR "\${prefix}/include") +SET(PKGCONFIGDIR "${PREFIX}/${LIBDIR}/pkgconfig" CACHE PATH PKGCONFIGDIR) +SET(CMAKE_INSTALL_PREFIX "${PREFIX}") + +# Set required packages +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED + glib-2.0 + tcore + aul + capi-system-device + pkgmgr + vconf + libtzplatform-config +) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wextra -fvisibility=hidden -fPIC -fdata-sections -ffunction-sections -Wl,--gc-sections") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-parameter -Wno-missing-field-initializers -Wdeclaration-after-statement -Wmissing-declarations -Wredundant-decls -Wcast-align") + +ADD_DEFINITIONS("-DFEATURE_TLOG_DEBUG") +ADD_DEFINITIONS("-DTCORE_LOG_TAG=\"UI_NOTI\"") +ADD_DEFINITIONS("-DPLUGIN_VERSION=${VERSION}") +ADD_DEFINITIONS("-DEXPORT_API=__attribute__((visibility(\"default\")))") + +IF (FEATURE_MULTISIM) + ADD_DEFINITIONS("-DTIZEN_FEATURE_MULTISIM") +ENDIF (FEATURE_MULTISIM) + +INCLUDE_DIRECTORIES( + ${CMAKE_SOURCE_DIR}/inc/ +) + +MESSAGE(${CMAKE_C_FLAGS}) +MESSAGE(${pkgs_LDFLAGS}) + +SET(SRCS + src/desc.c + src/notifier.c + src/notifier_launcher.c + src/notifier_internal.c + src/notifier_preferred_network.c + src/notifier_preferred_voice.c + src/notifier_util.c +) + +# library build +ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS} ${CDMA_SRCS} ${ACTIVATION_SRCS} ${TEST_SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS}) +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES PREFIX "" OUTPUT_NAME ${PROJECT_NAME}) + +# install +INSTALL(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${LIBDIR}/telephony/plugins) diff --git a/inc/notifier.h b/inc/notifier.h new file mode 100644 index 0000000..c7f239b --- /dev/null +++ b/inc/notifier.h @@ -0,0 +1,31 @@ +/* + * tel-plugin-ui_notifier + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Ja-young Gu + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include "notifier_internal.h" + +gboolean ui_notifier_init(TcorePlugin *plugin); +void ui_notifier_deinit(TcorePlugin *plugin); + +sim_slot_id __get_sim_slotid(CoreObject *source); diff --git a/inc/notifier_internal.h b/inc/notifier_internal.h new file mode 100644 index 0000000..b3bac24 --- /dev/null +++ b/inc/notifier_internal.h @@ -0,0 +1,167 @@ +/* + * tel-plugin-ui_notifier + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Ja-young Gu + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +////////////////////// SIM ////////////////////////// +#define IPC_MSG_SIM_NOT_PRESENTED "SimNotPresented" +#define IPC_MSG_SIM_CARD_REMOVED "SimRemoved" +#define IPC_MSG_SIM_CARD_ERROR "SimError" +#define IPC_MSG_SIM_CARD_CRASHED "SimCrashed" + +////////////////////// NETWORK ////////////////////////// +/* Emergency cb mode */ +#define IPC_MSG_NETWORK_EMERGENCY_CB_MODE_ENTER "NetworkEmergencyCbModeEnter" +#define IPC_MSG_NETWORK_EMERGENCY_CB_MODE_EXIT "NetworkEmergencyCbModeExit" +#define IPC_MSG_NETWORK_EMERGENCY_CB_MODE_READY "NetworkEmergencyCbModeReady" + +/* No Svc after manual network selection */ +#define IPC_MSG_SIM1_ADD_NETWORK_MANUAL_FAIL_NOTI "add_sim1_manual_network_fail_noti" +#define IPC_MSG_SIM1_DEL_NETWORK_MANUAL_FAIL_NOTI "del_sim1_manual_network_fail_noti" + +#define IPC_MSG_SIM2_ADD_NETWORK_MANUAL_FAIL_NOTI "add_sim2_manual_network_fail_noti" +#define IPC_MSG_SIM2_DEL_NETWORK_MANUAL_FAIL_NOTI "del_sim2_manual_network_fail_noti" + +/* No Svc after manual plmn selection */ +#define IPC_MSG_NETWORK_MANUAL_FAIL_POPUP "network_manual_fail_popup" +/* Roaming and roaming data allowed disalbed */ +#define IPC_MSG_NETWORK_DATA_ROAMING_POPUP "network_data_roaming_popup" +/* Roaming > Home network, Erase data roaming notification */ +#define IPC_MSG_NETWORK_DEL_DATA_ROAMING "del_network_data_roaming" + +/* DSAC rectricted */ +#define IPC_MSG_ADD_NETWORK_CS_RESTRICTED_NOTI "add_cs_restricted_state_noti" +#define IPC_MSG_ADD_NETWORK_PS_RESTRICTED_NOTI "add_ps_restricted_state_noti" +#define IPC_MSG_ADD_NETWORK_CS_PS_RESTRICTED_NOTI "add_cs_ps_restricted_state_noti" +#define IPC_MSG_DEL_NETWORK_RESTRICTED_NOTI "del_restricted_state_noti" + +/* Location update reject cause display */ +#define IPC_MSG_DISPLAY_NETWORK_LU_REJECT_CAUSE "DisplayNetworkLuRejectCause" + +/* NETWORK - Display MIP ERROR Cause */ +#define IPC_MSG_DISPLAY_MIP_ERROR_CAUSE "DisplayMIPErrorCause" + +/* NETWORK - Display NITZ Time Update */ +#define IPC_MSG_DISPLAY_NITZ_TIME_UPDATE "DisplayNitzTimeUpdate" +#define IPC_MSG_NITZ_MANUL_DATE_AND_TIME "nitz_manual_date_and_time" + +////////////////////// CALL ////////////////////////// +/* display information */ +#define IPC_CALL_DISPLAY_INFORMATION "DisplayInformation" + +////////////////////// activation /////////////////// +#define IPC_MSG_NETWORK_ACTIVATION_MODE "Network_Activation_Mode" +#define IPC_MSG_NETWORK_ACTIVATION_PASS "Network_Activation_Pass" +#define IPC_MSG_NETWORK_ACTIVATION_FAIL "Network_Activation_Fail" +#define IPC_MSG_NETWORK_ACTIVATION_FAIL_3TIMES "Network_Activation_Fail_3Times" +#define IPC_MSG_NETWORK_ACTIVATION_OTAPA_COMMITTED "Network_Activation_Otapa_Committed" + +#define NO_SVC_WAITING_TIMEOUT (25) +#define NITZ_TIMEZONE_SELECT_WAITING_TIMEOUT (30) + +#define PROP_NET_NITZ_TIMEZONE "nitz_timezone" + +struct activation_data { + int activation_fail_count; + CoreObject *co_modem; + char *esn; +} ; + +/** + * This structure defines the data needed to create desktop file. + */ +struct sat_desktop_file_data { + gboolean is_event; /* TRUE if any even available to process */ + gchar *title; /** + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <stdio.h> +#include <gio/gio.h> + +#define POPUP_IPC "msg" +#define POPUP_IPC_PARAM "param" +#define AUL_NAME "org.tizen.telephony-syspopup" +#define SYSPOPUP_NAME "telephony-syspopup" +#define UI_NOTI_ONE_SEC 1 + +void launch_pwlock(void); +void launch_pwlock_pin_block(void); +void launch_setup_ota(void); +void launch_telephony_popup(const char *message, const char *param, void *ud); + + diff --git a/inc/notifier_preferred_network.h b/inc/notifier_preferred_network.h new file mode 100644 index 0000000..d35324c --- /dev/null +++ b/inc/notifier_preferred_network.h @@ -0,0 +1,25 @@ +/* + * tel-plugin-ui_notifier + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Ja-young Gu <jygu@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <tcore.h> + +gboolean notifier_preferred_network_init(TcorePlugin *plugin); + diff --git a/inc/notifier_preferred_voice.h b/inc/notifier_preferred_voice.h new file mode 100644 index 0000000..8ee6a50 --- /dev/null +++ b/inc/notifier_preferred_voice.h @@ -0,0 +1,26 @@ +/* + * tel-plugin-ui_notifier + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Ja-young Gu <jygu@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include <tcore.h> + +gboolean notifier_preferred_voice_init(TcorePlugin *plugin); + + diff --git a/inc/notifier_util.h b/inc/notifier_util.h new file mode 100644 index 0000000..68929aa --- /dev/null +++ b/inc/notifier_util.h @@ -0,0 +1,30 @@ +/* + * tel-plugin-ui_notifier + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Ja-young Gu <jygu@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <systemd/sd-login.h> +#include <tzplatform_config.h> + +#define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER) + +void ui_notifier_lock_sleep(void); +void ui_notifier_unlock_sleep(void); +float ui_notifier_check_uptime(); \ No newline at end of file diff --git a/packaging/tel-plugin-ui_notifier.spec b/packaging/tel-plugin-ui_notifier.spec new file mode 100644 index 0000000..c41d5a7 --- /dev/null +++ b/packaging/tel-plugin-ui_notifier.spec @@ -0,0 +1,50 @@ +%define major 0 +%define minor 1 +%define patchlevel 0 + +Name: tel-plugin-ui_notifier +Version: %{major}.%{minor}.%{patchlevel} +Release: 1 +License: Apache +Summary: Telephony UI Notifier plugin +Group: System/Libraries +Source0: tel-plugin-ui_notifier-%{version}.tar.gz +BuildRequires: cmake +BuildRequires: pkgconfig(aul) +BuildRequires: pkgconfig(capi-system-device) +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(pkgmgr) +BuildRequires: pkgconfig(tcore) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(capi-appfw-application) +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig + +%description +Telephony UI Notifier plugin + +%prep +%setup -q + +%build +versionint=$[%{major} * 1000000 + %{minor} * 1000 + %{patchlevel}] +cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DVERSION=$versionint \ + -DLIB_INSTALL_DIR=%{_libdir} \ +%if 1%{?sec_product_feature_network_dsds} + -DFEATURE_MULTISIM=1 \ +%endif + +make %{?_smp_mflags} + +%post +/sbin/ldconfig + +%postun -p /sbin/ldconfig + +%install +%make_install + +%files +%manifest tel-plugin-ui_notifier.manifest +%defattr(-,root,root,-) +%{_libdir}/telephony/plugins/ui_notifier-plugin* diff --git a/src/desc.c b/src/desc.c new file mode 100644 index 0000000..c006f2a --- /dev/null +++ b/src/desc.c @@ -0,0 +1,59 @@ +/* + * tel-plugin-ui_notifier + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Ja-young Gu <jygu@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "notifier.h" + +#include <plugin.h> + +#ifndef PLUGIN_VERSION +#define PLUGIN_VERSION 1 +#endif + +static gboolean on_load() +{ + dbg("i'm load!"); + return TRUE; +} + +static gboolean on_init(TcorePlugin *plugin) +{ + dbg("i'm init!"); + g_assert(plugin != NULL); + + return ui_notifier_init(plugin); +} + +static void on_unload(TcorePlugin *plugin) +{ + dbg("i'm unload!"); + g_assert(plugin != NULL); + + ui_notifier_deinit(plugin); +} + +EXPORT_API struct tcore_plugin_define_desc plugin_define_desc = +{ + .name = "UI_NOTIFIER", + .priority = TCORE_PLUGIN_PRIORITY_LOW, + .version = PLUGIN_VERSION, + .load = on_load, + .init = on_init, + .unload = on_unload +}; diff --git a/src/notifier.c b/src/notifier.c new file mode 100644 index 0000000..86da6e8 --- /dev/null +++ b/src/notifier.c @@ -0,0 +1,844 @@ +/* + * tel-plugin-ui_notifier + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Ja-young Gu <jygu@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <tcore.h> +#include <server.h> +#include <plugin.h> +#include <storage.h> +#include <user_request.h> +#include <co_network.h> +#include <co_modem.h> +#include <co_sim.h> +#include <vconf.h> + +#include "notifier.h" +#include "notifier_util.h" +#include "notifier_internal.h" +#include "notifier_launcher.h" +#include "notifier_preferred_network.h" +#include "notifier_preferred_voice.h" + +//Temporaily add for build +#define VCONFKEY_TELEPHONY_PRIVATE_MANUAL_PLMN_SIM1 VCONFKEY_TELEPHONY_PRIVATE_MANUAL_PLMN +#define VCONFKEY_TELEPHONY_PRIVATE_MANUAL_PLMN_SIM2 VCONFKEY_TELEPHONY_PRIVATE_MANUAL_PLMN + +static gboolean on_prop_changed (CoreObject *co, const void *event_info, void *user_data); + +static gboolean _is_in_service(enum telephony_network_service_type service_type) +{ + switch (service_type) { + case NETWORK_SERVICE_TYPE_UNKNOWN: + case NETWORK_SERVICE_TYPE_NO_SERVICE: + case NETWORK_SERVICE_TYPE_EMERGENCY: + case NETWORK_SERVICE_TYPE_SEARCH: + return FALSE; + default: + return TRUE; + } +} + +static gboolean __is_file_exist(char *path) +{ + FILE* fp = NULL; + gboolean ret = FALSE; + + if (!path) + return FALSE; + + fp = fopen(path, "r"); + if(fp) { + info("[%s] exist", path); + fclose(fp); + ret = TRUE; + } + + return ret; +} + +sim_slot_id __get_sim_slotid(CoreObject *source) +{ + TcorePlugin *plugin = NULL; + char *cp_name = NULL; + + if (!source) { + return SLOT_ID_MAX; + } + plugin = tcore_object_ref_plugin(source); + if (!plugin) { + return SLOT_ID_MAX; + } + cp_name = (char *)tcore_server_get_cp_name_by_plugin(plugin); + if (!cp_name) { + return SLOT_ID_MAX; + } + if(g_str_has_suffix(cp_name , "0")){ + return SLOT_ID_PRIMARY; + } else if (g_str_has_suffix(cp_name , "1")){ + return SLOT_ID_SECONDARY; + } else if(g_str_has_suffix(cp_name , "2")){ + return SLOT_ID_TERTIARY; + } else { + return SLOT_ID_MAX; + } +} + +static gboolean __all_sims_absent(ui_noti_data *ud) +{ + guint id, sim_not_present_count = 0; + + for (id = 0; id < ud->modems_count; id++) { + if (ud->sim_status[id] == SIM_STATUS_CARD_NOT_PRESENT) { + sim_not_present_count++; + } + dbg("slot:[%d] sim_status : [0x%x]", id, ud->sim_status[id]); + } + + dbg("modems_count %d sim_not_present_count %d", ud->modems_count, sim_not_present_count); + + if (sim_not_present_count == ud->modems_count) { + dbg("Both SIMS are not present"); + return TRUE; + } + return FALSE; +} + +static void __update_first_bootup_info(TcorePlugin *p, sim_slot_id id, enum tel_sim_status sim_status) +{ + ui_noti_data *ud = NULL; + + if ((ud = tcore_plugin_ref_user_data(p)) == NULL) { + err("tcore_plugin_ref_user_data() returns NULL."); + return; + } + + if (sim_status == SIM_STATUS_CARD_ERROR || + sim_status == SIM_STATUS_CARD_NOT_PRESENT || + sim_status == SIM_STATUS_INIT_COMPLETED || + sim_status == SIM_STATUS_CARD_BLOCKED || + sim_status == SIM_STATUS_CARD_POWEROFF) { + + dbg("updating bootup info..slot[%d]", id); + ud->first_bootup_sim[id] = TRUE; + } +} + +static void _check_net_prop_event_registered(ui_noti_data *ud, CoreObject *co_network, TcorePlugin *p, sim_slot_id id) +{ + if (ud->prop_event_registered[id] == FALSE) { + dbg ("event register for id %d", id); + ud->prop_event_registered[id] = TRUE; + ud->co_network[id] = co_network; + tcore_object_add_callback (co_network, CORE_OBJECT_EVENT_PROPERTY_CHANGED, + on_prop_changed, p); + } +} + + +static void _update_roaming_popup(ui_noti_data *ud) +{ + gboolean roaming_status = ud->roaming_status[ud->default_data_slot]; + + info("DefaultDataSlot(%d), RoamingStatus(%d), MobileDataAllowed(%d), RoamingDataAllowed(%d), RoamingPopupLaunched(%d)", + ud->default_data_slot, roaming_status, ud->mobile_data_allowed, ud->roaming_data_allowed, ud->roaming_popup_launched); + + if (ud->mobile_data_allowed && roaming_status) { + if (!ud->roaming_data_allowed && !ud->roaming_popup_launched) { + info("Roaming data allowed enable popup required"); + ud->roaming_popup_launched = TRUE; + launch_roaming_data_allowed_popup(ud); + return; + } + } + + if (ud->roaming_popup_launched) { + info("Remove roaming notification"); + launch_telephony_popup(IPC_MSG_NETWORK_DEL_DATA_ROAMING, "", ud); + ud->roaming_popup_launched = FALSE; + } +} + + +#ifdef TIZEN_FEATURE_MULTISIM +static void _check_net_roaming_data_allowed_with_slot_id(ui_noti_data *ud, int roaming_status, sim_slot_id id) +{ + if (ud->roaming_status[id] != roaming_status) { + info("SIM%d Roaming Status Change:(%d)->(%d)", id+1, ud->roaming_status[id], roaming_status); + ud->roaming_status[id] = roaming_status; + _update_roaming_popup(ud); + } +} + +static void on_default_data_slot_changed(keynode_t* node, void* user_data) { + TcorePlugin *p = user_data; + ui_noti_data *ud = tcore_plugin_ref_user_data(p); + + if (!ud) + return; + + vconf_get_int(VCONFKEY_TELEPHONY_DB_DEFAULT_DATA_SUBS, &ud->default_data_slot); + dbg("default data slot:[%d]", ud->default_data_slot); + _update_roaming_popup(ud); +} +#else +static void _check_net_roaming_data_allowed(ui_noti_data *ud, int roaming_status, + enum telephony_network_service_domain_status ps_domain_status) +{ + + if (ud->roaming_status[SLOT_ID_DEFAULT] != roaming_status) { + info("Status Change:(%d)->(%d). PS(%d) Roam Data Allowed (%d)", + ud->roaming_status[SLOT_ID_DEFAULT], roaming_status, ps_domain_status, ud->roaming_data_allowed); + + ud->roaming_status[SLOT_ID_DEFAULT] = roaming_status; + + if (ud->roaming_status[SLOT_ID_DEFAULT]) { + int do_not_ask = 0; + vconf_get_int(VCONFKEY_TELEPHONY_PRIVATE_DATA_ROAMING_POPUP_CHECKBOX, &do_not_ask); + if (do_not_ask) { + info("Roaming area. But, User don't want to see popup"); + return; + } else { + info("Roaming area. We check roaming popup required"); + } + } + + _update_roaming_popup(ud); + } +} +#endif + +static void _check_net_manual_selection_no_svc(ui_noti_data *ud, enum telephony_network_service_type svc_type, sim_slot_id id) +{ + //if (!tfeature_is_supported(TFEATURE_UI_NO_SVC_MANUAL_PLMN_CHECK)) + // return; + + if (!ud->manual_plmn[id]) + return; + + + if (ud->sim_status[id] != SIM_STATUS_INIT_COMPLETED) { + info ("We don't need to check manual_selection with sim_status(%d)", ud->sim_status[id]); + return; + } + + if (ud->flight_mode) { + info ("We don't need to check manual_selection with flight mode(%d)", ud->flight_mode); + return; + } + if (ud->psmode) { + info ("We don't need to check manual_selection with power saving mode(%d)", ud->psmode); + return; + } + + ud->svc_type[id] = svc_type; + dbg ("For slot(%d) service_type (%d) manual_plmn (%s)", id, ud->svc_type[id], ud->manual_plmn[id]?ud->manual_plmn[id]:""); + + switch (ud->svc_type[id]) { + case NETWORK_SERVICE_TYPE_UNKNOWN: + break; + case NETWORK_SERVICE_TYPE_NO_SERVICE: + case NETWORK_SERVICE_TYPE_EMERGENCY: + case NETWORK_SERVICE_TYPE_SEARCH: + { + if (ud->manual_plmn[id]) { + if (ud->manual_plmn_popup_required[id]) { + info ("manual selection (%s) exist and home screen launched. launch popup", ud->manual_plmn[id]); + launch_no_svc_with_manual_plmn_popup(ud, id); + ud->manual_plmn_popup_required[id] = FALSE; + } else { + dbg ("popup is not required"); + } + } else { + dbg ("No manual plmn (Automatic). do nothing"); + } + } + break; + default : { + if (ud->manual_plmn[id]) { + cancel_no_svc_with_manual_plmn_popup(ud, id); + } + } + break; + } +} + +static void _check_net_manual_selection_no_svc_current(ui_noti_data *ud, sim_slot_id id) +{ + if (ud->co_network[id]) { + enum telephony_network_service_type svc_type; + tcore_network_get_service_type(ud->co_network[id], &svc_type); + _check_net_manual_selection_no_svc(ud, svc_type, id); + } +} + +static void _handle_prop_net_nitz_timezone(TcorePlugin *p, CoreObject *co) +{ + ui_noti_data *ud = NULL; + const char *value = NULL; + + if ((ud = tcore_plugin_ref_user_data(p)) == NULL) { + err("tcore_plugin_ref_user_data() returns NULL."); + return; + } + + value = tcore_object_ref_property (co, PROP_NET_NITZ_TIMEZONE); + info ("Nitz Timezone Status = %s", value); + + if (g_strcmp0 (value, "user_selection_required") == 0) { + launch_timezone_select_popup(ud); + } +} + +static void _handle_prop_net_manual_selection_status(TcorePlugin *p, CoreObject *co) +{ + ui_noti_data *ud = NULL; + const char *value = NULL; + sim_slot_id id; + + if ((ud = tcore_plugin_ref_user_data(p)) == NULL) { + err("tcore_plugin_ref_user_data() returns NULL."); + return; + } + + id = __get_sim_slotid(co); + value = tcore_object_ref_property (co, PROP_NET_MANUAL_SELECTION_STATUS); + info ("slot(%d), manual selection status = %s", id, value); + + if (g_strcmp0 (value, "waiting") == 0) { + dbg ("Waiting for manual selection result"); + cancel_no_svc_with_manual_plmn_popup(ud, id); + ud->manual_plmn_popup_required[id] = FALSE; + } + else if ((g_strcmp0 (value, "failure") == 0) + || (g_strcmp0 (value, "success") == 0)) { + dbg ("manual selection done. Check service type"); + ud->manual_plmn_popup_required[id] = TRUE; + _check_net_manual_selection_no_svc_current(ud, id); + } else { + dbg ("Changed to Automatic."); + cancel_no_svc_with_manual_plmn_popup(ud, id); + ud->manual_plmn_popup_required[id] = FALSE; + } +} + +static void _handle_prop_net_manual_plmn(TcorePlugin *p, CoreObject *co) +{ + ui_noti_data *ud = NULL; + const char *manual_plmn = NULL; + sim_slot_id id; + + if ((ud = tcore_plugin_ref_user_data(p)) == NULL) { + err("tcore_plugin_ref_user_data() returns NULL."); + return; + } + + id = __get_sim_slotid(co); + manual_plmn = tcore_object_ref_property (co, PROP_NET_MANUAL_PLMN); + dbg ("property changed (value = %s) for slot(%d)", (manual_plmn?manual_plmn:"Null"), id); + + if (manual_plmn == NULL) { + manual_plmn = ""; + free(ud->manual_plmn[id]); + ud->manual_plmn[id] = NULL; + } else { + free(ud->manual_plmn[id]); + ud->manual_plmn[id] = strdup(manual_plmn); + ud->manual_plmn_popup_required[id] = TRUE; + } + + if (id == SLOT_ID_PRIMARY) { + vconf_set_str(VCONFKEY_TELEPHONY_PRIVATE_MANUAL_PLMN_SIM1, manual_plmn); + } else if (id == SLOT_ID_SECONDARY) { + vconf_set_str(VCONFKEY_TELEPHONY_PRIVATE_MANUAL_PLMN_SIM2, manual_plmn); + } else { + warn("Unsupported id(%d)", id); + return; + } + info ("For slot(%d) key Set to : [%s], manual_plmn:[%s], popup_required:[%d]", + id, manual_plmn, ud->manual_plmn[id]?ud->manual_plmn[id]:"Null", ud->manual_plmn_popup_required[id]); + + _check_net_manual_selection_no_svc_current(ud, id); + +} + +static void _process_flight_mode_state(TcorePlugin *p, gboolean new_mode) +{ + ui_noti_data *ud = NULL; + guint id; + enum tel_sim_status sim_status; + + if ((ud = tcore_plugin_ref_user_data(p)) == NULL) { + err("tcore_plugin_ref_user_data() returns NULL."); + return; + } + + if (ud->flight_mode == new_mode) + return; + + do { + if (new_mode == FALSE && ud->flight_mode == TRUE) { // Flight enable -> Disable + dbg("Flight mode changed On to Off"); + for (id = 0; id < ud->modems_count; id++) { + sim_status = ud->sim_status[id]; + dbg("slot:[%d] sim_status : [0x%x]", id, ud->sim_status[id]); + if (sim_status == SIM_STATUS_PIN_REQUIRED || + sim_status == SIM_STATUS_PUK_REQUIRED || + sim_status == SIM_STATUS_NCK_REQUIRED || + sim_status == SIM_STATUS_NSCK_REQUIRED || + sim_status == SIM_STATUS_SPCK_REQUIRED || + sim_status == SIM_STATUS_CCK_REQUIRED) { + dbg("Launching pwlock(flight mode)"); + launch_pwlock(); + break; + } + } + } + } while (0); + ud->flight_mode = new_mode; + + //if (tfeature_is_supported(TFEATURE_UI_NO_SVC_MANUAL_PLMN_CHECK)) { + if(1) { + if (ud->flight_mode) { + dbg("Flight mode on. stop checking manual plmn"); + for (id = 0; id < ud->modems_count; id++) { + cancel_no_svc_with_manual_plmn_popup(ud, id); + ud->manual_plmn_popup_required[id] = FALSE; + } + } else { + dbg("Flight mode off. Check no svc manual plmn"); + for (id = 0; id < ud->modems_count; id++) { + ud->manual_plmn_popup_required[id] = TRUE; + _check_net_manual_selection_no_svc_current(ud, id); + } + } + } + +} + +static gboolean on_prop_changed (CoreObject *co, const void *event_info, + void *user_data) +{ + GSList *key = (GSList *)event_info; + + if (CORE_OBJECT_KEY_FIND(key, PROP_NET_MANUAL_PLMN)) { + //if (tfeature_is_supported(TFEATURE_UI_NO_SVC_MANUAL_PLMN_CHECK)) { + _handle_prop_net_manual_plmn((TcorePlugin *)user_data, co); + //} + } + else if (CORE_OBJECT_KEY_FIND(key, PROP_NET_MANUAL_SELECTION_STATUS)) { + //if (tfeature_is_supported(TFEATURE_UI_NO_SVC_MANUAL_PLMN_CHECK)) { + _handle_prop_net_manual_selection_status((TcorePlugin *)user_data, co); + //} + } + else if (CORE_OBJECT_KEY_FIND(key, PROP_NET_NITZ_TIMEZONE)) { + _handle_prop_net_nitz_timezone((TcorePlugin *)user_data, co); + } + + return TRUE; +} + +static enum tcore_hook_return on_hook_network_plmn_change(Server *s, CoreObject *source, + enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data) +{ + ui_noti_data *ud; + struct tnoti_network_change *info = data; + + ud = tcore_plugin_ref_user_data (user_data); + if (!ud || !info || strlen(info->plmn) == 0) { + dbg ("Invalid Data"); + return TCORE_HOOK_RETURN_CONTINUE; + } + + if ((ud->current_plmn && strncmp(info->plmn, ud->current_plmn, 3)) + || (!ud->current_plmn)) { + info("MCC change (%s) -> (%s)", ud->current_plmn?ud->current_plmn:"", info->plmn); + g_free(ud->current_plmn); + ud->current_plmn = g_strdup(info->plmn); + } + + return TCORE_HOOK_RETURN_CONTINUE; +} + +static enum tcore_hook_return on_hook_network_service_type_change(Server *s, CoreObject *source, + enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data) +{ + TcorePlugin *p = user_data; + ui_noti_data *ud; + struct tnoti_network_registration_status *info = data; + sim_slot_id id; + + ud = tcore_plugin_ref_user_data (user_data); + if (!ud) { + err ("tcore_plugin_ref_user_data() is NULL"); + return TCORE_HOOK_RETURN_CONTINUE; + } + + if (!info) { + err ("tnoti_network_registration_status() is NULL"); + return TCORE_HOOK_RETURN_CONTINUE; + } + + id = __get_sim_slotid(source); + if (ud->sim_status[id] == SIM_STATUS_CARD_NOT_PRESENT || + ud->sim_status[id]== SIM_STATUS_UNKNOWN) { + dbg ("No SIM or Unknown"); + return TCORE_HOOK_RETURN_CONTINUE; + } + + dbg("slot:[%d] sim_status : [0x%x]", id, ud->sim_status[id]); + + _check_net_prop_event_registered(ud, source, p, id); + if (_is_in_service(info->service_type)) { +#ifdef TIZEN_FEATURE_MULTISIM + _check_net_roaming_data_allowed_with_slot_id(ud, info->roaming_status, id); +#else + _check_net_roaming_data_allowed(ud, info->roaming_status, info->ps_domain_status); +#endif + } else { + warn("UE is not in service. Do not refer roaming status yet"); + } + _check_net_manual_selection_no_svc(ud, info->service_type, id); + + return TCORE_HOOK_RETURN_CONTINUE; +} + +static void on_hook_nitz_gmt_change(keynode_t* node, void* user_data) { + TcorePlugin *p = user_data; + ui_noti_data *ud = tcore_plugin_ref_user_data(p); + + if (!ud) + return; + + if (!ud->nitz_popup_launched) { + gboolean audo_update; + vconf_get_bool(VCONFKEY_SETAPPL_STATE_AUTOMATIC_TIME_UPDATE_BOOL, &audo_update); + if (audo_update == FALSE) + return; + + //if (tfeature_is_supported(TFEATURE_UI_NITZ_TIME_UPDATE_POPUP)) { + if(1) { + info("Launch NITZ Time Update popup (Only for First NITZ)"); + launch_telephony_popup(IPC_MSG_DISPLAY_NITZ_TIME_UPDATE, "", ud); + } + ud->nitz_popup_launched = TRUE; + } +} + +static void on_power_saving_mode_changed(keynode_t* node, void* user_data) { + TcorePlugin *p = user_data; + ui_noti_data *ud = tcore_plugin_ref_user_data(p); + guint id; + + if (!ud) + return; + + vconf_get_int(VCONFKEY_SETAPPL_PSMODE, &ud->psmode); + + //if (tfeature_is_supported(TFEATURE_UI_NO_SVC_MANUAL_PLMN_CHECK)) { + for (id = 0; id < ud->modems_count; id++) { + _check_net_manual_selection_no_svc_current(ud, id); + } + //} +} + +static enum tcore_hook_return on_hook_sim_status(Server *s, CoreObject *source, + enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data) +{ + TcorePlugin *p = user_data; + ui_noti_data *ud = NULL; + const struct tnoti_sim_status *sim = data; + const char *cp_name; + sim_slot_id id; + guint i, first_bootup_count = 0; + + if ((ud = tcore_plugin_ref_user_data(p)) == NULL) { + err("tcore_plugin_ref_user_data() returns NULL."); + return TCORE_HOOK_RETURN_CONTINUE; + } + + if (!ud->co_sim) { + ud->co_sim = source; + } + + id = __get_sim_slotid(source); + ud->sim_status[id] = sim->sim_status; + dbg("slot:[%d] sim_status : [0x%x]", id, ud->sim_status[id]); + + /* + * 14/10/17 + * PLM# : P141007-00246 + * Problem : when AT+CFUN=0 "SIM ERROR" popup is coming + * Requirement : should not raise a popup while in automation test. + */ + if (sim->sim_status == SIM_STATUS_CARD_ERROR || + sim->sim_status == SIM_STATUS_CARD_CRASHED || + sim->sim_status == SIM_STATUS_CARD_REMOVED) { + #define TMP_FILE_AT_CFUN_0 "/tmp/data-router/at_cfun0" + if (__is_file_exist(TMP_FILE_AT_CFUN_0)) { + dbg("not handling SIM ERROR/REMOVAL event."); + return TCORE_HOOK_RETURN_CONTINUE; + } + } + + switch(ud->sim_status[id]) { + case SIM_STATUS_CARD_NOT_PRESENT: + case SIM_STATUS_CARD_ERROR: + /* + * To let User knows current SIM Card has ERROR + * raise pop-up when initial SIM Card error case (SIM_STATUS_CARD_ERROR) + * since there is no displaying area to show "SIM Card Error" msg in Gear 3. + */ + info("NO SIM or SIM CARD ERROR!"); + /* launch NO SIM notification only when both sims are not present*/ + if (__all_sims_absent(ud)) { +#ifdef TIZEN_FEATURE_SHOW_NO_SIM_ONGOING_NOTI + launch_telephony_popup(IPC_MSG_SIM_NOT_PRESENTED, "", ud); +#endif + //if (tfeature_is_supported(TFEATURE_UI_SIM_RAISE_INVALID_SIM_POPUP)) { + launch_telephony_popup(IPC_MSG_SIM_CARD_ERROR, "", ud); + //} + } + break; + case SIM_STATUS_CARD_CRASHED: + info("SIM CARD CRASHED!"); +#ifdef TIZEN_FEATURE_SHOW_NO_SIM_ONGOING_NOTI + launch_telephony_popup(IPC_MSG_SIM_NOT_PRESENTED, "", ud); +#endif + //if (tfeature_is_supported(TFEATURE_UI_SIM_RAISE_INVALID_SIM_POPUP)) { + if(1) { + launch_telephony_popup(IPC_MSG_SIM_CARD_CRASHED, "", ud); + } else { + launch_telephony_popup(IPC_MSG_SIM_CARD_REMOVED, "", ud); + } + break; + case SIM_STATUS_CARD_REMOVED: + info("SIM IS REMOVED!"); + cp_name = tcore_server_get_cp_name_by_plugin(tcore_object_ref_plugin(source)); + dbg("cp_name: [%s]", cp_name); +#ifdef TIZEN_FEATURE_SHOW_NO_SIM_ONGOING_NOTI + if (__all_sims_absent(ud)) { + launch_telephony_popup(IPC_MSG_SIM_NOT_PRESENTED, "", ud); + } +#endif + launch_telephony_popup(IPC_MSG_SIM_CARD_REMOVED, "", ud); + break; + case SIM_STATUS_INIT_COMPLETED: + //if (tfeature_is_supported(TFEATURE_UI_NO_SVC_MANUAL_PLMN_CHECK)) { + _check_net_manual_selection_no_svc_current(ud, id); + //} + //if (tfeature_is_supported(TFEATURE_FUNCTION_CHECK_ACTIVATED_SIM)) { + // _check_sim_ota_status(); + //} + break; + case SIM_STATUS_PIN_REQUIRED: + case SIM_STATUS_PUK_REQUIRED: + case SIM_STATUS_CARD_BLOCKED: + case SIM_STATUS_NCK_REQUIRED: + case SIM_STATUS_NSCK_REQUIRED: + case SIM_STATUS_SPCK_REQUIRED: + case SIM_STATUS_CCK_REQUIRED: + case SIM_STATUS_LOCK_REQUIRED: + for (i = 0; i < ud->modems_count; i++) { + if (ud->first_bootup_sim[i] == TRUE) + first_bootup_count++; + } + + if (first_bootup_count == ud->modems_count) { + dbg("Launching pwlock(pin_block)"); + launch_pwlock_pin_block(); + } else { + dbg("On Bootup - No need to launch pwlock"); + } + break; + default: + break; + } + + /* Updating bootup info to detect first boot */ + __update_first_bootup_info(p, id, ud->sim_status[id]); + + return TCORE_HOOK_RETURN_CONTINUE; +} + +static void on_storage_key_callback(enum tcore_storage_key key, void *value, void *user_data) +{ + TcorePlugin *p = user_data; + GVariant *tmp = (GVariant *)value; + gboolean type_check = FALSE; + + if (!tmp || !p) { + err("Invalid cb data"); + return; + } + + switch(key) { + case STORAGE_KEY_FLIGHT_MODE_BOOL: + case STORAGE_KEY_SETAPPL_STATE_DATA_ROAMING_BOOL: + case STORAGE_KEY_3G_ENABLE: + { + type_check = g_variant_is_of_type(tmp, G_VARIANT_TYPE_BOOLEAN); + if (!type_check){ + err("wrong variant data type"); + g_variant_unref(tmp); + return; + } + } + break; + default: { + warn("unknown key"); + return; + } + break; + } + + if (key == STORAGE_KEY_FLIGHT_MODE_BOOL){ + gboolean new_mode; + new_mode = g_variant_get_boolean(tmp); + _process_flight_mode_state(p, new_mode); + } else if (key == STORAGE_KEY_SETAPPL_STATE_DATA_ROAMING_BOOL) { + ui_noti_data *ud = tcore_plugin_ref_user_data(p); + if (ud) { + ud->roaming_data_allowed = g_variant_get_boolean(tmp); + dbg("roaming_data_allowed changed (%d)", ud->roaming_data_allowed); + _update_roaming_popup(ud); + } + } else if (key == STORAGE_KEY_3G_ENABLE) { + ui_noti_data *ud = tcore_plugin_ref_user_data(p); + if (ud) { + ud->mobile_data_allowed = g_variant_get_boolean(tmp); + dbg("mobile_data_allowed changed (%d)", ud->mobile_data_allowed); + _update_roaming_popup(ud); + } + } + return; +} + +gboolean ui_notifier_init(TcorePlugin *plugin) +{ + Server *s; + ui_noti_data *ud; + guint id; + + ud = calloc(sizeof(ui_noti_data), 1); + if (tcore_plugin_link_user_data(plugin, ud) != TCORE_RETURN_SUCCESS) { + free(ud); + return FALSE; + } + + ud->flight_mode = FALSE; + ud->roaming_popup_launched = FALSE; + + s = tcore_plugin_ref_server(plugin); + ud->modems_count = tcore_server_get_modems_count(s); + + for (id = 0; id < ud->modems_count; id++) { + ud->sim_status[id] = SIM_STATUS_UNKNOWN; + ud->first_bootup_sim[id] = FALSE; + ud->roaming_status[id] = 0; + if (id == SLOT_ID_PRIMARY) { + ud->manual_plmn[id] = vconf_get_str (VCONFKEY_TELEPHONY_PRIVATE_MANUAL_PLMN_SIM1); + } else if (id == SLOT_ID_SECONDARY) { + ud->manual_plmn[id] = vconf_get_str (VCONFKEY_TELEPHONY_PRIVATE_MANUAL_PLMN_SIM2); + } else { + warn("Unsupported id(%d)", id); + break; + } + + ud->manual_plmn_noti_launched[id] = FALSE; + if (ud->manual_plmn[id] && strlen(ud->manual_plmn[id]) == 0) { + dbg("No saved manual plmn. set to NULL"); + free(ud->manual_plmn[id]); + ud->manual_plmn[id] = NULL; + ud->manual_plmn_popup_required[id] = FALSE; + } else { + dbg("For slot(%d), Saved manual plmn:(%s)", id, ud->manual_plmn[id]); + ud->manual_plmn_popup_required[id] = TRUE; + } + } + + ud->strg_vconf = tcore_server_find_storage(s, "vconf"); + ud->flight_mode = tcore_storage_get_bool(ud->strg_vconf, STORAGE_KEY_FLIGHT_MODE_BOOL); + ud->roaming_data_allowed = tcore_storage_get_bool(ud->strg_vconf, STORAGE_KEY_SETAPPL_STATE_DATA_ROAMING_BOOL); + ud->mobile_data_allowed = tcore_storage_get_bool(ud->strg_vconf, STORAGE_KEY_3G_ENABLE); + + vconf_get_int(VCONFKEY_SETAPPL_PSMODE, &ud->psmode); + vconf_get_int(VCONFKEY_TELEPHONY_DB_DEFAULT_DATA_SUBS, &ud->default_data_slot); + info("default data slot:[%d]", ud->default_data_slot); + + tcore_storage_set_key_callback(ud->strg_vconf, STORAGE_KEY_3G_ENABLE, on_storage_key_callback, plugin); + tcore_storage_set_key_callback(ud->strg_vconf, STORAGE_KEY_FLIGHT_MODE_BOOL, on_storage_key_callback, plugin); + tcore_storage_set_key_callback(ud->strg_vconf, STORAGE_KEY_SETAPPL_STATE_DATA_ROAMING_BOOL, on_storage_key_callback, plugin); + tcore_server_add_notification_hook(s, TNOTI_NETWORK_REGISTRATION_STATUS, on_hook_network_service_type_change, plugin); + tcore_server_add_notification_hook(s, TNOTI_NETWORK_CHANGE, on_hook_network_plmn_change, plugin); + tcore_server_add_notification_hook(s, TNOTI_SIM_STATUS, on_hook_sim_status, plugin); + + vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_GMT, on_hook_nitz_gmt_change, plugin); + vconf_notify_key_changed(VCONFKEY_SETAPPL_PSMODE, on_power_saving_mode_changed, plugin); +#ifdef TIZEN_FEATURE_MULTISIM + vconf_notify_key_changed(VCONFKEY_TELEPHONY_DB_DEFAULT_DATA_SUBS, on_default_data_slot_changed, plugin); +#endif + notifier_preferred_network_init(plugin); + notifier_preferred_voice_init(plugin); + + + return TRUE; +} + +void ui_notifier_deinit(TcorePlugin *plugin) +{ + ui_noti_data *ud; + Server *s; + guint id; + + s = tcore_plugin_ref_server(plugin); + ud = tcore_plugin_ref_user_data(plugin); + if (ud) { + ud->modems_count = tcore_server_get_modems_count(s); + + for (id = 0; id < ud->modems_count; id++) { + if (ud->no_svc_timer_id[id] != 0) { + g_source_remove(ud->no_svc_timer_id[id]); + } + if (ud->manual_plmn[id]) + free(ud->manual_plmn[id]); + if (ud->manual_plmn_cb_data[id]) + free(ud->manual_plmn_cb_data[id]); + } + + tcore_storage_remove_key_callback(ud->strg_vconf, STORAGE_KEY_3G_ENABLE, on_storage_key_callback); + tcore_storage_remove_key_callback(ud->strg_vconf, STORAGE_KEY_FLIGHT_MODE_BOOL, on_storage_key_callback); + tcore_storage_remove_key_callback(ud->strg_vconf, STORAGE_KEY_SETAPPL_STATE_DATA_ROAMING_BOOL, on_storage_key_callback); + if (ud->sim_plmn) + free(ud->sim_plmn); + if (ud->current_plmn) + free(ud->current_plmn); + } + + tcore_server_remove_notification_hook(s, on_hook_network_service_type_change); + tcore_server_remove_notification_hook(s, on_hook_network_plmn_change); + tcore_server_remove_notification_hook(s, on_hook_sim_status); + + vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_GMT, on_hook_nitz_gmt_change); + vconf_ignore_key_changed(VCONFKEY_SETAPPL_PSMODE, on_power_saving_mode_changed); +#ifdef TIZEN_FEATURE_MULTISIM + vconf_ignore_key_changed(VCONFKEY_TELEPHONY_DB_DEFAULT_DATA_SUBS, on_default_data_slot_changed); +#endif + + free(ud); +} diff --git a/src/notifier_internal.c b/src/notifier_internal.c new file mode 100644 index 0000000..ee68a04 --- /dev/null +++ b/src/notifier_internal.c @@ -0,0 +1,212 @@ +/* + * tel-plugin-ui_notifier + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Ja-young Gu <jygu@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <tcore.h> +#include <server.h> +#include <plugin.h> +#include <vconf.h> +#include <user_request.h> +#include <co_network.h> + +#include "notifier_internal.h" +#include "notifier_launcher.h" + +struct manual_plmn_noti_data { + ui_noti_data *ud; + sim_slot_id id; +}; + +static void _network_get_name_from_plmn(CoreObject *co, char *name, const char *plmn) +{ + struct tcore_network_operator_info *noi = NULL; + char mcc[4] = { 0, }; + const char *mnc; + + if (G_UNLIKELY(!plmn) || G_UNLIKELY(strlen(plmn) < 4)) { + warn("Invalid plmn"); + return; + } + + memcpy(mcc, plmn, 3); + mnc = plmn + 3; + + if (G_UNLIKELY(atoi(mcc) == 0)) { + err("atoi(mcc) is Zero. mcc[%s]", mcc); + return; + } + + noi = tcore_network_operator_info_find(co, mcc, mnc); + if (!noi) { + memcpy(name, plmn, NETWORK_MAX_PLMN_LEN+1); + } else { + memcpy(name, noi->name, NETWORK_MAX_NETWORK_NAME_LEN+1); + } + dbg("name:[%s] plmn:[%s]", name, plmn); +} + +static void _on_response_selection_mode(UserRequest *ur, + enum tcore_response_command command, + unsigned int data_len, const void *data, void *user_data) +{ + const struct tresp_network_get_plmn_selection_mode *info = data; + const char *manual_plmn = NULL; + char name[NETWORK_MAX_NETWORK_NAME_LEN+1]; + struct manual_plmn_noti_data *net_selection_info = user_data; + CoreObject *co; + sim_slot_id id; + + if (!info || !net_selection_info) + return; + + id = net_selection_info->id; + co = net_selection_info->ud->co_network[id]; + if (info->mode == NETWORK_SELECT_MODE_AUTOMATIC) { + info("Automatic Selection mode."); + tcore_object_set_property(co, PROP_NET_MANUAL_PLMN, NULL); + } else { + info("Manual Selection mode."); + manual_plmn = tcore_object_ref_property (co, PROP_NET_MANUAL_PLMN); + launch_telephony_popup(IPC_MSG_NETWORK_MANUAL_FAIL_POPUP, "", net_selection_info->ud); + _network_get_name_from_plmn(co, name, manual_plmn); + if (id == SLOT_ID_PRIMARY) + launch_telephony_popup(IPC_MSG_SIM1_ADD_NETWORK_MANUAL_FAIL_NOTI, name, net_selection_info->ud); + else + launch_telephony_popup(IPC_MSG_SIM2_ADD_NETWORK_MANUAL_FAIL_NOTI, name, net_selection_info->ud); + net_selection_info->ud->manual_plmn_noti_launched[id] = TRUE; + } + g_free(net_selection_info); +} + +static void _check_net_selection_mode_from_modem(ui_noti_data *ud, sim_slot_id id) +{ + struct manual_plmn_noti_data *net_selection_info; + + if (ud->co_network[id]) { + UserRequest *ur = NULL; + dbg("Get Plmn Selection Mode"); + net_selection_info = (struct manual_plmn_noti_data *)g_malloc0(sizeof(struct manual_plmn_noti_data)); + net_selection_info->ud = ud; + net_selection_info->id = id; + + ur = tcore_user_request_new (NULL, NULL); + tcore_user_request_set_command(ur, TREQ_NETWORK_GET_PLMN_SELECTION_MODE); + tcore_user_request_set_response_hook(ur, _on_response_selection_mode, net_selection_info); + if (TCORE_RETURN_SUCCESS != tcore_object_dispatch_request(ud->co_network[id], ur)) { + err("Request [0x%x] dispatch failed", TREQ_NETWORK_GET_PLMN_SELECTION_MODE); + tcore_user_request_unref(ur); + g_free(net_selection_info); + } + } +} + +static gboolean _on_timeout_no_svc_waiting(gpointer user_cb_data) +{ + enum telephony_network_service_type svc_type; + manual_plmn_data *cb_data = user_cb_data; + ui_noti_data *ud = (ui_noti_data *)cb_data->ud; + sim_slot_id id = cb_data->id; + + tcore_network_get_service_type(ud->co_network[id], &svc_type); + if (svc_type > NETWORK_SERVICE_TYPE_SEARCH) { + info ("In Service. Do not launch popup"); + } else { + dbg("For slot(%d), no svc timeout. check network mode again", id); + _check_net_selection_mode_from_modem(ud, id); + } + ud->no_svc_timer_id[id] = 0; + free(cb_data); + return G_SOURCE_REMOVE; +} + +void launch_no_svc_with_manual_plmn_popup(ui_noti_data *ud, sim_slot_id id) +{ + manual_plmn_data *cb_data = NULL; + const char *value = NULL; + + //tempporaily modify for build + //if (tfeature_is_supported(TFEATURE_UI_NO_SVC_MANUAL_PLMN_CHECK)) { + if(1) { + unsigned int timeout = NO_SVC_WAITING_TIMEOUT; + cancel_no_svc_with_manual_plmn_popup(ud, id); + cb_data = calloc(sizeof(manual_plmn_data), 1); + if (cb_data == NULL) { + err("memory allocation failed"); + return; + } + cb_data->ud = ud; + cb_data->id = id; + ud->manual_plmn_cb_data[id] = cb_data; + + value = tcore_object_ref_property (ud->co_network[id], PROP_NET_MANUAL_SELECTION_STATUS); + info ("slot(%d), manual selection status = %s", id, value); + + if (g_strcmp0 (value, "failure") == 0) { + dbg ("manual selection failed. Launch popup"); + _on_timeout_no_svc_waiting(cb_data); + } else { + ud->no_svc_timer_id[id] = g_timeout_add_seconds(timeout, + _on_timeout_no_svc_waiting, cb_data); + dbg("Add timer(%d) timeout(%d)", ud->no_svc_timer_id[id], timeout); + } + } else { + dbg("Feature is not defined. Do nothing"); + } +} + +void cancel_no_svc_with_manual_plmn_popup(ui_noti_data *ud, sim_slot_id id) +{ + const char *manual_plmn = NULL; + char name[NETWORK_MAX_NETWORK_NAME_LEN+1]; + + if (ud->no_svc_timer_id[id] != 0) { + gboolean ret; + ret = g_source_remove(ud->no_svc_timer_id[id]); + if (FALSE == ret) { + warn("g_source_remove fail"); + } + else { + dbg("timer(%d) was cancelled", ud->no_svc_timer_id[id]); + } + ud->no_svc_timer_id[id] = 0; + if (ud->manual_plmn_cb_data[id]) + free(ud->manual_plmn_cb_data[id]); + } + if (ud->manual_plmn_noti_launched[id] == TRUE) { + manual_plmn = tcore_object_ref_property (ud->co_network[id], PROP_NET_MANUAL_PLMN); + _network_get_name_from_plmn(ud->co_network[id], name, manual_plmn); + if (id == SLOT_ID_PRIMARY) + launch_telephony_popup(IPC_MSG_SIM1_DEL_NETWORK_MANUAL_FAIL_NOTI, name, ud); + else + launch_telephony_popup(IPC_MSG_SIM2_DEL_NETWORK_MANUAL_FAIL_NOTI, name, ud); + ud->manual_plmn_noti_launched[id] = FALSE; + } +} + +void launch_timezone_select_popup(ui_noti_data *ud) +{ + launch_telephony_popup(IPC_MSG_NITZ_MANUL_DATE_AND_TIME, "", ud); + + tcore_object_set_property (ud->co_network[SLOT_ID_DEFAULT], PROP_NET_NITZ_TIMEZONE, "requested"); +} + +void launch_roaming_data_allowed_popup(ui_noti_data *ud) +{ + launch_telephony_popup(IPC_MSG_NETWORK_DATA_ROAMING_POPUP, "", ud); +} diff --git a/src/notifier_launcher.c b/src/notifier_launcher.c new file mode 100644 index 0000000..e9f7096 --- /dev/null +++ b/src/notifier_launcher.c @@ -0,0 +1,173 @@ +/* + * tel-plugin-ui_notifier + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Ja-young Gu <jygu@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <tcore.h> +#include <server.h> +#include <plugin.h> +#include <vconf.h> +#include "notifier_internal.h" +#include "notifier_launcher.h" +#include "notifier_util.h" + +#include <bundle_internal.h> +#include <aul.h> + +static gpointer __launch_pwlock_internal(gpointer data) +{ + bundle *kb; + int ret; + + kb = bundle_create(); + if (kb == NULL) + return NULL; + + info("launch pwlock"); + + bundle_add(kb, "after_bootup", "1"); + ret = aul_launch_app_for_uid ("com.samsung.pwlock", kb, GLOBAL_USER); + if (ret < 0) + err("Unable to launch pwlock. Error [%d]", ret); + + bundle_free(kb); + return NULL; +} + +static gpointer __launch_pwlock_pin_block(gpointer data) +{ + bundle *kb; + int ret; + + kb = bundle_create(); + if (kb == NULL) + return NULL; + + info("launch pwlock for PIN Block"); + + bundle_add(kb, "after_bootup", "2"); + + ret = aul_launch_app_for_uid("com.samsung.pwlock", kb, GLOBAL_USER); + if (ret < 0) + err("Unable to launch pwlock. Error [%d]", ret); + + bundle_free(kb); + return NULL; +} + +static gpointer __launch_setup_ota_internal(gpointer data) +{ + int ret; + + info("launch setup ota app"); + ret = aul_launch_app_for_uid ("com.samsung.setup-kt-net", NULL, GLOBAL_USER); + if (ret < 0) + err("Unable to setup ota. Error [%d]", ret); + + info("launch setup done"); + return NULL; +} + +static gpointer __launch_telephony_popup_internal(gpointer data) +{ + struct __telephony_popup_payload_t *payload = data; + unsigned short retry_count = 0; + bundle *kb; + int ret; + + info("request telephony_syspopup ('%s', '%s')", + payload->message, payload->param); +RETRY: + + kb = bundle_create(); + if (kb == NULL) { + err("Fail to create bundle"); + goto EXIT; + } + + if(payload->message) { + bundle_add (kb, POPUP_IPC, payload->message); + } + + if(payload->param) { + bundle_add (kb, POPUP_IPC_PARAM, payload->param); + } + + info("Request sent to launch %s", AUL_NAME); + ret = aul_launch_app_for_uid(AUL_NAME, kb, GLOBAL_USER); + bundle_free(kb); + + if (ret < 0 && retry_count < 5) { + err("fail to launch (%d). Retry count [%d]",ret, retry_count); + retry_count++; + g_usleep(G_USEC_PER_SEC * 1); + goto RETRY; + } else { + info("success.('%s', '%s')", payload->message, payload->param); + } + +EXIT: + /* Free resources */ + g_free(payload->message); + g_free(payload->param); + g_free(payload); + + return NULL; +} + +void launch_pwlock_pin_block(void) +{ + GThread *thread; + + thread = g_thread_new("PWLOCK-APP", __launch_pwlock_pin_block, NULL); + g_thread_unref(thread); +} + +void launch_pwlock(void) +{ + GThread *thread; + + thread = g_thread_new("PWLOCK-APP", __launch_pwlock_internal, NULL); + g_thread_unref(thread); +} + +void launch_setup_ota(void) +{ + GThread *thread; + + thread = g_thread_new("SETUP-OTA-APP", __launch_setup_ota_internal, NULL); + g_thread_unref(thread); +} + +void launch_telephony_popup(const char *message, const char *param, void *data) +{ + GThread *thread; + ui_noti_data *ud = (ui_noti_data *)data; + struct __telephony_popup_payload_t *payload; + + if (!ud) + return; + + payload = g_malloc0(sizeof(struct __telephony_popup_payload_t)); + payload->message = g_strdup(message); + payload->param = g_strdup(param); + + ui_notifier_lock_sleep(); + thread = g_thread_new("TEL-POPUP", __launch_telephony_popup_internal, payload); + g_thread_unref(thread); + ui_notifier_unlock_sleep(); +} diff --git a/src/notifier_preferred_network.c b/src/notifier_preferred_network.c new file mode 100644 index 0000000..a139ecb --- /dev/null +++ b/src/notifier_preferred_network.c @@ -0,0 +1,333 @@ +/* + * tel-plugin-ui_notifier + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Ja-young Gu <jygu@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <tcore.h> +#include <plugin.h> +#include <server.h> +#include <co_call.h> +#include <storage.h> +#include <user_request.h> +#include "notifier_preferred_network.h" +#include "notifier_internal.h" +#include "notifier_util.h" + +#define MODEM_INDEX_UNDECIDED 0 +#define MODEM_INDEX_PRIMARY 1 +#define MODEM_INDEX_SECONDARY 2 +#define MODEM_INDEX_TERTIARY 3 +#define MODEM_INDEX_INVALID -1 + +static int __get_modem_index(TcorePlugin *plugin) +{ + char *cp_name = NULL; + + if (!plugin) + return MODEM_INDEX_INVALID; + + cp_name = (char *)tcore_server_get_cp_name_by_plugin(plugin); + if (!cp_name) + return MODEM_INDEX_INVALID; + + if (g_str_has_suffix(cp_name , "0")) + return MODEM_INDEX_PRIMARY; + else if (g_str_has_suffix(cp_name , "1")) + return MODEM_INDEX_SECONDARY; + else if(g_str_has_suffix(cp_name , "2")) + return MODEM_INDEX_TERTIARY; + else + return MODEM_INDEX_INVALID; + +} + +static gboolean __is_ongoing_call_exist(CoreObject *co_call) +{ + GSList* call_obj_list = NULL; + unsigned int total_call_cnt = 0; + unsigned int call_status_count = 0; + + total_call_cnt = tcore_call_object_total_length(co_call); + if (total_call_cnt == 0) { + dbg("Active call not found"); + return FALSE; + } + + for(call_status_count = TCORE_CALL_STATUS_ACTIVE; call_status_count <= TCORE_CALL_STATUS_WAITING; call_status_count++) { + call_obj_list = tcore_call_object_find_by_status(co_call,call_status_count); + if (call_obj_list) { + dbg("ongoing call(s) exist"); + g_slist_free(call_obj_list); + return TRUE; + } + } + dbg("ongoing call not found"); + return FALSE; +} + +static void __set_preferred_network(TcorePlugin *plugin, int modem_index, + enum telephony_call_preferred_voice_subs pv) +{ + CoreObject *co_network = NULL; + UserRequest *ur = NULL; + struct treq_network_set_default_subscription req; + + dbg("set preferred network based on modem index : %d, pv : %d", modem_index, pv); + if (MODEM_INDEX_INVALID == modem_index) + return; + + co_network = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_NETWORK); + if (!co_network) { + err("network co_object not found"); + return; + } + + switch(pv) { + case CALL_PREFERRED_VOICE_SUBS_UNKNOWN: + case CALL_PREFERRED_VOICE_SUBS_CURRENT_NETWORK: + case CALL_PREFERRED_VOICE_SUBS_ASK_ALWAYS: + /* preferred network have pirority to preferred voice - ignore preferred voice */ + /* SET preferred network to vconf */ + switch(modem_index ) { + case MODEM_INDEX_PRIMARY: + req.default_subs = NETWORK_DEFAULT_SUBS_SIM1; + break; + + case MODEM_INDEX_SECONDARY: + req.default_subs = NETWORK_DEFAULT_SUBS_SIM2; + break; + + case MODEM_INDEX_UNDECIDED: + default: + req.default_subs = NETWORK_DEFAULT_SUBS_UNKNOWN; + break; + } + break; + case CALL_PREFERRED_VOICE_SUBS_SIM1: + /* preferred voice have priority to preferred network */ + /* SET preferred network vconf */ + req.default_subs = NETWORK_DEFAULT_SUBS_SIM1; + break; + case CALL_PREFERRED_VOICE_SUBS_SIM2: + /* preferred voice have priority to preferred network */ + /* set preferred network vconf */ + req.default_subs = NETWORK_DEFAULT_SUBS_SIM2; + break; + default : + req.default_subs = NETWORK_DEFAULT_SUBS_UNKNOWN; + break; + } + + ur = tcore_user_request_new(NULL, NULL); + tcore_user_request_set_data(ur, sizeof(struct treq_network_set_default_subscription), &req); + tcore_user_request_set_command(ur, TREQ_NETWORK_SET_DEFAULT_SUBSCRIPTION); + + dbg("Setting preferred network [0x%x]", req.default_subs); + + if (TCORE_RETURN_SUCCESS != tcore_object_dispatch_request(co_network, ur)) { + err("Request [0x%x] dispatch failed", TREQ_NETWORK_SET_DEFAULT_SUBSCRIPTION); + tcore_user_request_unref(ur); + } +} + +static void __apply_preferred_voice_change(TcorePlugin *plugin) +{ + GSList *modem_list, *iter; + gboolean b_set_preferred_network = TRUE; + TcorePlugin *modem_plgn = NULL; + CoreObject *co_call = NULL; + Server *s; + + s = tcore_plugin_ref_server(plugin); + modem_list = tcore_server_get_modem_plugin_list(s); + if (!modem_list) + return; + + /* Check whether active/originating/incoming/waiting call exist in each modem */ + for (iter = modem_list; iter != NULL; iter = iter->next) { + modem_plgn = iter->data; + if (!modem_plgn) { + err("modem plgn not found"); + b_set_preferred_network = FALSE; + break; + } + + co_call = tcore_plugin_ref_core_object(modem_plgn, CORE_OBJECT_TYPE_CALL); + if(!co_call) { + dbg("call_obj not found - skip this plugin "); + continue; + } + + /* if exist, sustain modem index with PN value */ + if(__is_ongoing_call_exist(co_call)) { + dbg("call exist - sustain current PN value"); + b_set_preferred_network = FALSE; + break; + } + } + + g_slist_free(modem_list); + + if (b_set_preferred_network) { + ui_noti_data *ud = tcore_plugin_ref_user_data(plugin); + /* Active call not exist, update Preferred Network value to comply Preferred Voice value */ + dbg("call not exist - update PN to comply pv : %d", ud->default_voice_slot); + __set_preferred_network(modem_plgn, MODEM_INDEX_UNDECIDED, ud->default_voice_slot); + } +} + +static void __on_response_get_preferred_voice(UserRequest *ur, + enum tcore_response_command command, unsigned int data_len, const void *data, void *user_data) +{ + const struct tresp_call_get_preferred_voice_subscription *resp = data; + ui_noti_data *ud = tcore_plugin_ref_user_data(user_data); + + if (!resp || !ud) + return; + + if (ud->default_voice_slot != resp->preferred_subs) { + dbg("Preferred Voice Change (%d) -> (%d)", ud->default_voice_slot, resp->preferred_subs); + ud->default_voice_slot = resp->preferred_subs; + __apply_preferred_voice_change(user_data); + } else + dbg("Value(%d) was not changed.", ud->default_voice_slot); +} + +static void __get_preferred_voice(TcorePlugin *plugin) +{ + GSList *modem_list, *iter; + TcorePlugin *modem_plgn = NULL; + CoreObject *co_call = NULL; + UserRequest *ur = NULL; + + modem_list = tcore_server_get_modem_plugin_list(tcore_plugin_ref_server(plugin)); + for (iter = modem_list; iter != NULL; iter = iter->next) { + modem_plgn = iter->data; + co_call = tcore_plugin_ref_core_object(modem_plgn, CORE_OBJECT_TYPE_CALL); + if(co_call) + break; + } + g_slist_free(modem_list); + + if (!co_call) + return; + + ur = tcore_user_request_new(NULL, NULL); + tcore_user_request_set_command(ur, TREQ_CALL_GET_PREFERRED_VOICE_SUBSCRIPTION); + tcore_user_request_set_response_hook(ur, __on_response_get_preferred_voice, plugin); + + dbg("Getting preferred Voice"); + + if (TCORE_RETURN_SUCCESS != tcore_object_dispatch_request(co_call, ur)) { + err("Request [0x%x] dispatch failed", TREQ_CALL_GET_PREFERRED_VOICE_SUBSCRIPTION); + tcore_user_request_unref(ur); + } +} + +static enum tcore_hook_return on_hook_call_status_change(Server *s, CoreObject *source, + enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data) +{ + TcorePlugin *modem_plgn = NULL; + int modem_index = MODEM_INDEX_INVALID; + gboolean b_call_ongoing = FALSE; + + modem_plgn = tcore_object_ref_plugin(source); + modem_index = __get_modem_index(modem_plgn); + + switch(command) { + case TNOTI_CALL_STATUS_DIALING: + case TNOTI_CALL_STATUS_INCOMING: + /* call being setup - update pn to comply ongoing line */ + dbg("call under establishment - change perferred Network state"); + __set_preferred_network(modem_plgn, modem_index, CALL_PREFERRED_VOICE_SUBS_UNKNOWN); + break; + + case TNOTI_CALL_STATUS_IDLE: + /* call released - check ongoing call */ + b_call_ongoing = __is_ongoing_call_exist(source); + + /* if exist - sustain current PN */ + if (TRUE == b_call_ongoing) { + dbg("ongoing call exist - sustain current perferred network state"); + } else {/* if not exist - update PN to comply PV */ + ui_noti_data *ud = tcore_plugin_ref_user_data((TcorePlugin*)user_data); + __set_preferred_network(modem_plgn, MODEM_INDEX_UNDECIDED, ud->default_voice_slot); + } + break; + + default: + break; + } + return TCORE_HOOK_RETURN_CONTINUE; +} + + +static enum tcore_hook_return on_hook_call_preferred_voice_change(Server *s, CoreObject *source, + enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data) +{ + struct tnoti_call_preferred_voice_subscription *noti_data = data; + ui_noti_data *ud = tcore_plugin_ref_user_data(user_data); + + if (!noti_data || !ud) + return TCORE_HOOK_RETURN_CONTINUE; + + /* Ignore Duplicated TNOTI_CALL_PREFERRED_VOICE_SUBSCRIPTION */ + if (MODEM_INDEX_PRIMARY != __get_modem_index(tcore_object_ref_plugin(source))) + return TCORE_HOOK_RETURN_CONTINUE; + + if (ud->default_voice_slot != noti_data->preferred_subs) { + dbg("Preferred Voice Change (%d) -> (%d)", ud->default_voice_slot, noti_data->preferred_subs); + ud->default_voice_slot = noti_data->preferred_subs; + __apply_preferred_voice_change(user_data); + } else + dbg("Value(%d) was not changed.", ud->default_voice_slot); + + return TCORE_HOOK_RETURN_CONTINUE; +} + +gboolean notifier_preferred_network_init(TcorePlugin *plugin) +{ + Server *s = NULL; + unsigned int sim_count = 0; + GSList *list = NULL; + + s = tcore_plugin_ref_server(plugin); + if (!s) + return FALSE; + + list = tcore_server_get_modem_plugin_list(s); + sim_count = g_slist_length(list); + + if (sim_count < 2) { + err("device does not support DSDS. disable preferred network"); + g_slist_free(list); + return TRUE; + } + + /* add hook to call related events & PV change event */ + tcore_server_add_notification_hook(s, TNOTI_CALL_STATUS_IDLE, on_hook_call_status_change, plugin); + tcore_server_add_notification_hook(s, TNOTI_CALL_STATUS_INCOMING, on_hook_call_status_change, plugin); + tcore_server_add_notification_hook(s, TNOTI_CALL_STATUS_DIALING, on_hook_call_status_change, plugin); + tcore_server_add_notification_hook(s, TNOTI_CALL_PREFERRED_VOICE_SUBSCRIPTION, on_hook_call_preferred_voice_change, plugin); + + __get_preferred_voice(plugin); + + g_slist_free(list); + + return TRUE; +} diff --git a/src/notifier_preferred_voice.c b/src/notifier_preferred_voice.c new file mode 100644 index 0000000..0ff5423 --- /dev/null +++ b/src/notifier_preferred_voice.c @@ -0,0 +1,219 @@ +/* + * tel-plugin-ui_notifier + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Ja-young Gu <jygu@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <tcore.h> +#include <server.h> +#include <plugin.h> +#include <user_request.h> +#include <vconf.h> +#include <co_call.h> + +#include "notifier.h" +#include "notifier_preferred_voice.h" +#include "notifier_internal.h" +#include "notifier_util.h" + +static enum tcore_hook_return on_hook_sim_status(Server *s, + CoreObject *source, enum tcore_notification_command command, + unsigned int data_len, void *data, void *user_data) +{ + TcorePlugin *plugin = user_data; + TcorePlugin *modem_plugin; + ui_noti_data *ud = NULL; + + const struct tnoti_sim_status *sim = data; + enum tel_sim_status sim_status, other_sim_status; + + sim_slot_id slot_id, other_slot_id; + int pref_voice_subscription = -1; + TReturn ret; + + if (sim == NULL) { + err("sim data is NULL"); + return TCORE_HOOK_RETURN_CONTINUE; + } + + if ((ud = tcore_plugin_ref_user_data(plugin)) == NULL) { + err("tcore_plugin_ref_user_data() returns NULL."); + return TCORE_HOOK_RETURN_CONTINUE; + } + + modem_plugin = tcore_object_ref_plugin(source); + + slot_id = __get_sim_slotid(source); + other_slot_id = (slot_id == SLOT_ID_PRIMARY) ? SLOT_ID_SECONDARY : SLOT_ID_PRIMARY; + + sim_status = ud->sim_status[slot_id] = sim->sim_status; + other_sim_status = ud->sim_status[other_slot_id]; + dbg("SIM Status - SIM 1: [%d] SIM 2: [%d]", + slot_id == SLOT_ID_PRIMARY ? sim_status : other_sim_status, + slot_id == SLOT_ID_PRIMARY ? other_sim_status : sim_status); + + ret= vconf_get_int(VCONFKEY_TELEPHONY_PREFERRED_VOICE_SUBSCRIPTION, &pref_voice_subscription); + if (ret < 0) { + err("vconf_get_int() failed - Preferred Voice Subscription"); + return TCORE_HOOK_RETURN_CONTINUE; + } + dbg("Preferred Voice Subscription: [%d]", pref_voice_subscription); + + if ((sim_status == SIM_STATUS_CARD_NOT_PRESENT) + || (sim_status == SIM_STATUS_CARD_ERROR)) { + if (other_sim_status == SIM_STATUS_INIT_COMPLETED) { + /* + * Check for Preferred Voice Subscription value and if it is + * ASK ALWAYS + * OR + * CURRENT Network + * OR + * Matches our Subscription, then + * update it to other Subscription + */ + if ((pref_voice_subscription == CALL_PREFERRED_VOICE_SUBS_ASK_ALWAYS) + || (pref_voice_subscription == CALL_PREFERRED_VOICE_SUBS_CURRENT_NETWORK) + || ((slot_id == SLOT_ID_PRIMARY) + && (pref_voice_subscription == CALL_PREFERRED_VOICE_SUBS_SIM1)) + || ((slot_id == SLOT_ID_SECONDARY) + && (pref_voice_subscription == CALL_PREFERRED_VOICE_SUBS_SIM2))) { + + struct treq_call_set_preferred_voice_subscription req; + UserRequest *ur; + CoreObject *co_call; + + /* Create UR */ + ur = tcore_user_request_new(NULL, tcore_server_get_cp_name_by_plugin(modem_plugin)); + if (ur == NULL) { + err("Failed to create UR"); + return TCORE_HOOK_RETURN_CONTINUE; + } + + /* + * Send Set Preferred Voice request + */ + req.preferred_subs = (slot_id == SLOT_ID_PRIMARY) ? + CALL_PREFERRED_VOICE_SUBS_SIM2 : CALL_PREFERRED_VOICE_SUBS_SIM1; + + tcore_user_request_set_command(ur, TREQ_CALL_SET_PREFERRED_VOICE_SUBSCRIPTION); + tcore_user_request_set_data(ur, sizeof(struct treq_call_set_preferred_voice_subscription), &req); + + co_call = tcore_plugin_ref_core_object(modem_plugin, CORE_OBJECT_TYPE_CALL); + + dbg("Send request to set Preferred Voice subscription for SIM %d", + (slot_id == SLOT_ID_PRIMARY ? SLOT_ID_SECONDARY + 1 : SLOT_ID_PRIMARY + 1)); + + /* Dispatch request */ + ret = tcore_object_dispatch_request(co_call, ur); + if (ret != TCORE_RETURN_SUCCESS) { + err("Failed to disaptch request"); + + tcore_user_request_unref(ur); + } + } else { + dbg("Do nothing Preferred Voice Subscription is for other slot [%d]", + pref_voice_subscription); + } + } + } else if (sim_status == SIM_STATUS_INIT_COMPLETED) { + if ((other_sim_status == SIM_STATUS_CARD_NOT_PRESENT) + || (other_sim_status == SIM_STATUS_CARD_ERROR)) { + /* + * Check for Preferred Voice Subscription value and if it is + * ASK ALWAYS + * OR + * CURRENT Network + * OR + * Doesn't match our Subscription, then + * update it to our Subscription + */ + if ((pref_voice_subscription == CALL_PREFERRED_VOICE_SUBS_ASK_ALWAYS) + || (pref_voice_subscription == CALL_PREFERRED_VOICE_SUBS_CURRENT_NETWORK) + || ((slot_id == SLOT_ID_PRIMARY) + && (pref_voice_subscription == CALL_PREFERRED_VOICE_SUBS_SIM2)) + || ((slot_id == SLOT_ID_SECONDARY) + && (pref_voice_subscription == CALL_PREFERRED_VOICE_SUBS_SIM1))) { + struct treq_call_set_preferred_voice_subscription req; + UserRequest *ur; + CoreObject *co_call; + + /* Create UR */ + ur = tcore_user_request_new(NULL, tcore_server_get_cp_name_by_plugin(modem_plugin)); + if (ur == NULL) { + err("Failed to create UR"); + return TCORE_HOOK_RETURN_CONTINUE; + } + + /* + * Send Set Preferred Voice request + */ + req.preferred_subs = (slot_id == SLOT_ID_PRIMARY) ? + CALL_PREFERRED_VOICE_SUBS_SIM1 : CALL_PREFERRED_VOICE_SUBS_SIM2; + + tcore_user_request_set_command(ur, TREQ_CALL_SET_PREFERRED_VOICE_SUBSCRIPTION); + tcore_user_request_set_data(ur, sizeof(struct treq_call_set_preferred_voice_subscription), &req); + + co_call = tcore_plugin_ref_core_object(modem_plugin, CORE_OBJECT_TYPE_CALL); + + dbg("Send request to set Preferred Voice subscription for SIM %d", + (slot_id == SLOT_ID_PRIMARY ? SLOT_ID_PRIMARY + 1 : SLOT_ID_SECONDARY + 1)); + + /* Dispatch request */ + ret = tcore_object_dispatch_request(co_call, ur); + if (ret != TCORE_RETURN_SUCCESS) { + err("Failed to disaptch request"); + + tcore_user_request_unref(ur); + } + } else { + dbg("Do nothing Preferred Voice Subscription is for same slot [%d]", + pref_voice_subscription); + } + } + } + + return TCORE_HOOK_RETURN_CONTINUE; +} + +gboolean notifier_preferred_voice_init(TcorePlugin *plugin) +{ + Server *s = NULL; + unsigned int sim_count = 0; + + s = tcore_plugin_ref_server(plugin); + if (!s) + return FALSE; + + sim_count = tcore_server_get_modems_count(s); + + /* + * Proceed ahead only in case of Dual-/Multi- SIM + */ + if (sim_count < 2) { + err("device does not support DSDS. disable preferred voice"); + + return TRUE; + } + + /* + * Add notification hook for SIM status change + */ + tcore_server_add_notification_hook(s, + TNOTI_SIM_STATUS, on_hook_sim_status, plugin); + + return TRUE; +} diff --git a/src/notifier_util.c b/src/notifier_util.c new file mode 100644 index 0000000..87a6971 --- /dev/null +++ b/src/notifier_util.c @@ -0,0 +1,58 @@ +/* + * tel-plugin-ui_notifier + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Ja-young Gu <jygu@samsung.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "notifier_util.h" + +#include <stdio.h> +#include <string.h> +#include <tcore.h> +#include <device/power.h> + +void ui_notifier_lock_sleep(void) +{ + int ret = 0; + ret = device_power_request_lock(POWER_LOCK_CPU, 0); + if (ret < 0) + err("ret : (0x%x)", ret); +} + +void ui_notifier_unlock_sleep(void) +{ + int ret = 0; + device_power_release_lock(POWER_LOCK_CPU); + if (ret < 0) + err("ret : (0x%x)", ret); +} + +float ui_notifier_check_uptime() +{ + FILE *fp; + float uptime = 0.0, b = 0.0; + + fp = fopen("/proc/uptime", "r"); + + if (fp) { + if(fscanf(fp, "%f %f", &uptime, &b)){}; + fclose(fp); + } + dbg("uptime=[%f]", uptime); + + return uptime; +} diff --git a/tel-plugin-ui_notifier.manifest b/tel-plugin-ui_notifier.manifest new file mode 100644 index 0000000..dfdc35c --- /dev/null +++ b/tel-plugin-ui_notifier.manifest @@ -0,0 +1,5 @@ +<manifest> + <request> + <domain name="_"/> + </request> +</manifest>