Initial commit 65/125365/1
authorsinikang <sinikang@samsung.com>
Mon, 17 Apr 2017 06:08:36 +0000 (15:08 +0900)
committersinikang <sinikang@samsung.com>
Mon, 17 Apr 2017 06:10:53 +0000 (15:10 +0900)
Change-Id: Ibdb2f0d6a11a04ddecb61565bea40d0dea2655b5

39 files changed:
AUTHORS [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0644]
LICENSE [new file with mode: 0644]
include/internal/manager_call_internal.h [new file with mode: 0644]
include/internal/manager_internal.h [new file with mode: 0644]
include/internal/manager_network_internal.h [new file with mode: 0644]
include/internal/manager_sms_internal.h [new file with mode: 0644]
include/manager_call.h [new file with mode: 0644]
include/manager_core.h [new file with mode: 0644]
include/manager_modem.h [new file with mode: 0644]
include/manager_network.h [new file with mode: 0644]
include/manager_notification.h [new file with mode: 0644]
include/manager_phonebook.h [new file with mode: 0644]
include/manager_queue.h [new file with mode: 0644]
include/manager_request.h [new file with mode: 0644]
include/manager_server.h [new file with mode: 0644]
include/manager_sim.h [new file with mode: 0644]
include/manager_sms.h [new file with mode: 0644]
include/manager_ss.h [new file with mode: 0644]
include/manager_types.h [new file with mode: 0644]
include/manager_util.h [new file with mode: 0644]
packaging/tel-plugin-manager.spec [new file with mode: 0644]
src/desc-manager.c [new file with mode: 0644]
src/manager_call.c [new file with mode: 0644]
src/manager_core.c [new file with mode: 0644]
src/manager_modem.c [new file with mode: 0644]
src/manager_network.c [new file with mode: 0644]
src/manager_notification.c [new file with mode: 0644]
src/manager_phonebook.c [new file with mode: 0644]
src/manager_queue.c [new file with mode: 0644]
src/manager_request.c [new file with mode: 0644]
src/manager_server.c [new file with mode: 0644]
src/manager_sim.c [new file with mode: 0644]
src/manager_sms.c [new file with mode: 0644]
src/manager_ss.c [new file with mode: 0644]
src/manager_util.c [new file with mode: 0644]
src/network_name/manager_network_name.c [new file with mode: 0644]
src/network_name/manager_network_name.h [new file with mode: 0644]
tel-plugin-manager.manifest [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..f01b9df
--- /dev/null
@@ -0,0 +1,78 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(manager-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}/lib/pkgconfig" CACHE PATH PKGCONFIGDIR)
+SET(CMAKE_INSTALL_PREFIX "${PREFIX}")
+SET(DATAROOTDIR "\${prefix}/share")
+
+# Set required packages
+INCLUDE(FindPkgConfig)
+pkg_check_modules(pkgs REQUIRED
+       glib-2.0
+       tcore
+       libxml-2.0
+       vconf
+       openssl
+       tfeature
+)
+
+FOREACH(flag ${pkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/include/)
+
+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 -Wcast-align")
+
+ADD_DEFINITIONS("-DFEATURE_TLOG_DEBUG")
+ADD_DEFINITIONS("-DTCORE_LOG_TAG=\"MANAGER\"")
+ADD_DEFINITIONS("-DPLUGIN_VERSION=${VERSION}")
+ADD_DEFINITIONS("-DEXPORT_API=__attribute__((visibility(\"default\")))")
+
+IF (FEATURE_MULTISIM)
+       ADD_DEFINITIONS("-DTIZEN_FEATURE_MULTISIM")
+ENDIF (FEATURE_MULTISIM)
+IF (WEARABLE)
+  ADD_DEFINITIONS("-DTIZEN_FEATURE_WEARABLE")
+ENDIF (WEARABLE)
+MESSAGE(${CMAKE_C_FLAGS})
+MESSAGE(${pkgs_LDFLAGS})
+
+SET(SRCS
+       src/desc-manager.c
+       src/manager_core.c
+       src/manager_request.c
+       src/manager_notification.c
+       src/manager_util.c
+       src/manager_queue.c
+       src/manager_call.c
+       src/manager_ss.c
+       src/manager_sms.c
+       src/manager_network.c
+       src/network_name/manager_network_name.c
+       src/manager_modem.c
+       src/manager_sim.c
+       src/manager_server.c
+       src/manager_phonebook.c
+)
+
+
+# library build
+ADD_LIBRARY(manager-plugin SHARED ${SRCS})
+TARGET_LINK_LIBRARIES(manager-plugin ${pkgs_LDFLAGS})
+SET_TARGET_PROPERTIES(manager-plugin PROPERTIES PREFIX "" OUTPUT_NAME manager-plugin)
+
+# install
+##INSTALL(FILES ${CMAKE_SOURCE_DIR}/res/sim_pref.sql DESTINATION /usr/share/manager-plugin)
+##INSTALL(FILES ${CMAKE_SOURCE_DIR}/res/simpref_db_upgrade.sh DESTINATION /usr/share/upgrade/scripts)
+INSTALL(TARGETS manager-plugin
+               LIBRARY DESTINATION ${LIBDIR}/telephony/plugins)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/LICENSE DESTINATION /usr/share/license RENAME tel-plugin-manager)
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..0f31839
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,204 @@
+Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
diff --git a/include/internal/manager_call_internal.h b/include/internal/manager_call_internal.h
new file mode 100644 (file)
index 0000000..36dd2bf
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Imran Mohammed <md.imran@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.
+ */
+
+#ifndef __MANAGER_CALL_INTERNAL_H__
+#define __MANAGER_CALL_INTERNAL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ecc_rat_query_info {
+       int call_handle;
+       enum telephony_call_ecc_status rat_query_status;
+};
+
+struct early_ecc_rat_result_info {
+       enum telephony_network_access_technology rat;
+};
+
+struct manager_call_private_info {
+       struct ecc_rat_query_info rat_query_cache;
+       struct early_ecc_rat_result_info early_rat_result;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MANAGER_CALL_INTERNAL_H__ */
diff --git a/include/internal/manager_internal.h b/include/internal/manager_internal.h
new file mode 100644 (file)
index 0000000..4270511
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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.
+ */
+
+#ifndef __MANAGER_INTERNAL_H__
+#define __MANAGER_INTERNAL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MANAGER_FLIGHT_PROCESSING_NONE 0x0
+#define MANAGER_FLIGHT_PROCESSSING_ENABLE 0x1
+#define MANAGER_FLIGHT_PROCESSSING_DISABLE 0x2
+
+struct manager_private_data {
+       Manager *manager;
+
+       /* Queue */
+       GQueue *manager_queue;
+
+       /* Timer */
+       guint deregister_timer_id;
+
+       /* Cache data list - per each modem*/
+       GSList *board_list;
+
+       /* Flag to reject incoming call on other subscription when dial request is initiated*/
+       gboolean is_dial_initiated;
+
+       /* Flag to consume end notification for internal end request pertaining to MO/MT synchronization */
+       gboolean is_end_initiated;
+
+       /*Flag to identify if dds, ds, nw_mode are set on boot*/
+       gboolean boot_config_completed;
+
+       /*Flag to identify if end all request is under processing due to flight mode request*/
+       gboolean is_end_all_initiated;
+
+       /*Flag to identify if dial notification is already sent in case of Emergency call*/
+       gboolean is_dial_noti_sent;
+
+       /*Flag to identify if flight mode processing is in progress */
+       int fm_processing_state;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MANAGER_INTERNAL_H__ */
diff --git a/include/internal/manager_network_internal.h b/include/internal/manager_network_internal.h
new file mode 100644 (file)
index 0000000..fb85df4
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Imran Mohammed <md.imran@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.
+ */
+
+#ifndef __MANAGER_NETWORK_INTERNAL_H__
+#define __MANAGER_NETWORK_INTERNAL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct manager_network_eons_info NetworkEonsInfo;
+typedef struct manager_network_cache_info NetworkCacheInfo;
+
+#define MANAGER_NET_CHECK_NPI_EONS(npi) { if (G_UNLIKELY(!npi || !npi->eons_data)) { err("NPI error"); return; } }
+#define MANAGER_NET_CHECK_NPI_EONS_RET(npi) { if (G_UNLIKELY(!npi || !npi->eons_data)) { err("NPI error"); return FALSE; } }
+#define MANAGER_NET_CHECK_NPI_CACHE(npi) { if (G_UNLIKELY(!npi || !npi->cache_data)) { err("NPI error"); return; } }
+#define MANAGER_NET_CHECK_NPI_CACHE_RET(npi) { if (G_UNLIKELY(!npi || !npi->cache_data)) { err("NPI error"); return FALSE; } }
+
+struct manager_network_cache_info {
+       enum telephony_network_service_domain_status prev_cs_domain_status;
+       enum telephony_network_service_domain_status prev_ps_domain_status;
+       enum telephony_network_service_type prev_service_type;
+       gboolean prev_roaming_status;
+       unsigned char current_plmn[NETWORK_MAX_PLMN_LEN + 1];
+       unsigned int prev_lac;
+};
+
+struct manager_network_private_info {
+       CoreObject *co_network;
+       CoreObject *co_sim;
+       NetworkCacheInfo *cache_data;
+       NetworkEonsInfo *eons_data;
+       gboolean search_in_progress;
+       enum telephony_network_epdg_status epdg_status;
+
+       gboolean sent_ims_dereg;
+};
+
+NetworkPrivateInfo *manager_network_ref_npi_by_ur(Server *s, UserRequest *ur);
+NetworkPrivateInfo *manager_network_ref_npi_by_plugin(TcorePlugin *plugin);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MANAGER_NETWORK_INTERNAL_H__ */
diff --git a/include/internal/manager_sms_internal.h b/include/internal/manager_sms_internal.h
new file mode 100644 (file)
index 0000000..4104a20
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: JunHwan An <jh48.an@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.
+ */
+
+#ifndef __MANAGER_SMS_INTERNAL_H__
+#define __MANAGER_SMS_INTERNAL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+       SMS_TON_UNKNOWN = 0, /**< unknown */
+       SMS_TON_INTERNATIONAL = 1, /**< international number */
+       SMS_TON_NATIONAL = 2, /**< national number */
+       SMS_TON_NETWORK_SPECIFIC = 3, /**< network specific number */
+       SMS_TON_DEDICATED_ACCESS = 4, /**< subscriber number */
+       SMS_TON_ALPHA_NUMERIC = 5, /**< alphanumeric, GSM 7-bit default alphabet) */
+       SMS_TON_ABBREVIATED_NUMBER = 6, /**< abbreviated number */
+       SMS_TON_RESERVED_FOR_EXT = 7 /**< reserved for extension */
+} SimTypeOfNum_t;
+
+typedef enum {
+       SMS_NPI_UNKNOWN = 0, /**< Unknown */
+       SMS_NPI_ISDN_TEL = 1, /**< ISDN/Telephone numbering plan */
+       SMS_NPI_DATA_NUMBERING_PLAN = 3, /**< Data numbering plan */
+       SMS_NPI_TELEX = 4, /**< Telex numbering plan */
+       SMS_NPI_SVC_CNTR_SPECIFIC_PLAN = 5, /**< Service Center Specific plan */
+       SMS_NPI_SVC_CNTR_SPECIFIC_PLAN2 = 6, /**< Service Center Specific plan */
+       SMS_NPI_NATIONAL = 8, /**< National numbering plan */
+       SMS_NPI_PRIVATE = 9, /**< Private numbering plan */
+       SMS_NPI_ERMES_NUMBERING_PLAN = 10, /**< ERMES numbering plan */
+       SMS_NPI_RESERVED_FOR_EXT = 0xF /**< Reserved for extension */
+} SimNumberingPlanIdentity_t;
+
+typedef struct {
+       unsigned int DialNumLen; /**< length of address. If Service center address is not set, then this will be zero */
+       SimTypeOfNum_t Ton; /**< Type of number*/
+       SimNumberingPlanIdentity_t Npi; /**<Numbering plan identification*/
+       unsigned char szDiallingNum[SMS_ADDRESS_LEN_MAX + 1]; /**< destination address. If Address not set, then set to 0xFF */
+} SmsAddressInfo_t;
+
+typedef struct {
+       int year;
+       int month;
+       int day;
+       int hour;
+       int minute;
+       int second;
+} TmDateTime;
+
+typedef enum {
+       SMS_CODGRP_SM_GENERAL_DCS,                      /**< Bits 7..4 00xx */
+       SMS_CODGRP_CB_GENERAL_LANG,             /**< 0000 */
+       SMS_CODGRP_CB_ALPHA,                            /**< 0001 */
+       SMS_CODGRP_CB_RES1,                             /**< 0010 */
+       SMS_CODGRP_CB_RES2,                             /**< 0011 */
+       SMS_CODGRP_SM_AUTO_DELETION,            /**< 01xx Bits 5..0 are coded the same as SM_GENERAL_DCS */
+       SMS_CODGRP_CB_GENERAL_DCS,                      /**< 01xx behavior is as SM_GENERAL_DCS */
+       SMS_CODGRP_SM_WAITING_DISCARD,          /**< 1100 */
+       SMS_CODGRP_SM_WAITING_STORE,            /**< 1101 */
+       SMS_CODGRP_SM_WAITING_STORE_UCS2,       /**< 1110 */
+       SMS_CODGRP_CB_WAP,                                      /**< 1110 Cell Broadcast */
+       SMS_CODGRP_SM_CLASS_CODING,             /**< 1111 */
+       SMS_CODGRP_CB_CLASS_CODING,             /**< 1111 Cell Broadcast */
+       SMS_CODGRP_MAX
+} Sms_coding_group_type;
+
+typedef enum {
+       SMS_WAITING_VOICE_MSG,          /**< voice message waiting */
+       SMS_WAITING_FAX_MSG,            /**< FAX message waiting */
+       SMS_WAITING_EMAIL_MSG,          /**< E-mail waiting */
+       SMS_WAITING_OTHER_MSG,          /**< Other message waiting */
+       SMS_WAITING_MAX
+} Sms_waiting_type;
+
+typedef enum {
+       SMS_ALPHABET_DEFAULT,   /**< GSM alphabet default 7bit */
+       SMS_ALPHABET_8BIT,              /**< 8bit */
+       SMS_ALPHABET_UCS2,              /**< 16bit ucs2 */
+       SMS_ALPHABET_KSC5601,   /**< for Korean */
+       SMS_ALPHABET_MAX
+} Sms_alphabet_type;
+
+typedef enum {
+       SMS_CLASS_0 = 0x00,     /**< display immediately */
+       SMS_CLASS_1 = 0x01,     /**< may be stored */
+       SMS_CLASS_2 = 0x02,     /**< store in SIM */
+       SMS_CLASS_3 = 0x03,     /**< transfer to TE */
+       SMS_CLASS_NONE,
+       SMS_CLASS_MAX
+} Sms_class_type;
+
+typedef struct {
+       int bCompressed;                                                                /**< if text is compressed this is TRUE */
+       int bmsg_class_set;                                                             /**< message class indication. if TRUE = bits 1..0, if FALSE = reserved */
+       int bmsg_ind_active;                                                                    /**< message indication group. if TRUE = on, FALSE = off */
+       Sms_coding_group_type coding_group_type;                /**< Coding group, GSM 03.38 */
+       Sms_waiting_type waiting_type;                                  /**< Type of message waiting */
+       Sms_alphabet_type alphabet_type;                                /**< How to encode a message. */
+       Sms_class_type class_type;                                      /**< The message class */
+} Sms_coding_scheme;
+
+typedef enum {
+       SMS_TPDU_DELIVER = 0x00,                        // sc -> ms
+       SMS_TPDU_DELIVER_REPORT = 0x00,         // ms -> sc
+       SMS_TPDU_SUBMIT = 0x01,                         // ms -> sc
+       SMS_TPDU_SUBMIT_REPORT = 0x01,          // sc -> ms
+       SMS_TPDU_STATUS_REPORT = 0x02,          // sc -> ms
+       SMS_TPDU_COMMAND = 0x02,                        // ms -> sc
+       SMS_PDU_INVALID_TYPE
+} SmsTPDUType;
+
+typedef struct {
+       /************HEADER************/
+       SmsTPDUType msg_type;   //bit 0 ,1
+       int mms; // bit 2
+       int rp; // bit 7
+       int udhi;  //bit 6
+       int sri; // bit , 5status_report_indication
+
+       /************BODY************/
+       SmsAddressInfo_t orgAddr;
+       unsigned char pId;
+       TmDateTime scts;
+       Sms_coding_scheme dcs;
+       unsigned int udl;
+       char *userData;
+} TPDU_SMS_DELIVER;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MANAGER_SMS_INTERNAL_H__ */
diff --git a/include/manager_call.h b/include/manager_call.h
new file mode 100644 (file)
index 0000000..8a927cf
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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.
+ */
+
+#ifndef __MANAGER_CALL_H__
+#define __MANAGER_CALL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum tcore_manager_return manager_call_process_request(Server *server, UserRequest *ur);
+
+enum tcore_manager_return manager_call_process_notification(Manager *manager, CoreObject *source,
+                                                           enum tcore_notification_command command, unsigned int data_len, void *data);
+enum tcore_hook_return on_noti_manager_early_ecc_rat(Server *server,
+                                                    CoreObject *source, enum tcore_notification_command command, unsigned int data_len, void *data, void *user_data);
+
+gboolean manager_call_initialize_private_info(ModemBoard *mb);
+void     manager_call_clear_private_info(ModemBoard *mb);
+gboolean manager_call_is_during_call(TcorePlugin *plugin);
+
+void manager_call_process_modem_error(CoreObject *co_modem);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MANAGER_CALL_H__ */
diff --git a/include/manager_core.h b/include/manager_core.h
new file mode 100644 (file)
index 0000000..ff4c90d
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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.
+ */
+
+#ifndef __MANAGER_CORE_H__
+#define __MANAGER_CORE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "manager_types.h"
+
+typedef enum {
+       MANAGER_MODEM_BOARD_INDEX_INVALID = -1,
+       MANAGER_MODEM_BOARD_INDEX_0 = 0,
+       MANAGER_MODEM_BOARD_INDEX_1 = 1
+} ModemBoardIndex;
+
+typedef struct {
+       ModemBoardIndex index;
+       TcorePlugin *modem_plugin;
+       NetworkPrivateInfo *network_info;
+       CallPrivateInfo *call_info;
+       SimPrivateInfo *sim_info;
+       ModemPrivateInfo *modem_info;
+       GHashTable *fdn_contacts;
+       gboolean fdn_enabled;
+} ModemBoard;
+
+ModemBoard *    manager_core_get_modem_board(Manager *manager, TcorePlugin *modem_plugin);
+ModemBoardIndex manager_core_get_modem_board_index(TcorePlugin *modem_plugin);
+
+void manager_core_create_modem_board(TcorePlugin *manager_plugin, TcorePlugin *modem_plugin);
+void manager_core_destroy_modem_board(TcorePlugin *manager_plugin, TcorePlugin *modem_plugin);
+void manager_core_create_modem_board_list(TcorePlugin *manager_plugin);
+void manager_core_destroy_modem_board_list(TcorePlugin *manager_plugin);
+
+gboolean manager_core_init(TcorePlugin *plugin);
+void     manager_core_deinit(TcorePlugin *plugin);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MANAGER_CORE_H__ */
diff --git a/include/manager_modem.h b/include/manager_modem.h
new file mode 100644 (file)
index 0000000..403f95b
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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.
+ */
+
+#ifndef __MANAGER_MODEM_H__
+#define __MANAGER_MODEM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct manager_modem_private_info {
+       CoreObject *co_modem;
+       enum modem_state modem_status;
+};
+
+gboolean manager_modem_initialize_private_info(ModemBoard *mb);
+
+enum tcore_manager_return manager_modem_process_request(Server *server,
+                                                       UserRequest *ur);
+enum tcore_manager_return manager_modem_process_notification(Manager *manager,
+                                                            CoreObject *source, enum tcore_notification_command command,
+                                                            unsigned int data_len, void *data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MANAGER_MODEM_H__ */
diff --git a/include/manager_network.h b/include/manager_network.h
new file mode 100644 (file)
index 0000000..f8a4c4e
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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.
+ */
+
+#ifndef __MANAGER_NETWORK_H__
+#define __MANAGER_NETWORK_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum tcore_manager_return manager_network_deregister_ims(Manager *manager, UserRequest *ur);
+void manager_network_cancel_network_search(Manager *manager, Server *server);
+enum tcore_manager_return manager_network_process_request(Server *server,
+       UserRequest *ur);
+enum tcore_manager_return manager_network_process_notification(Manager *manager,
+       CoreObject *source,
+       enum tcore_notification_command command,
+       unsigned int data_len, void *data);
+
+gboolean manager_network_initialize_private_info(ModemBoard *mb);
+void     manager_network_clear_private_info(ModemBoard *mb);
+void     manager_network_process_modem_error(CoreObject *co_modem);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MANAGER_NETWORK_H__ */
diff --git a/include/manager_notification.h b/include/manager_notification.h
new file mode 100644 (file)
index 0000000..fe04ff4
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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.
+ */
+
+#ifndef __MANAGER_NOTIFICATION_H__
+#define __MANAGER_NOTIFICATION_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum tcore_manager_return manager_notification_handler(Manager *manager, CoreObject *source,
+                                                      enum tcore_notification_command command,
+                                                      unsigned int data_len, void *data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MANAGER_NOTIFICATION_H__ */
diff --git a/include/manager_phonebook.h b/include/manager_phonebook.h
new file mode 100644 (file)
index 0000000..d2f8d6d
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Ankit Jogi <ankit.jogi@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.
+ */
+
+#ifndef __MANAGER_PHONEBOOK_H__
+#define __MANAGER_PHONEBOOK_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum tcore_manager_return manager_phonebook_process_request(Server* server, UserRequest* ur);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MANAGER_PHONEBOOK_H__ */
diff --git a/include/manager_queue.h b/include/manager_queue.h
new file mode 100644 (file)
index 0000000..b4eaba6
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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.
+ */
+
+#ifndef __MANAGER_QUEUE_H__
+#define __MANAGER_QUEUE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+GQueue *manager_queue_init(void);
+void    manager_queue_deinit(GQueue *manager_queue);
+
+void         manager_queue_enqueue(Manager *manager, UserRequest *ur);
+UserRequest *manager_queue_dequeue(Manager *manager);
+gboolean     manager_queue_probe_command(Manager *manager, enum tcore_request_command command);
+guint        manager_get_queue_length(Manager *manager, enum tcore_request_command command);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MANAGER_QUEUE_H__ */
diff --git a/include/manager_request.h b/include/manager_request.h
new file mode 100644 (file)
index 0000000..cf6aab7
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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.
+ */
+
+#ifndef __MANAGER_REQUEST_H__
+#define __MANAGER_REQUEST_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum tcore_manager_return manager_request_handler(Manager *manager, UserRequest *ur);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MANAGER_REQUEST_H__ */
diff --git a/include/manager_server.h b/include/manager_server.h
new file mode 100644 (file)
index 0000000..c345e95
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Imran Mohammed <md.imran@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.
+ */
+
+#ifndef __MANAGER_SERVER_H__
+#define __MANAGER_SERVER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum tcore_manager_return manager_server_process_notification(Manager *manager,
+                                                             CoreObject *source, enum tcore_notification_command command,
+                                                             unsigned int data_len, void *data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MANAGER_SERVER_H__ */
+
diff --git a/include/manager_sim.h b/include/manager_sim.h
new file mode 100644 (file)
index 0000000..4ff40af
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Imran Mohammed <md.imran@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.
+ */
+
+#ifndef __MANAGER_SIM_H__
+#define __MANAGER_SIM_H__
+
+#include "manager_core.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct manager_sim_private_info {
+       CoreObject *co_sim;
+       enum tel_sim_status sim_status;
+       gboolean is_first_boot;
+};
+enum tcore_manager_return manager_sim_process_notification(Manager *manager,
+                                                          CoreObject *source, enum tcore_notification_command command,
+                                                          unsigned int data_len, void *data);
+enum tcore_manager_return manager_sim_process_request(Server *server, UserRequest *ur);
+void                      manager_network_resp_hook_set_network_mode(UserRequest *ur,
+                                                                    enum tcore_response_command command,
+                                                                    unsigned int data_len, const void *data, void *user_data);
+void manager_network_resp_hook_set_dds(UserRequest *ur,
+                                      enum tcore_response_command command,
+                                      unsigned int data_len, const void *data, void *user_data);
+void manager_network_resp_hook_set_ds(UserRequest *ur,
+                                     enum tcore_response_command command,
+                                     unsigned int data_len, const void *data, void *user_data);
+
+
+gboolean manager_sim_initialize_private_info(ModemBoard *mb);
+void set_nw_dds_ds_on_boot(Manager *manager);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MANAGER_SIM_H__ */
diff --git a/include/manager_sms.h b/include/manager_sms.h
new file mode 100644 (file)
index 0000000..14779b7
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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.
+ */
+
+#ifndef __MANAGER_SMS_H__
+#define __MANAGER_SMS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum tcore_manager_return manager_sms_process_request(Server *server, UserRequest *ur);
+enum tcore_manager_return manager_sms_process_notification(Manager *manager,
+                                                          CoreObject *source, enum tcore_notification_command command,
+                                                          unsigned int data_len, void *data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MANAGER_SMS_H__ */
diff --git a/include/manager_ss.h b/include/manager_ss.h
new file mode 100644 (file)
index 0000000..03addb9
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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.
+ */
+
+#ifndef __MANAGER_SS_H__
+#define __MANAGER_SS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum tcore_manager_return manager_ss_process_request(Server *server, UserRequest *ur);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MANAGER_SS_H__ */
diff --git a/include/manager_types.h b/include/manager_types.h
new file mode 100644 (file)
index 0000000..3373eef
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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.
+ */
+
+#ifndef __MANAGER_TYPES_H__
+#define __MANAGER_TYPES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct manager_network_private_info NetworkPrivateInfo;
+typedef struct manager_sim_private_info SimPrivateInfo;
+typedef struct manager_modem_private_info ModemPrivateInfo;
+typedef struct manager_private_data PrivateData;
+typedef struct manager_call_private_info CallPrivateInfo;
+
+//Temprarily added for build
+//Should be added belowVCONFKEYs to vconof-internal-keys
+#define VCONFKEY_TELEPHONY_SET_ECC_STATUS "db/priviate/telephony/set_ecc_status"
+#define VCONFKEY_TELEPHONY_SET_ECC_STATUS_NONE 0
+#define VCONFKEY_TELEPHONY_LAC_NETNAME "db/priviate/telephony/lac_netname"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MANAGER_TYPES_H__ */
diff --git a/include/manager_util.h b/include/manager_util.h
new file mode 100644 (file)
index 0000000..35e690a
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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.
+ */
+
+#ifndef __MANAGER_UTIL_H__
+#define __MANAGER_UTIL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "manager_types.h"
+
+TcorePlugin *manager_util_get_modem_plugin(Server *server, UserRequest *ur);
+TcorePlugin *manager_util_get_modem_plugin_by_subs_type(Server *server,
+       enum telephony_subscription_type subs_type);
+CoreObject * manager_util_get_core_object(Server *server, UserRequest *ur, unsigned int type);
+
+gboolean                                    manager_util_is_ims_registered(Server *server, UserRequest *ur, guint feature_type);
+enum telephony_network_ims_reg_network_type manager_util_get_ims_reg_network_type(Server *server, UserRequest *ur);
+
+gboolean manager_util_send_request(TcorePlugin *modem_plugin, enum tcore_request_command command,
+                                  unsigned int data_len, const void *data, UserRequestResponseHook resp_hook, void *user_data);
+
+TcorePlugin *             manager_util_get_other_subs_plugin(TcorePlugin *plugin);
+void                      manager_set_deregister_timer(Manager *manager, guint timer_id);
+void                      manager_clear_deregister_timer(Manager *manager);
+guint                     manager_get_deregister_timer(Manager *manager);
+gboolean                  manager_deregister_ims_timeout(gpointer user_data);
+void                      manager_util_process_pending_request(Manager *manager);
+enum tcore_manager_return manager_util_process_ims(Server *server, UserRequest *ur);
+void                      manager_util_write_to_proc_file(const char *data, int data_len);
+
+
+typedef enum  {
+       MANAGER_SUBS_DEFAULT,
+       MANAGER_SUBS_PRIMARY = MANAGER_SUBS_DEFAULT,
+       MANAGER_SUBS_SECONDARY,
+       MANAGER_SUBS_TERTIARY,
+       MANAGER_SUBS_MAX = MANAGER_SUBS_SECONDARY /* Only 2 are supported for now */
+} s_manager_subs_type;
+
+s_manager_subs_type s_manager_get_subs_type_ur(UserRequest *ur);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MANAGER_UTIL_H__ */
diff --git a/packaging/tel-plugin-manager.spec b/packaging/tel-plugin-manager.spec
new file mode 100644 (file)
index 0000000..6f40296
--- /dev/null
@@ -0,0 +1,59 @@
+%define major 0
+%define minor 1
+%define patchlevel 0
+
+Name:           tel-plugin-manager
+Version:        %{major}.%{minor}.%{patchlevel}
+Release:        2
+License:        Apache
+Summary:        Manager for telephony
+Group:          System/Libraries
+Source0:        %{name}-%{version}.tar.gz
+BuildRequires:  cmake
+BuildRequires:  pkgconfig(glib-2.0)
+BuildRequires:  pkgconfig(libtzplatform-config)
+BuildRequires:  pkgconfig(libxml-2.0)
+BuildRequires:  pkgconfig(tcore)
+BuildRequires:  pkgconfig(vconf)
+BuildRequires:  pkgconfig(openssl)
+BuildRequires:  pkgconfig(tfeature)
+BuildRequires:  pkgconfig(cynara-client)
+BuildRequires:  pkgconfig(cynara-session)
+
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+%description
+Manager for telephony
+
+%prep
+%setup -q
+
+%build
+versionint=$[%{major} * 1000000 + %{minor} * 1000 + %{patchlevel}]
+
+cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} \
+        -DVERSION=$versionint \
+        -DSYSCONFDIR=%{_sysconfdir} \
+       -DLIB_INSTALL_DIR=%{_libdir} \
+%if 0%{?sec_product_feature_network_dsds}
+    -DFEATURE_MULTISIM=1 \
+%endif
+%if 0%{?sec_product_feature_profile_wearable}
+    -DWEARABLE=1 \
+%endif
+
+make %{?_smp_mflags}
+
+%postun -p /sbin/ldconfig
+
+%install
+%make_install
+mkdir -p %{buildroot}%{_datadir}/license
+
+%files
+%manifest tel-plugin-manager.manifest
+%defattr(644,root,root,-)
+#%doc COPYING
+%{_libdir}/telephony/plugins/*
+%{_datadir}/license/tel-plugin-manager
diff --git a/src/desc-manager.c b/src/desc-manager.c
new file mode 100644 (file)
index 0000000..5b184db
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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 <glib.h>
+#include <tcore.h>
+#include <plugin.h>
+
+#include "manager_core.h"
+
+static gboolean on_load()
+{
+       dbg("Load!!!");
+
+       return TRUE;
+}
+
+static gboolean on_init(TcorePlugin *plugin)
+{
+       gboolean ret;
+
+       dbg("Init!!!");
+
+       if (plugin == NULL)
+               return FALSE;
+
+       /* Initialize Manager core */
+       ret = manager_core_init(plugin);
+       info("Init - [%s]", ret ? "Success" : "Fail");
+
+       return ret;
+}
+
+static void on_unload(TcorePlugin *plugin)
+{
+       dbg("Unload!!!");
+
+       if (plugin == NULL)
+               return;
+
+       return manager_core_deinit(plugin);
+}
+
+/* Manager Plug-in Descriptor */
+EXPORT_API struct tcore_plugin_define_desc plugin_define_desc = {
+       .name = "manager",
+       .priority = TCORE_PLUGIN_PRIORITY_MID + 2,
+       .version = 1,
+       .load = on_load,
+       .init = on_init,
+       .unload = on_unload
+};
+
diff --git a/src/manager_call.c b/src/manager_call.c
new file mode 100644 (file)
index 0000000..9b8567a
--- /dev/null
@@ -0,0 +1,1608 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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 <string.h>
+#include <vconf.h>
+#include <tfeature.h>
+
+#include <glib.h>
+#include <tcore.h>
+#include <server.h>
+#include <manager.h>
+#include <plugin.h>
+#include <core_object.h>
+#include <user_request.h>
+#include <co_call.h>
+#include <co_sim.h>
+#include <co_network.h>
+#include <type/network.h>
+
+#include "manager_queue.h"
+#include "manager_core.h"
+#include "manager_util.h"
+#include "manager_call.h"
+#include "manager_network.h"
+#include "manager_sim.h"
+#include "internal/manager_internal.h"
+#include "internal/manager_call_internal.h"
+
+struct silent_redial_hook_arg {
+       enum telephony_call_type type;
+       unsigned int handle;
+       TcorePlugin *modem_plgn;
+       enum telephony_call_end_cause prev_end_cause;
+};
+
+static void on_resp_manager_dial(UserRequest *ur, enum tcore_response_command command,
+                                unsigned int data_len, const void *data, void *user_data);
+
+static void on_resp_manager_set_ecc_status(UserRequest *ur, enum tcore_response_command command,
+                                          unsigned int data_len, const void *data, void *user_data);
+
+static void on_resp_manager_silent_redial(UserRequest *ur,
+                                         enum tcore_response_command command,
+                                         unsigned int data_len, const void *data, void *user_data);
+
+static CallPrivateInfo *__get_call_private_info(Server *s, UserRequest *ur)
+{
+       TcorePlugin *modem_plugin = manager_util_get_modem_plugin(s, ur);
+       ModemBoard *mb = manager_core_get_modem_board(tcore_server_ref_manager(s), modem_plugin);
+
+       if (G_UNLIKELY(!mb)) {
+               err("mb not found");
+               return NULL;
+       }
+       return mb->call_info;
+}
+
+#ifdef TIZEN_FEATURE_MULTISIM   /*only valid for Multi-SIM models. Not for wearable*/
+static gboolean __is_active_call(CoreObject *co_call)
+{
+       GSList *list = NULL;
+
+       list = tcore_call_object_find_by_status(co_call, TCORE_CALL_STATUS_ACTIVE);
+       if (list) {
+               g_slist_free(list);
+               return TRUE;
+       } else if ((list = tcore_call_object_find_by_status(co_call, TCORE_CALL_STATUS_HELD))) {
+               g_slist_free(list);
+               return TRUE;
+       } else {
+               return FALSE;
+       }
+}
+#endif
+
+static gboolean __is_mt_call_processing(CoreObject *co_call)
+{
+       TcorePlugin *plugin_subs = NULL, *plugin_subs_other = NULL;
+       CallObject *call_obj_sub = NULL, *call_obj_sub_other = NULL, *call_obj = NULL;
+       CoreObject *co_call_other;
+
+       plugin_subs = tcore_object_ref_plugin(co_call);
+       plugin_subs_other = manager_util_get_other_subs_plugin(plugin_subs);
+       co_call_other = tcore_plugin_ref_core_object(plugin_subs_other, CORE_OBJECT_TYPE_CALL);
+       call_obj_sub = tcore_call_object_current_on_mt_processing(co_call);
+       call_obj_sub_other = tcore_call_object_current_on_mt_processing(co_call_other);
+
+       if (call_obj_sub)
+               call_obj = call_obj_sub;
+       else if (call_obj_sub_other)
+               call_obj = call_obj_sub_other;
+
+       if (call_obj)
+               return TRUE;
+       else
+               return FALSE;
+}
+
+static int __is_ignore_ims_voice_status_indication(const char *plmn)
+{
+       if ((g_strcmp0(plmn, "45001") == 0) || (g_strcmp0(plmn, "00101") == 0))
+               return TRUE;
+       else
+               return FALSE;
+}
+
+static gboolean __is_emergency_only_via_cs(void)
+{
+       if (tfeature_is_supported(TFEATURE_FUNCTION_CS_OVERRIDE_EMERGENCY_CALL)) {
+               dbg("TFEATURE_FUNCTION_CS_OVERRIDE_EMERGENCY_CALL -  trigger Emergency call over CS only");
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+static gboolean __is_emergency_only_via_ps(void)
+{
+       if (tfeature_is_supported(TFEATURE_DEVICE_LTE_ONLY)) {
+               dbg("TFEATURE_DEVICE_LTE_ONLY-  enforce UE to trigger Emergency call over PS only");
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+static void __call_set_ecc_rat_status(CoreObject *co_call, enum telephony_call_ecc_status status, enum telephony_network_access_technology ecc_rat)
+{
+       struct treq_call_set_ecc_status ecc = { 0, };
+       UserRequest *ur = NULL;
+
+       dbg("ENTER");
+
+       ur = tcore_user_request_new(NULL, NULL);
+       tcore_user_request_set_command(ur, TREQ_CALL_SET_ECC_STATUS);
+
+       ecc.status = status;
+       ecc.ecc_rat = ecc_rat;
+
+       tcore_user_request_set_data(ur, sizeof(struct treq_call_set_ecc_status), &ecc);
+       if (tcore_object_dispatch_request(co_call, ur) != TCORE_RETURN_SUCCESS) {
+               err("TREQ_CALL_SET_ECC_STATUS failed!!!");
+               tcore_user_request_unref(ur);
+       }
+}
+
+static enum tcore_hook_return on_noti_manager_ecc_rat(Server *server,
+                                                     CoreObject *source, enum tcore_notification_command command,
+                                                     unsigned int data_len, void *data, void *user_data)
+{
+       const struct tnoti_network_ecc_rat *noti_data = data;
+       enum telephony_network_ecc_rat_search_status rat_search_status;
+       TcorePlugin *modem_plugin;
+       CoreObject *co_network = source;
+       CoreObject *co_call;
+       CallObject *call_obj;
+       GSList *list;
+       UserRequest *ur = user_data;
+
+       modem_plugin = tcore_object_ref_plugin(co_network);
+       co_call = tcore_plugin_ref_core_object(modem_plugin, CORE_OBJECT_TYPE_CALL);
+       list = tcore_call_object_find_by_status(co_call, TCORE_CALL_STATUS_SETUP_PENDING);
+       if (list == NULL) {
+               err("No setup_pending status call!!!");
+               tcore_server_remove_notification_hook(server, on_noti_manager_ecc_rat);
+               tcore_user_request_unref(ur);
+               return TCORE_HOOK_RETURN_CONTINUE;
+       }
+       call_obj = list->data;
+       g_slist_free(list);
+
+       tcore_network_get_ecc_rat_search_status(co_network, &rat_search_status);
+
+       if (rat_search_status == NETWORK_ECC_RAT_SEARCH_STATUS_WAITING) {
+               UserRequest *ur_dial;
+               struct treq_call_dial *req_data;
+               char *modem_name;
+
+               dbg("ECC RAT Search completed!!!");
+               tcore_network_set_ecc_rat_search_status(co_network, NETWORK_ECC_RAT_SEARCH_STATUS_READY);
+               modem_name = tcore_user_request_get_modem_name(ur);
+               ur_dial = tcore_user_request_new(NULL, modem_name);
+               req_data = (struct treq_call_dial *)tcore_user_request_ref_data(ur, NULL);
+               req_data->handle = tcore_call_object_get_handle(call_obj);
+               tcore_user_request_set_data(ur_dial, sizeof(struct treq_call_dial), req_data);
+               tcore_user_request_set_command(ur_dial, TREQ_CALL_DIAL);
+               tcore_user_request_set_response_hook(ur_dial, on_resp_manager_dial, co_call);
+               tcore_user_request_unref(ur);
+               g_free(modem_name);
+
+               if (noti_data->ecc_rat == NETWORK_ACT_LTE) {
+                       dbg("ecc_rat[%d], request to IMS", noti_data->ecc_rat);
+                       tcore_call_object_set_is_volte_call(call_obj, TRUE);
+                       tcore_server_dispatch_request_ex(server, ur_dial, TCORE_OPS_TYPE_IMS);
+               } else {
+                       dbg("ecc_rat[%d], request to CP", noti_data->ecc_rat);
+                       tcore_server_dispatch_request_ex(server, ur_dial, TCORE_OPS_TYPE_CP);
+               }
+
+               dbg("set call state to SETUP -dial triggered");
+               tcore_call_object_set_status(call_obj, TCORE_CALL_STATUS_SETUP);
+       }
+
+       tcore_server_remove_notification_hook(server, on_noti_manager_ecc_rat);
+       return TCORE_HOOK_RETURN_CONTINUE;
+}
+
+
+static enum tcore_hook_return on_noti_manager_ecc_rat_for_silent_redial(Server *server,
+                                                                       CoreObject *source, enum tcore_notification_command command,
+                                                                       unsigned int data_len, void *data, void *user_data)
+{
+       const struct tnoti_network_ecc_rat *noti_data = data;
+       enum telephony_network_ecc_rat_search_status rat_search_status;
+       CoreObject *co_network = source;
+       CoreObject *co_call;
+       CallObject *call_obj;
+       struct silent_redial_hook_arg *arg = (struct silent_redial_hook_arg *)user_data;
+
+       co_call = tcore_plugin_ref_core_object(tcore_object_ref_plugin(co_network), CORE_OBJECT_TYPE_CALL);
+       call_obj = tcore_call_object_find_by_handle(co_call, arg->handle);
+       if (call_obj == NULL) {
+               err("No setup_pending status call!!!");
+               tcore_server_remove_notification_hook(server, on_noti_manager_ecc_rat_for_silent_redial);
+               g_free(arg);
+               return TCORE_HOOK_RETURN_CONTINUE;
+       }
+
+       tcore_network_get_ecc_rat_search_status(co_network, &rat_search_status);
+       if (rat_search_status == NETWORK_ECC_RAT_SEARCH_STATUS_WAITING) {
+               UserRequest *ur_dial;
+               struct treq_call_dial req_data;
+
+               dbg("ECC RAT Search completed!!!Invoke redial!");
+               tcore_network_set_ecc_rat_search_status(co_network, NETWORK_ECC_RAT_SEARCH_STATUS_READY);
+               ur_dial = tcore_user_request_new(NULL, NULL);
+
+               req_data.handle = tcore_call_object_get_handle(call_obj);
+               req_data.type = tcore_call_object_get_type(call_obj);
+               tcore_call_object_get_number(call_obj, req_data.number);
+               req_data.ecc = tcore_call_object_get_emergency_category(call_obj);
+
+               tcore_user_request_set_data(ur_dial, sizeof(struct treq_call_dial), &req_data);
+               tcore_user_request_set_command(ur_dial, TREQ_CALL_DIAL);
+               tcore_user_request_set_response_hook(ur_dial, on_resp_manager_silent_redial, arg);
+
+               if (noti_data->ecc_rat == NETWORK_ACT_LTE) {
+                       dbg("ecc_rat[%d], request to IMS", noti_data->ecc_rat);
+                       tcore_call_object_set_is_volte_call(call_obj, TRUE);
+
+                       tcore_object_dispatch_request_with_type(co_call, ur_dial, TCORE_OPS_TYPE_IMS);
+               } else {
+                       dbg("ecc_rat[%d], request to CP", noti_data->ecc_rat);
+                       tcore_object_dispatch_request_with_type(co_call, ur_dial, TCORE_OPS_TYPE_CP);
+               }
+
+               dbg("set call state to SETUP -dial triggered");
+               tcore_call_object_set_status(call_obj, TCORE_CALL_STATUS_SETUP);
+       }
+
+       tcore_server_remove_notification_hook(server, on_noti_manager_ecc_rat_for_silent_redial);
+       return TCORE_HOOK_RETURN_CONTINUE;
+}
+
+
+static enum tcore_manager_return __call_search_ecc_rat(Server *server, UserRequest *ur)
+{
+       struct tresp_call_dial resp_data = { 0, };
+       CoreObject *co_call = NULL;
+       CallObject *call_obj = NULL;
+       UserRequest *ur_rat = NULL;
+       char *modem_name = NULL;
+       struct treq_call_set_ecc_status ecc;
+       struct treq_call_dial dial_info;
+       const struct treq_call_dial *orig_data = NULL;
+       CallPrivateInfo *cpi = NULL;
+
+       co_call = manager_util_get_core_object(server, ur, CORE_OBJECT_TYPE_CALL);
+       cpi = __get_call_private_info(server, ur);
+       if (cpi == NULL) {
+               err("null cpi");
+               return TCORE_MANAGER_RETURN_FAILURE;
+       }
+
+       /* set ECC status : CALL_ECC_STATUS_STARTED */
+       modem_name = tcore_user_request_get_modem_name(ur);
+       ur_rat = tcore_user_request_new(NULL, modem_name);
+       g_free(modem_name);
+
+       ecc.status = CALL_ECC_STATUS_STARTED;
+       ecc.ecc_rat = NETWORK_ACT_NOT_SPECIFIED;
+
+       tcore_user_request_set_command(ur_rat, TREQ_CALL_SET_ECC_STATUS);
+       tcore_user_request_set_data(ur_rat, sizeof(struct treq_call_set_ecc_status), &ecc);
+
+       /*create premature call object in case dialing notification is needed before actually requesting call dial*/
+       call_obj = tcore_call_object_new(co_call);
+       tcore_call_object_set_type(call_obj, CALL_TYPE_E911);
+       tcore_call_object_set_status(call_obj, TCORE_CALL_STATUS_SETUP_PENDING);
+       tcore_call_object_set_direction(call_obj, TCORE_CALL_DIRECTION_OUTGOING);
+
+       orig_data = (struct treq_call_dial *)tcore_user_request_ref_data(ur, NULL);
+
+       memcpy(&dial_info, orig_data, sizeof(struct treq_call_dial));
+       dial_info.handle = tcore_call_object_get_handle(call_obj);
+
+       /*save original dial request info as "metainfo" or RAT request*/
+       tcore_user_request_set_metainfo(ur_rat, sizeof(struct treq_call_dial), &dial_info);
+       tcore_user_request_set_response_hook(ur_rat, on_resp_manager_set_ecc_status, server);
+       if (tcore_server_dispatch_request_ex(server, ur_rat, TCORE_OPS_TYPE_CP)
+                       != TCORE_RETURN_SUCCESS) {
+               err("TREQ_CALL_SET_ECC_STATUS failed!!!");
+               tcore_user_request_unref(ur_rat);
+               return TCORE_MANAGER_RETURN_STOP;
+       }
+
+       dbg("ecc rat search triggered. update cpi info");
+       cpi->rat_query_cache.call_handle = dial_info.handle;
+       cpi->rat_query_cache.rat_query_status = CALL_ECC_STATUS_STARTED;
+
+       resp_data.err = CALL_ERROR_NONE;
+       tcore_user_request_send_response(ur, TRESP_CALL_DIAL,
+                                        sizeof(struct tresp_call_dial), &resp_data);
+       tcore_user_request_unref(ur);
+
+       /* Send dialing notification in advance to avoid delay of UI display - disable now. revive when UI stuck issue is really happening*/
+#if 0
+       noti_data.type = tcore_call_object_get_type(call_obj);
+       noti_data.handle = tcore_call_object_get_handle(call_obj);
+       tcore_server_send_notification(server, co_call,
+                                      TNOTI_CALL_STATUS_DIALING,
+                                      sizeof(struct tnoti_call_status_dialing), &noti_data);
+#endif
+
+       dbg("Waiting RAT completed notification");
+       return TCORE_MANAGER_RETURN_STOP;
+}
+
+static enum tcore_manager_return __call_handle_end_request(Server *server, UserRequest *ur)
+{
+       enum tcore_manager_return ret = TCORE_MANAGER_RETURN_CONTINUE;
+       enum tcore_request_command command = tcore_user_request_get_command(ur);
+
+       switch (command) {
+       case TREQ_CALL_END: {
+               struct treq_call_end *req_data = NULL;
+               int call_handle = INVALID_HANDLE;
+               CoreObject *co_call = manager_util_get_core_object(server, ur, CORE_OBJECT_TYPE_CALL);
+               CoreObject *co_network = manager_util_get_core_object(server, ur, CORE_OBJECT_TYPE_NETWORK);
+               CallObject *call_obj = NULL;
+               Manager *manager = tcore_server_ref_manager(server);
+               TcorePlugin *manager_plugin = tcore_manager_get_plugin(manager);
+               PrivateData *priv_data = tcore_plugin_ref_user_data(manager_plugin);
+               enum tcore_call_status call_status;
+
+               if (!co_network)
+                       return TCORE_MANAGER_RETURN_FAILURE;
+
+               if (priv_data->is_dial_noti_sent)
+                       priv_data->is_dial_noti_sent = FALSE;
+
+               req_data = (struct treq_call_end *)tcore_user_request_ref_data(ur, NULL);
+               call_handle = req_data->handle;
+
+               call_obj = tcore_call_object_find_by_handle(co_call, call_handle);
+               if (!call_obj) {
+                       err("invalid call handle - serious!");
+
+                       if (req_data->type == CALL_END_TYPE_ALL)
+                               info("END_ALL. call handle has no meaning. continue");
+                       else
+                               return TCORE_MANAGER_RETURN_FAILURE;
+               }
+
+               call_status = tcore_call_object_get_status(call_obj);
+               if ((TCORE_CALL_STATUS_SETUP == call_status)
+                   || (TCORE_CALL_STATUS_SETUP_PENDING == call_status)) {
+                       struct tresp_call_end resp;
+
+                       if (tfeature_is_supported(TFEATURE_FUNCTION_NET_CHECK_ECC_RAT)) {
+                               enum telephony_network_ecc_rat_search_status rat_search_status;
+
+                               tcore_network_get_ecc_rat_search_status(co_network, &rat_search_status);
+                               if (tcore_call_object_get_type(call_obj) == TCORE_CALL_TYPE_E911
+                                   && rat_search_status == NETWORK_ECC_RAT_SEARCH_STATUS_WAITING) {
+                                       struct tnoti_call_status_idle noti_data;
+
+                                       dbg("Call end requested during ECC RAT Searching, free call_obj");
+                                       tcore_network_set_ecc_rat_search_status(co_network, NETWORK_ECC_RAT_SEARCH_STATUS_IDLE);
+
+                                       resp.err = CALL_ERROR_NONE;
+                                       resp.type = req_data->type;
+                                       resp.handle = req_data->handle;
+                                       tcore_user_request_send_response(ur, TRESP_CALL_END, sizeof(struct tresp_call_end), &resp);
+                                       tcore_user_request_unref(ur);
+
+                                       noti_data.type = CALL_TYPE_E911;
+                                       noti_data.handle = tcore_call_object_get_handle(call_obj);
+                                       noti_data.cause = CALL_END_CAUSE_NONE;
+                                       tcore_call_object_free(co_call, call_obj);
+
+                                       tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_call)),
+                                                                      co_call, TNOTI_CALL_STATUS_IDLE,
+                                                                      sizeof(struct tnoti_call_status_idle), &noti_data);
+                                       return TCORE_MANAGER_RETURN_STOP;
+                               }
+                       }
+                       info("call %d release requested but SETUP/PENDING state - save release request into call obj and wait for call event", call_handle);
+                       info("SETUP state - wait for dialing notification then send release request to CP");
+                       info("PENDING state - wait for precondition result then release call_obj and notify CALL_END to application");
+
+                       tcore_call_object_set_is_release_pending(call_obj, TRUE);
+
+                       resp.err = CALL_ERROR_NONE;
+                       resp.type = req_data->type;
+                       resp.handle = req_data->handle;
+
+                       tcore_user_request_send_response(ur, TRESP_CALL_END, sizeof(struct tresp_call_end), &resp);
+                       tcore_user_request_unref(ur);
+                       ret = TCORE_MANAGER_RETURN_STOP;
+               } else {
+                       dbg("ordinary call release request - bypass request to modem plugin");
+                       if (tcore_call_object_check_cs_call_existence(co_call) == FALSE)
+                               ret = TCORE_MANAGER_RETURN_CONTINUE_IMS;
+                       else
+                               ret = TCORE_MANAGER_RETURN_CONTINUE;
+               }
+       }
+       break;
+
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+static void on_resp_manager_silent_redial(UserRequest *ur,
+                                         enum tcore_response_command command,
+                                         unsigned int data_len, const void *data, void *user_data)
+{
+       Server *s = NULL;
+       CoreObject *co = NULL;
+       const struct tresp_call_dial *rsp = data;
+       struct silent_redial_hook_arg *arg = user_data;
+
+       s = tcore_plugin_ref_server(arg->modem_plgn);
+       co = tcore_plugin_ref_core_object(arg->modem_plgn, CORE_OBJECT_TYPE_CALL);
+
+       if (rsp->err == CALL_ERROR_NONE) {
+               /* TODO: Current implementation of sending fallback notification is based on SKT operator requirment
+                *  Need to update the code for to handle genrically for all the operators once requirments are clear from operator side
+               */
+               if (arg->prev_end_cause == CALL_END_CAUSE_UNASSIGNED_NUMBER ||
+                   arg->prev_end_cause == CALL_END_CAUSE_INVALID_NUMBER_FORMAT ||
+                   arg->prev_end_cause == CALL_END_CAUSE_TEMPORARY_FAILURE) {
+                       struct tnoti_call_fallback noti;
+
+                       dbg("redial call returned SUCCESS. proceed normal call setup procedure & send CS Fallback Notification if service provider requested");
+                       noti.handle = arg->handle;
+                       noti.fallback_to = CALL_FALLBACK_TO_CS;
+                       tcore_server_send_notification(s, co, TNOTI_CALL_INFO_FALLBACK, sizeof(struct tnoti_call_fallback), &noti);
+               }
+       } else {
+               struct tnoti_call_status_idle noti;
+               CallObject *co_call = NULL;
+               dbg("redial call returned FAILURE. send CALL_END notification with previous end cause from IMS. release call_obj if exist");
+
+               noti.handle = arg->handle;
+               noti.type = arg->type;
+               noti.cause = arg->prev_end_cause;
+
+               co_call = tcore_call_object_find_by_handle(co, arg->handle);
+               if (NULL != co_call) {
+                       dbg("CALL_STATUS_IDLE noti sent but call_obj still remaining. release call_obj");
+                       tcore_call_object_free(co, co_call);
+               }
+
+               tcore_server_send_notification(s, co, TNOTI_CALL_STATUS_IDLE, sizeof(struct tnoti_call_status_idle), (void *)&noti);
+       }
+
+       g_free(arg);
+}
+
+
+static void on_resp_manager_dial(UserRequest *ur,
+                                enum tcore_response_command command,
+                                unsigned int data_len, const void *data, void *user_data)
+{
+       const struct tresp_call_dial *resp_data = data;
+       CoreObject *co_call = user_data;
+
+       if (resp_data->err != CALL_ERROR_NONE) {
+               struct tnoti_call_status_idle noti_data;
+               CallObject *call_obj;
+               GSList *list;
+
+               err("Dial failed, free call_obj");
+               list = tcore_call_object_find_by_status(co_call, TCORE_CALL_STATUS_SETUP);
+               if (list == NULL) {
+                       err("No setup status call!!!");
+                       return;
+               }
+               call_obj = list->data;
+               g_slist_free(list);
+
+               noti_data.type = tcore_call_object_get_type(call_obj);
+               noti_data.handle = tcore_call_object_get_handle(call_obj);
+               noti_data.cause = CALL_END_CAUSE_NONE;
+               tcore_call_object_free(co_call, call_obj);
+               tcore_server_send_notification(tcore_plugin_ref_server(tcore_object_ref_plugin(co_call)),
+                                              co_call, TNOTI_CALL_STATUS_IDLE,
+                                              sizeof(struct tnoti_call_status_idle), &noti_data);
+       }
+}
+
+
+
+static void on_resp_manager_set_ecc_status(UserRequest *ur,
+                                          enum tcore_response_command command,
+                                          unsigned int data_len, const void *data, void *user_data)
+{
+       const struct tresp_network_search_ecc_rat *resp_data = data;
+       Server *server = user_data;
+       CoreObject *co_call;
+       CoreObject *co_network;
+       CallObject *call_obj;
+       GSList *list;
+       char *modem_name;
+
+       co_call = manager_util_get_core_object(server, ur, CORE_OBJECT_TYPE_CALL);
+       co_network = manager_util_get_core_object(server, ur, CORE_OBJECT_TYPE_NETWORK);
+       modem_name = tcore_user_request_get_modem_name(ur);
+
+       list = tcore_call_object_find_by_status(co_call, TCORE_CALL_STATUS_SETUP_PENDING);
+       if (list == NULL) {
+               err("No TCORE_CALL_STATUS_SETUP_PENDING status call!!!");
+               return;
+       }
+       call_obj = list->data;
+       g_slist_free(list);
+
+       if (resp_data->result == TCORE_RETURN_SUCCESS) {
+               UserRequest *ur_cpy;
+               struct tnoti_call_status_dialing noti_data = {0,};
+               Manager *manager = tcore_server_ref_manager(server);
+               TcorePlugin *manager_plugin = tcore_manager_get_plugin(manager);
+               PrivateData *priv_data = tcore_plugin_ref_user_data(manager_plugin);
+
+               dbg("ECC RAT Search requested, waiting complete notification");
+               tcore_network_set_ecc_rat_search_status(co_network, NETWORK_ECC_RAT_SEARCH_STATUS_WAITING);
+
+               /* Register searching completed notification */
+               ur_cpy = tcore_user_request_new(NULL, modem_name);
+               tcore_user_request_set_data(ur_cpy, sizeof(struct treq_call_dial), tcore_user_request_ref_metainfo(ur, NULL));
+               tcore_server_add_notification_hook(server, TNOTI_NETWORK_ECC_RAT,
+                                                  on_noti_manager_ecc_rat, ur_cpy);
+
+               noti_data.type = tcore_call_object_get_type(call_obj);
+               noti_data.handle = tcore_call_object_get_handle(call_obj);
+               tcore_server_broadcast_notification(server, co_call,
+                                      TNOTI_CALL_STATUS_DIALING,
+                                      sizeof(struct tnoti_call_status_dialing), &noti_data);
+
+               priv_data->is_dial_noti_sent = TRUE;
+
+       } else {
+               UserRequest *ur_dial;
+               struct treq_call_dial *req_data;
+
+               dbg("ECC RAT Search failed, Need discussion and request to CP");
+               tcore_network_set_ecc_rat_search_status(co_network, NETWORK_ECC_RAT_SEARCH_STATUS_IDLE);
+               ur_dial = tcore_user_request_new(NULL, modem_name);
+               req_data = (struct treq_call_dial *)tcore_user_request_ref_data(ur, NULL);
+               req_data->handle = tcore_call_object_get_handle(call_obj);
+               tcore_user_request_set_data(ur_dial, sizeof(struct treq_call_dial), req_data);
+               tcore_user_request_set_command(ur_dial, TREQ_CALL_DIAL);
+               tcore_user_request_set_response_hook(ur_dial, on_resp_manager_dial, co_call);
+
+               tcore_server_dispatch_request_ex(server, ur_dial, TCORE_OPS_TYPE_CP);
+               tcore_call_object_set_status(call_obj, TCORE_CALL_STATUS_SETUP);
+       }
+       g_free(modem_name);
+}
+
+gboolean manager_call_is_during_call(TcorePlugin *plugin)
+{
+       CoreObject *co_call = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_CALL);
+       int total_call_length = 0;
+
+       if (!co_call) {
+               err("Cannot find CoreObject");
+               return FALSE;
+       }
+
+       total_call_length = tcore_call_object_total_length(co_call);
+       if (total_call_length > 1) {
+               dbg("Multiple call exists");
+               return TRUE;
+       } else if (total_call_length == 1) {
+               GSList *list = tcore_call_object_find_by_status(co_call, TCORE_CALL_STATUS_IDLE);
+               if (!list) {
+                       dbg("Single call exists");
+                       return TRUE;
+               } else {
+                       g_slist_free(list);
+                       return FALSE;
+               }
+       } else {
+               return FALSE;
+       }
+
+       return FALSE;
+}
+
+static enum tcore_manager_return manager_call_silent_redial(CoreObject *co_call, CallObject *call_obj, enum telephony_call_end_cause cause)
+{
+       UserRequest *ur;
+       struct treq_call_dial req;
+       struct silent_redial_hook_arg *arg = NULL;
+       TcorePlugin *plugin;
+
+       TReturn ret = TCORE_RETURN_SUCCESS;
+
+       plugin = tcore_object_ref_plugin(co_call);
+       arg = g_malloc0(sizeof(struct silent_redial_hook_arg));
+
+       if ((TFEATURE_SUPPORTED == tfeature_is_supported(TFEATURE_FUNCTION_NET_CHECK_ECC_RAT)) &&
+           (TCORE_CALL_TYPE_E911 == tcore_call_object_get_type(call_obj)) &&
+           (!tcore_sim_is_jio_sim(tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_SIM)))) {
+
+               CoreObject *co_network = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_NETWORK);
+               enum telephony_network_access_technology ecc_rat;
+
+               tcore_network_get_ecc_rat(co_network, &ecc_rat);
+
+               dbg("S.LSI ECC call redial case. send VoLTE ECC fail on RAT %d and waits for next RAT", ecc_rat);
+
+               __call_set_ecc_rat_status(co_call, CALL_ECC_STATUS_FAILED, ecc_rat);
+               tcore_network_set_ecc_rat_search_status(co_network, NETWORK_ECC_RAT_SEARCH_STATUS_WAITING);
+               tcore_call_object_set_status(call_obj, TCORE_CALL_STATUS_SETUP_PENDING);
+
+               arg->handle = tcore_call_object_get_handle(call_obj);;
+               arg->type = tcore_call_object_get_type(call_obj);
+               arg->modem_plgn = plugin;
+               arg->prev_end_cause = cause;
+
+               tcore_server_add_notification_hook(tcore_plugin_ref_server(plugin), TNOTI_NETWORK_ECC_RAT,
+                                                  on_noti_manager_ecc_rat_for_silent_redial, (void *)arg);
+
+               dbg("ECC_RAT requested. wait for notification  and block CALL_IDLE notification");
+               tcore_call_object_set_silent_redial_reason(call_obj, TCORE_CALL_SILENT_REDIAL_REASON_NONE);
+               tcore_call_object_set_is_volte_call(call_obj, FALSE);
+
+               return TCORE_MANAGER_RETURN_STOP;
+       } else {
+               memset(&req, 0, sizeof(struct treq_call_dial));
+
+               /*handle should be re-used for silent redial. This will block new call_object creation in lower layer */
+               req.handle = tcore_call_object_get_handle(call_obj);
+               req.type = tcore_call_object_get_type(call_obj);
+               tcore_call_object_get_number(call_obj, req.number);
+
+               if (req.type == CALL_TYPE_E911) {
+                       dbg("emergency call. read ecc_category from call_obj & set it to dial request");
+                       req.ecc = tcore_call_object_get_emergency_category(call_obj);
+               }
+
+               /*set user request*/
+               ur = tcore_user_request_new(NULL, tcore_server_get_cp_name_by_plugin(plugin));
+               tcore_user_request_set_data(ur, sizeof(struct treq_call_dial), &req);
+               tcore_user_request_set_command(ur, TREQ_CALL_DIAL);
+
+               /*set hook argument*/
+               arg->handle = req.handle;
+               arg->type = req.type;
+               arg->modem_plgn = plugin;
+               arg->prev_end_cause = cause;
+
+               tcore_user_request_set_response_hook(ur, on_resp_manager_silent_redial, arg);
+
+               /*this call is no more volte call. set volte flag to FALSE*/
+               tcore_call_object_set_is_volte_call(call_obj, FALSE);
+
+               ret = tcore_server_dispatch_request_ex(tcore_plugin_ref_server(plugin), ur, TCORE_OPS_TYPE_CP);
+               if (TCORE_RETURN_SUCCESS != ret) {
+                       dbg("redial request failed. let manager to send call end notification & release call_object");
+                       tcore_user_request_unref(ur);
+                       g_free(arg);
+                       tcore_call_object_free(co_call, call_obj);
+                       return TCORE_MANAGER_RETURN_CONTINUE;
+               } else {
+                       dbg("redial requst invoked. wait for response and block CALL_IDLE notification");
+                       tcore_call_object_set_silent_redial_reason(call_obj, TCORE_CALL_SILENT_REDIAL_REASON_NONE);
+                       return TCORE_MANAGER_RETURN_STOP;
+               }
+       }
+}
+
+void manager_call_process_modem_error(CoreObject *co_modem)
+{
+       Server *server = NULL;
+       TcorePlugin *plugin = NULL;
+       CoreObject *co_call = NULL;
+       int i;
+       gboolean volte_endall_requested = FALSE;
+
+       plugin = tcore_object_ref_plugin(co_modem);
+       server = tcore_plugin_ref_server(plugin);
+
+       co_call = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_CALL);
+       if (tcore_call_object_total_length(co_call) == 0) {
+               info("NO ongoing call(s)");
+               return;
+       }
+
+/*CP Crash - Call object cleanup process  */
+/*step 1/2. IMS VoLTE call - end all VoLTE calls (in case VoLTE call exists)*/
+/*release every valid/normal state call objects*/
+       for (i = TCORE_CALL_STATUS_IDLE; i < TCORE_CALL_STATUS_MAX; i++) {
+               GSList *list, *tmp;
+               CallObject *call_obj = NULL;
+               struct tnoti_call_status_idle data = { 0, };
+               tmp = list = tcore_call_object_find_by_status(co_call, i);
+
+               while (tmp) {
+                       call_obj = (CallObject *)tmp->data;
+                       if (call_obj) {
+                               if ((tcore_call_object_get_is_volte_call(call_obj) == TRUE) && (volte_endall_requested == FALSE)) {
+                                       UserRequest *ur = tcore_user_request_new(NULL, NULL);
+                                       struct treq_call_end req = { 0, };
+                                       CoreObject *co_call = tcore_plugin_ref_core_object(tcore_object_ref_plugin(co_modem), CORE_OBJECT_TYPE_CALL);
+
+                                       info("VoLTE call found. invoke END_ALL VoLTE calls - once");
+
+                                       req.type = CALL_END_TYPE_ALL;
+                                       req.handle = tcore_call_object_get_handle(call_obj);
+
+                                       tcore_user_request_set_command(ur, TREQ_CALL_END);
+                                       tcore_user_request_set_data(ur, sizeof(struct treq_call_end), &req);
+                                       if (TCORE_RETURN_SUCCESS != tcore_object_dispatch_request_with_type(co_call, ur, TCORE_OPS_TYPE_IMS)) {
+                                               dbg("END_ALL error");
+                                               tcore_user_request_free(ur);
+                                       }
+                                       volte_endall_requested = TRUE;
+                               }
+                               data.type = tcore_call_object_get_type(call_obj);
+                               data.handle = tcore_call_object_get_handle(call_obj);
+                               data.cause = CALL_END_CAUSE_NORMAL_CALL_CLEARING;
+
+                               info("data.handle : [%d], data.type : [%d]", data.handle, data.type);
+                               tcore_call_object_set_status(call_obj, TCORE_CALL_STATUS_IDLE);
+                               /* TODO: Need to check for requirment to send TNOTI_SAT_CALL_CTRL_RESULT notification */
+
+                               tcore_server_send_notification(server,
+                                                              co_call,
+                                                              TNOTI_CALL_STATUS_IDLE,
+                                                              sizeof(struct tnoti_call_status_idle),
+                                                              (void *)&data);
+                               tcore_call_object_free(co_call, call_obj);
+                       }
+
+                       /* Next Call object */
+                       tmp = g_slist_next(tmp);
+               }
+               g_slist_free(list);
+       }
+
+/*step 2/2. Send IMS_DEREGISTER to confirm cleanup all the resources related to IMS VoLTE call */
+       {
+               UserRequest *ur = tcore_user_request_new(NULL, NULL);
+               CoreObject *co_network = tcore_plugin_ref_core_object(tcore_object_ref_plugin(co_modem), CORE_OBJECT_TYPE_NETWORK);
+
+               tcore_user_request_set_command(ur, TREQ_NETWORK_IMS_DEREGISTER);
+               if (TCORE_RETURN_SUCCESS != tcore_object_dispatch_request_with_type(co_network, ur, TCORE_OPS_TYPE_IMS)) {
+                       dbg("IMS_DEREG error");
+                       tcore_user_request_free(ur);
+               }
+       }
+}
+
+enum tcore_manager_return manager_call_process_request(Server *server, UserRequest *ur)
+{
+       enum tcore_request_command command = tcore_user_request_get_command(ur);
+       enum tcore_manager_return mret = TCORE_MANAGER_RETURN_CONTINUE;
+       CoreObject *co_call = manager_util_get_core_object(server, ur, CORE_OBJECT_TYPE_CALL);
+
+       switch (command) {
+       case TREQ_CALL_DIAL: {
+               struct treq_call_dial *req_data;
+               CoreObject *co_network = manager_util_get_core_object(server, ur, CORE_OBJECT_TYPE_NETWORK);
+               enum telephony_network_ims_reg_network_type network_type;
+               enum telephony_network_service_type svc_type = NETWORK_SERVICE_TYPE_UNKNOWN;
+               GSList *session_list = NULL;
+               Manager *manager = tcore_server_ref_manager(server);
+               TcorePlugin *manager_plugin = tcore_manager_get_plugin(manager);
+               PrivateData *priv_data = tcore_plugin_ref_user_data(manager_plugin);
+
+               enum telephony_network_service_domain_status ps_status = NETWORK_SERVICE_DOMAIN_STATUS_NO;
+               enum telephony_network_service_domain_status cs_status = NETWORK_SERVICE_DOMAIN_STATUS_NO;
+
+               if (priv_data->fm_processing_state != MANAGER_FLIGHT_PROCESSING_NONE) {
+                       err("Flight processing ongoing %d", priv_data->fm_processing_state);
+                       return TCORE_MANAGER_RETURN_FAILURE;
+               }
+
+               /*
+                * Block MO call in case MT call is in processing state
+                */
+               if (__is_mt_call_processing(co_call)) {
+                       err("Already MT processing ongoing ignoring dial request");
+                       return TCORE_MANAGER_RETURN_FAILURE;
+               }
+
+               /*
+                * Setting is_dial_initiated flag to TRUE
+                */
+               priv_data->is_dial_initiated = TRUE;
+
+               if (!co_network) {
+                       err("co_network is NULL");
+                       break;
+               }
+
+               req_data = (struct treq_call_dial *)tcore_user_request_ref_data(ur, NULL);
+               if (NULL == req_data) {
+                       err("req_data is NULL");
+                       break;
+               }
+
+               if (req_data->type == CALL_TYPE_E911) {
+                       /*
+                        * Emergency call handling -
+                        *   #step 1. check CS only based on Network Policy
+                        */
+                       if (TRUE == __is_emergency_only_via_cs()) {
+                               info("This device only induce emergency call to CS");
+                               return TCORE_MANAGER_RETURN_CONTINUE;
+                       }
+
+                       /*
+                        * Fetch ECC RAT information from CP in case
+                        * network mode is LTE.
+                        */
+                       if (tfeature_is_supported(TFEATURE_FUNCTION_NET_CHECK_ECC_RAT)) {
+                               dbg("S.LSI modem. Query RAT for Emergency call");
+                               if (req_data->type == CALL_TYPE_E911) {
+                                       int ecc_status = VCONFKEY_TELEPHONY_SET_ECC_STATUS_NONE;
+                                       if (vconf_get_int(VCONFKEY_TELEPHONY_SET_ECC_STATUS, &ecc_status) < 0)
+                                               warn("get VCONFKEY_TELEPHONY_SET_ECC_STATUS err");
+                                       info("ecc_status : %d", ecc_status);
+
+                                       /*  For Every case request CP for ECC RAT information
+                                       enum telephony_network_access_technology act = NETWORK_ACT_UNKNOWN;
+
+                                       tcore_network_get_access_technology(co_network, &act);
+                                       if (act < NETWORK_ACT_LTE) {
+                                               info("Non LTE AcT... proceed with CS!");
+                                               break;
+                                       }
+                                       */
+                                       info("early IPC_CALL_ECC_STATUS not requested. follow ordinay rat decision procedure");
+
+                                       /* Update VCONF key */
+                                       vconf_set_int(VCONFKEY_TELEPHONY_SET_ECC_STATUS,
+                                               VCONFKEY_TELEPHONY_SET_ECC_STATUS_NONE);
+
+                                       /* Search ECC RAT */
+                                       mret = __call_search_ecc_rat(server, ur);
+                                       break;
+                               }
+                       }
+
+                       if (TRUE == __is_emergency_only_via_ps()) {
+                               dbg("This device only induce emergency call to PS");
+                               if ((TCORE_RETURN_SUCCESS ==
+                                               tcore_network_get_service_status(co_network,
+                                               TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, &ps_status)) &&
+                                               (NETWORK_SERVICE_DOMAIN_STATUS_NO != ps_status)) {
+                                       dbg("PS_STATUS : %d. INDUCE Emergency to PS");
+                                       return TCORE_MANAGER_RETURN_CONTINUE_IMS;
+                               } else {
+                                       err("tcore_network_get_service_status() failed or ps_status is NO_SVC : %d", ps_status);
+                                       return TCORE_MANAGER_RETURN_FAILURE;
+                               }
+                       }
+
+                       /*
+                        * Emergency call handling -
+                        *    #step 2. we can go CS or PS
+                        */
+                       /*  READ) cs/ps status
+                        *      if) cs == NOSVC && ps == NOSVC : both No - NO SVC : FAIL : END
+                        *      if) cs is over Emergency && ps is NOSVC => GOTO CS : END
+                        *      if) cs is NOSVC && ps is over Emergency => GOTO PS : END
+                        *  if) both available => GOTO CS : END
+                        */
+                       tcore_network_get_service_status(co_network,
+                               TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET, &ps_status);
+                       tcore_network_get_service_status(co_network,
+                               TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT, &cs_status);
+
+                       if ((ps_status == NETWORK_SERVICE_DOMAIN_STATUS_NO) &&
+                                       (cs_status == NETWORK_SERVICE_DOMAIN_STATUS_NO)) {
+                               dbg("CS/PS all NO SVC. can't trigger Emergency Call");
+                               return TCORE_MANAGER_RETURN_FAILURE;
+                       } else if ((ps_status == NETWORK_SERVICE_DOMAIN_STATUS_NO) &&
+                                       (cs_status > NETWORK_SERVICE_DOMAIN_STATUS_NO)) {
+                               dbg("CS emergency available / PS NO SVC  - induce over CS");
+                               return TCORE_MANAGER_RETURN_CONTINUE;
+                       } else if ((ps_status > NETWORK_SERVICE_DOMAIN_STATUS_NO) &&
+                                       ((cs_status == NETWORK_SERVICE_DOMAIN_STATUS_NO))) {
+                               dbg("PS emergency available / CS NO SVC  - induce over PS");
+                               return TCORE_MANAGER_RETURN_CONTINUE_IMS;
+                       } else {
+                               err("CS/PS both available for Emergency. Need further investigation & induce to CS default");
+                               return TCORE_MANAGER_RETURN_CONTINUE;
+                       }
+               } else {
+                       /*
+                        * Special Cases. VoLTE only models
+                        * Request should be send to IMS only.
+                        */
+                       if (tfeature_is_supported(TFEATURE_DEVICE_LTE_ONLY)) {
+                               dbg("LTE only model. induce request only to IMS");
+                               return TCORE_MANAGER_RETURN_CONTINUE_IMS;
+                       }
+
+                       /*
+                        * 0. Check LTE status
+                        *
+                        * VoLTE should be supported only over LTE network.
+                        * VoLTE call should not be triggered to IMS during transition state (IMS -> 3G)
+                        */
+                       tcore_network_get_service_type(co_network, &svc_type);
+                       session_list = tcore_call_object_get_all_session_ids(co_call);
+
+                       if ((NETWORK_SERVICE_TYPE_LTE != svc_type) && session_list) {
+                               dbg("Not on LTE network - But still old VoLTE call is present - return ERROR !!");
+                               g_slist_free(session_list);
+                               priv_data->is_dial_initiated = FALSE;
+                               return TCORE_MANAGER_RETURN_FAILURE;
+                       }
+
+                       /*
+                        * 1. Check IMS registration
+                        *
+                        * Voice : NETWORK_IMS_REG_FEATURE_TYPE_VOLTE
+                        * Video : NETWORK_IMS_REG_FEATURE_TYPE_VT
+                        */
+                       if ((req_data->type == CALL_TYPE_VOICE)
+                           && (!manager_util_is_ims_registered(server, ur, NETWORK_IMS_REG_FEATURE_TYPE_VOLTE))) {
+                               break;
+                       } else if ((req_data->type == CALL_TYPE_VIDEO)
+                                  && (!manager_util_is_ims_registered(server, ur, NETWORK_IMS_REG_FEATURE_TYPE_VT))) {
+                               break;
+                       }
+
+                       /*
+                        * 2. Check IMS registered network type
+                        *
+                        * Wi-Fi - By-Pass Network support for IMS Voice support
+                        * Others - Confirm Network support for IMS Voice support
+                        */
+                       network_type = manager_util_get_ims_reg_network_type(server, ur);
+                       if (network_type == NETWORK_IMS_REG_NETWORK_TYPE_WIFI) {
+                               dbg("IMS Registered network type: [WiFi]");
+                       } else if (network_type == NETWORK_IMS_REG_NETWORK_TYPE_MOBILE) {
+                               char *network_plmn = NULL;
+                               gboolean is_ignore = FALSE; /* ignore ims voice status indication*/
+                               gboolean ims_voice_status = FALSE;
+
+                               dbg("IMS Registered network type: [Mobile]");
+
+                               /*
+                                * 3. Check IMS Voice Status
+                                */
+                               network_plmn = tcore_network_get_plmn(co_network);
+                               is_ignore = __is_ignore_ims_voice_status_indication(network_plmn);
+                               g_free(network_plmn);
+
+                               tcore_network_get_ims_voice_status(co_network, &ims_voice_status);
+
+                               if ((is_ignore == FALSE) && (ims_voice_status == FALSE)) {
+                                       dbg("is_ignore: [%s] ims_voice_status: [%s]",
+                                           (is_ignore ? "TRUE" : "FALSE"),
+                                           (ims_voice_status ? "TRUE" : "FALSE"));
+                                       break;
+                               }
+                       } else {
+                               err("IMS Registered network type: [Unknown]");
+                               break;
+                       }
+
+                       /*
+                        * 4. Check whether legacy CS Call exists or not
+                        */
+                       if (tcore_call_object_check_cs_call_existence(co_call) == FALSE)
+                               mret = TCORE_MANAGER_RETURN_CONTINUE_IMS;
+                       else
+                               dbg("CS Call exists!");
+               }
+       }
+       break;
+
+       case TREQ_CALL_END: {
+               mret = __call_handle_end_request(server, ur);
+       }
+       break;
+
+       case TREQ_CALL_ANSWER: {
+               int handle = 0;
+               const struct treq_call_answer *req_data = tcore_user_request_ref_data(ur, NULL);
+               handle = req_data->handle;
+               if (tcore_call_object_get_is_volte_call(tcore_call_object_find_by_handle(co_call, handle))) {
+                       dbg("TREQ_CALL_ANSWER: it's VoLTE call - send request to IMS framework");
+                       mret = TCORE_MANAGER_RETURN_CONTINUE_IMS;
+               } else
+                       mret = TCORE_MANAGER_RETURN_CONTINUE;
+       }
+       break;
+
+       case TREQ_CALL_HOLD: {
+               int handle = 0;
+               const struct treq_call_hold *req_data = tcore_user_request_ref_data(ur, NULL);
+               handle = req_data->handle;
+               if (tcore_call_object_get_is_volte_call(tcore_call_object_find_by_handle(co_call, handle))) {
+                       dbg("TREQ_CALL_HOLD: it's VoLTE call - send request to IMS framework");
+                       mret = TCORE_MANAGER_RETURN_CONTINUE_IMS;
+               } else
+                       mret = TCORE_MANAGER_RETURN_CONTINUE;
+       }
+       break;
+
+       case TREQ_CALL_ACTIVE: {
+               int handle = 0;
+               const struct treq_call_active *req_data = tcore_user_request_ref_data(ur, NULL);
+               handle = req_data->handle;
+               if (tcore_call_object_get_is_volte_call(tcore_call_object_find_by_handle(co_call, handle))) {
+                       dbg("TREQ_CALL_ACTIVE: it's VoLTE call - send request to IMS framework");
+                       mret = TCORE_MANAGER_RETURN_CONTINUE_IMS;
+               } else
+                       mret = TCORE_MANAGER_RETURN_CONTINUE;
+       }
+       break;
+
+       case TREQ_CALL_SWAP: {
+               int handle = 0;
+               const struct treq_call_swap *req_data = tcore_user_request_ref_data(ur, NULL);
+               handle = req_data->handle;
+               if (tcore_call_object_get_is_volte_call(tcore_call_object_find_by_handle(co_call, handle))) {
+                       dbg("TREQ_CALL_SWAP: it's VoLTE call - send request to IMS framework");
+                       mret = TCORE_MANAGER_RETURN_CONTINUE_IMS;
+               } else
+                       mret = TCORE_MANAGER_RETURN_CONTINUE;
+       }
+       break;
+
+       case TREQ_CALL_JOIN: {
+               int handle = 0;
+               const struct treq_call_join *req_data = tcore_user_request_ref_data(ur, NULL);
+               handle = req_data->handle;
+               if (tcore_call_object_get_is_volte_call(tcore_call_object_find_by_handle(co_call, handle))) {
+                       dbg("TREQ_CALL_JOIN: it's VoLTE call - send request to IMS framework");
+                       mret = TCORE_MANAGER_RETURN_CONTINUE_IMS;
+               } else
+                       mret = TCORE_MANAGER_RETURN_CONTINUE;
+       }
+       break;
+
+       case TREQ_CALL_SPLIT: {
+               int handle = 0;
+               const struct treq_call_split *req_data = tcore_user_request_ref_data(ur, NULL);
+               handle = req_data->handle;
+               if (tcore_call_object_get_is_volte_call(tcore_call_object_find_by_handle(co_call, handle))) {
+                       dbg("TREQ_CALL_SPLIT: it's VoLTE call - send request to IMS framework");
+                       mret = TCORE_MANAGER_RETURN_CONTINUE_IMS;
+               } else
+                       mret = TCORE_MANAGER_RETURN_CONTINUE;
+       }
+       break;
+
+       case TREQ_CALL_DEFLECT: {
+               int handle = 0;
+               const struct treq_call_deflect *req_data = tcore_user_request_ref_data(ur, NULL);
+               handle = req_data->handle;
+               if (tcore_call_object_get_is_volte_call(tcore_call_object_find_by_handle(co_call, handle))) {
+                       dbg("TREQ_CALL_DEFLECT: it's VoLTE call - send request to IMS framework");
+                       mret = TCORE_MANAGER_RETURN_CONTINUE_IMS;
+               } else
+                       mret = TCORE_MANAGER_RETURN_CONTINUE;
+       }
+       break;
+
+       case TREQ_CALL_TRANSFER: {
+               int handle = 0;
+               const struct treq_call_transfer *req_data = tcore_user_request_ref_data(ur, NULL);
+               handle = req_data->handle;
+               if (tcore_call_object_get_is_volte_call(tcore_call_object_find_by_handle(co_call, handle))) {
+                       dbg("TREQ_CALL_TRANSFER: it's VoLTE call - send request to IMS framework");
+                       mret = TCORE_MANAGER_RETURN_CONTINUE_IMS;
+               } else
+                       mret = TCORE_MANAGER_RETURN_CONTINUE;
+       }
+       break;
+
+       case TREQ_CALL_UPGRADE: {
+               int handle = 0;
+               const struct treq_call_upgrade *req_data = tcore_user_request_ref_data(ur, NULL);
+
+               handle = req_data->handle;
+               if (tcore_call_object_get_is_volte_call(tcore_call_object_find_by_handle(co_call, handle))) {
+                       dbg("TREQ_CALL_UPGRADE: it's VoLTE call - send request to IMS framework");
+                       mret = TCORE_MANAGER_RETURN_CONTINUE_IMS;
+               } else
+                       mret = TCORE_MANAGER_RETURN_CONTINUE;
+       }
+       break;
+
+       case TREQ_CALL_DOWNGRADE: {
+               int handle = 0;
+               const struct treq_call_downgrade *req_data = tcore_user_request_ref_data(ur, NULL);
+
+               handle = req_data->handle;
+               if (tcore_call_object_get_is_volte_call(tcore_call_object_find_by_handle(co_call, handle))) {
+                       dbg("TREQ_CALL_DOWNGRADE: it's VoLTE call - send request to IMS framework");
+                       mret = TCORE_MANAGER_RETURN_CONTINUE_IMS;
+               } else
+                       mret = TCORE_MANAGER_RETURN_CONTINUE;
+       }
+       break;
+
+       case TREQ_CALL_CONFIRM_UPGRADE: {
+               int handle = 0;
+               const struct treq_call_confirm_upgrade *req_data = tcore_user_request_ref_data(ur, NULL);
+
+               handle = req_data->handle;
+               if (tcore_call_object_get_is_volte_call(tcore_call_object_find_by_handle(co_call, handle))) {
+                       dbg("TREQ_CALL_CONFIRM_UPGRADE: it's VoLTE call - send request to IMS framework");
+                       mret = TCORE_MANAGER_RETURN_CONTINUE_IMS;
+               } else
+                       mret = TCORE_MANAGER_RETURN_CONTINUE;
+       }
+       break;
+
+       case TREQ_CALL_START_CONFERENCE: {
+               struct treq_call_start_conference *req_data;
+               CoreObject *co_network = manager_util_get_core_object(server, ur, CORE_OBJECT_TYPE_NETWORK);
+               enum telephony_network_ims_reg_network_type network_type;
+               enum telephony_network_service_type svc_type = NETWORK_SERVICE_TYPE_UNKNOWN;
+               GSList *session_list = NULL;
+
+               if (!co_network)
+                       break;
+
+               req_data = (struct treq_call_start_conference *)tcore_user_request_ref_data(ur, NULL);
+
+               /*0. Check LTE status
+                *
+                * resource-based conf.call should be supported only over LTE network.
+                * VoLTE call should not be triggered to IMS during transition state (IMS -> 3G)
+               */
+               tcore_network_get_service_type(co_network, &svc_type);
+               session_list = tcore_call_object_get_all_session_ids(co_call);
+
+               if ((NETWORK_SERVICE_TYPE_LTE != svc_type) && session_list) {
+                       dbg("Not on LTE network - But still old VoLTE call is present - return ERROR !!");
+                       g_slist_free(session_list);
+                       return TCORE_MANAGER_RETURN_FAILURE;
+               }
+
+
+               /*
+                * 1. Check IMS registration
+                *
+                * Voice : NETWORK_IMS_REG_FEATURE_TYPE_VOLTE
+                * Video : NETWORK_IMS_REG_FEATURE_TYPE_VT
+                */
+               if ((req_data->type == CALL_TYPE_VOICE)
+                   && (!manager_util_is_ims_registered(server, ur, NETWORK_IMS_REG_FEATURE_TYPE_VOLTE))) {
+                       break;
+               } else if ((req_data->type == CALL_TYPE_VIDEO)
+                          && (!manager_util_is_ims_registered(server, ur, NETWORK_IMS_REG_FEATURE_TYPE_VT))) {
+                       break;
+               }
+
+               /*
+                * 2. Check IMS registered network type
+                *
+                * Wi-Fi - By-Pass Network support for IMS Voice support
+                * Others - Confirm Network support for IMS Voice support
+                */
+               network_type = manager_util_get_ims_reg_network_type(server, ur);
+               if (network_type == NETWORK_IMS_REG_NETWORK_TYPE_WIFI) {
+                       dbg("IMS Registered network type: [WiFi]");
+               } else if (network_type == NETWORK_IMS_REG_NETWORK_TYPE_MOBILE) {
+                       char *network_plmn = NULL;
+                       gboolean is_ignore = FALSE; /* ignore ims voice status indication*/
+                       gboolean ims_voice_status = FALSE;
+
+                       dbg("IMS Registered network type: [Mobile]");
+
+                       /*
+                        * 3. Check IMS Voice Status
+                        */
+                       network_plmn = tcore_network_get_plmn(co_network);
+                       is_ignore = __is_ignore_ims_voice_status_indication(network_plmn);
+                       g_free(network_plmn);
+
+                       tcore_network_get_ims_voice_status(co_network, &ims_voice_status);
+
+                       if ((is_ignore == FALSE) && (ims_voice_status == FALSE)) {
+                               dbg("is_ignore: [%s] ims_voice_status: [%s]",
+                                   (is_ignore ? "TRUE" : "FALSE"),
+                                   (ims_voice_status ? "TRUE" : "FALSE"));
+                               break;
+                       }
+               } else {
+                       err("IMS Registered network type: [Unknown]");
+                       break;
+               }
+
+               /*
+                * 4. Check whether legacy CS Call exists or not
+                */
+               if (tcore_call_object_check_cs_call_existence(co_call) == FALSE)
+                       mret = TCORE_MANAGER_RETURN_CONTINUE_IMS;
+               else
+                       dbg("CS Call exists!");
+       }
+       break;
+
+       case TREQ_CALL_MODIFY_PARTICIPANTS_IN_CONFERENCE: {
+               int handle = 0;
+               const struct treq_call_modify_participans_in_conference *req_data = tcore_user_request_ref_data(ur, NULL);
+
+               handle = req_data->handle;
+               if (tcore_call_object_get_is_volte_call(tcore_call_object_find_by_handle(co_call, handle))) {
+                       dbg("TREQ_CALL_MODIFY_PARTICIPANTS_IN_CONFERENCE: it's VoLTE call - send request to IMS framework");
+                       mret = TCORE_MANAGER_RETURN_CONTINUE_IMS;
+               } else
+                       mret = TCORE_MANAGER_RETURN_CONTINUE;
+       }
+       break;
+
+       case TREQ_CALL_START_CONT_DTMF:
+       case TREQ_CALL_STOP_CONT_DTMF:
+       case TREQ_CALL_SEND_BURST_DTMF: {
+               /* check whether legacy call exists or not */
+               if (tcore_call_object_check_cs_call_existence(co_call) == FALSE)
+                       mret = TCORE_MANAGER_RETURN_CONTINUE_IMS;
+       }
+       break;
+
+       case TREQ_CALL_SET_PREFERRED_VOICE_SUBSCRIPTION: {
+
+               dbg("adding hook to update DS to db");
+                       /* Set Response hook */
+               tcore_user_request_set_response_hook(ur, manager_network_resp_hook_set_ds, server);
+       }
+       break;
+
+
+       default:
+               break;
+       }
+
+       return mret;
+}
+
+enum tcore_manager_return manager_call_process_notification(Manager *manager, CoreObject *source,
+                                                           enum tcore_notification_command command, unsigned int data_len, void *data)
+{
+       enum tcore_manager_return ret = TCORE_MANAGER_RETURN_CONTINUE;
+       CoreObject *co_call = source;
+       TcorePlugin *manager_plugin = tcore_manager_get_plugin(manager);
+       PrivateData *priv_data = tcore_plugin_ref_user_data(manager_plugin);
+       ModemBoard *mb = manager_core_get_modem_board(manager, tcore_object_ref_plugin(source));
+
+       dbg("enter. notification : %x", command);
+
+       switch (command) {
+       case TNOTI_CALL_STATUS_DIALING: {
+               struct tnoti_call_status_dialing *dialing_noti = data;
+               int call_handle;
+               CallObject *call_obj = NULL;
+               gboolean is_release_pending = FALSE;
+
+               /* Unsetting is_dial_initiated flag on rececipt of dial notification*/
+               priv_data->is_dial_initiated = FALSE;
+
+
+               call_handle = dialing_noti->handle;
+               call_obj = tcore_call_object_find_by_handle(co_call, call_handle);
+               if (!call_obj) {
+                       err("call object with handle %d not found - serious!", call_handle);
+                       return TCORE_MANAGER_RETURN_FAILURE;
+               }
+
+               is_release_pending = tcore_call_object_get_is_release_pending(call_obj);
+               if (is_release_pending) {
+                       TcorePlugin *plugin;
+                       struct treq_call_end call_end;
+                       UserRequest *ur;
+
+                       info("call release request saved - invoke call release");
+
+                       plugin = tcore_object_ref_plugin(co_call);
+                       ur = tcore_user_request_new(NULL, tcore_server_get_cp_name_by_plugin(plugin));
+                       call_end.type = dialing_noti->type;
+                       call_end.handle = call_handle;
+
+                       tcore_user_request_set_data(ur, sizeof(struct treq_call_end), &call_end);
+                       tcore_user_request_set_command(ur, TREQ_CALL_END);
+
+                       if (tcore_call_object_get_is_volte_call(call_obj))
+                               tcore_server_dispatch_request_ex(tcore_plugin_ref_server(plugin), ur, TCORE_OPS_TYPE_IMS);
+                       else
+                               tcore_server_dispatch_request_ex(tcore_plugin_ref_server(plugin), ur, TCORE_OPS_TYPE_CP);
+
+                       ret = TCORE_MANAGER_RETURN_STOP;  /*do not send Dialing notification*/
+               } else {
+                       dbg("release not pending. candidate of notification to application");
+                       if (priv_data->is_dial_noti_sent) {
+                               priv_data->is_dial_noti_sent = FALSE;
+                               ret = TCORE_MANAGER_RETURN_STOP;
+                       } else {
+                               ret = TCORE_MANAGER_RETURN_CONTINUE;
+                       }
+
+                       if (TCORE_CALL_SILENT_REDIAL_REASON_NONE != tcore_call_object_get_silent_redial_reason(call_obj)) {
+                               dbg("Silent redial case - ignore dial notification from modem");
+                               tcore_call_object_set_silent_redial_reason(call_obj, TCORE_CALL_SILENT_REDIAL_REASON_NONE);
+                               ret = TCORE_MANAGER_RETURN_STOP;  /*do not send Dialing notification*/
+                       }
+               }
+       }
+       break;
+
+       case TNOTI_CALL_STATUS_INCOMING: {
+#ifdef TIZEN_FEATURE_MULTISIM   /*only valid for Multi-SIM models. Not for wearable*/
+               gboolean is_reject_incoming = FALSE;
+               struct tnoti_call_status_incoming *incoming_noti = data;
+               TcorePlugin *plugin_subs = NULL, *plugin_subs_other = NULL;
+               CallObject *call_obj_sub_mo = NULL, *call_obj_sub_mt = NULL, *call_obj_sub_other = NULL;
+               CoreObject *co_call_other;
+
+               plugin_subs = tcore_object_ref_plugin(co_call);
+               plugin_subs_other = manager_util_get_other_subs_plugin(plugin_subs);
+               co_call_other = tcore_plugin_ref_core_object(plugin_subs_other, CORE_OBJECT_TYPE_CALL);
+               call_obj_sub_mo = tcore_call_object_current_on_mo_processing(co_call);
+               call_obj_sub_mt = tcore_call_object_current_on_mt_processing(co_call);
+               call_obj_sub_other = tcore_call_object_current_on_mo_processing(co_call_other);
+
+               /* Check for calls in MO setup state in both the subscriptions */
+               if (call_obj_sub_mo ||call_obj_sub_other ) {
+                       info("MO call in setup state present on current/other subscription ");
+                       is_reject_incoming = TRUE;
+               }
+
+               /* Check for active call on other subscription */
+               if (is_reject_incoming == FALSE && __is_active_call(co_call_other)) {
+                       info("Active call is present on other subscription ");
+                       is_reject_incoming = TRUE;
+               }
+
+               /* Check for MO call initiation flag */
+               /* Dial call is initiated dial response is successful, but dial notification is not received.
+                 * Incoming notification is received from other subscription in between.
+                 * Reject incoming call
+               */
+               if (is_reject_incoming == FALSE && priv_data->is_dial_initiated) {
+                       info("MO call in setup state present on other subscription ");
+                       is_reject_incoming = TRUE;
+               }
+
+               /* Check for MT call in incoming state in other subscriptions */
+
+               if (is_reject_incoming == FALSE && (call_obj_sub_other = tcore_call_object_current_on_mt_processing(co_call_other))) {
+                       info("MT call in setup state present on other subscription ");
+                       is_reject_incoming = TRUE;
+               }
+               if (is_reject_incoming) {
+                       struct treq_call_end call_end;
+                       UserRequest *ur;
+
+                       info("Releasing call, already MO processing is ongoing");
+
+                       ur = tcore_user_request_new(NULL, tcore_server_get_cp_name_by_plugin(plugin_subs));
+                       call_end.type = incoming_noti->type;
+                       call_end.handle = incoming_noti->handle;
+
+                       tcore_user_request_set_data(ur, sizeof(struct treq_call_end), &call_end);
+                       tcore_user_request_set_command(ur, TREQ_CALL_END);
+
+                       if (tcore_call_object_get_is_volte_call(call_obj_sub_mo) || tcore_call_object_get_is_volte_call(call_obj_sub_mt))
+                               tcore_server_dispatch_request_ex(tcore_plugin_ref_server(plugin_subs), ur, TCORE_OPS_TYPE_IMS);
+                       else
+                               tcore_server_dispatch_request_ex(tcore_plugin_ref_server(plugin_subs), ur, TCORE_OPS_TYPE_CP);
+
+                       /* Internal release request initiated for incoming call on other subscription */
+                       priv_data->is_end_initiated = TRUE;
+
+                       ret = TCORE_MANAGER_RETURN_STOP;  /*do not send Incoming notification*/
+
+               }
+
+               /*
+                * Check if Network Search is in progress and cancel the same
+                */
+               if (ret !=  TCORE_MANAGER_RETURN_STOP) {
+                       info("Cancel any on-going Network Search");
+                       manager_network_cancel_network_search(manager, tcore_plugin_ref_server(plugin_subs));
+               }
+#endif
+
+
+       }
+       break;
+
+       case TNOTI_CALL_STATUS_IDLE: {
+               struct tnoti_call_status_idle *idle_noti = data;
+               int call_handle;
+               CallObject *call_obj = NULL;
+               enum tcore_call_silent_redial_reason redial_reason = TCORE_CALL_SILENT_REDIAL_REASON_NONE;
+               gboolean is_ecc_used_rat_search = FALSE;
+               gboolean send_ecc_rat_end = FALSE;
+               CallPrivateInfo *cpi = NULL;
+
+               call_handle = idle_noti->handle;
+               cpi = mb->call_info;
+
+               /* Unsetting is_dial_initiated flag on rececipt of dial notification */
+               priv_data->is_dial_initiated = FALSE;
+
+               if ((cpi->rat_query_cache.call_handle == call_handle) &&
+                   (idle_noti->type == CALL_TYPE_E911)) {
+                       dbg("this emergency call used ECC_RAT_SEARCH");
+                       is_ecc_used_rat_search = TRUE;
+               }
+
+               if (priv_data->is_dial_noti_sent)
+                       priv_data->is_dial_noti_sent = FALSE;
+
+               call_obj = tcore_call_object_find_by_handle(co_call, call_handle);
+               redial_reason = tcore_call_object_get_silent_redial_reason(call_obj);
+
+               /* Flight mode end all request handling */
+               if (tcore_call_object_total_length(co_call) == 0 || (tcore_call_object_total_length(co_call) == 1)) {
+                       if (manager_queue_probe_command(manager, TREQ_MODEM_SET_FLIGHTMODE)) {
+                               UserRequest *ur = manager_queue_dequeue(manager);
+                               PrivateData *priv_data = tcore_plugin_ref_user_data(manager_plugin);
+                               priv_data->is_end_all_initiated = TRUE;
+                               info("Dispatching flight mode request");
+                               tcore_server_dispatch_request(tcore_plugin_ref_server(manager_plugin),ur);
+                       }
+               }
+
+               if (NULL == call_obj && priv_data->is_end_initiated == FALSE) {
+                       dbg("call object released. Not a candidate of silent redial");
+                       if (TRUE == is_ecc_used_rat_search) {
+                               enum telephony_network_access_technology latest_ecc_rat;
+                               CoreObject *co_network = NULL;
+                               co_network = tcore_plugin_ref_core_object(tcore_object_ref_plugin(co_call), CORE_OBJECT_TYPE_NETWORK);
+                               tcore_network_get_ecc_rat(co_network, &latest_ecc_rat);
+
+                               __call_set_ecc_rat_status(co_call, CALL_ECC_STATUS_ENDED, latest_ecc_rat);
+
+                               dbg("reset rat_query_cache");
+                               cpi->rat_query_cache.call_handle = INVALID_HANDLE;
+                               cpi->rat_query_cache.rat_query_status = CALL_ECC_STATUS_NONE;
+                       }
+                       return TCORE_MANAGER_RETURN_CONTINUE;
+               }
+
+
+               if ((TCORE_CALL_SILENT_REDIAL_REASON_MULTIRAT_EMERGENCY == redial_reason) ||
+                   (TCORE_CALL_SILENT_REDIAL_REASON_CS_FALLBACK == redial_reason)) {
+
+                       if (priv_data->fm_processing_state == MANAGER_FLIGHT_PROCESSSING_ENABLE) {
+                               dbg("Flight mode enabled, don't initiate silent redial");
+                               tcore_call_object_free(co_call, call_obj);
+                       } else {
+                               dbg("redial reason : %d. invoke silent redial to CS", redial_reason);
+                               ret = manager_call_silent_redial(co_call, call_obj, idle_noti->cause);
+                               /* In case of silent redial of emergency call set this flag to TRUE
+                                * to avoid sending dial noti received from CS domain
+                                */
+                               if (TCORE_CALL_TYPE_E911 == tcore_call_object_get_type(call_obj))
+                                       priv_data->is_dial_noti_sent = TRUE;
+                       }
+                       send_ecc_rat_end = FALSE;
+
+               } else if (priv_data->is_end_initiated == TRUE) {
+                       dbg("Internal release request consume end notification");
+                       priv_data->is_end_initiated = FALSE;
+                       ret = TCORE_MANAGER_RETURN_STOP;  /*do not send End notification*/
+                       send_ecc_rat_end = TRUE;
+               } else {
+                       dbg("call not released but not a target of silent-redial. Ignore");
+                       ret = TCORE_MANAGER_RETURN_CONTINUE;
+                       send_ecc_rat_end = TRUE;
+               }
+
+               if (is_ecc_used_rat_search == TRUE && send_ecc_rat_end == TRUE) {
+                       enum telephony_network_access_technology latest_ecc_rat;
+                       CoreObject *co_network = NULL;
+                       co_network = tcore_plugin_ref_core_object(tcore_object_ref_plugin(co_call), CORE_OBJECT_TYPE_NETWORK);
+                       tcore_network_get_ecc_rat(co_network, &latest_ecc_rat);
+
+                       __call_set_ecc_rat_status(co_call, CALL_ECC_STATUS_ENDED, latest_ecc_rat);
+
+                       dbg("reset rat_query_cache");
+                       cpi->rat_query_cache.call_handle = INVALID_HANDLE;
+                       cpi->rat_query_cache.rat_query_status = CALL_ECC_STATUS_NONE;
+               }
+               return ret;
+       }
+       break;
+
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+gboolean manager_call_initialize_private_info(ModemBoard *mb)
+{
+       CallPrivateInfo *cpi;
+
+       if (G_UNLIKELY(!mb))
+               return FALSE;
+
+       if (mb->call_info)
+               manager_call_clear_private_info(mb);
+
+       mb->call_info = g_try_malloc0(sizeof(struct manager_call_private_info));
+
+       cpi = mb->call_info;
+       cpi->rat_query_cache.call_handle = INVALID_HANDLE;
+       cpi->rat_query_cache.rat_query_status = CALL_ECC_STATUS_NONE;
+       cpi->early_rat_result.rat = NETWORK_ACT_UNKNOWN;
+
+       dbg("Initialized call private info");
+       return TRUE;
+}
+
+
+void manager_call_clear_private_info(ModemBoard *mb)
+{
+       CallPrivateInfo *cpi;
+
+       if (G_UNLIKELY(!mb || !mb->call_info))
+               return;
+
+       cpi = mb->call_info;
+       g_free(cpi);
+       mb->call_info = NULL;
+
+       dbg("done");
+}
+
+
+enum tcore_hook_return on_noti_manager_early_ecc_rat(Server *server,
+                                                    CoreObject *source, enum tcore_notification_command command,
+                                                    unsigned int data_len, void *data, void *user_data)
+{
+       const struct tnoti_network_ecc_rat *noti_data = data;
+       CoreObject *co_network = source;
+       TcorePlugin *modem_plugin = NULL;
+       ModemBoard *mb = NULL;
+       CallPrivateInfo *cpi = NULL;
+
+       modem_plugin = tcore_object_ref_plugin(co_network);
+
+       mb = manager_core_get_modem_board(tcore_server_ref_manager(server), modem_plugin);
+       cpi = mb->call_info;
+
+       if (noti_data->status == NETWORK_ACT_STATUS_NONE) {
+               dbg("no available rat for ecc");
+               cpi->early_rat_result.rat = NETWORK_ACT_NOT_SPECIFIED;
+       } else if (noti_data->status == NETWORK_ACT_STATUS_USED) {
+               cpi->early_rat_result.rat = noti_data->ecc_rat;
+               dbg("use rat %d for ecc", cpi->early_rat_result.rat);
+       }
+
+       dbg("early_rat result noti comes before dial request comes. remove notification hook");
+       tcore_server_remove_notification_hook(server, on_noti_manager_early_ecc_rat);
+
+       return TCORE_HOOK_RETURN_CONTINUE;
+}
diff --git a/src/manager_core.c b/src/manager_core.c
new file mode 100644 (file)
index 0000000..a0c8470
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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 <glib.h>
+#include <tcore.h>
+#include <manager.h>
+#include <plugin.h>
+#include <server.h>
+
+#include "manager_core.h"
+#include "manager_request.h"
+#include "manager_notification.h"
+#include "manager_queue.h"
+#include "manager_network.h"
+#include "manager_sim.h"
+#include "internal/manager_internal.h"
+#include "manager_call.h"
+#include "manager_modem.h"
+
+static void __create_modem_board_sub_modules(ModemBoard *mb)
+{
+       dbg("enter");
+       /* Initialize network private info cache */
+       manager_network_initialize_private_info(mb);
+
+       /*Initialize call private info cache*/
+       manager_call_initialize_private_info(mb);
+       manager_sim_initialize_private_info(mb);
+       manager_modem_initialize_private_info(mb);
+}
+
+static void __destroy_modem_board_sub_modules(ModemBoard *mb)
+{
+       dbg("enter");
+       /* Clear network private info cache */
+       manager_network_clear_private_info(mb);
+}
+
+void manager_core_create_modem_board(TcorePlugin *manager_plugin, TcorePlugin *modem_plugin)
+{
+       ModemBoard *mb = NULL;
+       GSList *list = NULL;
+       ModemBoardIndex index = manager_core_get_modem_board_index(modem_plugin);
+       PrivateData *priv_data = tcore_plugin_ref_user_data(manager_plugin);
+
+       if (G_UNLIKELY(!priv_data))
+               return;
+
+       if (index == MANAGER_MODEM_BOARD_INDEX_INVALID) {
+               warn("Wrong Modem Index");
+               return;
+       }
+
+       /* Check Duplicated */
+       for (list = priv_data->board_list; list; list = list->next) {
+               mb = list->data;
+               if (G_UNLIKELY(!mb))
+                       continue;
+
+               if (mb->index == index) {
+                       warn("We already have Modem Index(%d)", index);
+                       return;
+               }
+       }
+
+       /* Create Modem Board */
+       mb = g_try_malloc0(sizeof(ModemBoard));
+       mb->index = index;
+       mb->modem_plugin = modem_plugin;
+       mb->fdn_enabled = FALSE;
+       mb->fdn_contacts = NULL;
+       priv_data->board_list = g_slist_append(priv_data->board_list, mb);
+
+       __create_modem_board_sub_modules(mb);
+       dbg("modem (%d) added, so modem board(%p) added", index, mb);
+}
+
+void manager_core_destroy_modem_board(TcorePlugin *manager_plugin, TcorePlugin *modem_plugin)
+{
+       ModemBoard *mb = NULL;
+       GSList *list = NULL;
+       PrivateData *priv_data = tcore_plugin_ref_user_data(manager_plugin);
+
+       if (G_UNLIKELY(!priv_data))
+               return;
+
+       /* Traverse through mb list and destroy matching mb */
+       for (list = priv_data->board_list; list; list = list->next) {
+               mb = list->data;
+               if (G_UNLIKELY(!mb))
+                       continue;
+
+               if (mb->modem_plugin == modem_plugin) {
+                       dbg("modem(%d) removed, so blackboard(%p) removed", mb->index, mb);
+                       __destroy_modem_board_sub_modules(mb);
+                       priv_data->board_list = g_slist_remove(priv_data->board_list, mb);
+                       break;
+               }
+
+               if (TRUE == mb->fdn_enabled && mb->fdn_contacts)
+                       g_hash_table_destroy(mb->fdn_contacts);
+               mb->fdn_contacts = NULL;
+       }
+}
+
+ModemBoard *manager_core_get_modem_board(Manager *manager, TcorePlugin *modem_plugin)
+{
+       GSList *list = NULL;
+       TcorePlugin *manager_plugin = tcore_manager_get_plugin(manager);
+       PrivateData *priv_data = tcore_plugin_ref_user_data(manager_plugin);
+
+       if (G_UNLIKELY(!priv_data))
+               return NULL;
+
+       for (list = priv_data->board_list; list; list = list->next) {
+               ModemBoard *mb = list->data;
+               if (G_UNLIKELY(!mb))
+                       continue;
+               if (mb->modem_plugin == modem_plugin) {
+                       dbg("modem(%d) selected. board(%p)", mb->index, mb);
+                       return mb;
+               }
+       }
+       return NULL;
+}
+
+ModemBoardIndex manager_core_get_modem_board_index(TcorePlugin *modem_plugin)
+{
+       const char *cp_name = tcore_server_get_cp_name_by_plugin(modem_plugin);
+
+       if (g_str_has_suffix((const gchar *)cp_name, "0"))
+               return MANAGER_MODEM_BOARD_INDEX_0;
+       else if (g_str_has_suffix((const gchar *)cp_name, "1"))
+               return MANAGER_MODEM_BOARD_INDEX_1;
+       else
+               return MANAGER_MODEM_BOARD_INDEX_INVALID;
+}
+
+/* Create list for already existing modem plugin's that were present before manager intialization */
+void manager_core_create_modem_board_list(TcorePlugin *manager_plugin)
+{
+       Server *s = tcore_plugin_ref_server(manager_plugin);
+       GSList *list = NULL;
+       GSList *modem_plugin_list = tcore_server_get_modem_plugin_list(s);
+
+       if (G_UNLIKELY(!modem_plugin_list))
+               return;
+
+       /* Traverse through each modem plugin and create mb */
+       for (list = modem_plugin_list; list; list = list->next) {
+               TcorePlugin *modem_plugin = list->data;
+               if (modem_plugin)
+                       manager_core_create_modem_board(manager_plugin, modem_plugin);
+       }
+
+       g_slist_free(modem_plugin_list);
+}
+
+void manager_core_destroy_modem_board_list(TcorePlugin *manager_plugin)
+{
+       Server *s = tcore_plugin_ref_server(manager_plugin);
+       GSList *list = NULL;
+       GSList *modem_plugin_list = tcore_server_get_modem_plugin_list(s);
+
+       if (G_UNLIKELY(!modem_plugin_list))
+               return;
+
+       /* Traverse through each modem plugin and destroy mb */
+       for (list = modem_plugin_list; list; list = list->next) {
+               TcorePlugin *modem_plugin = list->data;
+               if (modem_plugin)
+                       manager_core_destroy_modem_board(manager_plugin, modem_plugin);
+       }
+       g_slist_free(modem_plugin_list);
+}
+
+/* Core initializer */
+gboolean manager_core_init(TcorePlugin *plugin)
+{
+       Manager *manager;
+       PrivateData *priv_data = NULL;
+
+       /* Create manager */
+       manager = tcore_manager_new(plugin);
+
+       /*
+        * Set handlers -
+        *    Request dispatcher
+        *    Notification handler
+        */
+       if (tcore_manager_set_request_dispatcher(manager,
+                                                manager_request_handler) != TCORE_RETURN_SUCCESS) {
+               err("Failed to set Request dispatcher");
+               goto ERROR;
+       }
+
+       if (tcore_manager_set_notification_handler(manager,
+                                                  manager_notification_handler) != TCORE_RETURN_SUCCESS) {
+               err("Failed to set Notification handler");
+               goto ERROR;
+       }
+
+       /* Private data for Manager plug-in */
+       priv_data = g_malloc0(sizeof(PrivateData));
+       /* Link private data to plug-in */
+       tcore_plugin_link_user_data(plugin, priv_data);
+
+       /* Update Manager */
+       priv_data->manager = manager;
+       priv_data->board_list = NULL;
+
+       /* Flag to track dial initiated or not for MO/MT synchronization */
+       priv_data->is_dial_initiated = FALSE;
+
+       /* Flag to consume end notification when internal end request is raised for MO/MT synchronization */
+       priv_data->is_end_initiated = FALSE;
+
+       /*Flag to identify if boot is completed*/
+       priv_data->boot_config_completed = FALSE;
+
+       /* Flag to identify if end all request processing is ongoing due to flight mode enable*/
+       priv_data->is_end_all_initiated = FALSE;
+
+       /*Flag to identify if dial notification is already sent in case of Emergency call*/
+       priv_data->is_dial_noti_sent = FALSE;
+
+       /* Create manager modem balckboard cache */
+       manager_core_create_modem_board_list(plugin);
+
+       /* Create and initialize Manager queue */
+       priv_data->manager_queue = manager_queue_init();
+       if (G_UNLIKELY(priv_data->manager_queue == NULL)) {
+               err("Failed to create Manager queue");
+               goto ERROR;
+       }
+
+       return TRUE;
+
+ ERROR:
+       /* Free resource */
+       g_free(priv_data);
+
+       /* Destroy manager */
+       tcore_manager_free(plugin, manager);
+
+       return FALSE;
+}
+
+/* Core de-initializer */
+void manager_core_deinit(TcorePlugin *plugin)
+{
+       PrivateData *priv_data;
+
+       priv_data = tcore_plugin_ref_user_data(plugin);
+       if (priv_data != NULL) {
+               /* Destroy manager */
+               tcore_manager_free(plugin, priv_data->manager);
+
+               /* Clear and free Manager queue */
+               manager_queue_deinit(priv_data->manager_queue);
+
+               /* Destroy manager modem balckboard cache */
+               manager_core_destroy_modem_board_list(plugin);
+
+               /* Free private data */
+               g_free(priv_data);
+               tcore_plugin_link_user_data(plugin, NULL);
+       }
+}
diff --git a/src/manager_modem.c b/src/manager_modem.c
new file mode 100644 (file)
index 0000000..775aa9a
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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 <string.h>
+#include <glib.h>
+#include <tcore.h>
+#include <server.h>
+#include <manager.h>
+#include <plugin.h>
+#include <core_object.h>
+#include <user_request.h>
+#include <co_call.h>
+
+#include "manager_core.h"
+#include "manager_util.h"
+#include "manager_queue.h"
+#include "manager_network.h"
+#include "manager_modem.h"
+#include "manager_call.h"
+#include "manager_sim.h"
+#include "internal/manager_internal.h"
+#include "tfeature.h"
+
+#include <vconf.h>
+
+/*
+ * Timeout of 1 second for normal cases, we may have to consider 4 sec for Verizon.
+ */
+#define MANAGER_FLIGHT_MODE_REQUEST_TIMEOUT     (1000)  /* 1 seconds */
+#define MANAGER_MODEM_POWER_OFF_REQUEST_TIMEOUT (1000)  /* 1 seconds */
+
+static enum tcore_hook_return on_noti_hook_manager_call_status_idle(Server *server,
+                                                                      CoreObject *source, enum tcore_notification_command command,
+                                                                      unsigned int data_len, void *data, void *user_data)
+{
+       TcorePlugin *modem_plugin = tcore_object_ref_plugin(source);
+       UserRequest *ur = user_data;
+
+       if (manager_call_is_during_call(modem_plugin)) {
+               dbg("Call is still in progress");
+               return TCORE_HOOK_RETURN_CONTINUE;
+       }
+
+       info("Call was disconnected. Dispatch pending ur(%p)", ur);
+
+       if (tcore_server_dispatch_request_ex(server, ur, TCORE_OPS_TYPE_CP) != TCORE_RETURN_SUCCESS) {
+               err("Failed to dispatch request");
+       }
+
+       tcore_server_remove_notification_hook(server, on_noti_hook_manager_call_status_idle);
+
+       return TCORE_HOOK_RETURN_CONTINUE;
+}
+
+static void manager_modem_resp_hook_flight_mode(UserRequest *ur,
+                                               enum tcore_response_command command,
+                                               unsigned int data_len, const void *data, void *user_data)
+{
+       TcorePlugin *manager_plugin = (TcorePlugin *)user_data;
+       PrivateData *priv_data = tcore_plugin_ref_user_data(manager_plugin);
+
+       priv_data->fm_processing_state = MANAGER_FLIGHT_PROCESSING_NONE;
+       info("flight mode request completed");
+}
+
+static enum tcore_manager_return __handle_flight_mode_end(Server *server, UserRequest *ur)
+{
+       TcorePlugin *plugin_subs_other, *plugin_subs;
+       CoreObject *co_call, *co_call_other;
+       gboolean end_all_calls = FALSE;
+       Manager *manager = tcore_server_ref_manager(server);
+       TcorePlugin *manager_plugin = tcore_manager_get_plugin(manager);
+       PrivateData *priv_data = tcore_plugin_ref_user_data(manager_plugin);
+
+       /* In case of active calls, release all calls before sending flight mode request */
+       co_call = manager_util_get_core_object(server, ur, CORE_OBJECT_TYPE_CALL);
+       plugin_subs = tcore_object_ref_plugin(co_call);
+       plugin_subs_other = manager_util_get_other_subs_plugin(plugin_subs);
+       co_call_other = tcore_plugin_ref_core_object(plugin_subs_other, CORE_OBJECT_TYPE_CALL);
+
+       info("handle flight mode reqeust ");
+       if (priv_data->is_end_all_initiated == FALSE) {
+               if (tcore_call_object_total_length(co_call) > 0) {
+                       end_all_calls = TRUE;
+               } else if (tcore_call_object_total_length(co_call_other) > 0 ) {
+                       end_all_calls = TRUE;
+                       co_call = co_call_other;
+                       plugin_subs = plugin_subs_other;
+               }
+       } else{
+               priv_data->is_end_all_initiated = FALSE;
+       }
+
+       if(end_all_calls == TRUE) {
+
+               UserRequest *new_ur = tcore_user_request_new(NULL, tcore_server_get_cp_name_by_plugin(plugin_subs));
+               struct treq_call_end req = { 0, };
+
+               info("Releasing all calls in case of flight mode request");
+
+               req.type = CALL_END_TYPE_ALL;
+
+               tcore_user_request_set_command(new_ur, TREQ_CALL_END);
+               tcore_user_request_set_data(new_ur, sizeof(struct treq_call_end), &req);
+               if (TCORE_RETURN_SUCCESS != tcore_server_dispatch_request(server,new_ur)) {
+                       err("END_ALL request failed!!r");
+                       tcore_user_request_free(new_ur);
+               } else {
+                       info("queueing flight mode request");
+                       manager_queue_enqueue(manager, ur);
+                       return TCORE_MANAGER_RETURN_STOP;
+               }
+       }
+
+       return TCORE_MANAGER_RETURN_CONTINUE;
+
+}
+enum tcore_manager_return manager_modem_process_request(Server *server,
+                                                       UserRequest *ur)
+{
+       enum tcore_request_command command = tcore_user_request_get_command(ur);
+       enum tcore_manager_return manager_ret = TCORE_MANAGER_RETURN_CONTINUE;
+
+       switch (command) {
+       case TREQ_MODEM_SET_FLIGHTMODE: {
+               struct treq_modem_set_flightmode *flight_mode = (struct treq_modem_set_flightmode *)tcore_user_request_ref_data(ur, 0);
+               Manager *manager = tcore_server_ref_manager(server);
+               TcorePlugin *manager_plugin = tcore_manager_get_plugin(manager);
+               PrivateData *priv_data = tcore_plugin_ref_user_data(manager_plugin);
+
+               info("flight mode request is in progress");
+               /* Add response hook */
+               tcore_user_request_set_response_hook(ur,
+                       manager_modem_resp_hook_flight_mode, manager_plugin);
+
+               if (flight_mode->enable == 0) {
+                       dbg("Flight mode disable, not required to deregister IMS");
+                       priv_data->fm_processing_state = MANAGER_FLIGHT_PROCESSSING_DISABLE;
+
+                       return manager_ret;
+               }
+
+               priv_data->fm_processing_state = MANAGER_FLIGHT_PROCESSSING_ENABLE;
+               /* In case calls are present, end all calls before processing flight mode request */
+               if (__handle_flight_mode_end(server, ur) == TCORE_MANAGER_RETURN_STOP) {
+                       return TCORE_MANAGER_RETURN_STOP;
+               }
+               manager_ret = manager_util_process_ims(server, ur);
+       }
+       break;
+
+       case TREQ_MODEM_POWER_LOW:
+       case TREQ_MODEM_POWER_OFF: {
+               if (tfeature_is_supported(TFEATURE_DEVICE_WEARABLE)) {
+                       TcorePlugin *modem_plugin = manager_util_get_modem_plugin(server, ur);
+                       if (manager_call_is_during_call(modem_plugin)) {
+                               info("Call is in progress. Hold ur(%p)", ur);
+                               tcore_server_add_notification_hook(server, TNOTI_CALL_STATUS_IDLE,
+                                                                        on_noti_hook_manager_call_status_idle, ur);
+                               return TCORE_MANAGER_RETURN_STOP;
+                       }
+               }
+
+               manager_ret = manager_util_process_ims(server, ur);
+       }
+       break;
+
+       /*
+        * All other requests, would be routed to CP.
+        */
+       default:
+               break;
+       }
+
+       return manager_ret;
+}
+
+static void __update_private_info(Manager *manager, CoreObject *co_modem, enum modem_state modem_status)
+{
+       ModemBoard *mb = manager_core_get_modem_board(manager, tcore_object_ref_plugin(co_modem));
+
+       mb->modem_info->co_modem = co_modem;
+       mb->modem_info->modem_status = modem_status;
+
+}
+
+gboolean manager_modem_initialize_private_info(ModemBoard *mb)
+{
+       if (G_UNLIKELY(!mb))
+               return FALSE;
+
+       if (mb->modem_info)
+               mb->modem_info->modem_status = MODEM_STATE_UNKNOWN;
+
+       mb->modem_info = g_malloc0(sizeof(struct manager_modem_private_info));
+       mb->modem_info->co_modem = tcore_plugin_ref_core_object(mb->modem_plugin, CORE_OBJECT_TYPE_MODEM);
+       mb->modem_info->modem_status = MODEM_STATE_UNKNOWN;
+
+       dbg("Initialized modem private info");
+       return TRUE;
+}
+enum tcore_manager_return manager_modem_process_notification(Manager *manager,
+                                                            CoreObject *source, enum tcore_notification_command command,
+                                                            unsigned int data_len, void *data)
+{
+       enum tcore_manager_return ret = TCORE_MANAGER_RETURN_CONTINUE;
+       TcorePlugin *manager_plugin = tcore_manager_get_plugin(manager);
+       PrivateData *priv_data = tcore_plugin_ref_user_data(manager_plugin);
+
+       if (!data || !priv_data) {
+               err("Invalid data");
+               return ret;
+       }
+
+       switch (command) {
+       case TNOTI_MODEM_POWER: {
+               const struct tnoti_modem_power *modem_power = data;
+
+               if (modem_power == NULL) {
+                       err("modem_power data is NULL");
+                       return ret;
+               }
+
+               switch (modem_power->state) {
+               case MODEM_STATE_ERROR:
+                       dbg("Modem RESET happened");
+                       manager_network_process_modem_error(source);
+                       manager_call_process_modem_error(source);
+                       priv_data->fm_processing_state = MANAGER_FLIGHT_PROCESSING_NONE;
+                       break;
+
+               case MODEM_STATE_ONLINE: {
+                       char *msg = g_strdup("setRadioPower on");
+                       dbg("Write MODEM_STATE to /sys/class/sec/bsp/boot_stat");
+                       manager_util_write_to_proc_file(msg, strlen(msg));
+                       g_free(msg);
+               }
+               break;
+
+               default:
+                       break;
+               }
+               __update_private_info(manager, source, modem_power->state);
+#ifdef TIZEN_SUPPORT_SIM_PREFERRED_SUBSCRIPTION
+               set_nw_dds_ds_on_boot(manager);
+#endif
+       }
+       break;
+
+       default:
+               break;
+       }
+
+       return ret;
+}
+
diff --git a/src/manager_network.c b/src/manager_network.c
new file mode 100644 (file)
index 0000000..267110d
--- /dev/null
@@ -0,0 +1,941 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <tcore.h>
+#include <server.h>
+#include <manager.h>
+#include <plugin.h>
+#include <user_request.h>
+#include <co_network.h>
+#include <co_sim.h>
+#include <tfeature.h>
+#include <vconf.h>
+#include <openssl/sha.h>
+
+#include "manager_core.h"
+#include "manager_util.h"
+#include "manager_modem.h"
+#include "manager_network.h"
+#include "manager_queue.h"
+#include "manager_sim.h"
+#include "internal/manager_internal.h"
+#include "internal/manager_network_internal.h"
+#include "network_name/manager_network_name.h"
+
+#define NET_CACHE_MASK_PLMN 0x0001
+#define NET_CACHE_MASK_LAC  0x0002
+#define NET_CACHE_MASK_NET_CHANGE 0x000F
+
+#define NET_CACHE_MASK_ROAM 0x0010
+#define NET_CACHE_MASK_CS 0x0020
+#define NET_CACHE_MASK_PS 0x0040
+#define NET_CACHE_MASK_SVC  0x0080
+#define NET_CACHE_MASK_NET_REGI 0x00F0
+
+#define NET_IMS_MASK_REGI (NETWORK_IMS_REG_FEATURE_TYPE_VOLTE | NETWORK_IMS_REG_FEATURE_TYPE_SMS | NETWORK_IMS_REG_FEATURE_TYPE_VT)
+
+
+static char *__network_get_fake_home_on(NetworkPrivateInfo *npi)
+{
+       char *xml_fake_home_on = NULL;
+
+       do {
+               if (G_UNLIKELY(!npi || !npi->eons_data))
+                       break;
+
+               if (!npi->eons_data->spn_override_info)
+                       manager_network_load_spn_override_info(npi);
+
+               if (npi->eons_data->spn_override_info)
+                       xml_fake_home_on = npi->eons_data->spn_override_info->fake_home_on;
+       } while (0);
+
+       return xml_fake_home_on;
+}
+
+static char *__network_get_fake_roaming_on(NetworkPrivateInfo *npi)
+{
+       char *xml_fake_roaming_on = NULL;
+
+       do {
+               if (G_UNLIKELY(!npi || !npi->eons_data))
+                       break;
+
+               if (!npi->eons_data->spn_override_info)
+                       manager_network_load_spn_override_info(npi);
+
+               if (npi->eons_data->spn_override_info)
+                       xml_fake_roaming_on = npi->eons_data->spn_override_info->fake_roaming_on;
+       } while (0);
+       return xml_fake_roaming_on;
+}
+
+static gboolean __network_is_roaming_between_operators(NetworkPrivateInfo *npi, gboolean is_roaming)
+{
+       gboolean final_roaming;
+       char *fake_home_on = NULL;
+       char *plmn = NULL;
+
+       final_roaming = is_roaming;
+       do {
+               if (final_roaming == FALSE) /* Already home network */
+                       break;
+
+               fake_home_on = __network_get_fake_home_on(npi);
+               if (!fake_home_on)
+                       break;
+
+               plmn = tcore_network_get_plmn(npi->co_network);
+               if (!plmn)
+                       break;
+
+               if (strlen(fake_home_on) == 3 && (strncmp(fake_home_on, plmn, 3) == 0)) {
+                       info("[SPN_OVERRIDE] fake home on matched by MCC. change to home (mcc:%s)", fake_home_on);
+                       final_roaming = FALSE;
+               } else if (strstr(fake_home_on, plmn)) {
+                       info("[SPN_OVERRIDE] fake home on matched. change to home (list:%s, cur:%s)", fake_home_on, plmn);
+                       final_roaming = FALSE;
+               } else {
+                       dbg("[SPN_OVERRIDE] fake home on not matched. keep current (list:%s, cur:%s)", fake_home_on, plmn);
+               }
+       } while (0);
+
+       g_free(plmn);
+       return final_roaming;
+}
+
+static gboolean __network_is_fake_roaming_between_operators(NetworkPrivateInfo *npi)
+{
+       gboolean ret = FALSE;
+       char *fake_roaming_on = NULL;
+       char *plmn = NULL;
+
+       do {
+               fake_roaming_on = __network_get_fake_roaming_on(npi);
+               if (!fake_roaming_on)
+                       break;
+
+               plmn = tcore_network_get_plmn(npi->co_network);
+               if (!plmn)
+                       break;
+
+               if (strstr(fake_roaming_on, plmn)) {
+                       info("[SPN_OVERRIDE] fake roam on matched.(list:%s, cur:%s)", fake_roaming_on, plmn);
+                       ret = TRUE;
+               } else {
+                       dbg("[SPN_OVERRIDE] fake roam on not matched.(list:%s, cur:%s)", fake_roaming_on, plmn);
+               }
+       } while (0);
+
+       g_free(plmn);
+       return ret;
+}
+
+static void __network_update_excp_roaming_state(NetworkPrivateInfo *npi,
+                                               struct tnoti_network_registration_status *data)
+{
+       if (G_UNLIKELY(!data || !npi))
+               return;
+
+       if (data->service_type <= NETWORK_SERVICE_TYPE_SEARCH)
+               return;
+
+       if (data->roaming_status == TRUE) {
+               /* Roaming. we should check fake home*/
+               if (__network_is_roaming_between_operators(npi, data->roaming_status) == FALSE) {
+                       info("[SPN_OVERRIDE] Fake home applied. Change to home network");
+                       tcore_network_set_roaming_state(npi->co_network, FALSE);
+                       data->roaming_status = FALSE;
+               } else {
+                       dbg("[SPN_OVERRIDE] Keep current. (Roaming)");
+               }
+       } else {
+               if (__network_is_fake_roaming_between_operators(npi) == TRUE) {
+                       info("[SPN_OVERRIDE] Fake roaming applied. Change to roam network");
+                       tcore_network_set_roaming_state(npi->co_network, TRUE);
+                       data->roaming_status = TRUE;
+               } else {
+                       dbg("[SPN_OVERRIDE] Keep current. (Home)");
+               }
+       }
+}
+
+static int __network_update_net_regi_cache(NetworkPrivateInfo *npi, struct tnoti_network_registration_status *data)
+{
+       int ret_mask = 0;
+
+       MANAGER_NET_CHECK_NPI_CACHE_RET(npi);
+       if (!data)
+               return 0;
+
+       if (npi->cache_data->prev_cs_domain_status != data->cs_domain_status) {
+               npi->cache_data->prev_cs_domain_status = data->cs_domain_status;
+               ret_mask |= NET_CACHE_MASK_CS;
+       }
+
+       if (npi->cache_data->prev_ps_domain_status != data->ps_domain_status) {
+               npi->cache_data->prev_ps_domain_status = data->ps_domain_status;
+               ret_mask |= NET_CACHE_MASK_PS;
+       }
+
+       if (npi->cache_data->prev_service_type != data->service_type) {
+               npi->cache_data->prev_service_type = data->service_type;
+               ret_mask |= NET_CACHE_MASK_SVC;
+       }
+
+       if (npi->cache_data->prev_roaming_status != data->roaming_status) {
+               npi->cache_data->prev_roaming_status = data->roaming_status;
+               ret_mask |= NET_CACHE_MASK_ROAM;
+       }
+
+       return ret_mask;
+}
+
+static int __network_update_net_change_cache(NetworkPrivateInfo *npi, struct tnoti_network_change *data)
+{
+       int ret_mask = 0;
+       char *plmn = data ? data->plmn : NULL;
+       unsigned int lac = data ? data->gsm.lac : 0;
+
+       MANAGER_NET_CHECK_NPI_CACHE_RET(npi);
+
+       if (plmn && (strlen(plmn) > 0)
+           && (memcmp(npi->cache_data->current_plmn, plmn, NETWORK_MAX_PLMN_LEN) != 0)) {
+               info("update current_plmn cache info [%s] -> [%s]", npi->cache_data->current_plmn, plmn);
+               memcpy(npi->cache_data->current_plmn, plmn, NETWORK_MAX_PLMN_LEN);
+               ret_mask |= NET_CACHE_MASK_PLMN;
+       }
+
+       if (npi->cache_data->prev_lac != lac) {
+               npi->cache_data->prev_lac = lac;
+               ret_mask |= NET_CACHE_MASK_LAC;
+       }
+       return ret_mask;
+}
+
+static void __network_update_net_regi_noti_with_ims_regi_info(NetworkPrivateInfo *npi,
+       struct tnoti_network_registration_status *data)
+{
+       struct tel_network_ims_registration_info ims_info = { 0, };
+
+       if (tcore_network_get_ims_reg_info(npi->co_network, &ims_info) != TCORE_RETURN_SUCCESS) {
+               err("Failed to get IMS registration information");
+               return;
+       }
+
+       if (ims_info.is_registered) {
+               struct tnoti_network_ims_registration_info noti_data;
+               gboolean send_ims_noti = FALSE;
+
+               if (ims_info.network_type == NETWORK_IMS_REG_NETWORK_TYPE_WIFI) {
+                       /*
+                        * IMS registered on VoWiFi : Set CS network registration status - FULL
+                        */
+                       data->cs_domain_status = NETWORK_SERVICE_DOMAIN_STATUS_FULL;
+                       tcore_network_set_service_status(npi->co_network,
+                               TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT,
+                               data->cs_domain_status);
+
+                       /*
+                        * IMS registered on VoWiFi : Set PS network registration status - FULL
+                        */
+                       data->ps_domain_status = NETWORK_SERVICE_DOMAIN_STATUS_FULL;
+                       tcore_network_set_service_status(npi->co_network,
+                               TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET,
+                               data->ps_domain_status);
+
+                       /*
+                        * IMS registered on VoWiFi : Set Service type LTE
+                        */
+                       data->service_type = NETWORK_SERVICE_TYPE_LTE;
+                       tcore_network_set_service_type(npi->co_network, data->service_type);
+               } else if ((ims_info.feature_mask & NET_IMS_MASK_REGI)
+                               && (data->ps_domain_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL)) {
+                       /*
+                        * IMS registered on VoLTE : Set CS network registration status - FULL
+                        */
+                       data->cs_domain_status = NETWORK_SERVICE_DOMAIN_STATUS_FULL;
+                       tcore_network_set_service_status(npi->co_network,
+                               TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT,
+                               data->cs_domain_status);
+
+                       /*
+                        * Send IMS registration notification,
+                        * if explicit de-registration notification was sent
+                        */
+                       if (npi->sent_ims_dereg == TRUE) {
+                               noti_data.is_registered = ims_info.is_registered;
+                               noti_data.feature_mask = ims_info.feature_mask;
+                               noti_data.network_type = ims_info.network_type;
+                               noti_data.ecmp_mode = ims_info.ecmp_mode;
+
+                               npi->sent_ims_dereg = FALSE;
+
+                               send_ims_noti = TRUE;
+                       }
+               } else if ((ims_info.feature_mask & NET_IMS_MASK_REGI)
+                               && (data->ps_domain_status == NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY)) {
+                       if (npi->sent_ims_dereg == FALSE) {
+                               /*
+                                * PS is in Emergency service,
+                                * send IMS De-registered notification
+                                */
+                               noti_data.is_registered = FALSE;
+                               noti_data.feature_mask = 0;
+                               noti_data.network_type = NETWORK_IMS_REG_NETWORK_TYPE_MOBILE;
+                               noti_data.ecmp_mode = NETWORK_IMS_REG_ECMP_MODE_NOT_SUPPORT;
+
+                               npi->sent_ims_dereg = TRUE;
+
+                               send_ims_noti = TRUE;
+                       }
+               }
+
+               /*
+                * Send IMS registration notification
+                */
+               if (send_ims_noti) {
+                       Server *s;
+
+                       s = tcore_plugin_ref_server(tcore_object_ref_plugin(npi->co_network));
+
+                       info("Sending IMS Registration notification - [%s]",
+                               (noti_data.is_registered ? "REGISTERED" : "DEREGISTERED"));
+
+                       /* Send notification */
+                       tcore_server_broadcast_notification(s,
+                               npi->co_network,
+                               TNOTI_NETWORK_IMS_REGISTRATION_STATUS,
+                               sizeof(noti_data), &noti_data);
+               }
+
+               dbg("IMS regi(0x%x). new CS:[%d->%d] new PS:[%d->%d] SvcType:[%d->%d]",
+                       ims_info.feature_mask,
+                       npi->cache_data->prev_cs_domain_status, data->cs_domain_status,
+                       npi->cache_data->prev_ps_domain_status, data->ps_domain_status,
+                       npi->cache_data->prev_service_type, data->service_type);
+       } else { /* IMS de-registered */
+               CoreObject *co_sim = npi->co_sim;
+               gboolean is_jio_sim;
+
+               is_jio_sim = tcore_sim_is_jio_sim(co_sim);
+               if (is_jio_sim) {
+                       if (data->cs_domain_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
+                               info("Updating JIO SIM CS status/Service type as Emergency until IMS registration!");
+
+                               /*
+                                * IMS not yet registered : Set CS network registration status - EMERGENCY
+                                */
+                               data->cs_domain_status = NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY;
+                               tcore_network_set_service_status(npi->co_network,
+                                       TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT,
+                                       data->cs_domain_status);
+                               npi->cache_data->prev_cs_domain_status = NETWORK_SERVICE_DOMAIN_STATUS_EMERGENCY;
+                       }
+               }
+       }
+}
+
+static void __network_process_ims_regi_event(Manager *manager, NetworkPrivateInfo *npi,
+                                            struct tnoti_network_ims_registration_info *data)
+{
+       TcorePlugin *manager_plugin = tcore_manager_get_plugin(manager);
+       PrivateData *priv_data = tcore_plugin_ref_user_data(manager_plugin);
+       struct tnoti_network_registration_status net_regi = { 0, };
+       gboolean process_pending_req = FALSE;
+
+       /*
+        * Check CS Network service status
+        * If Cached CS service status is FULL, then return.
+        * Else, send updated Network registration status based on IMS registration status.
+        *      IMS Registered - CS Service status FULL
+        *      IMS NOT registered - previous CS Service status
+        */
+       if (npi->cache_data->prev_cs_domain_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
+               /*
+                * CS Network service status is FULL -
+                * check if IMS De-registered.
+                *
+                * In case IMS is De-Registered,
+                * process pending Flight mode request or modem
+                * Power OFF request.
+                */
+               if (data->is_registered == FALSE)
+                       process_pending_req = TRUE;
+
+               goto OUT;
+       }
+
+       if (data->is_registered && (data->feature_mask & NET_IMS_MASK_REGI)) {
+               /* IMS registered : Set CS network registration status - FULL */
+               net_regi.cs_domain_status = NETWORK_SERVICE_DOMAIN_STATUS_FULL;
+               net_regi.ps_domain_status = npi->cache_data->prev_ps_domain_status;
+               net_regi.service_type = npi->cache_data->prev_service_type;
+
+               tcore_network_set_service_status(npi->co_network,
+                       TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT,
+                       net_regi.cs_domain_status);
+
+               if (data->network_type == NETWORK_IMS_REG_NETWORK_TYPE_WIFI) {
+                       net_regi.service_type = NETWORK_SERVICE_TYPE_LTE;
+                       tcore_network_set_service_type(npi->co_network, net_regi.service_type);
+
+                       /* Update PS domain status in case of VoWiFi */
+                       net_regi.ps_domain_status = NETWORK_SERVICE_DOMAIN_STATUS_FULL;
+                       tcore_network_set_service_status(npi->co_network,
+                               TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET,
+                               net_regi.ps_domain_status);
+               }
+
+               info("IMS REGI! CS info need to be updated. CS:[%d->%d] PS:[%d->%d] SvcType:[%d] ",
+                       npi->cache_data->prev_cs_domain_status, net_regi.cs_domain_status,
+                       npi->cache_data->prev_ps_domain_status, net_regi.ps_domain_status,
+                       net_regi.service_type);
+       } else {
+               net_regi.cs_domain_status = npi->cache_data->prev_cs_domain_status;
+               net_regi.ps_domain_status = npi->cache_data->prev_ps_domain_status;
+               net_regi.service_type = npi->cache_data->prev_service_type;
+
+               tcore_network_set_service_status(npi->co_network,
+                       TCORE_NETWORK_SERVICE_DOMAIN_TYPE_CIRCUIT,
+                       net_regi.cs_domain_status);
+               tcore_network_set_service_type(npi->co_network,
+                       net_regi.service_type);
+
+               dbg("IMS DE-REGI! CS info need to be reverted: CS:[%d] SvcType:[%d]",
+                   net_regi.cs_domain_status, net_regi.service_type);
+
+               /* Need to process Flight mode */
+               process_pending_req = TRUE;
+
+               /* Reset explicit IMS de-registration sent flag */
+               npi->sent_ims_dereg = FALSE;
+       }
+
+       /* Update other Network registration status fields */
+       tcore_network_get_service_status(npi->co_network,
+               TCORE_NETWORK_SERVICE_DOMAIN_TYPE_PACKET,
+               &net_regi.ps_domain_status);
+       net_regi.roaming_status = tcore_network_get_roaming_state(npi->co_network);
+
+       if (priv_data->fm_processing_state != MANAGER_FLIGHT_PROCESSSING_ENABLE) {
+               Server *s;
+
+               s = tcore_plugin_ref_server(tcore_object_ref_plugin(npi->co_network));
+
+               info("Sending network registration status notification");
+
+               /* Send notification without manager */
+               tcore_server_broadcast_notification(s,
+                       npi->co_network,
+                       TNOTI_NETWORK_REGISTRATION_STATUS,
+                       sizeof(struct tnoti_network_registration_status), &net_regi);
+       }
+
+ OUT:
+       if ((process_pending_req == TRUE)
+                       && (manager_get_deregister_timer(manager) != 0)) {
+               /*
+                * Process Flight mode request or/and Modem Power OFF request, if any
+                */
+               dbg("Processing any pending Modem request(s) - Presently not handling processing for IMS De-registration notification (depend on timeout)");
+               /*manager_util_process_pending_request(manager);*/
+       }
+}
+
+NetworkPrivateInfo *manager_network_ref_npi_by_ur(Server *s, UserRequest *ur)
+{
+       TcorePlugin *modem_plugin;
+       Manager *manager;
+       ModemBoard *mb;
+
+       modem_plugin = manager_util_get_modem_plugin(s, ur);
+       manager = tcore_server_ref_manager(s);
+       mb = manager_core_get_modem_board(manager, modem_plugin);
+       if (G_UNLIKELY(!mb)) {
+               err("mb not found");
+               return NULL;
+       }
+
+       return mb->network_info;
+}
+
+NetworkPrivateInfo *manager_network_ref_npi_by_plugin(TcorePlugin *modem_plugin)
+{
+       Server *s = tcore_plugin_ref_server(modem_plugin);
+       Manager *manager = tcore_server_ref_manager(s);
+       ModemBoard *mb;
+
+       mb = manager_core_get_modem_board(manager, modem_plugin);
+       if (G_UNLIKELY(!mb)) {
+               err("mb not found");
+               return NULL;
+       }
+
+       return mb->network_info;
+}
+
+gboolean manager_network_initialize_private_info(ModemBoard *mb)
+{
+       NetworkPrivateInfo *npi;
+
+       if (G_UNLIKELY(!mb))
+               return FALSE;
+
+       if (mb->network_info)
+               manager_network_clear_private_info(mb);
+
+       mb->network_info = g_try_malloc0(sizeof(struct manager_network_private_info));
+
+       npi = mb->network_info;
+       npi->co_network = tcore_plugin_ref_core_object(mb->modem_plugin, CORE_OBJECT_TYPE_NETWORK);
+       npi->co_sim = tcore_plugin_ref_core_object(mb->modem_plugin, CORE_OBJECT_TYPE_SIM);
+       npi->cache_data = g_try_malloc0(sizeof(struct manager_network_cache_info));
+       if (G_LIKELY(npi->cache_data)) {
+               npi->cache_data->prev_cs_domain_status = NETWORK_SERVICE_DOMAIN_STATUS_NO;
+               npi->cache_data->prev_ps_domain_status = NETWORK_SERVICE_DOMAIN_STATUS_NO;
+               npi->cache_data->prev_service_type = NETWORK_SERVICE_TYPE_NO_SERVICE;
+               npi->cache_data->prev_roaming_status = FALSE;
+               npi->cache_data->prev_lac = 0;
+       }
+
+       npi->eons_data = g_try_malloc0(sizeof(struct manager_network_eons_info));
+       if (G_LIKELY(npi->eons_data)) {
+               npi->eons_data->spdi = g_try_malloc0(sizeof(struct tel_sim_spdi));
+               npi->eons_data->opl = g_try_malloc0(sizeof(struct tel_sim_opl_list));
+               npi->eons_data->pnn = g_try_malloc0(sizeof(struct tel_sim_pnn_list));
+               npi->eons_data->long_nitz_name = g_strdup("long_nitz");
+               npi->eons_data->short_nitz_name = g_strdup("short_nitz");
+               npi->eons_data->spn_override_info = NULL;
+               npi->eons_data->lac_netname_info = NULL;
+               npi->eons_data->backup_name_ind_msg = NULL;
+               npi->eons_data->is_eons_ready = FALSE;
+               npi->eons_data->is_eons_updated = FALSE;
+               npi->eons_data->is_sim_refreshed = FALSE;
+               npi->eons_data->name_type = NETWORK_NAME_TYPE_NONE;
+               npi->eons_data->spn_name_type = NETWORK_SPN_NAME_TYPE_NONE;
+               npi->eons_data->sim_network_name_state = 0;
+               npi->eons_data->sim_network_name_support_list = 0;
+       }
+
+       dbg("Initialized network private info");
+       return TRUE;
+}
+
+void manager_network_clear_private_info(ModemBoard *mb)
+{
+       NetworkPrivateInfo *npi;
+
+       if (G_UNLIKELY(!mb || !mb->network_info))
+               return;
+
+       npi = mb->network_info;
+
+       if (npi->eons_data) {
+               g_free(npi->eons_data->spdi);
+               if (npi->eons_data->opl->list)
+                       g_free(npi->eons_data->opl->list);
+               if (npi->eons_data->pnn->list)
+                       g_free(npi->eons_data->pnn->list);
+               if (npi->eons_data->spn_override_info) {
+                       g_free(npi->eons_data->spn_override_info->spn);
+                       g_free(npi->eons_data->spn_override_info->imsi_subset);
+                       g_free(npi->eons_data->spn_override_info->fake_home_on);
+                       g_free(npi->eons_data->spn_override_info->fake_roaming_on);
+                       g_free(npi->eons_data->spn_override_info->spn_display_rule);
+                       g_free(npi->eons_data->spn_override_info);
+               }
+               if (npi->eons_data->lac_netname_info) {
+                       g_free(npi->eons_data->lac_netname_info->lac_netname);
+                       if (npi->eons_data->lac_netname_info->lac_netname_hash)
+                               g_hash_table_destroy(npi->eons_data->lac_netname_info->lac_netname_hash);
+                       g_free(npi->eons_data->lac_netname_info);
+               }
+               g_free(npi->eons_data->long_nitz_name);
+               g_free(npi->eons_data->short_nitz_name);
+               g_free(npi->eons_data->backup_name_ind_msg);
+               g_free(npi->eons_data);
+               npi->eons_data = NULL;
+       }
+
+       if (npi->cache_data) {
+               g_free(npi->cache_data);
+               npi->cache_data = NULL;
+       }
+
+       g_free(npi);
+       mb->network_info = NULL;
+
+       dbg("done");
+}
+
+static void on_manager_resp_ims_deregister(UserRequest *ur,
+       enum tcore_response_command command,
+       unsigned int data_len, const void *data, void *user_data)
+{
+       const struct tresp_network_ims_deregister *resp = data;
+       if (resp && resp->result == TCORE_RETURN_SUCCESS) {
+               /*
+                * Wait for IMS De-Registration notification to initiate Flight mode
+                * or/and modem power off request (if any pending)
+                */
+               info("Wait for IMS De-registration notification");
+       } else {
+               /* Initiate Flight mode request or/and modem power off request(if any pending) */
+               warn("IMS De-registration failed(result:%d)!. Process pending modem requests now",
+                    resp ? resp->result : -1);
+               manager_util_process_pending_request(user_data);
+       }
+}
+
+enum tcore_manager_return manager_network_deregister_ims(Manager *manager, UserRequest *ur)
+{
+       Server *server = tcore_plugin_ref_server(tcore_manager_get_plugin(manager));
+       UserRequest *ur_ims;
+       char *modem_name;
+       enum tcore_manager_return ret = TCORE_MANAGER_RETURN_CONTINUE;
+
+       modem_name = tcore_user_request_get_modem_name(ur);
+       ur_ims = tcore_user_request_new(NULL, modem_name);
+       g_free(modem_name);
+       if (!ur_ims) {
+               err("Failed to create 'UR'");
+               return ret;
+       }
+
+       /* IMS De-Registration request processing*/
+       tcore_user_request_set_command(ur_ims, TREQ_NETWORK_IMS_DEREGISTER);
+       tcore_user_request_set_response_hook(ur_ims,
+               on_manager_resp_ims_deregister, manager);
+
+       /* Dispatch request to Network Core Object */
+       if (tcore_server_dispatch_request_ex(server,
+                       ur_ims, TCORE_OPS_TYPE_IMS) != TCORE_RETURN_SUCCESS) {
+               err("Failed to dispatch request");
+               /* Unref 'UR' */
+               tcore_user_request_unref(ur_ims);
+               return ret;
+       }
+
+       /* Stop propogation of Request */
+       ret = TCORE_MANAGER_RETURN_STOP;
+       return ret;
+
+}
+
+void manager_network_process_modem_error(CoreObject *co_modem)
+{
+       TcorePlugin *plugin = tcore_object_ref_plugin(co_modem);
+       Server *server = tcore_plugin_ref_server(plugin);
+       ModemBoard *mb = manager_core_get_modem_board(tcore_server_ref_manager(server), plugin);
+
+       /* Initialize network private info */
+       manager_network_initialize_private_info(mb);
+
+       /* Initialize first boot info */
+       mb->sim_info->is_first_boot = TRUE;
+}
+
+static void manager_network_resp_hook_search_network(UserRequest *ur,
+       enum tcore_response_command command,
+       unsigned int data_len, const void *data, void *user_data)
+{
+       Server *server = (Server *)user_data;
+       NetworkPrivateInfo *npi;
+
+       npi = manager_network_ref_npi_by_ur(server, ur);
+       if (npi) {
+               npi->search_in_progress = FALSE;
+               info("search_in_progress: [%d]", npi->search_in_progress);
+       }
+
+       if (tfeature_is_supported(TFEATURE_FUNCTION_MANAGER_NETWORK_NAME_ENABLE)) {
+               struct tresp_network_search *resp = (struct tresp_network_search *)data;
+
+               if (resp && resp->result == TCORE_RETURN_SUCCESS) {
+                       int count;
+                       CoreObject *co_network = manager_util_get_core_object(server, ur, CORE_OBJECT_TYPE_NETWORK);
+
+                       for (count = 0; count < resp->list_count; count++) {
+                               manager_network_get_name_from_plmn(co_network,
+                                       resp->list[count].name, resp->list[count].plmn);
+                       }
+               }
+       }
+}
+
+static void manager_network_resp_hook_get_preferred_plmn(UserRequest *ur,
+       enum tcore_response_command command,
+       unsigned int data_len, const void *data, void *user_data)
+{
+       struct tresp_network_get_preferred_plmn *resp = (struct tresp_network_get_preferred_plmn *)data;
+
+       if (resp && resp->result == TCORE_RETURN_SUCCESS) {
+               int count;
+               Server *s = user_data;
+               CoreObject *co_network = manager_util_get_core_object(s, ur, CORE_OBJECT_TYPE_NETWORK);
+
+               for (count = 0; count < resp->list_count; count++) {
+                       manager_network_get_name_from_plmn(co_network,
+                                                          resp->list[count].name, resp->list[count].plmn);
+               }
+       }
+}
+
+void manager_network_cancel_network_search(Manager *manager, Server *server)
+{
+       GSList *modem_plg_list;
+       TcorePlugin *modem_plg;
+       GSList *cur;
+       UserRequest *ur = NULL;
+       char *cp_name = NULL;
+       NetworkPrivateInfo *npi;
+
+       TReturn ret;
+
+       modem_plg_list = tcore_server_get_modem_plugin_list(server);
+       for (cur = modem_plg_list; cur; cur = cur->next) {
+               modem_plg = cur->data;
+               if (modem_plg == NULL) {
+                       dbg("No Modem Plug-in");
+                       continue;
+               }
+
+               npi = manager_network_ref_npi_by_plugin(modem_plg);
+               if (npi && (npi->search_in_progress == TRUE)) {
+                       cp_name = (char *)tcore_server_get_cp_name_by_plugin(modem_plg);
+                       dbg("Initiating Network Search Cancel for %s", cp_name);
+
+                       ur = tcore_user_request_new(NULL, cp_name);
+                       tcore_user_request_set_command(ur, TREQ_NETWORK_SET_CANCEL_MANUAL_SEARCH);
+
+                       ret = tcore_server_dispatch_request(server, ur);
+                       if (ret != TCORE_RETURN_SUCCESS) {
+                               err("Request cmd(0x%x) failed ret: [%d]",
+                                       TREQ_NETWORK_SET_CANCEL_MANUAL_SEARCH, ret);
+
+                               /* Unref 'ur' */
+                               tcore_user_request_unref(ur);
+                       }
+               }
+       }
+       g_slist_free(modem_plg_list);
+}
+
+enum tcore_manager_return manager_network_process_request(Server *server,
+       UserRequest *ur)
+{
+       enum tcore_request_command command = tcore_user_request_get_command(ur);
+       enum tcore_manager_return manager_ret = TCORE_MANAGER_RETURN_CONTINUE;
+       Manager *manager = tcore_server_ref_manager(server);
+       TcorePlugin *manager_plugin = tcore_manager_get_plugin(manager);
+       PrivateData *priv_data = tcore_plugin_ref_user_data(manager_plugin);
+       TcorePlugin *modem_plugin = NULL;
+       CoreObject *co_sim = NULL;
+
+       if (priv_data->fm_processing_state != MANAGER_FLIGHT_PROCESSING_NONE) {
+               info("flight mode request is in progress. Do not process any network requests");
+               return TCORE_MANAGER_RETURN_FAILURE;
+       }
+
+       switch (command) {
+       case TREQ_NETWORK_SEARCH: {
+               NetworkPrivateInfo *npi;
+
+               npi = manager_network_ref_npi_by_ur(server, ur);
+               if (npi) {
+                       npi->search_in_progress = TRUE;
+                       dbg("search_in_progress: [%d]", npi->search_in_progress);
+               }
+
+               /* Add response hook */
+               tcore_user_request_set_response_hook(ur,
+                       manager_network_resp_hook_search_network, server);
+       }
+       break;
+
+       case TREQ_NETWORK_GET_PREFERRED_PLMN: {
+               if (tfeature_is_supported(TFEATURE_FUNCTION_MANAGER_NETWORK_NAME_ENABLE)) {
+                       /* Add response hook */
+                       tcore_user_request_set_response_hook(ur,
+                               manager_network_resp_hook_get_preferred_plmn, server);
+               }
+       }
+       break;
+
+       case TREQ_NETWORK_SET_MODE: {
+               int subscription = -1;
+               int vconf_ret;
+
+               vconf_ret = vconf_get_int(VCONFKEY_TELEPHONY_DB_DEFAULT_DATA_SUBS, &subscription);
+               if (vconf_ret < 0) {
+                       info("Get DDS from vconf failed");
+                       return manager_ret;
+               } else {
+                       info("Default data subscirption is %d", subscription);
+                       if (subscription == (int)s_manager_get_subs_type_ur(ur))
+                               manager_ret = manager_util_process_ims(server, ur);
+               }
+
+               modem_plugin = manager_util_get_modem_plugin(server, ur);
+               co_sim = tcore_plugin_ref_core_object(modem_plugin, CORE_OBJECT_TYPE_SIM);
+               if (tcore_sim_get_status(co_sim) == SIM_STATUS_INIT_COMPLETED)
+                       tcore_user_request_set_response_hook(ur, manager_network_resp_hook_set_network_mode, modem_plugin);
+       }
+       break;
+
+       case TREQ_NETWORK_SET_PLMN_SELECTION_MODE: {
+               int subscription = -1;
+               int vconf_ret;
+
+               vconf_ret = vconf_get_int(VCONFKEY_TELEPHONY_DB_DEFAULT_DATA_SUBS, &subscription);
+               if (vconf_ret < 0) {
+                       info("Get DDS from vconf failed");
+
+                       return manager_ret;
+               } else {
+                       info("Default data subscirption is %d", subscription);
+
+                       if (subscription != (int)s_manager_get_subs_type_ur(ur))
+                               return manager_ret;
+               }
+               manager_ret = manager_util_process_ims(server, ur);
+       }
+       break;
+
+       case TREQ_NETWORK_SET_DEFAULT_DATA_SUBSCRIPTION: {
+               int subscription = -1;
+               int vconf_ret;
+
+               vconf_ret = vconf_get_int(VCONFKEY_TELEPHONY_DB_DEFAULT_DATA_SUBS, &subscription);
+               if (vconf_ret < 0) {
+                       info("Get DDS from vconf failed");
+                       return manager_ret;
+               } else {
+                       info("Default data subscirption is %d", subscription);
+
+                       if (subscription == (int)s_manager_get_subs_type_ur(ur))
+                               return manager_ret;
+               }
+
+               modem_plugin = manager_util_get_modem_plugin(server, ur);
+               co_sim = tcore_plugin_ref_core_object(modem_plugin, CORE_OBJECT_TYPE_SIM);
+
+               if (tcore_sim_get_status(co_sim) == SIM_STATUS_INIT_COMPLETED) {
+                       /* Add response hook */
+                       tcore_user_request_set_response_hook(ur,
+                               manager_network_resp_hook_set_dds, modem_plugin);
+
+                       info("added hook to update database");
+               }
+
+               manager_ret = manager_util_process_ims(server, ur);
+       }
+       break;
+
+       /*
+        * All other requests, would be routed to CP.
+        */
+       default:
+               break;
+       }
+
+       return manager_ret;
+}
+
+enum tcore_manager_return manager_network_process_notification(Manager *manager,
+       CoreObject *source,
+       enum tcore_notification_command command,
+       unsigned int data_len, void *data)
+{
+       enum tcore_manager_return ret = TCORE_MANAGER_RETURN_CONTINUE;
+       CoreObject *co_network = source;
+       TcorePlugin *plugin = tcore_object_ref_plugin(co_network);
+       NetworkPrivateInfo *npi = manager_network_ref_npi_by_plugin(plugin);
+
+       if (G_UNLIKELY(!data || !npi))
+               return ret;
+
+       switch (command) {
+       case TNOTI_NETWORK_REGISTRATION_STATUS: {
+               int change_mask = 0;
+               struct tnoti_network_registration_status *noti_status = data;
+               char *msg = NULL;
+               if (noti_status->cs_domain_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
+                       msg = g_strdup("Voice SVC is acquired");
+                       dbg("Write CS_STATUS to /sys/class/sec/bsp/boot_stat");
+                       manager_util_write_to_proc_file(msg, strlen(msg));
+                       g_free(msg);
+               }
+
+               if (noti_status->ps_domain_status == NETWORK_SERVICE_DOMAIN_STATUS_FULL) {
+                       msg = g_strdup("Data SVC is acquired");
+                       dbg("Write PS_STATUS to /sys/class/sec/bsp/boot_stat");
+                       manager_util_write_to_proc_file(msg, strlen(msg));
+                       g_free(msg);
+               }
+
+               __network_update_excp_roaming_state(npi, data);
+               change_mask = __network_update_net_regi_cache(npi, data);
+
+               if (tfeature_is_supported(TFEATURE_FUNCTION_MANAGER_NETWORK_NAME_ENABLE)) {
+                       if (change_mask & NET_CACHE_MASK_ROAM)
+                               manager_network_update_spn_display(npi);
+               }
+               __network_update_net_regi_noti_with_ims_regi_info(npi, data);
+       }
+       break;
+
+       case TNOTI_NETWORK_IMS_REGISTRATION_STATUS:
+               __network_process_ims_regi_event(manager, npi, data);
+               if (tfeature_is_supported(TFEATURE_FUNCTION_MANAGER_NETWORK_NAME_ENABLE))
+                       manager_network_update_spn_display(npi);
+       break;
+
+       case TNOTI_NETWORK_EPDG_STATUS: {
+               struct tnoti_network_epdg_status *noti_data = data;
+               npi->epdg_status = noti_data->status;
+               if (tfeature_is_supported(TFEATURE_FUNCTION_MANAGER_NETWORK_NAME_ENABLE))
+                       manager_network_update_spn_display(npi);
+       }
+       break;
+
+       case TNOTI_NETWORK_IDENTITY:
+               if (tfeature_is_supported(TFEATURE_FUNCTION_MANAGER_NETWORK_NAME_ENABLE))
+                       ret = manager_network_process_nitz_name(data, npi);
+               break;
+
+       case TNOTI_NETWORK_CHANGE:
+               if (tfeature_is_supported(TFEATURE_FUNCTION_MANAGER_NETWORK_NAME_ENABLE)) {
+                       if (__network_update_net_change_cache(npi, data))
+                               manager_network_update_spn_display(npi);
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       return ret;
+}
diff --git a/src/manager_notification.c b/src/manager_notification.c
new file mode 100644 (file)
index 0000000..5a0b59c
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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 <glib.h>
+#include <tcore.h>
+#include <manager.h>
+
+#include "manager_core.h"
+#include "manager_call.h"
+#include "manager_ss.h"
+#include "manager_modem.h"
+#include "manager_network.h"
+#include "manager_sim.h"
+#include "manager_server.h"
+#include "manager_sms.h"
+#include "manager_notification.h"
+
+enum tcore_manager_return manager_notification_handler(Manager *manager,
+       CoreObject *source,
+       enum tcore_notification_command command,
+       unsigned int data_len, void *data)
+{
+       enum tcore_manager_return mret;
+       int module = (command & 0x0FF00000);
+
+       switch (module) {
+       case TCORE_TYPE_CALL:
+               mret = manager_call_process_notification(manager,
+                       source, command, data_len, data);
+       break;
+
+       case TCORE_TYPE_MODEM:
+               mret = manager_modem_process_notification(manager,
+                       source, command, data_len, data);
+       break;
+
+       case TCORE_TYPE_NETWORK:
+               mret = manager_network_process_notification(manager,
+                       source, command, data_len, data);
+       break;
+
+       case TCORE_TYPE_SIM:
+               mret = manager_sim_process_notification(manager,
+                       source, command, data_len, data);
+       break;
+
+       case TCORE_TYPE_SERVER:
+               mret = manager_server_process_notification(manager,
+                       source, command, data_len, data);
+       break;
+
+       case TCORE_TYPE_SMS:
+               mret = manager_sms_process_notification(manager,
+                       source, command, data_len, data);
+       break;
+
+       default:
+               return TCORE_MANAGER_RETURN_CONTINUE;
+       }
+
+       if (mret == TCORE_MANAGER_RETURN_STOP)
+               dbg("module:[0x%x] ret:[STOP]");
+       else if (mret == TCORE_MANAGER_RETURN_CONTINUE_IMS)
+               dbg("module:[0x%x] ret:[IMS]");
+       else
+               dbg("module:[0x%x] ret:[FAIL]");
+
+       return mret;
+}
diff --git a/src/manager_phonebook.c b/src/manager_phonebook.c
new file mode 100644 (file)
index 0000000..06fb220
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Ankit Jogi <ankit.jogi@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 <stdlib.h>
+
+#include <tcore.h>
+#include <server.h>
+#include <plugin.h>
+#include <tfeature.h>
+#include <vconf.h>
+#include <user_request.h>
+#include <manager.h>
+#include <core_object.h>
+#include <co_phonebook.h>
+
+#include "manager_core.h"
+#include "manager_util.h"
+#include "manager_phonebook.h"
+
+static void __on_hook_change_pb_record(UserRequest *ur, enum tcore_response_command command,
+       unsigned int data_len, const void *data, void *user_data)
+{
+       Server *server = (Server *)user_data;
+       TcorePlugin *modem_plugin = manager_util_get_modem_plugin(server, ur);
+       Manager *manager = tcore_server_ref_manager(server);
+       ModemBoard *mb = manager_core_get_modem_board(manager, modem_plugin);
+
+       if (!modem_plugin || !server || !manager || !mb) {
+               err("NULL data : modem_plugin[%p], server[%p], manager[%p], mb[%p]", modem_plugin, server, manager, mb);
+               return;
+       }
+
+       if (TRESP_PHONEBOOK_UPDATERECORD == command) {
+               struct tresp_phonebook_update_record * update_record_resp = (struct tresp_phonebook_update_record *)data;
+
+               if (update_record_resp && PB_SUCCESS == update_record_resp->result) {
+                       struct treq_phonebook_update_record *update_record_req = (struct treq_phonebook_update_record *)tcore_user_request_ref_data(ur, NULL);
+                       info("FDN record add successful, add to cache !!");
+
+                       g_hash_table_insert(mb->fdn_contacts, g_strdup((const char *)update_record_req->number), g_strdup_printf("%d", update_record_req->index));
+               } else {
+                       err("FDN record add failed !!");
+               }
+       } else if (TRESP_PHONEBOOK_DELETERECORD == command) {
+               struct tresp_phonebook_delete_record *delete_record_resp = (struct tresp_phonebook_delete_record *)data;
+
+               if (delete_record_resp && PB_SUCCESS == delete_record_resp->result) {
+                       int index = 0;
+                       GHashTableIter iter;
+                       gpointer key, value;
+                       struct treq_phonebook_delete_record *delete_record_req = (struct treq_phonebook_delete_record *)tcore_user_request_ref_data(ur, NULL);
+                       info("FDN record delete successful, delete from cache !!");
+
+                       g_hash_table_iter_init(&iter, mb->fdn_contacts);
+                       while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+                               index = atoi((const char *) value);
+                               if (index == delete_record_req->index) { /* valid index of FDN record deleted*/
+                                       info("Deleted record index found, remove it from cache : index[%d] number[%s]", index, key);
+                                       g_hash_table_remove(mb->fdn_contacts, key);
+                               }
+                       }
+               } else {
+                       err("FDN record delete failed !!");
+               }
+       } else {
+               err("Invalid response command [0x%x]", command);
+       }
+}
+
+enum tcore_manager_return manager_phonebook_process_request(Server* server, UserRequest* ur)
+{
+       enum tcore_request_command command = tcore_user_request_get_command(ur);
+       enum tcore_manager_return manager_ret = TCORE_MANAGER_RETURN_CONTINUE;
+       TcorePlugin *modem_plugin = manager_util_get_modem_plugin(server, ur);
+       Manager *manager = tcore_server_ref_manager(server);
+       ModemBoard *mb = manager_core_get_modem_board(manager, modem_plugin);
+
+       switch (command) {
+       case TREQ_PHONEBOOK_UPDATERECORD: {
+               struct treq_phonebook_update_record *update_record_req = (struct treq_phonebook_update_record *)tcore_user_request_ref_data(ur, NULL);
+
+               if (PB_TYPE_FDN == update_record_req->phonebook_type && TRUE == mb->fdn_enabled) {
+                       info("Update Record received for FDN when FDN is enabled !!");
+                       tcore_user_request_set_response_hook(ur, __on_hook_change_pb_record, server);
+               }
+       }
+       break;
+       case TREQ_PHONEBOOK_DELETERECORD: {
+               struct treq_phonebook_delete_record *delete_record_req = (struct treq_phonebook_delete_record *)tcore_user_request_ref_data(ur, NULL);
+
+               if (PB_TYPE_FDN == delete_record_req->phonebook_type && TRUE == mb->fdn_enabled) {
+                       info("Delete Record received for FDN when FDN is enabled !!");
+                       tcore_user_request_set_response_hook(ur, __on_hook_change_pb_record, server);
+               }
+       }
+       /*
+        * All other requests, would be routed to CP.
+        */
+       default:
+       break;
+       }
+
+       return manager_ret;
+}
diff --git a/src/manager_queue.c b/src/manager_queue.c
new file mode 100644 (file)
index 0000000..0747496
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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 <glib.h>
+#include <tcore.h>
+#include <manager.h>
+#include <plugin.h>
+#include <user_request.h>
+
+#include "manager_types.h"
+#include "manager_queue.h"
+#include "internal/manager_internal.h"
+
+#define INVALID_PEEK_INDEX      (-1)
+
+typedef struct {
+       enum tcore_request_command command;
+       GSList *ur_list;        /* UR list */
+} ManagerQueueNode;
+
+/******************************* Internal APIs *******************************/
+static void __unref_ur(gpointer data)
+{
+       UserRequest *ur = data;
+       tcore_user_request_unref(ur);
+}
+
+static void __clear_queue(GQueue *manager_queue)
+{
+       ManagerQueueNode *node = NULL;
+
+       while (NULL != (node = g_queue_pop_head(manager_queue))) {
+               g_slist_free_full(node->ur_list, __unref_ur);
+               g_free(node);
+       }
+}
+
+static gint __get_peek_index(GQueue *manager_queue, enum tcore_request_command command)
+{
+       UserRequest *ur = NULL;
+       gint peek_index = 0;
+
+       g_assert(manager_queue != NULL);
+
+       /*
+        * Peek each 'node' and check if there is a 'ur'
+        * with matching 'command'.
+        */
+       while (TRUE) {
+               ur = g_queue_peek_nth(manager_queue, peek_index);
+               if (ur == NULL)
+                       break;
+
+               if (tcore_user_request_get_command(ur) == command)
+                       break;
+
+               peek_index++;
+       }
+
+       return ((ur == NULL) ? INVALID_PEEK_INDEX : peek_index);
+}
+
+static GQueue *__get_queue(Manager *manager)
+{
+       TcorePlugin *plugin = tcore_manager_get_plugin(manager);
+       PrivateData *priv_data = tcore_plugin_ref_user_data(plugin);
+       g_assert(priv_data != NULL);
+
+       return priv_data->manager_queue;
+}
+
+/******************************* External APIs *******************************/
+GQueue *manager_queue_init(void)
+{
+       GQueue *manager_queue = g_queue_new();
+
+       if (G_UNLIKELY(!manager_queue)) {
+               err("Failed to create Manager queue");
+               return NULL;
+       }
+       g_queue_init(manager_queue);
+
+       return manager_queue;
+}
+
+void manager_queue_deinit(GQueue *manager_queue)
+{
+       if (!manager_queue)
+               return;
+
+       /*
+        * In case Queue is NOT empty, then clear the queue.
+        */
+       if (g_queue_is_empty(manager_queue) == FALSE)
+               __clear_queue(manager_queue);
+
+       g_queue_free(manager_queue);
+}
+
+void manager_queue_enqueue(Manager *manager, UserRequest *ur)
+{
+       GQueue *manager_queue;
+
+       g_assert(manager != NULL);
+       g_assert(ur != NULL);
+
+       manager_queue = __get_queue(manager);
+       g_assert(manager_queue != NULL);
+
+       /* Reference 'ur' */
+       ur = tcore_user_request_ref(ur);
+       g_queue_push_tail(manager_queue, ur);
+}
+
+gboolean manager_queue_probe_command(Manager *manager,
+                                    enum tcore_request_command command)
+{
+       GQueue *manager_queue;
+       gint peek_index;
+
+       g_assert(manager != NULL);
+       g_assert(command != 0);
+
+       manager_queue = __get_queue(manager);
+       g_assert(manager_queue != NULL);
+
+       peek_index = __get_peek_index(manager_queue, command);
+
+       return(peek_index == INVALID_PEEK_INDEX ? FALSE : TRUE);
+}
+
+guint manager_get_queue_length(Manager *manager,
+                              enum tcore_request_command command)
+{
+       GQueue *manager_queue;
+       guint queue_length = 0;
+
+       g_assert(manager != NULL);
+       g_assert(command != 0);
+
+       manager_queue = __get_queue(manager);
+       g_assert(manager_queue != NULL);
+
+       queue_length = g_queue_get_length(manager_queue);
+
+       return queue_length;
+}
+
+UserRequest *manager_queue_dequeue(Manager *manager)
+{
+       UserRequest *ur = NULL;
+       GQueue *manager_queue;
+
+       g_assert(manager != NULL);
+
+       manager_queue = __get_queue(manager);
+       g_assert(manager_queue != NULL);
+
+       if (g_queue_get_length(manager_queue) == 0)
+               return NULL;
+
+       ur = (UserRequest *)g_queue_pop_head(manager_queue);
+       g_assert(ur != NULL);
+
+       tcore_user_request_unref(ur);
+
+       return ur;
+}
+
diff --git a/src/manager_request.c b/src/manager_request.c
new file mode 100644 (file)
index 0000000..12c02e6
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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 <manager.h>
+#include <plugin.h>
+#include <core_object.h>
+#include <user_request.h>
+
+#include "manager_core.h"
+#include "manager_call.h"
+#include "manager_ss.h"
+#include "manager_sms.h"
+#include "manager_modem.h"
+#include "manager_network.h"
+#include "manager_request.h"
+#include "manager_sim.h"
+#include "manager_phonebook.h"
+
+enum tcore_manager_return manager_request_handler(Manager *manager, UserRequest *ur)
+{
+       Server *server = tcore_plugin_ref_server(tcore_manager_get_plugin(manager));
+       enum tcore_request_command command = tcore_user_request_get_command(ur);
+       enum tcore_manager_return mret;
+       int module = (command & 0x0FF00000);
+
+       switch (module) {
+       case TCORE_TYPE_CALL:
+               mret = manager_call_process_request(server, ur);
+               break;
+
+       case TCORE_TYPE_SS:
+               mret = manager_ss_process_request(server, ur);
+               break;
+
+       case TCORE_TYPE_SMS:
+               mret = manager_sms_process_request(server, ur);
+               break;
+
+       case TCORE_TYPE_MODEM:
+               mret = manager_modem_process_request(server, ur);
+               break;
+
+       case TCORE_TYPE_NETWORK:
+               mret = manager_network_process_request(server, ur);
+               break;
+
+       case TCORE_TYPE_SIM:
+               mret = manager_sim_process_request(server, ur);
+       break;
+       case TCORE_TYPE_PHONEBOOK:
+               mret = manager_phonebook_process_request(server, ur);
+       break;
+       /*
+        * All other modules, would be routed to CP.
+        * Need to handle other modules as well
+        */
+       default:
+               return TCORE_MANAGER_RETURN_CONTINUE;
+       }
+
+       dbg("Command:[0x%x] mret:[%s]", command,
+           (mret == TCORE_MANAGER_RETURN_FAILURE ? "FALIURE" :
+            (mret == TCORE_MANAGER_RETURN_STOP ? "STOP" :
+             (mret == TCORE_MANAGER_RETURN_CONTINUE ? "TO MODEM" :
+              (mret == TCORE_MANAGER_RETURN_CONTINUE_IMS ? "TO IMS" :
+                   "UNKNOWN RESULT")))));
+
+       return mret;
+}
diff --git a/src/manager_server.c b/src/manager_server.c
new file mode 100644 (file)
index 0000000..2010dee
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Imran Mohammed <md.imran@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 <manager.h>
+
+#include "manager_core.h"
+#include "manager_server.h"
+
+enum tcore_manager_return manager_server_process_notification(Manager *manager,
+                                                             CoreObject *source, enum tcore_notification_command command,
+                                                             unsigned int data_len, void *data)
+{
+       enum tcore_manager_return ret = TCORE_MANAGER_RETURN_CONTINUE;
+       TcorePlugin *manager_plugin = tcore_manager_get_plugin(manager);
+       TcorePlugin *modem_plugin = data;
+
+       switch (command) {
+       case TNOTI_SERVER_ADDED_MODEM_PLUGIN:
+               info("Modem Plugin Added. Create modem(%s) board", tcore_server_get_cp_name_by_plugin(modem_plugin));
+               manager_core_create_modem_board(manager_plugin, modem_plugin);
+               break;
+
+       case TNOTI_SERVER_REMOVED_MODEM_PLUGIN:
+               info("Modem Plugin Removed. Destroy modem(%s) board", tcore_server_get_cp_name_by_plugin(modem_plugin));
+               manager_core_destroy_modem_board(manager_plugin, modem_plugin);
+               break;
+
+       default:
+               break;
+       }
+       return ret;
+}
diff --git a/src/manager_sim.c b/src/manager_sim.c
new file mode 100644 (file)
index 0000000..04ea831
--- /dev/null
@@ -0,0 +1,1529 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Imran Mohammed <md.imran@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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include <tcore.h>
+#include <server.h>
+#include <plugin.h>
+#include <tfeature.h>
+#include <vconf.h>
+#include <user_request.h>
+#include <manager.h>
+#include <core_object.h>
+#include <co_sim.h>
+#include <openssl/sha.h>
+
+#include "storage.h"
+#include "manager_core.h"
+#include "manager_util.h"
+#include "manager_sim.h"
+#include "manager_types.h"
+#include "manager_call.h"
+#include "manager_modem.h"
+
+#include "network_name/manager_network_name.h"
+#include "internal/manager_internal.h"
+
+#ifdef TIZEN_SUPPORT_SIM_PREFERRED_SUBSCRIPTION
+#define SIM_PREF_DB_PATH "/opt/dbspace/.sim_pref.db"
+#endif
+#define CALL_MSG_PREF_ALWAYS_ASK "always ask"
+
+#define IMSI_MAX_SIZE 16
+
+typedef enum {
+       S_NETWORK_SIM_NONE = 0,
+       S_NETWORK_SIM_SLOT1,
+       S_NETWORK_SIM_SLOT2,
+} __network_sim_present;
+
+static void __read_fdn_contacts(unsigned short index, TcorePlugin *modem_plugin);
+static void __get_fdn_contacts_info(TcorePlugin *modem_plugin);
+
+static gboolean __expect_other_sim_init(enum tel_sim_status sim_status)
+{
+       return (sim_status != SIM_STATUS_CARD_NOT_PRESENT  &&
+       sim_status != SIM_STATUS_CARD_ERROR &&
+       sim_status != SIM_STATUS_CARD_POWEROFF &&
+       sim_status != SIM_STATUS_UNKNOWN &&
+       sim_status != SIM_STATUS_CARD_BLOCKED &&
+       sim_status != SIM_STATUS_CARD_REMOVED &&
+       sim_status != SIM_STATUS_CARD_CRASHED);
+}
+
+static void __process_fdn_change(TcorePlugin *modem_plugin, gboolean fdn_status)
+{
+       Server *server = tcore_plugin_ref_server(modem_plugin);
+       Manager *manager = tcore_server_ref_manager(server);
+       ModemBoard *mb = manager_core_get_modem_board(manager, modem_plugin);
+
+       info("Enter : fdn_status[%d]", fdn_status);
+
+       if (!server || !manager || !mb) {
+               err("NULL data : server[%p], manager[%p], mb[%p]", server, manager, mb);
+               return;
+       }
+
+       if (mb->fdn_contacts)
+               g_hash_table_destroy(mb->fdn_contacts);
+       mb->fdn_contacts = NULL;
+
+       if (TRUE == fdn_status) {
+               mb->fdn_enabled = TRUE;
+
+               /* Create a hashtable for FDN contacts */
+               mb->fdn_contacts = (GHashTable *)g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+
+               __get_fdn_contacts_info(modem_plugin);
+       } else {
+               mb->fdn_enabled = FALSE;
+       }
+}
+static void __on_resp_get_fdn_status(UserRequest *ur, enum tcore_response_command command,
+                                    unsigned int data_len, const void *data, void *user_data)
+{
+       struct tresp_sim_get_facility_status *get_fac_status_resp = (struct tresp_sim_get_facility_status *)data;
+       TcorePlugin *modem_plugin = (TcorePlugin *)user_data;
+
+       if (!get_fac_status_resp || !modem_plugin) {
+               err("NULL data : get_fac_status_resp[%p], modem_plugin[%p]", get_fac_status_resp, modem_plugin);
+               return;
+       }
+
+       if (SIM_PIN_OPERATION_SUCCESS == get_fac_status_resp->result) {
+               if (SIM_FACILITY_FD == get_fac_status_resp->type && get_fac_status_resp->b_enable) {
+                       info("FDN is enabled at bootup, cache FDN contacts !!");
+                       __process_fdn_change(modem_plugin, TRUE);
+               }
+       } else {
+               err("Failed to get FDN status at bootup !!");
+       }
+}
+
+static void __get_fdn_status_info(TcorePlugin *modem_plugin)
+{
+       struct treq_sim_get_facility_status get_fac_status = { 0, };
+       gboolean ret = FALSE;
+
+       info("send Get FDN status at bootup");
+
+       get_fac_status.type = SIM_FACILITY_FD;
+
+       ret = manager_util_send_request(modem_plugin, TREQ_SIM_GET_FACILITY_STATUS,
+                                       sizeof(get_fac_status), &get_fac_status, __on_resp_get_fdn_status, modem_plugin);
+
+       if (!ret)
+               err("Fail to send FDN status info !!");
+}
+
+static void __on_resp_read_fdn_record(UserRequest *ur, enum tcore_response_command command,
+                                     unsigned int data_len, const void *data, void *user_data)
+{
+       struct tresp_phonebook_read_record *pb_read_record_resp = (struct tresp_phonebook_read_record *)data;
+       TcorePlugin *modem_plugin = (TcorePlugin *)user_data;
+       Server *server = tcore_plugin_ref_server(modem_plugin);
+       Manager *manager = tcore_server_ref_manager(server);
+       ModemBoard *mb = manager_core_get_modem_board(manager, modem_plugin);
+
+       if (!pb_read_record_resp || !modem_plugin || !server || !manager || !mb) {
+               err("NULL data : pb_read_record_resp[%p], modem_plugin[%p], server[%p], manager[%p], mb[%p]",
+                   pb_read_record_resp, modem_plugin, server, manager, mb);
+               return;
+       }
+
+       if (pb_read_record_resp && PB_SUCCESS == pb_read_record_resp->result) {
+               /* Insert number and index to hashtable */
+               g_hash_table_insert(mb->fdn_contacts, g_strdup((const char *)pb_read_record_resp->number), g_strdup_printf("%d", pb_read_record_resp->index));
+
+               /* Check if other records available, then send NEXT read record */
+               if (pb_read_record_resp->next_index > 0 && 0xFFFF != pb_read_record_resp->next_index)
+                       __read_fdn_contacts(pb_read_record_resp->next_index, modem_plugin);
+       } else {
+               err("failed to read FDN record !!");
+       }
+}
+
+void __read_fdn_contacts(unsigned short index, TcorePlugin *modem_plugin)
+{
+       struct treq_phonebook_read_record pb_read_record = { 0, };
+       gboolean ret = FALSE;
+
+       info("send PB read record request : index [%d]", index);
+
+       pb_read_record.phonebook_type = PB_TYPE_FDN;
+       pb_read_record.index = index;
+
+       ret = manager_util_send_request(modem_plugin, TREQ_PHONEBOOK_READRECORD,
+                                       sizeof(pb_read_record), &pb_read_record, __on_resp_read_fdn_record, modem_plugin);
+
+       if (!ret)
+               err("Fail to send FDN read record !!");
+}
+
+static void __on_resp_get_info_fdn(UserRequest *ur, enum tcore_response_command command,
+                                  unsigned int data_len, const void *data, void *user_data)
+{
+       struct tresp_phonebook_get_info *pb_get_info_resp = (struct tresp_phonebook_get_info *)data;
+       TcorePlugin *modem_plugin = (TcorePlugin *)user_data;
+
+       if (pb_get_info_resp && PB_SUCCESS == pb_get_info_resp->result) {
+               info("FDN get info : count[%d]", pb_get_info_resp->used_count);
+
+               if (pb_get_info_resp->used_count > 0)
+                       __read_fdn_contacts(pb_get_info_resp->index_min, modem_plugin);
+       } else {
+               err("failed to get FDN info !!");
+       }
+}
+
+void __get_fdn_contacts_info(TcorePlugin *modem_plugin)
+{
+       struct treq_phonebook_get_info pb_get_info = { 0, };
+       gboolean ret = FALSE;
+
+       dbg("send PB get info request !!");
+
+       pb_get_info.phonebook_type = PB_TYPE_FDN;
+
+       ret = manager_util_send_request(modem_plugin, TREQ_PHONEBOOK_GETMETAINFO,
+                                       sizeof(pb_get_info), &pb_get_info, __on_resp_get_info_fdn, modem_plugin);
+
+       if (!ret)
+               err("Fail to send FDN get info !!");
+}
+
+static void __on_hook_change_fdn_status(UserRequest *ur, enum tcore_response_command command,
+                                       unsigned int data_len, const void *data, void *user_data)
+{
+       Server *server = (Server *)user_data;
+       TcorePlugin *modem_plugin = manager_util_get_modem_plugin(server, ur);
+
+       if (!modem_plugin || !server) {
+               err("NULL data : modem_plugin[%p], server[%p]", modem_plugin, server);
+               return;
+       }
+
+       if (TRESP_SIM_ENABLE_FACILITY == command) {
+               struct tresp_sim_enable_facility *enable_resp = (struct tresp_sim_enable_facility *)data;
+
+               if (enable_resp && SIM_PIN_OPERATION_SUCCESS == enable_resp->result) {
+                       info("FDN enabled, start caching FDN records !!");
+
+                       __process_fdn_change(modem_plugin, TRUE);
+               } else {
+                       err("Enable facility failed !!");
+               }
+       } else if (TRESP_SIM_DISABLE_FACILITY == command) {
+               struct tresp_sim_disable_facility *disable_resp = (struct tresp_sim_disable_facility *)data;
+
+               if (disable_resp && SIM_PIN_OPERATION_SUCCESS == disable_resp->result) {
+                       info("FDN disabled, clear FDN cache !!");
+
+                       __process_fdn_change(modem_plugin, FALSE);
+               } else {
+                       err("Disable facility failed !!");
+               }
+       } else {
+               err("Invalid response command [0x%x]", command);
+       }
+}
+static void __send_network_mode_request(TcorePlugin *plugin, int nw_mode)
+{
+       UserRequest *ur = NULL;
+       struct treq_network_set_mode req_data;
+       Server *s = tcore_plugin_ref_server(plugin);
+       TReturn ret = TCORE_RETURN_EINVAL;
+       const char *modem_name = tcore_server_get_cp_name_by_plugin(plugin);
+
+       if (!modem_name) {
+               err("modem name is null !!");
+               return;
+       }
+       info("Sending Netwok mode[%d] request to [%s]", nw_mode, modem_name);
+       req_data.mode = nw_mode;
+       ur = tcore_user_request_new(NULL, modem_name);
+       tcore_user_request_set_command(ur, TREQ_NETWORK_SET_MODE);
+       tcore_user_request_set_data(ur, sizeof(struct treq_network_set_mode), &req_data);
+       tcore_user_request_set_response_hook(ur, manager_network_resp_hook_set_network_mode, plugin);
+       ret = tcore_server_dispatch_request_ex(s, ur, TCORE_OPS_TYPE_CP);
+       if (ret != TCORE_RETURN_SUCCESS) {
+               err("Request cmd(0x%x) failed ret: [%d]", TREQ_NETWORK_SET_MODE, ret);
+               tcore_user_request_unref(ur);
+       }
+}
+
+static void __update_private_info(Manager *manager, CoreObject *co_sim, enum tel_sim_status sim_status)
+{
+       ModemBoard *mb = manager_core_get_modem_board(manager, tcore_object_ref_plugin(co_sim));
+
+       mb->sim_info->co_sim = co_sim;
+       mb->sim_info->sim_status = sim_status;
+
+}
+
+static gboolean __are_both_sims_ready_after_boot(Manager *manager)
+{
+       GSList *list = NULL;
+       TcorePlugin *manager_plugin = tcore_manager_get_plugin(manager);
+       PrivateData *priv_data = tcore_plugin_ref_user_data(manager_plugin);
+       enum tel_sim_status sim_status[2] ={};
+       enum modem_state modem_status[2] = {MODEM_STATE_UNKNOWN,MODEM_STATE_UNKNOWN};
+       gboolean ret = FALSE;
+
+       dbg("Enter");
+
+       if (G_UNLIKELY(!priv_data))
+               return FALSE;
+
+       if (priv_data->boot_config_completed)
+               return FALSE;
+
+       for (list = priv_data->board_list; list; list = list->next) {
+               int sim_index = -1;
+               ModemBoard *mb = list->data;
+               if (G_UNLIKELY(!mb))
+                       continue;
+               sim_index = manager_core_get_modem_board_index(tcore_object_ref_plugin(mb->sim_info->co_sim));
+               sim_status[sim_index] = mb->sim_info->sim_status;
+               modem_status[sim_index] = mb->modem_info->modem_status;
+       }
+       if (SIM_STATUS_INIT_COMPLETED == sim_status[0]) {
+               if (!(SIM_STATUS_UNKNOWN == sim_status[1] || SIM_STATUS_INITIALIZING == sim_status[1]))
+                       ret = TRUE;
+       } else if (SIM_STATUS_INIT_COMPLETED == sim_status[1]) {
+               if (!(SIM_STATUS_UNKNOWN == sim_status[0] || SIM_STATUS_INITIALIZING == sim_status[0]))
+                       ret = TRUE;
+       }
+       dbg("sim_status1[%d], sim_status2[%d], ret[%s]", sim_status[0], sim_status[1], ret ? "TRUE" : "FALSE");
+       dbg("modem_status1[%d], modem_status2[%d]", modem_status[0], modem_status[1]);
+       if(ret && (modem_status[0] == MODEM_STATE_UNKNOWN || modem_status[1] == MODEM_STATE_UNKNOWN))
+               ret = FALSE;
+       if(ret) {
+               dbg("sim_status for both cards recieved");
+               if ( SIM_STATUS_INIT_COMPLETED ==  sim_status[0] && SIM_STATUS_INIT_COMPLETED == sim_status[1])
+                       ret = TRUE;
+               else if(SIM_STATUS_INIT_COMPLETED == sim_status[1]  && __expect_other_sim_init(sim_status[0]))
+                       ret = FALSE;
+               else if(SIM_STATUS_INIT_COMPLETED ==  sim_status[0] && __expect_other_sim_init(sim_status[1]))
+                       ret = FALSE;
+       }
+       if(ret)
+               priv_data->boot_config_completed = TRUE;
+       dbg("ret[%d]",ret);
+       return ret;
+}
+
+static gchar* __generate_hash(gchar *txt)
+{
+       gchar *txt_hash = NULL;
+       SHA256_CTX ctx;
+       unsigned char md[SHA256_DIGEST_LENGTH];
+       int i;
+
+       if (g_strcmp0((const char *)txt, "") == 0) {
+               return txt_hash;
+       }
+       SHA256_Init(&ctx);
+       SHA256_Update(&ctx, txt, strlen(txt));
+       SHA256_Final(md, &ctx);
+       txt_hash = g_malloc0(SHA256_DIGEST_LENGTH * 2 + 1);
+       for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
+               snprintf(txt_hash + (i * 2), 3, "%02x", md[i]);
+       return txt_hash;
+}
+
+#ifdef TIZEN_SUPPORT_SIM_PREFERRED_SUBSCRIPTION
+static char *__find_imsi_hash(CoreObject *co_sim)
+{
+
+       struct tel_sim_imsi *imsi_info = NULL;
+       char *imsi = NULL;
+       char *imsi_db_key = NULL;
+       if(!co_sim) {
+               err("co_sim is NULL");
+               return NULL;
+       }
+       imsi_info = (struct tel_sim_imsi *)tcore_sim_get_imsi(co_sim);
+       if (imsi_info != NULL) {
+               imsi = g_strdup_printf("%s%s",
+                                      imsi_info->plmn, imsi_info->msin);
+               dbg("imsi is %s", imsi);
+               imsi_db_key = __generate_hash(imsi);
+               g_free(imsi);
+               g_free(imsi_info);
+       }
+       return imsi_db_key;
+}
+#endif
+
+/* Return nw_mode if present in DB otherwise -1*/
+static int __find_nw_mode(TcorePlugin *modem_plugin)
+{
+#ifdef TIZEN_SUPPORT_SIM_PREFERRED_SUBSCRIPTION
+       int nw_mode = -1;
+       GHashTable *in_param, *out_param;
+       Storage *strg = NULL;
+       gpointer handle;
+       char szQuery[3000];
+       gboolean rv = FALSE;
+       GHashTableIter iter;
+       gpointer key, value;
+       Server *s;
+       char *imsi_db_key;
+
+       s = tcore_plugin_ref_server(modem_plugin);
+       imsi_db_key = __find_imsi_hash(tcore_plugin_ref_core_object(modem_plugin, CORE_OBJECT_TYPE_SIM));
+       if (!imsi_db_key)
+               return nw_mode;
+
+       strg = tcore_server_find_storage(s, "database");
+       if (strg == NULL) {
+               err("Storage is NULL");
+               g_free(imsi_db_key);
+               return -1;
+       }
+
+       handle = tcore_storage_create_handle(strg, SIM_PREF_DB_PATH);
+       if (handle == NULL) {
+               err("Failed to get Storage handle");
+               g_free(imsi_db_key);
+               return -1;
+       }
+
+       in_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
+       g_hash_table_insert(in_param, "1", g_strdup(imsi_db_key));
+
+       memset(szQuery, 0x0, sizeof(szQuery));
+       snprintf(szQuery, sizeof(szQuery), "%s",
+                "select nw_mode from network_mode where imsi_hash = ?");
+
+       rv = tcore_storage_read_query_database(strg, handle, szQuery, in_param, &out_param, 1);
+       info("Read Database: [%s]", (rv == TRUE ? "SUCCESS" : "FAIL"));
+
+       g_hash_table_iter_init(&iter, out_param);
+       while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+               GHashTableIter iter2;
+               gpointer key2, value2;
+
+               if (value) {
+                       g_hash_table_iter_init(&iter2, (GHashTable *)value);
+                       while (g_hash_table_iter_next(&iter2, &key2, &value2) == TRUE) {
+                               if (g_str_equal(key2, "0") == TRUE) {
+                                       if (!value2 || (g_strcmp0((const char *)value2, "") == 0))
+                                               nw_mode = -1;
+                                       else
+                                               nw_mode = atoi((const char *)value2);
+
+                                       /* TODO - Check this logic */
+                                       break;
+                               }
+                       }
+               }
+       }
+       g_free(imsi_db_key);
+       return nw_mode;
+#else
+       info("SIM PREFERRED SUBSCRIPTION on DB is not supported");
+       return -1;
+#endif
+}
+
+static gboolean __add_nw_mode(TcorePlugin *modem_plugin, int nw_mode)
+{
+#ifdef TIZEN_SUPPORT_SIM_PREFERRED_SUBSCRIPTION
+       GHashTable *in_param;
+       Storage *strg_db = NULL;
+       gpointer handle;
+       char szQuery[3000];
+       gboolean rv = FALSE;
+       Server *s;
+       char *imsi_db_key;
+
+       s = tcore_plugin_ref_server(modem_plugin);
+       imsi_db_key = __find_imsi_hash(tcore_plugin_ref_core_object(modem_plugin, CORE_OBJECT_TYPE_SIM));
+       if (imsi_db_key) {
+               strg_db = tcore_server_find_storage(s, "database");
+               handle = tcore_storage_create_handle(strg_db, SIM_PREF_DB_PATH);
+               if (handle == NULL) {
+                       err("Failed to get Storage handle");
+                       g_free(imsi_db_key);
+                       return rv;
+               }
+
+               in_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
+               g_hash_table_insert(in_param, "1",
+                                   g_strdup(imsi_db_key));
+               g_hash_table_insert(in_param, "2",
+                                   g_strdup_printf("%d", nw_mode));
+
+
+               memset(szQuery, 0x0, sizeof(szQuery));
+               snprintf(szQuery, sizeof(szQuery), "%s",
+                        "insert or replace into network_mode values(?,?)");
+
+               rv = tcore_storage_update_query_database(strg_db, handle, szQuery, in_param);
+               info("Update Database: [%s]", (rv == TRUE ? "SUCCESS" : "FAIL"));
+
+               /* Free resources */
+               g_hash_table_destroy(in_param);
+
+               /* De-initialize Storage */
+               tcore_storage_remove_handle(strg_db, handle);
+
+               g_free(imsi_db_key);
+       }
+
+       return rv;
+#else
+       info("SIM PREFERRED SUBSCRIPTION on DB is not supported");
+       return TRUE;
+#endif 
+}
+
+#if 0
+static gboolean __update_dds_rank(Server *s, char *imsi_db_key, int dds_rank)
+{
+       GHashTable *in_param;
+       Storage *strg_db = NULL;
+       gpointer handle;
+       char szQuery[3000];
+       gboolean rv = FALSE;
+
+       strg_db = tcore_server_find_storage(s, "database");
+       handle = tcore_storage_create_handle(strg_db, SIM_PREF_DB_PATH);
+       if (handle == NULL) {
+               err("Failed to get Storage handle");
+               return rv;
+       }
+
+       in_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
+       g_hash_table_insert(in_param, "1",
+                           g_strdup_printf("%d", dds_rank));
+       g_hash_table_insert(in_param, "2",
+                           g_strdup(imsi_db_key));
+
+
+       memset(szQuery, 0x0, sizeof(szQuery));
+       snprintf(szQuery, sizeof(szQuery), "%s",
+                "update dds set \
+               rank = ? \
+               where imsi_hash = ?");
+
+       rv = tcore_storage_update_query_database(strg_db, handle, szQuery, in_param);
+       info("Update Database: [%s]", (rv == TRUE ? "SUCCESS" : "FAIL"));
+
+       /* Free resources */
+       g_hash_table_destroy(in_param);
+
+       /* De-initialize Storage */
+       tcore_storage_remove_handle(strg_db, handle);
+
+       return rv;
+}
+#endif
+
+static void __on_resp_get_netmode(UserRequest *ur,
+                                                   enum tcore_response_command command,
+                                                   unsigned int data_len, const void *data, void *user_data)
+{
+       const struct tresp_network_get_mode *resp = data;
+       int req_nw_mode = *(int *)tcore_user_request_ref_data(ur, NULL);
+       int existing_mode = -1;
+       TcorePlugin *plugin = user_data;
+
+       if (!resp || resp->result != TCORE_RETURN_SUCCESS) {
+               warn("GET_MODE fail");
+       }
+       else
+               existing_mode = resp->mode;
+
+       info("req_nw_mode = [%d], existing_network_mode:[%d]", req_nw_mode, existing_mode);
+       if (req_nw_mode != existing_mode) {
+               __send_network_mode_request(plugin, req_nw_mode);
+       } else {
+               info("updating DB if in case this is the first time");
+               __add_nw_mode(plugin, req_nw_mode);
+       }
+
+}
+
+static void __get_n_set_network_mode(TcorePlugin *plugin, int nw_mode)
+{
+       UserRequest *ur = NULL;
+       Server *s = tcore_plugin_ref_server(plugin);
+       TReturn ret = TCORE_RETURN_EINVAL;
+       const char *modem_name = tcore_server_get_cp_name_by_plugin(plugin);
+
+       if (!modem_name) {
+               err("modem name is null !!");
+               return;
+       }
+       info("Sending Netwok mode[%d] request to [%s]", nw_mode, modem_name);
+
+       ur = tcore_user_request_new(NULL, modem_name);
+       tcore_user_request_set_command(ur, TREQ_NETWORK_GET_MODE);
+       tcore_user_request_set_data(ur, sizeof(int), &nw_mode);
+       tcore_user_request_set_response_hook(ur, __on_resp_get_netmode, plugin);
+       ret = tcore_server_dispatch_request_ex(s, ur, TCORE_OPS_TYPE_CP);
+       if (ret != TCORE_RETURN_SUCCESS) {
+               err("Request cmd(0x%x) failed ret: [%d]", TREQ_NETWORK_GET_MODE, ret);
+               tcore_user_request_unref(ur);
+       }
+}
+
+#ifdef TIZEN_SUPPORT_SIM_PREFERRED_SUBSCRIPTION
+/* returns rank 0 if imsi_db_key is not present in db*/
+static int __find_dds_rank(TcorePlugin *modem_plugin)
+{
+       int dds_rank = 0;
+       GHashTable *in_param, *out_param;
+       Storage *strg = NULL;
+       gpointer handle;
+       char szQuery[3000];
+       gboolean rv = FALSE;
+       GHashTableIter iter;
+       gpointer key, value;
+       Server *s;
+       char *imsi_db_key;
+
+       s = tcore_plugin_ref_server(modem_plugin);
+       imsi_db_key = __find_imsi_hash(tcore_plugin_ref_core_object(modem_plugin, CORE_OBJECT_TYPE_SIM));
+       if (!imsi_db_key)
+               return -1;
+
+       strg = tcore_server_find_storage(s, "database");
+       handle = tcore_storage_create_handle(strg, SIM_PREF_DB_PATH);
+       if (handle == NULL) {
+               err("Failed to get Storage handle");
+               g_free(imsi_db_key);
+               return -1;
+       }
+
+       in_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
+       g_hash_table_insert(in_param, "1", g_strdup(imsi_db_key));
+
+       memset(szQuery, 0x0, sizeof(szQuery));
+       snprintf(szQuery, sizeof(szQuery), "%s",
+                "select rank from dds where imsi_hash = ?");
+
+       rv = tcore_storage_read_query_database(strg, handle, szQuery, in_param, &out_param, 1);
+       info("Read Database: [%s]", (rv == TRUE ? "SUCCESS" : "FAIL"));
+
+       g_hash_table_iter_init(&iter, out_param);
+       while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+               GHashTableIter iter2;
+               gpointer key2, value2;
+
+               if (value) {
+                       g_hash_table_iter_init(&iter2, (GHashTable *)value);
+                       while (g_hash_table_iter_next(&iter2, &key2, &value2) == TRUE) {
+                               if (g_str_equal(key2, "0") == TRUE) {
+                                       if (!value2 || (g_strcmp0((const char *)value2, "") == 0))
+                                               dds_rank = 0;
+                                       else
+                                               dds_rank = atoi((const char *)value2);
+
+                                       /* TODO - Check this logic */
+                                       break;
+                               }
+                       }
+               }
+       }
+       g_free(imsi_db_key);
+       return dds_rank;
+}
+
+/*returns 0 if no entries are present*/
+static int __find_max_dds_rank(TcorePlugin *modem_plugin)
+{
+       int dds_rank = 0;
+       GHashTable *in_param, *out_param;
+       Storage *strg = NULL;
+       gpointer handle;
+       char szQuery[3000];
+       gboolean rv = FALSE;
+       GHashTableIter iter;
+       gpointer key, value;
+       Server *s;
+
+       s = tcore_plugin_ref_server(modem_plugin);
+
+       strg = tcore_server_find_storage(s, "database");
+       handle = tcore_storage_create_handle(strg, SIM_PREF_DB_PATH);
+       if (handle == NULL) {
+               err("Failed to get Storage handle");
+               return -1;
+       }
+
+       in_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
+
+       memset(szQuery, 0x0, sizeof(szQuery));
+       snprintf(szQuery, sizeof(szQuery), "%s",
+                "select max(rank) from dds");
+
+       rv = tcore_storage_read_query_database(strg, handle, szQuery, in_param, &out_param, 1);
+       info("Read Database: [%s]", (rv == TRUE ? "SUCCESS" : "FAIL"));
+
+       g_hash_table_iter_init(&iter, out_param);
+       while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+               GHashTableIter iter2;
+               gpointer key2, value2;
+
+               if (value) {
+                       g_hash_table_iter_init(&iter2, (GHashTable *)value);
+                       while (g_hash_table_iter_next(&iter2, &key2, &value2) == TRUE) {
+                               if (g_str_equal(key2, "0") == TRUE) {
+                                       if (!value2 || (g_strcmp0((const char *)value2, "") == 0))
+                                               dds_rank = 0;
+                                       else
+                                               dds_rank = atoi((const char *)value2);
+
+                                       /* TODO - Check this logic */
+                                       break;
+                               }
+                       }
+               }
+       }
+       return dds_rank;
+}
+
+static gboolean __add_dds_rank(TcorePlugin *modem_plugin, int dds_rank)
+{
+       GHashTable *in_param;
+       Storage *strg_db = NULL;
+       gpointer handle;
+       char szQuery[3000];
+       gboolean rv = FALSE;
+       Server *s;
+       char *imsi_db_key;
+
+       s = tcore_plugin_ref_server(modem_plugin);
+       imsi_db_key = __find_imsi_hash(tcore_plugin_ref_core_object(modem_plugin, CORE_OBJECT_TYPE_SIM));
+       if (!imsi_db_key)
+               return FALSE;
+
+       strg_db = tcore_server_find_storage(s, "database");
+       handle = tcore_storage_create_handle(strg_db, SIM_PREF_DB_PATH);
+       if (handle == NULL) {
+               err("Failed to get Storage handle");
+               g_free(imsi_db_key);
+               return rv;
+       }
+
+       in_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
+       g_hash_table_insert(in_param, "1",
+                           g_strdup(imsi_db_key));
+       g_hash_table_insert(in_param, "2",
+                           g_strdup_printf("%d", dds_rank));
+
+
+       memset(szQuery, 0x0, sizeof(szQuery));
+       snprintf(szQuery, sizeof(szQuery), "%s",
+                "insert or replace into dds values(?,?)");
+
+       rv = tcore_storage_update_query_database(strg_db, handle, szQuery, in_param);
+       info("Update Database: [%s]", (rv == TRUE ? "SUCCESS" : "FAIL"));
+
+       /* Free resources */
+       g_hash_table_destroy(in_param);
+
+       /* De-initialize Storage */
+       tcore_storage_remove_handle(strg_db, handle);
+       g_free(imsi_db_key);
+       return rv;
+}
+
+static int __find_ds_rank_with_hash(Server *s, char *hash_key)
+{
+       int ds_rank = 0;
+       GHashTable *in_param, *out_param;
+       Storage *strg = NULL;
+       gpointer handle;
+       char szQuery[3000];
+       gboolean rv = FALSE;
+       GHashTableIter iter;
+       gpointer key, value;
+
+
+       strg = tcore_server_find_storage(s, "database");
+       handle = tcore_storage_create_handle(strg, SIM_PREF_DB_PATH);
+       if (handle == NULL) {
+               err("Failed to get Storage handle");
+               return -1;
+       }
+
+       in_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
+       g_hash_table_insert(in_param, "1", g_strdup(hash_key));
+
+       memset(szQuery, 0x0, sizeof(szQuery));
+       snprintf(szQuery, sizeof(szQuery), "%s",
+                "select rank from call_sms_pref where imsi_hash = ?");
+
+       rv = tcore_storage_read_query_database(strg, handle, szQuery, in_param, &out_param, 1);
+       info("Read Database: [%s]", (rv == TRUE ? "SUCCESS" : "FAIL"));
+       g_hash_table_destroy(in_param);
+
+       g_hash_table_iter_init(&iter, out_param);
+       while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+               GHashTableIter iter2;
+               gpointer key2, value2;
+
+               if (value) {
+                       g_hash_table_iter_init(&iter2, (GHashTable *)value);
+                       while (g_hash_table_iter_next(&iter2, &key2, &value2) == TRUE) {
+                               if (g_str_equal(key2, "0") == TRUE) {
+                                       if (!value2 || (g_strcmp0((const char *)value2, "") == 0))
+                                               ds_rank = 0;
+                                       else
+                                               ds_rank = atoi((const char *)value2);
+
+                                       /* TODO - Check this logic */
+                                       break;
+                               }
+                       }
+               }
+       }
+       return ds_rank;
+}
+static int __find_ds_rank(TcorePlugin *modem_plugin)
+{
+       int ds_rank = 0;
+       Server *s;
+       char *imsi_db_key;
+
+       s = tcore_plugin_ref_server(modem_plugin);
+       imsi_db_key = __find_imsi_hash(tcore_plugin_ref_core_object(modem_plugin, CORE_OBJECT_TYPE_SIM));
+
+       ds_rank = __find_ds_rank_with_hash( s, imsi_db_key);
+       return ds_rank;
+}
+
+/*returns 0 if no entries are present*/
+static int __find_max_ds_rank(Server *s)
+{
+       int ds_rank = 0;
+       GHashTable *in_param, *out_param;
+       Storage *strg = NULL;
+       gpointer handle;
+       char szQuery[3000];
+       gboolean rv = FALSE;
+       GHashTableIter iter;
+       gpointer key, value;
+
+       strg = tcore_server_find_storage(s, "database");
+       handle = tcore_storage_create_handle(strg, SIM_PREF_DB_PATH);
+       if (handle == NULL) {
+               err("Failed to get Storage handle");
+               return -1;
+       }
+
+       in_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
+
+       memset(szQuery, 0x0, sizeof(szQuery));
+       snprintf(szQuery, sizeof(szQuery), "%s",
+                "select max(rank) from call_sms_pref");
+
+       rv = tcore_storage_read_query_database(strg, handle, szQuery, in_param, &out_param, 1);
+       info("Read Database: [%s]", (rv == TRUE ? "SUCCESS" : "FAIL"));
+       g_hash_table_destroy(in_param);
+
+       g_hash_table_iter_init(&iter, out_param);
+       while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+               GHashTableIter iter2;
+               gpointer key2, value2;
+
+               if (value) {
+                       g_hash_table_iter_init(&iter2, (GHashTable *)value);
+                       while (g_hash_table_iter_next(&iter2, &key2, &value2) == TRUE) {
+                               if (g_str_equal(key2, "0") == TRUE) {
+                                       if (!value2 || (g_strcmp0((const char *)value2, "") == 0))
+                                               ds_rank = 0;
+                                       else
+                                               ds_rank = atoi((const char *)value2);
+
+                                       /* TODO - Check this logic */
+                                       break;
+                               }
+                       }
+               }
+       }
+       return ds_rank;
+}
+
+static gboolean __update_ds_rank_for_key(Server *s, char *key,int ds_rank)
+{
+       GHashTable *in_param;
+       Storage *strg_db = NULL;
+       gpointer handle;
+       char szQuery[3000];
+       gboolean rv = FALSE;
+
+       strg_db = tcore_server_find_storage(s, "database");
+       handle = tcore_storage_create_handle(strg_db, SIM_PREF_DB_PATH);
+       if (handle == NULL) {
+               err("Failed to get Storage handle");
+               return rv;
+       }
+
+       in_param = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
+       g_hash_table_insert(in_param, "1",
+                           g_strdup(key));
+       g_hash_table_insert(in_param, "2",
+                           g_strdup_printf("%d", ds_rank));
+
+
+       memset(szQuery, 0x0, sizeof(szQuery));
+       snprintf(szQuery, sizeof(szQuery), "%s",
+                "insert or replace into call_sms_pref values(?,?)");
+
+       rv = tcore_storage_update_query_database(strg_db, handle, szQuery, in_param);
+       info("Update Database: [%s]", (rv == TRUE ? "SUCCESS" : "FAIL"));
+
+       /* Free resources */
+       g_hash_table_destroy(in_param);
+
+       /* De-initialize Storage */
+       tcore_storage_remove_handle(strg_db, handle);
+       return rv;
+}
+
+static gboolean __add_ds_rank(TcorePlugin *modem_plugin, int ds_rank)
+{
+       gboolean rv = FALSE;
+       Server *s;
+       char *imsi_db_key;
+
+       s = tcore_plugin_ref_server(modem_plugin);
+       imsi_db_key = __find_imsi_hash(tcore_plugin_ref_core_object(modem_plugin, CORE_OBJECT_TYPE_SIM));
+       if(imsi_db_key) {
+               rv = __update_ds_rank_for_key( s, imsi_db_key, ds_rank);
+               g_free(imsi_db_key);
+       }
+       else
+               dbg("imsi_db_key is NULL");
+       return rv;
+}
+#else
+/* returns rank 0 if imsi_db_key is not present in db*/
+static int __find_dds_rank(TcorePlugin *modem_plugin)
+{
+       info("SIM PREFERRED SUBSCRIPTION on DB is not supported");
+       return 0;
+}
+
+/*returns 0 if no entries are present*/
+static int __find_max_dds_rank(TcorePlugin *modem_plugin)
+{
+       info("SIM PREFERRED SUBSCRIPTION on DB is not supported");
+       return 0;
+}
+
+static gboolean __add_dds_rank(TcorePlugin *modem_plugin, int dds_rank)
+{
+       info("SIM PREFERRED SUBSCRIPTION on DB is not supported");
+       return FALSE;
+}
+
+static int __find_ds_rank_with_hash(Server *s, char *hash_key)
+{
+       info("SIM PREFERRED SUBSCRIPTION on DB is not supported");
+       return 0;
+}
+
+static int __find_ds_rank(TcorePlugin *modem_plugin)
+{
+       info("SIM PREFERRED SUBSCRIPTION on DB is not supported");
+       return 0;
+}
+
+/*returns 0 if no entries are present*/
+static int __find_max_ds_rank(Server *s)
+{
+       info("SIM PREFERRED SUBSCRIPTION on DB is not supported");
+       return 0;
+}
+
+static gboolean __update_ds_rank_for_key(Server *s, char *key,int ds_rank)
+{
+       info("SIM PREFERRED SUBSCRIPTION on DB is not supported");
+       return FALSE;
+}
+
+static gboolean __add_ds_rank(TcorePlugin *modem_plugin, int ds_rank)
+{
+       info("SIM PREFERRED SUBSCRIPTION on DB is not supported");
+       return FALSE;
+}
+
+#endif
+
+gboolean manager_sim_initialize_private_info(ModemBoard *mb)
+{
+       if (G_UNLIKELY(!mb))
+               return FALSE;
+
+       if (mb->sim_info)
+               mb->sim_info->sim_status = SIM_STATUS_UNKNOWN;
+
+       mb->sim_info = g_try_malloc0(sizeof(struct manager_sim_private_info));
+       mb->sim_info->co_sim = tcore_plugin_ref_core_object(mb->modem_plugin, CORE_OBJECT_TYPE_SIM);
+       mb->sim_info->sim_status = SIM_STATUS_UNKNOWN;
+       mb->sim_info->is_first_boot = TRUE;
+
+       dbg("Initialized sim private info");
+       return TRUE;
+}
+
+void manager_network_resp_hook_set_network_mode(UserRequest *ur,
+                                               enum tcore_response_command command,
+                                               unsigned int data_len, const void *data, void *user_data)
+{
+
+       TcorePlugin *plugin = (TcorePlugin *)user_data;
+       struct tresp_network_set_mode *resp = (struct tresp_network_set_mode *)data;
+       int nw_mode = ((struct treq_network_set_mode *)tcore_user_request_ref_data(ur, NULL))->mode;
+
+       if (resp && resp->result == TCORE_RETURN_SUCCESS) {
+               __add_nw_mode(plugin, nw_mode);
+               info("nw_mode[%d], resp->result is %d", nw_mode, resp->result);
+       } else {
+               err("resp is [%p]", resp);
+       }
+}
+
+void manager_network_resp_hook_set_dds(UserRequest *ur,
+                                      enum tcore_response_command command,
+                                      unsigned int data_len, const void *data, void *user_data)
+{
+       TcorePlugin *modem_plugin = (TcorePlugin *)user_data;
+       int subs_id = manager_core_get_modem_board_index(modem_plugin);
+       struct tresp_network_set_default_data_subscription *resp = (struct tresp_network_set_default_data_subscription *)data;
+
+       if (resp->result == TCORE_RETURN_SUCCESS) {
+               info("updating rank for [%d]", subs_id);
+               __add_dds_rank(modem_plugin, __find_max_dds_rank(modem_plugin) + 1);
+       } else
+               dbg("resp->result is %d", resp->result);
+}
+
+void manager_network_resp_hook_set_ds(UserRequest *ur,
+                                     enum tcore_response_command command,
+                                     unsigned int data_len, const void *data, void *user_data)
+{
+       const struct treq_call_set_preferred_voice_subscription *req;
+       enum telephony_call_preferred_voice_subs pref_subs;
+       Server *server  = (Server*)user_data;
+       struct tresp_call_set_preferred_voice_subscription *resp = (struct tresp_call_set_preferred_voice_subscription *)data;
+       int max_ds_rank;
+
+       if (resp->err == CALL_ERROR_NONE) {
+               req = tcore_user_request_ref_data(ur, NULL);
+               if (NULL != req) {
+                       pref_subs = req->preferred_subs;
+                       max_ds_rank = __find_max_ds_rank(server);
+                       info("updating rank for [%d], max_ds_rank [%d]", pref_subs, max_ds_rank);
+                       if (pref_subs == CALL_PREFERRED_VOICE_SUBS_ASK_ALWAYS) {
+                               char *always_ask_hash = __generate_hash(CALL_MSG_PREF_ALWAYS_ASK);
+                               if(always_ask_hash) {
+                                       __update_ds_rank_for_key(server, always_ask_hash, max_ds_rank+1);
+                                       info("updated rank for always ask with hash -%s", always_ask_hash);
+                                       g_free(always_ask_hash);
+                               }
+                       }
+                       else{
+                               TcorePlugin *modem_plugin;
+                               enum telephony_subscription_type subs_type;
+
+                               subs_type = ((pref_subs == CALL_PREFERRED_VOICE_SUBS_SIM1) ?
+                                       TELEPHONY_SUBSCRIPTION_TYPE_PRIMARY : TELEPHONY_SUBSCRIPTION_TYPE_SECONDARY);
+                               modem_plugin = manager_util_get_modem_plugin_by_subs_type(server, subs_type);
+                               __add_ds_rank(modem_plugin, max_ds_rank+1);
+                       }
+               }
+       } else
+               dbg("resp->error is %d", resp->err);
+}
+
+static void __send_dds_request(TcorePlugin *plugin )
+{
+       UserRequest *ur = NULL;
+       Server *s = tcore_plugin_ref_server(plugin);
+       TReturn ret = TCORE_RETURN_EINVAL;
+       const char *modem_name = tcore_server_get_cp_name_by_plugin(plugin);
+
+       if (!modem_name) {
+               err("modem name is null !!");
+               return;
+       }
+       info("Sending dds request to [%s]", modem_name);
+       ur = tcore_user_request_new(NULL, modem_name);
+       tcore_user_request_set_command(ur, TREQ_NETWORK_SET_DEFAULT_DATA_SUBSCRIPTION);
+       tcore_user_request_set_response_hook(ur, manager_network_resp_hook_set_dds, plugin);
+       ret = tcore_server_dispatch_request(s, ur);
+       if (ret != TCORE_RETURN_SUCCESS) {
+               err("Request cmd(0x%x) failed ret: [%d]", TREQ_NETWORK_SET_MODE, ret);
+               tcore_user_request_unref(ur);
+       }
+}
+
+static void __send_ds_request(Server *s, enum telephony_call_preferred_voice_subs preferred_subs)
+{
+       UserRequest *ur = NULL;
+       TReturn ret = TCORE_RETURN_EINVAL;
+       struct treq_call_set_preferred_voice_subscription req_data;
+       const char *modem_name = tcore_server_get_cp_name_by_plugin( manager_util_get_modem_plugin_by_subs_type(s, 0));
+       if (!modem_name) {
+               err("modem name is null !!");
+               return;
+       }
+       info("Sending ds request to [%d]", preferred_subs);
+
+       req_data.preferred_subs = preferred_subs;
+       ur = tcore_user_request_new(NULL, modem_name);
+       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_data);
+       tcore_user_request_set_response_hook(ur, manager_network_resp_hook_set_ds, s);
+       ret = tcore_server_dispatch_request_ex(s, ur, TCORE_OPS_TYPE_CP);
+       if (ret != TCORE_RETURN_SUCCESS) {
+               err("Request cmd(0x%x) failed ret: [%d]", TREQ_CALL_SET_PREFERRED_VOICE_SUBSCRIPTION, ret);
+               tcore_user_request_unref(ur);
+       }
+       else
+               info("sent ds request to [%d]", preferred_subs);
+}
+
+
+static void __network_mode_set_on_boot(Manager *manager)
+{
+
+       GSList *modems, *iter;
+       TcorePlugin *modem_plugin = NULL;
+       int nw_mode[2] = { -2, -2}; // Initialised to -2 i.e SIM's are not present
+       ModemBoard *mb = NULL;
+       Server *s = tcore_plugin_ref_server(tcore_manager_get_plugin(manager));
+       enum telephony_subscription_type sim_index = TELEPHONY_SUBSCRIPTION_TYPE_DEFAULT;
+
+       info("Both SIM status received, process network mode...");
+       modems = tcore_server_get_modem_plugin_list(s);
+
+       for (iter = modems; iter != NULL; iter = iter->next) {
+               modem_plugin = iter->data;
+               if (!modem_plugin) {
+                       err("Modem plugin is null !!");
+                       continue;
+               }
+               sim_index = manager_core_get_modem_board_index(modem_plugin);
+               mb = manager_core_get_modem_board(manager, modem_plugin);
+
+               if (mb->sim_info->sim_status == SIM_STATUS_INIT_COMPLETED) {
+                       nw_mode[sim_index] = __find_nw_mode(modem_plugin);
+               }
+       }
+
+       /*if both sim cards are present*/
+       if (nw_mode[0] !=-2 && nw_mode[1] !=-2) {
+               /* if both sims are new in DB*/
+               if(nw_mode[0] == -1 && nw_mode[1] == -1) {
+                       nw_mode[0] = NETWORK_MODE_GSM | NETWORK_MODE_WCDMA | NETWORK_MODE_LTE;
+                       nw_mode[1] = NETWORK_MODE_GSM;
+               }
+               /* if SIM1 is new in DB*/
+               else if(nw_mode[0] == -1) {
+                       /*if SIM2 is not GSM set SIM1 is set to GSM*/
+                       if(nw_mode[1] != NETWORK_MODE_GSM )
+                               nw_mode[0] = NETWORK_MODE_GSM;
+                       else
+                               nw_mode[0] = NETWORK_MODE_GSM | NETWORK_MODE_WCDMA | NETWORK_MODE_LTE;
+               }
+               /* Similar to above case */
+               else if(nw_mode[1] == -1) {
+                       if(nw_mode[0] != NETWORK_MODE_GSM )
+                               nw_mode[1] = NETWORK_MODE_GSM;
+                       else
+                               nw_mode[1] = NETWORK_MODE_GSM | NETWORK_MODE_WCDMA | NETWORK_MODE_LTE;
+               }
+               /* if atleast one of them is not GSM downgrade 2nd SIM to GSM*/
+               else if (!(nw_mode[0] == NETWORK_MODE_GSM || nw_mode[1] == NETWORK_MODE_GSM)) {
+                       nw_mode[1] = NETWORK_MODE_GSM;
+               }
+       }
+       /*if SIM1 is not present and SIM2 is new, default is AUTO LTE*/
+       else if ( nw_mode[0] == -2) {
+               if (nw_mode[1] == -1)
+                       nw_mode[1] = NETWORK_MODE_GSM | NETWORK_MODE_WCDMA | NETWORK_MODE_LTE;
+       }
+       /*if SIM2 is not present and SIM1 is new, default is AUTO LTE*/
+       else if (nw_mode[1] == -2) {
+               if (nw_mode[0] == -1)
+                       nw_mode[0] = NETWORK_MODE_GSM | NETWORK_MODE_WCDMA | NETWORK_MODE_LTE;
+       }
+
+       for (iter = modems; iter != NULL; iter = iter->next) {
+               modem_plugin = iter->data;
+               if (!modem_plugin) {
+                       err("Modem plugin is null !!");
+                       continue;
+               }
+               sim_index = manager_core_get_modem_board_index(modem_plugin);
+               mb = manager_core_get_modem_board(manager, modem_plugin);
+
+               if (mb->sim_info->sim_status == SIM_STATUS_INIT_COMPLETED) {
+                       __get_n_set_network_mode(modem_plugin, nw_mode[sim_index]);
+               }
+       }
+       g_slist_free(modems);
+
+}
+
+static void __dds_set_on_boot(Manager *manager)
+{
+
+       GSList *modems, *iter;
+       TcorePlugin *modem_plugin = NULL;
+       int dds_rank[TELEPHONY_SUBSCRIPTION_TYPE_MAX] = { -1, -1 };
+       ModemBoard *mb = NULL;
+       Server *s = tcore_plugin_ref_server(tcore_manager_get_plugin(manager));
+       enum telephony_subscription_type sim_index = TELEPHONY_SUBSCRIPTION_TYPE_DEFAULT;
+       TcorePlugin *modem_plugins[TELEPHONY_SUBSCRIPTION_TYPE_MAX] = {};
+       int subs_id = TELEPHONY_SUBSCRIPTION_TYPE_DEFAULT;
+
+       info("Both SIM status received, process dds...");
+       modems = tcore_server_get_modem_plugin_list(s);
+
+       for (iter = modems; iter != NULL; iter = iter->next) {
+               modem_plugin = iter->data;
+               if (!modem_plugin) {
+                       err("Modem plugin is null !!");
+                       continue;
+               }
+               sim_index = manager_core_get_modem_board_index(modem_plugin);
+               mb = manager_core_get_modem_board(manager, modem_plugin);
+
+               if (mb->sim_info->sim_status == SIM_STATUS_INIT_COMPLETED)
+                       dds_rank[sim_index] = __find_dds_rank(modem_plugin);
+
+               modem_plugins[sim_index] = modem_plugin;
+       }
+       g_slist_free(modems);
+
+       info("dds_rank[0]=[%d] && dds_rank[1]=[%d] ", dds_rank[TELEPHONY_SUBSCRIPTION_TYPE_PRIMARY], dds_rank[TELEPHONY_SUBSCRIPTION_TYPE_SECONDARY]);
+       if (dds_rank[TELEPHONY_SUBSCRIPTION_TYPE_PRIMARY] == -1 && dds_rank[1] == -1) {
+               /*TODO: what if both sims are not present*/
+       } else if (dds_rank[TELEPHONY_SUBSCRIPTION_TYPE_PRIMARY] == -1)
+               subs_id = TELEPHONY_SUBSCRIPTION_TYPE_SECONDARY;
+       else if (dds_rank[TELEPHONY_SUBSCRIPTION_TYPE_SECONDARY] == -1)
+               subs_id = TELEPHONY_SUBSCRIPTION_TYPE_PRIMARY;
+       else if (dds_rank[TELEPHONY_SUBSCRIPTION_TYPE_PRIMARY] && dds_rank[TELEPHONY_SUBSCRIPTION_TYPE_SECONDARY]) {
+               if (dds_rank[TELEPHONY_SUBSCRIPTION_TYPE_PRIMARY] > dds_rank[TELEPHONY_SUBSCRIPTION_TYPE_SECONDARY])
+                       subs_id = TELEPHONY_SUBSCRIPTION_TYPE_PRIMARY;
+               else if(dds_rank[TELEPHONY_SUBSCRIPTION_TYPE_PRIMARY] < dds_rank[TELEPHONY_SUBSCRIPTION_TYPE_SECONDARY])
+                       subs_id = TELEPHONY_SUBSCRIPTION_TYPE_SECONDARY;
+               //In case of same rank, setting DDS based on previous boot setting.
+               else {
+                       int vconf_ret;
+
+                       vconf_ret = vconf_get_int(VCONFKEY_TELEPHONY_DB_DEFAULT_DATA_SUBS, &subs_id);
+                       if (vconf_ret < 0) {
+                               err("can't find vconf, giving to default");
+                               subs_id = TELEPHONY_SUBSCRIPTION_TYPE_DEFAULT;
+                       }
+               }
+       } else if (dds_rank[TELEPHONY_SUBSCRIPTION_TYPE_PRIMARY])
+               subs_id = TELEPHONY_SUBSCRIPTION_TYPE_PRIMARY;
+       else if (dds_rank[TELEPHONY_SUBSCRIPTION_TYPE_SECONDARY])
+               subs_id = TELEPHONY_SUBSCRIPTION_TYPE_SECONDARY;
+
+       info("setting dds for subs_id=[%d]", subs_id);
+       __send_dds_request(modem_plugins[subs_id]);
+
+}
+
+static void __ds_set_on_boot(Manager *manager)
+{
+
+       GSList *modems, *iter;
+       TcorePlugin *modem_plugin = NULL;
+       int ds_rank[TELEPHONY_SUBSCRIPTION_TYPE_MAX] = { -1, -1 };
+       ModemBoard *mb = NULL;
+       Server *s = tcore_plugin_ref_server(tcore_manager_get_plugin(manager));
+       enum telephony_subscription_type sim_index = TELEPHONY_SUBSCRIPTION_TYPE_DEFAULT;
+       char *always_ask_hash = NULL;
+       int always_ask_ds_rank = 0;
+       enum telephony_call_preferred_voice_subs preferred_subs = CALL_PREFERRED_VOICE_SUBS_SIM1;
+
+       dbg("Both SIM status received, process ds...");
+       always_ask_hash = __generate_hash(CALL_MSG_PREF_ALWAYS_ASK);
+       if(always_ask_hash) {
+               always_ask_ds_rank = __find_ds_rank_with_hash( s, always_ask_hash);
+               dbg("always_ask_ds_rank = [%d]", always_ask_ds_rank);
+               g_free(always_ask_hash);
+       }
+       modems = tcore_server_get_modem_plugin_list(s);
+
+       for (iter = modems; iter != NULL; iter = iter->next) {
+               modem_plugin = iter->data;
+               if (!modem_plugin) {
+                       err("Modem plugin is null !!");
+                       continue;
+               }
+               sim_index = manager_core_get_modem_board_index(modem_plugin);
+               mb = manager_core_get_modem_board(manager, modem_plugin);
+
+               if (mb->sim_info->sim_status == SIM_STATUS_INIT_COMPLETED)
+                       ds_rank[sim_index] = __find_ds_rank(modem_plugin);
+
+       }
+       g_slist_free(modems);
+
+       info("ds_rank[0]=[%d] && ds_rank[1]=[%d] && always_ask_ds_rank = [%d]", ds_rank[0], ds_rank[1], always_ask_ds_rank);
+       if (ds_rank[0] == -1 && ds_rank[1] == -1) {
+               /*TODO: what if both sims are not present*/
+       } else if (ds_rank[TELEPHONY_SUBSCRIPTION_TYPE_PRIMARY] == -1)
+               preferred_subs = CALL_PREFERRED_VOICE_SUBS_SIM2;
+       else if (ds_rank[TELEPHONY_SUBSCRIPTION_TYPE_SECONDARY] == -1)
+               preferred_subs = CALL_PREFERRED_VOICE_SUBS_SIM1;
+       else if (ds_rank[TELEPHONY_SUBSCRIPTION_TYPE_PRIMARY] > ds_rank[TELEPHONY_SUBSCRIPTION_TYPE_SECONDARY]){
+               if(ds_rank[TELEPHONY_SUBSCRIPTION_TYPE_PRIMARY] > always_ask_ds_rank)
+                       preferred_subs = CALL_PREFERRED_VOICE_SUBS_SIM1;
+               else
+                       preferred_subs = CALL_PREFERRED_VOICE_SUBS_ASK_ALWAYS;
+       }
+       else{
+               if(ds_rank[TELEPHONY_SUBSCRIPTION_TYPE_SECONDARY] > always_ask_ds_rank)
+                       preferred_subs = CALL_PREFERRED_VOICE_SUBS_SIM2;
+               else
+                       preferred_subs = CALL_PREFERRED_VOICE_SUBS_ASK_ALWAYS;
+       }
+
+       info("preferred_subs= [%d]", preferred_subs);
+       __send_ds_request(s, preferred_subs);
+
+}
+
+static void __set_nw_dds_ds_on_boot(Manager *manager)
+{
+       info("setting nw,dds,ds on boot");
+       __network_mode_set_on_boot(manager);
+       __dds_set_on_boot(manager);
+       __ds_set_on_boot(manager);
+}
+
+static enum tcore_hook_return on_noti_hook_manager_call_status_idle(Server *server,
+                                                                      CoreObject *source, enum tcore_notification_command command,
+                                                                      unsigned int data_len, void *data, void *user_data)
+{
+       TcorePlugin *modem_plugin = tcore_object_ref_plugin(source);
+       Manager *manager = user_data;
+
+       if (manager_call_is_during_call(modem_plugin)) {
+               dbg("Call is still in progress");
+               return TCORE_HOOK_RETURN_CONTINUE;
+       }
+
+       info("Call was disconnected.");
+
+       __set_nw_dds_ds_on_boot(manager);
+
+       tcore_server_remove_notification_hook(server, on_noti_hook_manager_call_status_idle);
+
+       return TCORE_HOOK_RETURN_CONTINUE;
+}
+
+void set_nw_dds_ds_on_boot(Manager *manager)
+{
+       if (__are_both_sims_ready_after_boot(manager)) {
+               Server *server = tcore_plugin_ref_server(tcore_manager_get_plugin(manager));
+               GSList *modem_plugin_list = tcore_server_get_modem_plugin_list(server);
+               GSList *list = NULL;
+               gboolean is_call_in_progress = FALSE;
+
+               /* Traverse through each modem plugin and destroy mb */
+               for (list = modem_plugin_list; list; list = list->next) {
+                       TcorePlugin *modem_plugin = list->data;
+                       if (modem_plugin && manager_call_is_during_call(modem_plugin)) {
+                               info("Call is in progress. Hold setting of nw, dds, ds");
+                               tcore_server_add_notification_hook(server, TNOTI_CALL_STATUS_IDLE,
+                                                                        on_noti_hook_manager_call_status_idle, manager);
+                               is_call_in_progress = TRUE;
+                               break;
+                       }
+               }
+               if(!is_call_in_progress) {
+                       info("There are no calls in progress");
+                       __set_nw_dds_ds_on_boot(manager);
+               }
+               g_slist_free(modem_plugin_list);
+       }
+}
+enum tcore_manager_return manager_sim_process_notification(Manager *manager,
+                                                          CoreObject *source, enum tcore_notification_command command,
+                                                          unsigned int data_len, void *data)
+{
+       enum tcore_manager_return ret = TCORE_MANAGER_RETURN_CONTINUE;
+
+       switch (command) {
+       case TNOTI_SIM_STATUS: {
+               const struct tnoti_sim_status *sim = data;
+               ModemBoard *mb = manager_core_get_modem_board(manager, tcore_object_ref_plugin(source));
+
+               if (!sim || !mb) {
+                       err("NULL data sim[%p], mb[%p]", sim, mb);
+                       return ret;
+               }
+
+               switch (sim->sim_status) {
+               case SIM_STATUS_INIT_COMPLETED:
+                       if (mb->sim_info->is_first_boot == FALSE) {
+                               dbg("SIM file reading already completed !!");
+                               return ret;
+                       }
+                       if (tfeature_is_supported(TFEATURE_FUNCTION_MANAGER_NETWORK_NAME_ENABLE)) {
+                               mb->sim_info->is_first_boot = FALSE;
+                               manager_network_get_sim_network_name(source);
+                       }
+                       /* Get FDN status for VoLTE call */
+                       {
+                               TcorePlugin *modem_plugin = tcore_object_ref_plugin(source);
+                               ModemBoard *mb = manager_core_get_modem_board(manager, modem_plugin);
+
+                               if (FALSE == mb->fdn_enabled) {
+                                       info("Cache FDN status at bootup !!");
+                                       __get_fdn_status_info(modem_plugin);
+                               }
+                       }
+                       break;
+
+               default:
+                       break;
+               }
+               __update_private_info(manager, source, sim->sim_status);
+#ifdef TIZEN_SUPPORT_SIM_PREFERRED_SUBSCRIPTION
+               set_nw_dds_ds_on_boot(manager);
+#endif
+       }
+       break;
+
+       case TNOTI_SIM_REFRESHED: {
+               struct tnoti_sim_refreshed *noti_data = data;
+               int i = 0;
+               gboolean is_eons_updated = FALSE;
+               gboolean is_fdn_updated = FALSE;
+               TcorePlugin *modem_plugin = tcore_object_ref_plugin(source);
+               ModemBoard *mb = manager_core_get_modem_board(manager, modem_plugin);
+
+               info("cmd_type=[%d], b_full_file_changed=[%d]", noti_data->cmd_type, noti_data->b_full_file_changed);
+
+               if (noti_data->b_full_file_changed == TRUE) {
+                       is_eons_updated = TRUE;
+                       is_fdn_updated = TRUE;
+               } else {
+                       for (i = 0; i < noti_data->file_list.file_count; i++) {
+                               switch (noti_data->file_list.file_id[i]) {
+                               case SIM_EF_CPHS_OPERATOR_NAME_STRING:
+                               case SIM_EF_SPN:
+                               case SIM_EF_SPDI:
+                               case SIM_EF_OPL:
+                               case SIM_EF_PNN:
+                                       is_eons_updated = TRUE;
+                                       goto OUT;
+
+                               default:
+                                       /* Check for EF-FDN refresh */
+                                       if (0x6F3B == noti_data->file_list.file_id[i]) {
+                                               dbg("FDN refresh !! Update FDN cache if FDN enabled !!");
+                                               is_fdn_updated = TRUE;
+                                       }
+                                       break;
+                               }
+                       }
+               }
+ OUT:
+               if (is_eons_updated) {
+                       info("EONS Field was refreshed");
+                       if (tfeature_is_supported(TFEATURE_FUNCTION_MANAGER_NETWORK_NAME_ENABLE)) {
+                               manager_network_process_sim_refreshed(source);
+                               manager_network_get_sim_network_name(source);
+                       }
+               }
+
+               if (is_fdn_updated && mb->fdn_enabled) {
+                       __process_fdn_change(modem_plugin, TRUE);
+               }
+       }
+       break;
+
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+enum tcore_manager_return manager_sim_process_request(Server *server, UserRequest *ur)
+{
+       enum tcore_request_command command = tcore_user_request_get_command(ur);
+       enum tcore_manager_return manager_ret = TCORE_MANAGER_RETURN_CONTINUE;
+
+       switch (command) {
+
+       case TREQ_SIM_SET_POWERSTATE: {
+               int subscription = -1;
+               int vconf_ret;
+
+               struct treq_sim_set_powerstate *sim_powerstate = (struct treq_sim_set_powerstate *)tcore_user_request_ref_data(ur, 0);
+               if (sim_powerstate->state == SIM_POWER_ON) {
+                       dbg("Request for sim power on, no need of IMS deregister");
+                       return manager_ret;
+               }
+
+               vconf_ret = vconf_get_int(VCONFKEY_TELEPHONY_DB_DEFAULT_DATA_SUBS, &subscription);
+               if (vconf_ret < 0) {
+                       info("Get DDS from vconf failed");
+                       return manager_ret;
+               } else {
+                       info("Default data subscirption is %d", subscription);
+                       if (subscription != (int)s_manager_get_subs_type_ur(ur))
+                               return manager_ret;
+               }
+               manager_ret = manager_util_process_ims(server, ur);
+
+       }
+       break;
+
+       case TREQ_SIM_ENABLE_FACILITY:
+       case TREQ_SIM_DISABLE_FACILITY:
+       {
+               dbg("FDN request received, set RESPONSE hook !!");
+               tcore_user_request_set_response_hook(ur, __on_hook_change_fdn_status, server);
+       }
+       break;
+
+       /*
+        * All other requests, would be routed to CP.
+        */
+       default:
+               break;
+       }
+
+       return manager_ret;
+}
diff --git a/src/manager_sms.c b/src/manager_sms.c
new file mode 100644 (file)
index 0000000..b913349
--- /dev/null
@@ -0,0 +1,643 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <tfeature.h>
+#include <tcore.h>
+#include <plugin.h>
+#include <manager.h>
+#include <user_request.h>
+#include <server.h>
+#include <manager.h>
+#include <core_object.h>
+#include <co_sms.h>
+#include <co_network.h>
+
+#include <type/sms.h>
+
+#include "manager_util.h"
+#include "manager_sms.h"
+#include "internal/manager_sms_internal.h"
+
+/** BER-TLV tag for SMS-PP download. TS 31.111 section 9.1. */
+#define BER_SMS_PP_DOWNLOAD_TAG 0xd1
+#define COMPREHENSION_TLV_TAG_DEVICE_IDENTITIES (0x80|0x02)
+#define COMPREHENSION_TLV_TAG_ADDRESS 0x06
+#define COMPREHENSION_TLV_TAG_SMS_TPDU (0x80|0x0b)
+
+struct manager_sms_decoded_param {
+       unsigned char dcs;
+       unsigned char pid;
+};
+
+struct manager_sms_send_apdu_resp_user_data {
+       TcorePlugin *modem_plugin;
+       struct manager_sms_decoded_param decoded_param;
+};
+
+struct manager_sms_rp_ack {
+       TcorePlugin *modem_plugin;
+       int result;
+       unsigned int pdu_len;
+       unsigned char pdu[SMS_SMDATA_SIZE_MAX];
+       struct tnoti_sms_incoming_msg *msg_data;
+       unsigned char dcs;
+       unsigned char pid;
+};
+
+static gboolean __sms_util_is7bit_dcs(unsigned char dcs)
+{
+       return ((dcs & 0x8C) == 0x00) || ((dcs & 0xF4) == 0xF0);
+}
+
+static Sms_class_type __sms_util_decode_dcs(unsigned char dcs)
+{
+       if (dcs < 0x80) {
+               if (dcs & 0x10) {
+                       switch (dcs & 0x03) {
+                       case 0x00:
+                               return SMS_CLASS_0;
+                               break;
+
+                       case 0x01:
+                               return SMS_CLASS_1;
+                               break;
+
+                       case 0x02:
+                               return SMS_CLASS_2;
+                               break;
+
+                       case 0x03:
+                               return SMS_CLASS_3;
+                               break;
+
+                       default:
+                               return SMS_CLASS_NONE;
+                               break;
+                       }
+               } else
+                       return SMS_CLASS_NONE;
+       } else if (dcs >= 0x40 && dcs < 0x80) {
+               if (dcs & 0x10) {
+                       switch (dcs & 0x03) {
+                       case 0x00:
+                               return SMS_CLASS_0;
+                               break;
+
+                       case 0x01:
+                               return SMS_CLASS_1;
+                               break;
+
+                       case 0x02:
+                               return SMS_CLASS_2;
+                               break;
+
+                       case 0x03:
+                               return SMS_CLASS_3;
+                               break;
+
+                       default:
+                               return SMS_CLASS_NONE;
+                               break;
+                       }
+               } else
+                       return SMS_CLASS_NONE;
+       } else if (dcs == 0xC0) {
+               return SMS_CLASS_NONE;
+       } else if (dcs < 0xE0) {
+               return SMS_CLASS_NONE;
+       } else if (dcs < 0xF0) {
+               return SMS_CLASS_NONE;
+       } else {
+               switch (dcs & 0x03) {
+               case 0x00:
+                       return SMS_CLASS_0;
+                       break;
+
+               case 0x01:
+                       return SMS_CLASS_1;
+                       break;
+
+               case 0x02:
+                       return SMS_CLASS_2;
+                       break;
+
+               case 0x03:
+                       return SMS_CLASS_3;
+                       break;
+
+               default:
+                       return SMS_CLASS_NONE;
+                       break;
+               }
+       }
+       return SMS_CLASS_NONE;
+}
+
+static unsigned int __sms_util_decode_origin_address(unsigned char *tpdu)
+{
+       unsigned int len = 0;
+       int offset = 0;
+       int ton;
+
+       ton = (tpdu[offset + 1] & 0x70) >> 4;
+       if (ton != SMS_TON_ALPHA_NUMERIC)
+               len = tpdu[offset];
+       else
+               len = (((tpdu[offset] + 1) / 2) * 8) / 7;
+
+       dbg("ton:0x%x, len:0x%x", ton, len);
+       return len;
+}
+
+static gboolean __sms_is_usim_data_download(Sms_class_type msg_class, unsigned char pid)
+{
+       if (msg_class == SMS_CLASS_2 && pid == 0x7F)
+               return TRUE;
+       else
+               return FALSE;
+}
+
+static int __sms_get_envelop_body_length(int sca_len, int tpdu_len)
+{
+       /* Add 4 bytes for device identities TLV + 1 byte for SMS TPDU tag byte*/
+       int length = tpdu_len + 5;
+       /* Add 1 byte for TPDU length, or 2 bytes if length > 127*/
+       length += (tpdu_len > 127 ? 2 : 1);
+       /* Add length of address tag, if present (+ 2 bytes for tag and length)*/
+       if (sca_len != 0) {
+               length = length + 2 + sca_len;
+       }
+       return length;
+}
+
+static void __sms_on_resp_send_delivery_report(UserRequest *ur, enum tcore_response_command command,
+                                              unsigned int data_len, const void *data, void *user_data)
+{
+       const struct tresp_sms_set_delivery_report *resp = data;
+       dbg("Result : %d", resp ? resp->result : -1);
+}
+
+static void __sms_on_resp_get_sca(UserRequest *ur, enum tcore_response_command command,
+                                 unsigned int data_len, const void *data, void *user_data)
+{
+       const struct tresp_sms_get_sca *resp = data;
+       struct manager_sms_rp_ack *rp_ack = user_data;
+       struct treq_sms_set_delivery_report report;
+       gboolean ret;
+       unsigned char ton, npi;
+
+       if (G_UNLIKELY(!resp || !rp_ack))
+               return;
+
+       tcore_util_hex_dump("[SCA] ", data_len, resp);
+
+       if (resp->result != TCORE_RETURN_SUCCESS) {
+               warn("Fail to Get SCA address(0x%x)", resp->result);
+               goto EXIT;
+       }
+
+       memset(&report, 0, sizeof(struct treq_sms_set_delivery_report));
+       ton = resp->scaAddress.typeOfNum;
+       npi = resp->scaAddress.numPlanId;
+       report.dataInfo.format = SMS_NETTYPE_3GPP;
+       report.dataInfo.sca[0] = (resp->scaAddress.dialNumLen * 2); /*SCA length*/
+       report.dataInfo.sca[1] = 0x80 + (ton << 4) + npi; /* ton + npi*/
+       memcpy(&report.dataInfo.sca[2], resp->scaAddress.diallingNum, resp->scaAddress.dialNumLen);
+
+       report.dataInfo.msgLength = rp_ack->pdu_len;
+       memcpy(report.dataInfo.tpduData, rp_ack->pdu, rp_ack->pdu_len);
+       report.rspType = rp_ack->result;
+       tcore_util_hex_dump("[DELIVERY] ", SMS_SMSP_ADDRESS_LEN + report.dataInfo.msgLength + 2 * sizeof(int), &report);
+
+       ret = manager_util_send_request(rp_ack->modem_plugin, TREQ_SMS_SET_DELIVERY_REPORT,
+                                       sizeof(report), &report, __sms_on_resp_send_delivery_report, NULL);
+
+       if (!ret)
+               warn("Fail to Send delivery report");
+
+ EXIT:
+       g_free(rp_ack);
+}
+
+static void __sms_send_rp_ack(struct manager_sms_rp_ack *rp_ack)
+{
+       struct treq_sms_get_sca request;
+       struct manager_sms_rp_ack *user_data;
+       gboolean ret;
+
+       if (G_UNLIKELY(!rp_ack))
+               return;
+
+       request.index = 0;
+       user_data = g_memdup(rp_ack, sizeof(struct manager_sms_rp_ack));
+       ret = manager_util_send_request(rp_ack->modem_plugin, TREQ_SMS_GET_SCA,
+                                       sizeof(struct treq_sms_get_sca), &request, __sms_on_resp_get_sca, user_data);
+
+       if (!ret)
+               g_free(user_data);
+       else
+               dbg("GET SCA was sent");
+}
+
+static void __sms_send_ack_for_envelope_response(const void *data, void *user_data)
+{
+#define GSM_SMS_FAIL_CAUSE_USIM_DATA_DOWNLOAD_ERROR 0xD5
+       const struct tresp_sat_envelop_data *response = data;
+       struct manager_sms_send_apdu_resp_user_data *ud = user_data;
+       struct manager_sms_rp_ack rp_ack;
+       TcorePlugin *modem_plugin = ud ? ud->modem_plugin : NULL;
+       gboolean success;
+       int sw1 = 0;
+       int sw2 = 0;
+       unsigned char pid;
+       unsigned char dcs;
+       unsigned int payload_len = 0;
+       unsigned char *payload = NULL;
+       int index = 0;
+
+       if (!response || !ud) {
+               warn("Invalid param");
+               return;
+       }
+
+       if (response->envelop_resp == ENVELOPE_SUCCESS) {
+               sw1 = 0x90;
+               sw2 = 0x00;
+       } else if (response->envelop_resp == ENVELOPE_SIM_BUSY) {
+               sw1 = 0x93;
+               sw2 = 0x00;
+       } else {
+               sw1 = 0x62;
+       }
+
+       if ((sw1 == 0x90 && sw2 == 0x00) || sw1 == 0x91) {
+               info("USIM data download succeeded");
+               success = TRUE;
+       } else if (sw1 == 0x93 && sw2 == 0x00) {
+               info("USIM data download failed: Toolkit busy");
+               return;
+       } else if (sw1 == 0x62 || sw1 == 0x63) {
+               info("USIM data download failed");
+               success = FALSE;
+       } else {
+               info("Unexpected SW1/SW2 response from UICC");
+               success = FALSE;
+       }
+
+       memset(&rp_ack, 0x0, sizeof(struct manager_sms_rp_ack));
+       rp_ack.modem_plugin = modem_plugin;
+       pid = ud->decoded_param.pid;
+       dcs = ud->decoded_param.dcs;
+       info("pid:0x%x, dcs:0x%x", pid, dcs);
+
+       if (payload == NULL || payload_len == 0) {
+               if (success) {
+                       rp_ack.pdu[index++] = 0x00; /* TP-MTI*/
+                       rp_ack.pdu[index++] = 0x00; /* TP-PI*/
+                       rp_ack.pdu_len = index;
+                       rp_ack.result = SMS_SENDSMS_SUCCESS;
+               } else {
+                       rp_ack.pdu[index++] = 0x00;     /* TP-MTI, TP-UDHI*/
+                       rp_ack.pdu[index++] = GSM_SMS_FAIL_CAUSE_USIM_DATA_DOWNLOAD_ERROR;      /* TP-FCS*/
+                       rp_ack.pdu[index++] = 0x07;     /* TP-PI: TP-PID, TP-DCS, TP-UDL present*/
+                       rp_ack.pdu[index++] = pid;
+                       rp_ack.pdu[index++] = dcs;
+                       rp_ack.pdu_len = index;
+                       rp_ack.result = -1; /* FAILURE.. Temp code*/
+               }
+               __sms_send_rp_ack(&rp_ack);
+               return;
+       }
+
+       if (success) {
+               rp_ack.pdu[index++] = 0x00;             /* TP-MTI, TP-UDHI*/
+               rp_ack.pdu[index++] = 0x07;             /* TP-PI: TP-PID, TP-DCS, TP-UDL present*/
+       } else {
+               rp_ack.pdu[index++] = 0x00;             /* TP-MTI, TP-UDHI*/
+               rp_ack.pdu[index++] = GSM_SMS_FAIL_CAUSE_USIM_DATA_DOWNLOAD_ERROR;      /* TP-FCS*/
+               rp_ack.pdu[index++] = 0x07;             /* TP-PI: TP-PID, TP-DCS, TP-UDL present*/
+       }
+
+       rp_ack.pdu[index++] = pid;
+       rp_ack.pdu[index++] = dcs;
+
+       if (__sms_util_is7bit_dcs(dcs)) {
+               int septetCount = payload_len * 8 / 7;
+               rp_ack.pdu[index++] = septetCount;
+       } else {
+               rp_ack.pdu[index++] = payload_len;
+       }
+
+       memcpy(&rp_ack.pdu[index], payload, payload_len);
+       rp_ack.pdu_len = index;
+       rp_ack.result = SMS_SENDSMS_SUCCESS;
+
+       __sms_send_rp_ack(&rp_ack);
+}
+
+static void __sms_on_resp_apdu(UserRequest *ur, enum tcore_response_command command,
+                              unsigned int data_len, const void *data, void *user_data)
+{
+       const struct tresp_sat_envelop_data *resp = data;
+
+       if (G_UNLIKELY(!data))
+               return;
+
+       info("result:[0x%x] sub_cmd:[0x%x] envelop_resp:[%d]", resp->result, resp->sub_cmd, resp->envelop_resp);
+       __sms_send_ack_for_envelope_response(data, user_data);
+       g_free(user_data);
+}
+
+static void __send_smspp_envelop_cmd(TcorePlugin *modem_plugin, struct tnoti_sms_incoming_msg *sms_data,
+                                                                                               unsigned int sca_len, unsigned char *sca, unsigned char ton,
+                                                                                               unsigned char dcs, unsigned char pid)
+{
+       struct treq_sat_envelop_cmd_data envelope;
+       struct manager_sms_send_apdu_resp_user_data *manager_data = NULL;
+       unsigned int tpdu_len;
+       unsigned int body_len;
+       unsigned int total_len;
+       unsigned int index = 0;
+       gboolean ret;
+
+       dbg("Enter");
+
+       memset(&envelope, 0x0, sizeof(struct treq_sat_envelop_cmd_data));
+
+       tpdu_len = sms_data->msgInfo.msgLength;
+       body_len = __sms_get_envelop_body_length(sca_len, tpdu_len);
+
+       /* Add 1 byte for SMS-PP download tag and 1-2 bytes for BER-TLV length. */
+       total_len = body_len + 1 + (body_len > 127 ? 2 : 1);
+       dbg("sca_len:0x%x, tpdu_len:0x%x, body_len:0x%x, total_len:0x%x", sca_len, tpdu_len, body_len, total_len);
+
+       envelope.sub_cmd = ENVELOP_EVENT_DOWNLOAD;
+       envelope.envelop_data.event_download.event = 0x11;
+
+       envelope.envelop_data.event_download.sms_pp.data_len = total_len;
+       /* SMS-PP download tag and length (assumed to be < 256 bytes). */
+       envelope.envelop_data.event_download.sms_pp.data[index++] = BER_SMS_PP_DOWNLOAD_TAG;
+       if (body_len > 127) {
+               envelope.envelop_data.event_download.sms_pp.data[index++] = 0x81; // length 128-255 encoded as 0x81 + length
+       }
+       envelope.envelop_data.event_download.sms_pp.data[index++] = body_len;
+
+       /* Device identities TLV */
+       envelope.envelop_data.event_download.sms_pp.data[index++] = COMPREHENSION_TLV_TAG_DEVICE_IDENTITIES;
+       envelope.envelop_data.event_download.sms_pp.data[index++] = 2;
+       envelope.envelop_data.event_download.sms_pp.data[index++] = DEVICE_ID_NETWORK;
+       envelope.envelop_data.event_download.sms_pp.data[index++] = DEVICE_ID_SIM;
+
+       /* Address TLV (if present). Encoded length is assumed to be < 127 bytes. */
+       if (sca_len != 0) {
+               envelope.envelop_data.event_download.sms_pp.data[index++] = COMPREHENSION_TLV_TAG_ADDRESS;
+               envelope.envelop_data.event_download.sms_pp.data[index++] = sca_len;
+               envelope.envelop_data.event_download.sms_pp.data[index++] = ton;
+               memcpy(&envelope.envelop_data.event_download.sms_pp.data[index], sca, sca_len-1);
+               index += sca_len-1;
+       }
+
+       /* SMS TPDU TLV. Length is assumed to be < 256 bytes. */
+       envelope.envelop_data.event_download.sms_pp.data[index++] = COMPREHENSION_TLV_TAG_SMS_TPDU;
+       if (tpdu_len > 127) {
+               envelope.envelop_data.event_download.sms_pp.data[index++] = 0x81; /* length 128-255 encoded as 0x81 + length */
+       }
+       envelope.envelop_data.event_download.sms_pp.data[index++] = tpdu_len;
+       memcpy(&envelope.envelop_data.event_download.sms_pp.data[index], sms_data->msgInfo.tpduData, tpdu_len);
+       index += tpdu_len;
+
+       tcore_util_hex_dump("[ENVELOP]", index, envelope.envelop_data.event_download.sms_pp.data);
+       /* Verify that we calculated the payload size correctly. */
+       if (index != envelope.envelop_data.event_download.sms_pp.data_len) {
+               info("calculated incorrect envelope length (%d != %d), aborting.", index, envelope.envelop_data.event_download.sms_pp.data_len);
+               return;
+       } else
+               info("Sending SMS_PP_DOWNLOAD to Modem");
+
+       manager_data = g_malloc0(sizeof(struct manager_sms_send_apdu_resp_user_data));
+       manager_data->modem_plugin = modem_plugin;
+       manager_data->decoded_param.dcs = dcs;
+       manager_data->decoded_param.pid = pid;
+
+       ret = manager_util_send_request(modem_plugin, TREQ_SAT_REQ_ENVELOPE,
+                               sizeof(struct treq_sat_envelop_cmd_data), &envelope, __sms_on_resp_apdu, manager_data);
+
+       if (!ret) {
+               warn("Fail to send ENVELOPE_COMMAND !!");
+               g_free(manager_data);
+       }
+}
+
+static void __sms_on_resp_get_sca_for_envelop(UserRequest *ur, enum tcore_response_command command,
+       unsigned int data_len, const void *data, void *user_data)
+{
+       const struct tresp_sms_get_sca *resp = data;
+       struct manager_sms_rp_ack *rp_data = user_data;
+       unsigned char ton = 0;
+
+       dbg("Enter");
+
+       if (G_UNLIKELY(!resp || !rp_data)) {
+               err("NULL data : resp[%p], rp_data[*p]");
+               return;
+       }
+
+       tcore_util_hex_dump("[SCA] ", data_len, resp);
+
+       if (resp->result == TCORE_RETURN_SUCCESS) {
+               tcore_util_hex_dump("[SCA] ", data_len, resp);
+
+               ton = 0x80 + (resp->scaAddress.typeOfNum<< 4) + resp->scaAddress.numPlanId;
+
+               /* Send ENVELOPE_CMD to SIM */
+               __send_smspp_envelop_cmd(rp_data->modem_plugin, rp_data->msg_data, resp->scaAddress.dialNumLen+1, (unsigned char *)resp->scaAddress.diallingNum, ton, rp_data->dcs, rp_data->pid);
+       } else {
+               warn("Fail to Get SCA address(0x%x)", resp->result);
+       }
+
+       /* Free user data */
+       g_free(rp_data->msg_data);
+       g_free(rp_data);
+}
+
+static void __sms_handle_usim_data_download(TcorePlugin *modem_plugin,
+       struct tnoti_sms_incoming_msg *data, struct manager_sms_decoded_param *decoded_param)
+{
+       unsigned int sca_len;
+
+       dbg("Enter");
+
+       if (G_UNLIKELY(!data || !modem_plugin || !decoded_param)) {
+               err("NULL data : data[%p], modem_plugin[%p], decoded_param[%p]", data, modem_plugin, decoded_param);
+               return;
+       }
+
+       sca_len = data->msgInfo.sca[0];
+
+       if (sca_len != 0) {
+               /* Send ENVELOPE_CMD to SIM */
+               __send_smspp_envelop_cmd(modem_plugin, data, sca_len, &data->msgInfo.sca[2], data->msgInfo.sca[1], decoded_param->dcs, decoded_param->pid);
+       } else {
+               struct treq_sms_get_sca request;
+               struct manager_sms_rp_ack *user_data = g_malloc0(sizeof(struct manager_sms_rp_ack));
+               gboolean ret;
+
+               request.index = 0;
+               user_data->msg_data = g_memdup(data, sizeof(struct tnoti_sms_incoming_msg));
+               user_data->modem_plugin = modem_plugin;
+               user_data->dcs = decoded_param->dcs;
+               user_data->pid = decoded_param->pid;
+
+               ret = manager_util_send_request(modem_plugin, TREQ_SMS_GET_SCA,
+                       sizeof(struct treq_sms_get_sca), &request, __sms_on_resp_get_sca_for_envelop, user_data);
+               if (!ret) {
+                       g_free(user_data->msg_data);
+                       g_free(user_data);
+                       err("GET SCA is send failed !!");
+               } else {
+                       dbg("GET SCA is sent");
+               }
+       }
+}
+
+static enum tcore_manager_return __sms_dispatch_msg_radio_specific(TcorePlugin *modem_plugin,
+                                                                  struct tnoti_sms_incoming_msg *data)
+{
+       Sms_class_type msg_class;
+       unsigned char mti, pid, dcs;
+       unsigned char *tpdu;
+       int position = 0;
+       int oa_len;
+
+       info("Parse SMS for USIM Download");
+
+       if (G_UNLIKELY(!data))
+               return TCORE_MANAGER_RETURN_CONTINUE;
+
+       tpdu = data->msgInfo.tpduData;
+
+       /* TPDU[0] => PDU Type[Bit1|Bit0] => MTI(Message Type Indicator) */
+       mti = tpdu[position++] & 0x03;
+       if (mti != SMS_TPDU_DELIVER)
+               return TCORE_MANAGER_RETURN_CONTINUE;
+
+       /* OA (Originator Address - Address of the originating SME)*/
+       oa_len = __sms_util_decode_origin_address(&tpdu[position]);
+       position += 2;
+       if (oa_len % 2)
+               position += oa_len / 2 + 1;
+       else
+               position += oa_len / 2;
+
+       /* PID (Protocol Identifier) */
+       pid = tpdu[position++];
+
+       /* DCS (Data Coding Scheme) */
+       dcs = tpdu[position++];
+       msg_class = __sms_util_decode_dcs(dcs);
+
+       dbg("pid:0x%x, dcs:0x%x, msg_class:0x%x", pid, dcs, msg_class);
+
+       if (__sms_is_usim_data_download(msg_class, pid)) {
+               struct manager_sms_decoded_param param = { dcs, pid };
+
+               __sms_handle_usim_data_download(modem_plugin, data, &param);
+               return TCORE_MANAGER_RETURN_STOP;
+       } else
+               info("Not USIM Download Message");
+       return TCORE_MANAGER_RETURN_CONTINUE;
+}
+
+enum tcore_manager_return manager_sms_process_request(Server *server, UserRequest *ur)
+{
+       enum tcore_request_command command = tcore_user_request_get_command(ur);
+       CoreObject *co_sms = manager_util_get_core_object(server, ur, CORE_OBJECT_TYPE_SMS);
+
+       if ((command == TREQ_SMS_SEND_UMTS_MSG)
+           || (command == TREQ_SMS_SEND_CDMA_MSG)) {
+               enum tcore_sms_routing_policy routing_policy;
+               routing_policy = tcore_sms_get_sms_routing(co_sms);
+               dbg("sms routing policy : %d", routing_policy);
+
+               switch (routing_policy) {
+               case TCORE_SMS_ROUTING_POLICY_IMS_ALWAYS:
+                       return TCORE_MANAGER_RETURN_CONTINUE_IMS;
+                       break;
+
+               case TCORE_SMS_ROUTING_POLICY_CS_ALWAYS:
+                       return TCORE_MANAGER_RETURN_CONTINUE;
+                       break;
+
+               case TCORE_SMS_ROUTING_POLICY_IMS_CS:
+               default: {
+                       if (manager_util_is_ims_registered(server, ur, NETWORK_IMS_REG_FEATURE_TYPE_SMS)) {
+                               return TCORE_MANAGER_RETURN_CONTINUE_IMS;
+                               /**
+                               * Special Cases. VoLTE only models
+                               * Request should be send to IMS only.
+                               **/
+                       } else if (tfeature_is_supported(TFEATURE_DEVICE_LTE_ONLY)) {
+                               dbg("LTE only model. induce request only to IMS");
+                               return TCORE_MANAGER_RETURN_CONTINUE_IMS;
+                       }
+               }
+               break;
+
+               }
+       } else if (command == TREQ_SMS_SET_DELIVERY_REPORT) {
+               dbg("Delivery report do not get affected from sms_over_ip_notification");
+               if (manager_util_is_ims_registered(server, ur, NETWORK_IMS_REG_FEATURE_TYPE_SMS)) {
+                       return TCORE_MANAGER_RETURN_CONTINUE_IMS;
+                       /**
+                       * Special Cases. VoLTE only models
+                       * Request should be send to IMS only.
+                       **/
+               } else if (tfeature_is_supported(TFEATURE_DEVICE_LTE_ONLY)) {
+                       dbg("LTE only model. induce request only to IMS");
+                       return TCORE_MANAGER_RETURN_CONTINUE_IMS;
+               }
+       }
+       return TCORE_MANAGER_RETURN_CONTINUE;
+}
+
+
+enum tcore_manager_return manager_sms_process_notification(Manager *manager,
+                                                          CoreObject *source, enum tcore_notification_command command,
+                                                          unsigned int data_len, void *data)
+{
+       enum tcore_manager_return ret = TCORE_MANAGER_RETURN_CONTINUE;
+       TcorePlugin *modem_plugin = tcore_object_ref_plugin(source);
+
+       switch (command) {
+       case TNOTI_SMS_INCOM_MSG: {
+               ret = __sms_dispatch_msg_radio_specific(modem_plugin, data);
+       }
+       break;
+
+       default:
+               break;
+       }
+       return ret;
+}
+
diff --git a/src/manager_ss.c b/src/manager_ss.c
new file mode 100644 (file)
index 0000000..c899201
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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 <user_request.h>
+#include <co_ss.h>
+
+#include "manager_util.h"
+#include "manager_ss.h"
+
+#include "tfeature.h"
+
+enum tcore_manager_return manager_ss_process_request(Server *server, UserRequest *ur)
+{
+       enum tcore_request_command command = tcore_user_request_get_command(ur);
+       CoreObject *co_ss = manager_util_get_core_object(server, ur, CORE_OBJECT_TYPE_SS);
+
+       if (!co_ss)
+               return TCORE_MANAGER_RETURN_FAILURE;
+
+       switch (command) {
+       case TREQ_SS_SEND_USSD: {
+               enum tcore_ussd_routing_policy ussd_routing_policy;
+
+               ussd_routing_policy = tcore_ss_get_ussd_routing(co_ss);
+               if (ussd_routing_policy == TCORE_SS_USSD_ROUTING_POLICY_IMS_ALWAYS)
+                       return TCORE_MANAGER_RETURN_CONTINUE_IMS;
+               else if ((ussd_routing_policy == TCORE_SS_USSD_ROUTING_POLICY_IMS_CS)
+                        && (manager_util_is_ims_registered(server, ur,
+                                                           NETWORK_IMS_REG_FEATURE_TYPE_VOLTE) == TRUE))
+                       return TCORE_MANAGER_RETURN_CONTINUE_IMS;
+               else
+                       return TCORE_MANAGER_RETURN_CONTINUE;
+       }
+       break;
+
+       /*
+        * For all other SS requests,
+        * other than USSD single policy holds good
+        */
+       default: {
+               enum tcore_ss_routing_policy ss_routing_policy;
+
+               ss_routing_policy = tcore_ss_get_ss_routing(co_ss);
+               if (ss_routing_policy == TCORE_SS_ROUTING_POLICY_IMS_ALWAYS)
+                       return TCORE_MANAGER_RETURN_CONTINUE_IMS;
+               else if ((ss_routing_policy == TCORE_SS_ROUTING_POLICY_IMS_CS)
+                        && (manager_util_is_ims_registered(server, ur, NETWORK_IMS_REG_FEATURE_TYPE_VOLTE) == TRUE))
+                       return TCORE_MANAGER_RETURN_CONTINUE_IMS;
+               else if (tfeature_is_supported(TFEATURE_DEVICE_LTE_ONLY)) {
+                       dbg("LTE only model. induce request only to IMS");
+                       return TCORE_MANAGER_RETURN_CONTINUE_IMS;
+               } else
+                       return TCORE_MANAGER_RETURN_CONTINUE;
+       }
+       break;
+       }
+}
+
diff --git a/src/manager_util.c b/src/manager_util.c
new file mode 100644 (file)
index 0000000..1e7bcf7
--- /dev/null
@@ -0,0 +1,376 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Suresh Kumar N <suresh.n@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 <stdio.h>
+#include <glib.h>
+#include <tcore.h>
+#include <server.h>
+#include <manager.h>
+#include <plugin.h>
+#include <core_object.h>
+#include <user_request.h>
+#include <co_network.h>
+
+#include "manager_types.h"
+#include "manager_util.h"
+#include "manager_queue.h"
+#include "internal/manager_internal.h"
+#include "manager_core.h"
+#include "manager_network.h"
+
+#include "tfeature.h"
+
+/* not supported in Platform */
+#if 0
+#define PATH_BOOT_STAT "/sys/class/sec/bsp/boot_stat"
+#endif
+#define MANAGER_IMS_DEREGISTER_REQUEST_TIMEOUT (1000)  /* 1 seconds - Sync from Tizen 2.4 (Z2), mobile profile) */
+#define MANAGER_IMS_DEREGISTER_REQUEST_TIMEOUT_VZW (4000)  /*IMS Deregister timeout for Vzw*/
+
+void manager_set_deregister_timer(Manager *manager, guint timer_id)
+{
+       TcorePlugin *plugin = tcore_manager_get_plugin(manager);
+       PrivateData *priv_data = tcore_plugin_ref_user_data(plugin);
+       g_assert(priv_data != NULL);
+
+       if (priv_data->deregister_timer_id != 0)
+               g_source_remove(priv_data->deregister_timer_id);
+
+       priv_data->deregister_timer_id = timer_id;
+}
+
+void manager_clear_deregister_timer(Manager *manager)
+{
+       TcorePlugin *plugin = tcore_manager_get_plugin(manager);
+       PrivateData *priv_data = tcore_plugin_ref_user_data(plugin);
+       g_assert(priv_data != NULL);
+
+       priv_data->deregister_timer_id = 0;
+}
+
+guint manager_get_deregister_timer(Manager *manager)
+{
+       TcorePlugin *plugin = tcore_manager_get_plugin(manager);
+       PrivateData *priv_data = tcore_plugin_ref_user_data(plugin);
+       g_assert(priv_data != NULL);
+
+       return priv_data->deregister_timer_id;
+}
+
+TcorePlugin *manager_util_get_modem_plugin(Server *server, UserRequest *ur)
+{
+       gchar *modem_name = NULL;
+       TcorePlugin *plugin = NULL;
+
+       modem_name = tcore_user_request_get_modem_name(ur);
+       if (G_UNLIKELY(!modem_name)) {
+               err("modem_name is NULL");
+               return NULL;
+       }
+
+       plugin = tcore_server_find_plugin(server, (const char *)modem_name);
+       g_free(modem_name);
+       if (G_UNLIKELY(!plugin)) {
+               err("plugin is NULL");
+               return NULL;
+       }
+
+       return plugin;
+}
+
+TcorePlugin *manager_util_get_modem_plugin_by_subs_type(Server *server,
+       enum telephony_subscription_type subs_type)
+{
+       TcorePlugin *plugin = NULL;
+       CoreObject *co_modem = NULL;
+       GSList *plugin_list = NULL, *list = NULL;
+       dbg("subs_type = [%d]", subs_type);
+       list = plugin_list = tcore_server_get_modem_plugin_list(server);
+       while (list) {
+               plugin = (TcorePlugin *)(list->data);
+               co_modem = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_MODEM);
+               if (co_modem != NULL) {
+                       dbg(" tcore_object_ref_subscription_type(co_modem) = [%d]",  tcore_object_ref_subscription_type(co_modem));
+                       if (subs_type == tcore_object_ref_subscription_type(co_modem))
+                               break;
+               }
+
+               plugin = NULL;
+               list = g_slist_next(list);
+       }
+       g_slist_free(plugin_list);
+       dbg("plugin is %x", plugin);
+       return plugin;
+}
+
+CoreObject *manager_util_get_core_object(Server *server, UserRequest *ur, unsigned int type)
+{
+       CoreObject *co = tcore_plugin_ref_core_object(manager_util_get_modem_plugin(server, ur), type);
+       if (G_UNLIKELY(!co)) {
+               err("core object[0x%x] is NULL", type);
+               return NULL;
+       }
+       return co;
+}
+
+gboolean manager_util_is_ims_registered(Server *server, UserRequest *ur, guint feature_type)
+{
+       CoreObject *co_network = NULL;
+       struct tel_network_ims_registration_info ims_reg_info = { 0, };
+
+       co_network = manager_util_get_core_object(server, ur, CORE_OBJECT_TYPE_NETWORK);
+       if (co_network == NULL) {
+               err("co_network is NULL");
+               return FALSE;
+       }
+
+       /* Fetch IMS registered from co_network */
+       if (tcore_network_get_ims_reg_info(co_network, &ims_reg_info) != TCORE_RETURN_SUCCESS) {
+               err("Failed to get IMS registration information");
+               return FALSE;
+       }
+
+       if (ims_reg_info.is_registered == FALSE)
+               return FALSE;
+       else
+               return(ims_reg_info.feature_mask & feature_type);
+}
+
+enum telephony_network_ims_reg_network_type manager_util_get_ims_reg_network_type(Server *server, UserRequest *ur)
+{
+       CoreObject *co_network = NULL;
+       struct tel_network_ims_registration_info ims_reg_info = { 0, };
+
+       co_network = manager_util_get_core_object(server, ur, CORE_OBJECT_TYPE_NETWORK);
+       if (co_network == NULL) {
+               err("co_network is NULL");
+               return NETWORK_IMS_REG_NETWORK_TYPE_UNKNOWN;
+       }
+
+       /* Fetch IMS registered from co_network */
+       if (tcore_network_get_ims_reg_info(co_network, &ims_reg_info) != TCORE_RETURN_SUCCESS) {
+               err("Failed to get IMS registration information");
+               return NETWORK_IMS_REG_NETWORK_TYPE_UNKNOWN;
+       }
+
+       return ims_reg_info.network_type;
+}
+
+gboolean manager_util_send_request(TcorePlugin *modem_plugin, enum tcore_request_command command,
+                                  unsigned int data_len, const void *data, UserRequestResponseHook resp_hook, void *user_data)
+{
+       UserRequest *ur;
+       TReturn ret_code;
+
+       if (G_UNLIKELY(!data || !modem_plugin))
+               return FALSE;
+
+       ur = tcore_user_request_new(NULL, tcore_server_get_cp_name_by_plugin(modem_plugin));
+       tcore_user_request_set_command(ur, command);
+       tcore_user_request_set_data(ur, data_len, data);
+       if (resp_hook)
+               tcore_user_request_set_response_hook(ur, resp_hook, user_data);
+
+       ret_code = tcore_server_dispatch_request(tcore_plugin_ref_server(modem_plugin), ur);
+       if (ret_code != TCORE_RETURN_SUCCESS) {
+               err("Request cmd(0x%x) failed. ret_code=%d", command, ret_code);
+               tcore_user_request_unref(ur);
+               return FALSE;
+       }
+       return TRUE;
+}
+
+void manager_util_process_pending_request(Manager *manager)
+{
+       Server *server;
+       UserRequest *ur;
+
+       /*
+        * Set deregister timer -Stop
+        */
+       manager_set_deregister_timer(manager, 0);
+
+       server = tcore_plugin_ref_server(tcore_manager_get_plugin(manager));
+
+       /*
+        * Process any pending request(s)
+        * if 'ur' available then process the Request.
+        */
+       ur = manager_queue_dequeue(manager);
+       while (ur != NULL) {
+               dbg("ur = %x", ur);
+               /* Dispatch request to Corresponding Core Object */
+               if (tcore_server_dispatch_request_ex(server, ur,
+                                                    TCORE_OPS_TYPE_CP) != TCORE_RETURN_SUCCESS) {
+                       err("Failed to dispatch request");
+
+                       /* Unref 'UR' */
+                       tcore_user_request_unref(ur);
+               }
+
+               /* Get next 'ur' */
+               ur = manager_queue_dequeue(manager);
+       }
+}
+
+TcorePlugin *manager_util_get_other_subs_plugin(TcorePlugin *plugin)
+{
+       GSList *modem_list, *iter;
+       gboolean is_found = FALSE;
+       TcorePlugin *other_plugin = NULL;
+       Server *s = tcore_plugin_ref_server(plugin);
+
+       modem_list = tcore_server_get_modem_plugin_list(s);
+       if (!modem_list)
+               return NULL;
+
+       for (iter = modem_list; iter != NULL; iter = iter->next) {
+               other_plugin = iter->data;
+               if (!other_plugin)
+                       break;
+
+               if (plugin != other_plugin) {
+                       is_found = TRUE;
+                       break;
+               }
+       }
+
+       g_slist_free(modem_list);
+       if (is_found == TRUE) {
+               err("Current:[%p] Other:[%p]", plugin, other_plugin);
+               return other_plugin;
+       } else {
+               err("other_sub_plugin not found.");
+               return NULL;
+       }
+}
+
+gboolean manager_deregister_ims_timeout(gpointer user_data)
+{
+       Manager *manager = user_data;
+
+       /*
+        * Need to handle Flight mode or power off Request processing in case of timeout.
+        * Timeout scenario is deduced based on timer validity.
+        */
+       if (manager_get_deregister_timer(manager) != 0) {
+               dbg("Timeout for IMS DeRegister request! Processing pending Flight mode or/and power off request(s)");
+
+               /*
+                * Clear deregister timer
+                * (to avoid g_source_remove() of expired timer)
+                */
+               manager_clear_deregister_timer(manager);
+
+               /* Process pending Flight mode or/and modem power off requests */
+               manager_util_process_pending_request(manager);
+       }
+
+       /*
+        * Removing 'Source'
+        *
+        * %FALSE if the source should be removed
+        */
+       return FALSE;
+}
+
+s_manager_subs_type s_manager_get_subs_type_ur(UserRequest *ur)
+{
+       gchar *cp_name = tcore_user_request_get_modem_name(ur);
+       s_manager_subs_type subs = MANAGER_SUBS_PRIMARY;
+       if (g_str_has_suffix(cp_name, "1"))
+               subs = MANAGER_SUBS_SECONDARY;
+       else
+               subs = MANAGER_SUBS_DEFAULT;
+       g_free(cp_name);
+       return subs;
+}
+
+enum tcore_manager_return manager_util_process_ims(Server *server,
+                                                  UserRequest *ur)
+{
+       gboolean request_present;
+       gboolean start_timer = FALSE;
+       Manager *manager = tcore_server_ref_manager(server);
+       enum tcore_manager_return manager_ret = TCORE_MANAGER_RETURN_CONTINUE;
+       enum tcore_request_command command = tcore_user_request_get_command(ur);
+
+       int deregister_timeout = MANAGER_IMS_DEREGISTER_REQUEST_TIMEOUT;
+
+       request_present = manager_queue_probe_command(manager,
+                                                     command);
+       if (request_present == TRUE) {
+               manager_ret = TCORE_MANAGER_RETURN_STOP;
+       } else {
+
+               if (manager_get_deregister_timer(manager) != 0) {
+                       /* Already requested for deregistration*/
+                       dbg("Deregistration in progress, enqueue the request");
+                       /* Enqueue plmn selection mode request, process it once we get the de-registartion notification */
+                       manager_queue_enqueue(manager, ur);
+                       return TCORE_MANAGER_RETURN_STOP;
+               }
+               manager_ret = manager_network_deregister_ims(manager, ur);
+               start_timer = (manager_ret == TCORE_MANAGER_RETURN_STOP) ? TRUE : FALSE;
+       }
+
+       /*
+        * Request is Enqueued only in case Request propogation need to be halted.
+        */
+       if (manager_ret == TCORE_MANAGER_RETURN_STOP) {
+               /* Enqueue plmn selection mode request */
+               manager_queue_enqueue(manager, ur);
+
+               /*
+                * Start timer in case of First PLMN selection mode Request,
+                * 'start_timer' would be set TRUE.
+                *
+                * In all other cases we rely on previous timer.
+                */
+               if (start_timer == TRUE) {
+                       guint timer;
+
+                       /* Start timer */
+                       timer = g_timeout_add(deregister_timeout,
+                                             manager_deregister_ims_timeout, manager);
+                       manager_set_deregister_timer(manager, timer);
+               }
+       }
+       return manager_ret;
+}
+
+void manager_util_write_to_proc_file(const char *data, int data_len)
+{
+/* not supported in Platform */
+#if 0
+       int write;
+       FILE *fp = fopen(PATH_BOOT_STAT, "w");
+       if (fp != NULL) {
+               write = fwrite(data, data_len, 1, fp);
+               dbg("Write [%s] to [%s] return : [%d]", data, PATH_BOOT_STAT, write);
+               fclose(fp);
+       } else {
+               err("fopen() failed. Could not write to %s", PATH_BOOT_STAT);
+       }
+#else
+       info("boot_stat is not supported in Platform");
+#endif
+}
+
diff --git a/src/network_name/manager_network_name.c b/src/network_name/manager_network_name.c
new file mode 100644 (file)
index 0000000..cbb36d2
--- /dev/null
@@ -0,0 +1,1942 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Imran Mohammed <md.imran@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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <tcore.h>
+#include <server.h>
+#include <manager.h>
+#include <plugin.h>
+#include <user_request.h>
+#include <co_network.h>
+#include <co_sim.h>
+#include <vconf.h>
+
+#include <tzplatform_config.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <tfeature.h>
+
+#include "manager_core.h"
+#include "manager_modem.h"
+#include "internal/manager_network_internal.h"
+#include "manager_network_name.h"
+
+#define NETWORK_MCC_MNC_OPER_LIST_CSC_DB "/opt/system/csc-default/usr/network/.delta_opername.db"
+#define NETWORK_MCC_MNC_OPER_LIST_GSMA_DB tzplatform_mkpath(TZ_SYS_DB, ".mcc_mnc_oper_list.db")
+
+static void __network_update_lac_netname(NetworkPrivateInfo *npi);
+static void __network_update_china_spn_display(NetworkPrivateInfo *npi);
+
+static gboolean __network_is_vowifi_registered(NetworkPrivateInfo *npi)
+{
+       struct tel_network_ims_registration_info ims_reg_info = {0,};
+       CoreObject *co_network = npi->co_network;
+
+       if (npi->epdg_status != NETWORK_EPDG_STATUS_HO_LTE_TO_IWLAN) {
+               return FALSE;
+       }
+
+       /* Fetch IMS registered from co_network */
+       if (tcore_network_get_ims_reg_info(co_network, &ims_reg_info) != TCORE_RETURN_SUCCESS) {
+               err("Failed to get IMS registration information");
+               return FALSE;
+       }
+
+       if (ims_reg_info.is_registered == FALSE) {
+               return FALSE;
+       } else {
+               if (ims_reg_info.network_type == NETWORK_IMS_REG_NETWORK_TYPE_WIFI)
+                       return (ims_reg_info.feature_mask & NETWORK_IMS_REG_FEATURE_TYPE_VOLTE);
+               else
+                       return FALSE;
+       }
+}
+
+static gboolean __network_is_spdi(NetworkPrivateInfo *npi)
+{
+       int i = 0;
+       char *plmn = NULL;
+
+       MANAGER_NET_CHECK_NPI_EONS_RET(npi);
+
+       if (!npi->eons_data->spdi) {
+               err("No SPDI");
+               return FALSE;
+       }
+
+       if (npi->eons_data->spdi->plmn_count == 0) {
+               dbg("npi->eons_data->spdi->plmn_count is Zero");
+               return FALSE;
+       }
+
+       plmn = tcore_network_get_plmn(npi->co_network);
+       if (G_UNLIKELY(!plmn)) {
+               err("plmn is NULL");
+               return FALSE;
+       }
+
+       for (i = 0; i < npi->eons_data->spdi->plmn_count; i++) {
+               if (g_strcmp0(plmn, (char *)npi->eons_data->spdi->list[i].plmn) == 0) {
+                       info("plmn(%s) is in spdi list", plmn);
+                       g_free(plmn);
+                       return TRUE;
+               }
+       }
+
+       g_free(plmn);
+       return FALSE;
+}
+
+static gboolean __network_is_plmn_matched(NetworkPrivateInfo *npi)
+{
+       char *plmn = NULL;
+       struct tel_sim_imsi *imsi = NULL;
+       gboolean is_matched = FALSE;
+
+       MANAGER_NET_CHECK_NPI_EONS_RET(npi);
+
+       plmn = tcore_network_get_plmn(npi->co_network);
+       if (G_UNLIKELY(!plmn)) {
+               err("plmn is NULL");
+               return FALSE;
+       }
+
+       imsi = tcore_sim_get_imsi(npi->co_sim);
+       if (G_UNLIKELY(!imsi)) {
+               err("imsi is NULL");
+               is_matched = FALSE;
+               goto OUT;
+       }
+
+       if (g_strcmp0(plmn, imsi->plmn) == 0) {
+               info("currnet plmn(%s) and sim plmn(%s) are matching", plmn, imsi->plmn);
+               is_matched = TRUE;
+       } else {
+               info("currnet plmn(%s) and sim plmn(%s) are not matching", plmn, imsi->plmn);
+       }
+
+ OUT:
+       g_free(plmn);
+       g_free(imsi);
+
+       return is_matched;
+}
+
+static gboolean __network_is_hplmn(NetworkPrivateInfo *npi)
+{
+       /* Checks if plmn is HPLMN */
+       if (__network_is_plmn_matched(npi) == TRUE)
+               return TRUE;
+
+       /* Checks if plmn is in the spdiNetworks list */
+       if (__network_is_spdi(npi) == TRUE)
+               return TRUE;
+
+       return FALSE;
+}
+
+static void __network_post_network_identity(NetworkPrivateInfo *npi)
+{
+       Server *server;
+
+       MANAGER_NET_CHECK_NPI_EONS(npi);
+
+       server = tcore_plugin_ref_server(tcore_object_ref_plugin(npi->co_network));
+
+       if (npi->eons_data->backup_name_ind_msg) {
+               dbg("Processing delayed network identity indication");
+               /* Send Notification - Network Identity */
+               tcore_server_send_notification(server, npi->co_network, TNOTI_NETWORK_IDENTITY,
+                                              sizeof(struct tnoti_network_identity), npi->eons_data->backup_name_ind_msg);
+               g_free(npi->eons_data->backup_name_ind_msg);
+               npi->eons_data->backup_name_ind_msg = NULL;
+       } else {
+               char *plmn = NULL;
+               struct tnoti_network_identity noti = { { 0 }, };
+
+               /* Post network identity on eons ready if there is no backup network name indication */
+               dbg("posting network name on eons ready as there is no backup network name indication");
+               plmn = tcore_network_get_plmn(npi->co_network);
+               if (plmn) {
+                       g_strlcpy(noti.plmn, plmn, strlen(plmn) + 1);
+                       g_free(plmn);
+                       if (npi->eons_data->long_nitz_name && strlen(npi->eons_data->long_nitz_name) != 0 && g_strcmp0(npi->eons_data->long_nitz_name, "long_nitz") != 0)
+                               g_strlcpy(noti.full_name, npi->eons_data->long_nitz_name, strlen(npi->eons_data->long_nitz_name) + 1);
+
+                       if (npi->eons_data->short_nitz_name && strlen(npi->eons_data->short_nitz_name) != 0 && g_strcmp0(npi->eons_data->short_nitz_name, "short_nitz") != 0)
+                               g_strlcpy(noti.short_name, npi->eons_data->short_nitz_name, strlen(npi->eons_data->short_nitz_name) + 1);
+
+                       dbg("TNOTI : short_name[%s], full_name[%s], plmn[%s]",
+                           noti.short_name,
+                           noti.full_name,
+                           noti.plmn);
+
+                       /* Send Notification - Network Identity */
+                       tcore_server_send_notification(server, npi->co_network, TNOTI_NETWORK_IDENTITY,
+                                                      sizeof(struct tnoti_network_identity), &noti);
+               }
+       }
+}
+
+static void __network_compare_nwname_spn(NetworkPrivateInfo *npi, gboolean ignorecase)
+{
+       enum tcore_network_name_priority network_name_priority;
+       gchar *spn = NULL;
+       gchar *nwname = NULL;
+       CoreObject *co_network = npi ? npi->co_network : NULL;
+
+       tcore_network_get_network_name_priority(co_network, &network_name_priority);
+
+       do {
+               if (network_name_priority != TCORE_NETWORK_NAME_PRIORITY_ANY) {
+                       dbg("Condition is [%d] - Nothing to update name priority", network_name_priority);
+                       break;
+               }
+
+               /* spn */
+               spn = tcore_network_get_network_name(co_network, TCORE_NETWORK_NAME_TYPE_SPN);
+               if (!spn) {
+                       warn("No SPN - Nothing to update name priority");
+                       break;
+               }
+
+               /* plmn_name */
+               nwname = tcore_network_get_network_name(co_network, TCORE_NETWORK_NAME_TYPE_FULL);
+               if (nwname) {
+                       info("NWNAME = NITZ_FULL[%s], spn = [%s]", nwname, spn);
+                       if (strlen(nwname) == 0) {
+                               g_free(nwname);
+                               nwname = NULL;
+                       }
+               }
+
+               if (!nwname) {
+                       nwname = tcore_network_get_network_name(co_network, TCORE_NETWORK_NAME_TYPE_SHORT);
+                       if (nwname) {
+                               info("NWNAME = NITZ_SHORT[%s], spn = [%s]", nwname, spn);
+                               if (strlen(nwname) == 0) {
+                                       g_free(nwname);
+                                       nwname = NULL;
+                               }
+                       }
+               }
+
+               if (!nwname) {
+                       /* pre-define table */
+                       char mcc[4] = { 0, };
+                       char mnc[4] = { 0, };
+                       char *plmn_str = tcore_network_get_plmn(co_network);
+
+                       if (plmn_str) {
+                               struct tcore_network_operator_info *noi = NULL;
+                               g_snprintf(mcc, 4, "%s", plmn_str);
+                               g_snprintf(mnc, 4, "%s", plmn_str + 3);
+                               if (mnc[2] == '#')
+                                       mnc[2] = '\0';
+
+                               g_free(plmn_str);
+                               noi = tcore_network_operator_info_find(co_network, mcc, mnc);
+                               if (noi) {
+                                       info("NWNAME = PREDEFINED TABLE[%s], spn = [%s]", noi->name, spn);
+                                       nwname = g_strdup(noi->name);
+                               }
+                       }
+               }
+
+               if (!nwname) {
+                       warn("No NWNAME - Nothing to update name priority");
+                       break;
+               }
+
+               if (ignorecase) {
+                       if (g_ascii_strcasecmp(spn, nwname) == 0) {
+                               tcore_network_set_network_name_priority(co_network, TCORE_NETWORK_NAME_PRIORITY_NETWORK);
+                               dbg("SPN == NWNAME (ignorecase). Change priority to (%d)", TCORE_NETWORK_NAME_PRIORITY_NETWORK);
+                       }
+               } else {
+                       if (g_strcmp0(spn, nwname) == 0) {
+                               tcore_network_set_network_name_priority(co_network, TCORE_NETWORK_NAME_PRIORITY_NETWORK);
+                               dbg("SPN == NWNAME. Change priority to (%d)", TCORE_NETWORK_NAME_PRIORITY_NETWORK);
+                       }
+               }
+       } while (0);
+
+       g_free(spn);
+       g_free(nwname);
+}
+
+static void __network_apply_operator_features(NetworkPrivateInfo *npi)
+{
+       if (tfeature_is_supported(TFEATURE_FUNCTION_DISPLAY_CHN_SPN)) {
+               dbg("Update China spn display");
+               __network_update_china_spn_display(npi);
+               __network_compare_nwname_spn(npi, FALSE);
+       } else if (tfeature_is_supported(TFEATURE_FUNCTION_DISPLAY_PLMN_NAME_ONLY)) {
+               dbg("Display plmn name only");
+               if (G_LIKELY(npi))
+                       tcore_network_set_network_name_priority(npi->co_network, TCORE_NETWORK_NAME_PRIORITY_NETWORK);
+       } else {
+               __network_compare_nwname_spn(npi, FALSE);
+       }
+
+       if (tfeature_is_supported(TFEATURE_FUNCTION_DISPLAY_LAC_NETNAME))
+               __network_update_lac_netname(npi);
+
+}
+
+static void __network_load_spn_conf_xml(char *docname, char *groupname, void **i_doc, void **i_root_node)
+{
+       xmlDocPtr *doc = (xmlDocPtr *)i_doc;
+       xmlNodePtr *root_node = (xmlNodePtr *)i_root_node;
+
+       dbg("docname:%s, groupname:%s", docname, groupname);
+
+       *doc = xmlParseFile(docname);
+       if (*doc) {
+               *root_node = xmlDocGetRootElement(*doc);
+               if (*root_node) {
+                       dbg("*root_node->name:%s", (*root_node)->name);
+                       if (0 == xmlStrcmp((*root_node)->name, (const xmlChar *)groupname)) {
+                               *root_node = (*root_node)->xmlChildrenNode;
+                       } else {
+                               xmlFreeDoc(*doc);
+                               *doc = NULL;
+                               *root_node = NULL;
+                       }
+               } else {
+                       xmlFreeDoc(*doc);
+                       *doc = NULL;
+               }
+       } else
+               err("Cannot parse doc(%s)", docname);
+}
+
+static void __network_unload_spn_conf_xml(void **i_doc, void **i_root_node)
+{
+       xmlDocPtr *doc = (xmlDocPtr *)i_doc;
+       xmlNodePtr *root_node = (xmlNodePtr *)i_root_node;
+
+       dbg("unloading XML");
+       if (doc && *doc) {
+               xmlFreeDoc(*doc);
+               *doc = NULL;
+               if (root_node)
+                       *root_node = NULL;
+       }
+}
+
+static gboolean __network_load_mcc_mnc_oper_list_from_mvno_table(CoreObject *co_network, const char *plmn)
+{
+       struct tcore_network_operator_info *noi = NULL;
+       struct tel_sim_imsi *imsi = NULL;
+       CoreObject *co_sim = NULL;
+       unsigned int i = 0;
+       struct mvno_info {
+               char operator_plmn[6 + 1];
+               char imsi_plmn[6 + 1];
+               char sp_code[9 + 1];
+               char operator_name[40 + 1];
+       };
+       struct mvno_info mvno_table[] = {
+               /* Chile*/
+               { "73002", "73008", "", "vtr" },
+               { "73002", "73007", "01", "Gtd_Telsur" },
+               { "73002", "73007", "02", "Virgin" },
+               { "73002", "73007", "03", "GTEL Netline" },
+               { "73002", "73007", "04", "Colo-Colo" },
+               { "73001", "73001", "300", "Falabella" },
+               { "73001", "73010", "300", "Falabella" },
+               { "73001", "73009", "", "Nextel R" },
+               { "73010", "73001", "300", "Falabella" },
+               { "73010", "73010", "300", "Falabella" },
+               { "73010", "73009", "", "Nextel R" },
+               /* Colombia*/
+               { "732103", "732130", "", "Avantel 4G LTE" },
+               { "732111", "732130", "", "Avantel 4G LTE" },
+               { "732123", "732130", "", "Avantel 4G LTE" },
+               { "732101", "732130", "", "Avantel 4G LTE" },
+               { "732103", "732103", "017", "ETB 4G" },
+               { "732103", "732187", "", "ETB 4G" },
+               { "732103", "732103", "054", "Exito" },
+               { "732103", "732103", "055", "Exito" },
+               { "732103", "732103", "018", "Uff Movil" },
+               { "732103", "732103", "019", "Uff Movil" },
+               { "732103", "732103", "024", "UNE" },
+               { "732103", "732103", "0027", "UNE" },
+               { "732103", "732103", "0028", "UNE" },
+               { "732103", "732103", "0029", "UNE" },
+               { "33403", "334090", "", "NextelXT" },
+               { "33403", "334090", "", "NextelXT" },
+               { "334030", "334090", "", "NextelXT" },
+               { "334030", "334090", "", "NextelXT" },
+               { "732123", "732123", "900", "Virgin Mobile" },
+               { "732123", "732154", "", "Virgin Mobile" },
+       };
+
+       if (plmn == NULL) {
+               err("plmn is NULL.");
+               goto OUT;
+       }
+
+       co_sim = tcore_plugin_ref_core_object(tcore_object_ref_plugin(co_network), CORE_OBJECT_TYPE_SIM);
+       imsi = tcore_sim_get_imsi(co_sim);
+       if (imsi == NULL) {
+               err("imsi is NULL. SIM is not init_completed yet.");
+               goto OUT;
+       }
+
+       noi = g_malloc0(sizeof(struct tcore_network_operator_info));
+       dbg("Operator PLMN[%s], SIM PLMN[%s], MSIN[%s]", plmn, imsi->plmn, imsi->msin);
+       for (i = 0; i < sizeof(mvno_table) / sizeof(struct mvno_info); i++) {
+               if (strncmp(plmn, mvno_table[i].operator_plmn, strlen(plmn)) != 0)
+                       continue;
+
+               if (strncmp(imsi->plmn, mvno_table[i].imsi_plmn, strlen(imsi->plmn)) == 0) {
+                       info("Operator[PLMN[%s], SIM PLMN[%s], MSIN[%s]], MVNO Table[operator_plmn[%s], sim_plmn[%s], sp_code[%s], Oprator Name[%s]]",
+                            plmn, imsi->plmn, imsi->msin,
+                            mvno_table[i].operator_plmn, mvno_table[i].imsi_plmn, mvno_table[i].sp_code, mvno_table[i].operator_name);
+                       if (strlen(mvno_table[i].sp_code) == 0 || g_str_has_prefix(imsi->msin, mvno_table[i].sp_code) == TRUE) {
+                               g_snprintf(noi->mcc, 4, "%s", &mvno_table[i].operator_plmn[0]);
+                               g_snprintf(noi->mnc, 4, "%s", &mvno_table[i].operator_plmn[3]);
+                               g_snprintf(noi->name, NETWORK_MAX_NETWORK_NAME_LEN + 1, "%s", mvno_table[i].operator_name);
+                               noi->type = TCORE_NETWORK_OPERATOR_INFO_TYPE_DELTA_DB;  /* just set as DELTA_DB (same priority)*/
+                               info("[MVNO] load name from MVNO TABLE : mcc[%s] mnc[%s] name[%s] type:[%d]", noi->mcc, noi->mnc, noi->name, noi->type);
+                               tcore_network_operator_info_add(co_network, noi);
+                               g_free(noi);
+                               g_free(imsi);
+                               return TRUE;
+                       }
+               }
+       }
+ OUT:
+       g_free(noi);
+       g_free(imsi);
+       return FALSE;
+}
+
+static void __network_load_lac_netname_info(NetworkPrivateInfo *npi)
+{
+       struct tel_sim_imsi *imsi = NULL;
+       gboolean is_vivo_operator = FALSE;
+
+       MANAGER_NET_CHECK_NPI_EONS(npi);
+
+       if (npi->eons_data->lac_netname_info) {
+               dbg("[LACNETNAME] already loaded");
+               return;
+       }
+
+       imsi = tcore_sim_get_imsi(npi->co_sim);
+       if (!imsi || strlen(imsi->plmn) == 0) {
+               info("[LACNETNAME] Cannot find SIM plmn yet");
+               goto EXIT;
+       }
+
+       npi->eons_data->lac_netname_info = g_malloc0(sizeof(LacNetnameInfo));
+
+       if ((g_strcmp0(imsi->plmn, "72406") == 0) || (g_strcmp0(imsi->plmn, "72410") == 0)
+           || (g_strcmp0(imsi->plmn, "72411") == 0) || (g_strcmp0(imsi->plmn, "72423") == 0)) {
+               info("[LACNETNAME] VIVO operator SIM (%s) card.", imsi->plmn);
+               is_vivo_operator = TRUE;
+       } else {
+               info("[LACNETNAME] SIM (%s) was not matched. lac netname will not be used", imsi->plmn);
+       }
+
+       if (is_vivo_operator) {
+               AreaCodeInfo vivo_table[] = {
+                       { "11", "SP" }, { "12", "SP" }, { "13", "SP" }, { "14", "SP" }, { "15", "SP" },
+                       { "16", "SP" }, { "17", "SP" }, { "18", "SP" }, { "19", "SP" }, { "21", "RJ" },
+                       { "22", "RJ" }, { "24", "RJ" }, { "27", "ES" }, { "28", "ES" }, { "31", "MG" },
+                       { "32", "MG" }, { "33", "MG" }, { "34", "MG" }, { "35", "MG" }, { "37", "MG" },
+                       { "38", "MG" }, { "41", "PR" }, { "42", "PR" }, { "43", "PR" }, { "44", "PR" },
+                       { "45", "PR" }, { "46", "PR" }, { "47", "SC" }, { "48", "SC" }, { "49", "SC" },
+                       { "51", "RS" }, { "53", "RS" }, { "54", "RS" }, { "55", "RS" }, { "61", "DF" },
+                       { "62", "GO" }, { "63", "TO" }, { "64", "GO" }, { "65", "MT" }, { "66", "MT" },
+                       { "67", "MS" }, { "68", "AC" }, { "69", "RO" }, { "71", "BA" }, { "73", "BA" },
+                       { "74", "BA" }, { "75", "BA" }, { "77", "BA" }, { "79", "SE" }, { "81", "PE" },
+                       { "82", "AL" }, { "83", "PB" }, { "84", "RN" }, { "85", "CE" }, { "86", "PI" },
+                       { "87", "PE" }, { "88", "CE" }, { "89", "PI" }, { "91", "PA" }, { "92", "AM" },
+                       { "93", "PA" }, { "94", "PA" }, { "95", "RR" }, { "96", "AP" }, { "97", "AM" },
+                       { "98", "MA" }, { "99", "MA" },
+               };
+
+               unsigned int i = 0;
+               npi->eons_data->lac_netname_info->lac_netname_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+               if (!npi->eons_data->lac_netname_info->lac_netname_hash) {
+                       err("[LACNETNAME] Cannot create lac_netname_hash");
+                       g_free(npi->eons_data->lac_netname_info);
+                       npi->eons_data->lac_netname_info = NULL;
+                       goto EXIT;
+               }
+
+               for (i = 0; i < sizeof(vivo_table) / sizeof(AreaCodeInfo); i++) {
+                       dbg("[LACNETNAME] [%d] Added to hash [%s] (%s)", i, vivo_table[i].areacode, vivo_table[i].state);
+                       g_hash_table_insert(npi->eons_data->lac_netname_info->lac_netname_hash, g_strdup(vivo_table[i].areacode), g_strdup(vivo_table[i].state));
+               }
+               info("[LACNETNAME] [%d] Items was added for VIVO operator", (sizeof(vivo_table) / sizeof(AreaCodeInfo)));
+       }
+ EXIT:
+       g_free(imsi);
+}
+
+/* Loads operator info from the database */
+static void __network_load_network_operator_info(CoreObject *co_network, const char *plmn)
+{
+       TcorePlugin *plugin = tcore_object_ref_plugin(co_network);
+       struct tcore_network_operator_info *noi = NULL;
+       char mcc[4] = { 0, };
+       const char *mnc;
+
+       if (!plmn) {
+               err("plmn is NULL");
+               return;
+       }
+
+       if (strlen(plmn) < 4) {
+               err("strlen of plmn is %d", strlen(plmn));
+               return;
+       }
+
+       memcpy(mcc, plmn, 3);
+       mnc = plmn + 3;
+
+       if (atoi(mcc) == 0) {
+               err("atoi(mcc) is Zero. mcc[%s]", mcc);
+               return;
+       }
+
+       if (tfeature_is_supported(TFEATURE_FUNCTION_DISPLAY_PLMN_FAKING_4MVNO)) {
+               CoreObject *co_sim = NULL;
+               struct tel_sim_imsi *imsi = NULL;
+
+               co_sim = tcore_plugin_ref_core_object(tcore_object_ref_plugin(co_network), CORE_OBJECT_TYPE_SIM);
+               imsi = tcore_sim_get_imsi(co_sim);
+               if (imsi == NULL) {
+                       err("imsi is NULL. SIM is not init_completed yet.");
+                       return;
+               } else if (strlen(imsi->plmn) < 5) {
+                       err("sim plmn length is invalid.");
+                       g_free(imsi);
+                       return;
+               } else {
+                       g_free(imsi);
+               }
+       }
+
+       noi = tcore_network_operator_info_find(co_network, mcc, mnc);
+       if (noi) {
+               info("noi already available. noi(mcc[%s]mnc[%s]name[%s]type[%d]))", noi->mcc, noi->mnc, noi->name, noi->type);
+       } else {
+               if (TFEATURE_SUPPORTED == tfeature_is_supported(TFEATURE_FUNCTION_DISPLAY_PLMN_FAKING_4MVNO) &&
+                   TRUE == __network_load_mcc_mnc_oper_list_from_mvno_table(co_network, plmn))
+                       info("Operator info is loaded from sp code table");
+               else if (tcore_network_load_mcc_mnc_oper_list_from_db(plugin, co_network, mcc, mnc, NETWORK_MCC_MNC_OPER_LIST_CSC_DB) == TRUE)
+                       info("Operator info is loaded from CSC database");
+               else if (tcore_network_load_mcc_mnc_oper_list_from_db(plugin, co_network, mcc, mnc, NETWORK_MCC_MNC_OPER_LIST_GSMA_DB) == TRUE)
+                       info("Operator info is loaded from GSMA database");
+               else
+                       warn("Operator info is not found in CSC and GSMA db");
+       }
+}
+
+static char *__network_get_override_spn(NetworkPrivateInfo *npi, char *ef_spn, struct tel_sim_imsi *imsi)
+{
+       char *final_spn = NULL, *xml_spn = NULL, *xml_imsi_subset = NULL;
+       gboolean spn_override = FALSE;
+
+       do {
+               if (G_UNLIKELY(!npi || !npi->eons_data))
+                       break;
+
+               if (!npi->eons_data->spn_override_info)
+                       manager_network_load_spn_override_info(npi);
+
+               if (!npi->eons_data->spn_override_info)
+                       break;
+
+               if (!imsi)
+                       break;
+
+               xml_spn = npi->eons_data->spn_override_info->spn;
+               xml_imsi_subset = npi->eons_data->spn_override_info->imsi_subset;
+
+               if (!xml_spn)
+                       break;
+
+               info("[SPN_OVERRIDE] xml_spn:[%s] msin:[%s] subset:[%s] ", xml_spn ? xml_spn : "", imsi->msin, xml_imsi_subset ? xml_imsi_subset : "");
+
+               if (!xml_imsi_subset) {
+                       info("[SPN_OVERRIDE] SPN found. do SPN override");
+                       spn_override = TRUE;
+                       break;
+               }
+
+               if (g_str_has_prefix(imsi->msin, xml_imsi_subset)) {
+                       info("[SPN_OVERRIDE] Subset matched. do SPN override");
+                       spn_override = TRUE;
+                       break;
+               } else {
+                       info("[SPN_OVERRIDE] SPN is existed, but Subset is not matched");
+                       break;
+               }
+       } while (0);
+
+       if (spn_override)
+               final_spn = xml_spn;
+       else
+               final_spn = ef_spn;
+
+       return final_spn;
+}
+
+static char *__network_get_lac_netname(NetworkPrivateInfo *npi, unsigned int lac)
+{
+       char *lac_netname = NULL;
+       gchar *key = NULL;
+       gchar *code = NULL;
+
+       do {
+               if (G_UNLIKELY(!npi || !npi->eons_data))
+                       break;
+
+               if (!npi->eons_data->lac_netname_info) {
+                       dbg("[LACNETNAME] Loading netname_info");
+                       __network_load_lac_netname_info(npi);
+               }
+
+               if (npi->eons_data->lac_netname_info) {
+                       if (!npi->eons_data->lac_netname_info->lac_netname_hash)
+                               break;
+
+                       key = g_strdup_printf("%d", (lac % 100));
+                       code = g_hash_table_lookup(npi->eons_data->lac_netname_info->lac_netname_hash, key);
+                       if (code)
+                               lac_netname = g_strdup_printf("%s %s", code, key);
+
+                       dbg("[LACNETNAME] find lac name(%s) from lac(%d), key(%s), code (%s)", lac_netname, lac, key, code);
+                       g_free(key);
+               }
+       } while (0);
+
+       return lac_netname;
+}
+
+static void __network_get_exceptional_name_from_plmn(NetworkPrivateInfo *npi, char *name, const char *plmn)
+{
+       MANAGER_NET_CHECK_NPI_EONS(npi);
+       if (G_UNLIKELY(!plmn) || G_UNLIKELY(strlen(plmn) < 4)) {
+               dbg("Invalid plmn");
+               return;
+       }
+
+       if (((g_strcmp0(plmn, "45400") == 0) || (g_strcmp0(plmn, "45402") == 0) ||
+            (g_strcmp0(plmn, "45410") == 0) || (g_strcmp0(plmn, "45418") == 0))
+           && (FALSE == tcore_network_get_roaming_state(npi->co_network))) {
+               struct tel_sim_spn *spn = tcore_sim_get_spn(npi->co_sim);
+               if (spn && strlen((char *)spn->spn) > 0) {
+                       dbg("CSL Network, SPN(%s) sholud be displayed instead of PLMN(%s)", spn->spn, name);
+                       memset(name, 0, NETWORK_MAX_NETWORK_NAME_LEN + 1);
+                       memcpy(name, spn->spn, strlen((const char *)spn->spn));
+               } else
+                       warn("Cannot get spn");
+               g_free(spn);
+       } else if ((g_strcmp0(plmn, "50502") == 0) && (TRUE == tcore_network_get_roaming_state(npi->co_network))) {
+               /* in Vodaphone AU requirement */
+               /* check for roaming status if in roaming set name to Vodafone AU R */
+               dbg("Vodafone AU R updated due to operator request ");
+               memset(name, 0, NETWORK_MAX_NETWORK_NAME_LEN + 1);
+               memcpy(name, "Vodafone AU R", strlen("Vodafone AU R"));
+       }
+}
+
+static char *__network_get_exceptional_eons_name(NetworkPrivateInfo *npi)
+{
+       gboolean is_hplmn = FALSE;
+
+       if (G_UNLIKELY(!npi || !npi->eons_data))
+               return NULL;
+
+       is_hplmn = __network_is_hplmn(npi);
+       if (is_hplmn) {
+               info("Home PLMN and PNN exist. We can set PNN[0] to EONS name");
+               if (strlen((char *)npi->eons_data->pnn->list[0].short_name) != 0 ||
+                   strlen((char *)npi->eons_data->pnn->list[0].full_name) != 0) {
+                       unsigned short short_buf_len, long_buf_len;
+                       unsigned char short_buf[255] = { 0, };
+                       unsigned char long_buf[255] = { 0, };
+
+                       tcore_util_convert_string_to_utf8(short_buf, &short_buf_len, ALPHABET_FORMAT_8BIT_DATA,
+                                                         (const unsigned char *)npi->eons_data->pnn->list[0].short_name,
+                                                         strlen((const char *)npi->eons_data->pnn->list[0].short_name));
+                       tcore_util_convert_string_to_utf8(long_buf, &long_buf_len, ALPHABET_FORMAT_8BIT_DATA,
+                                                         (const unsigned char *)npi->eons_data->pnn->list[0].full_name,
+                                                         strlen((const char *)npi->eons_data->pnn->list[0].full_name));
+
+                       if (strlen((const char *)long_buf) != 0)
+                               return g_strdup((const char *)long_buf);
+                       else if (strlen((const char *)short_buf) != 0)
+                               return g_strdup((const char *)short_buf);
+               } else {
+                       warn("No ONS name in PNN");
+               }
+       }
+
+       return NULL;
+}
+
+static char *__network_get_eons_name(NetworkPrivateInfo *npi, const char *plmn, gboolean use_lac)
+{
+       gboolean is_plmn_matched = TRUE;
+       gboolean is_opl_matched = FALSE;
+       gboolean is_na_plmn = FALSE;
+       unsigned int cur_lac = 0;
+       int ref_pnn_id = 0;
+       int i = 0, j = 0;
+       char *network_plmn = NULL;
+
+       if (!npi || !npi->eons_data || !npi->eons_data->opl || !npi->eons_data->pnn) {
+               warn("NPI Error");
+               return NULL;
+       }
+
+       if (!npi->eons_data->is_eons_ready) {
+               warn("eons not ready");
+               return NULL;
+       }
+
+       if (npi->eons_data->pnn->pnn_count == 0) {
+               dbg("pnn_count is Zero");
+               return NULL;
+       }
+
+       if (npi->eons_data->opl->opl_count == 0) {
+               dbg("opl_count is Zero");
+               return __network_get_exceptional_eons_name(npi);
+       }
+
+       if (G_UNLIKELY(!plmn)) {
+               warn("plmn is NULL");
+               return NULL;
+       }
+
+       network_plmn = g_strdup(plmn);
+
+       /* if NA PLMN & the length is 5 then add '0' at 6th digit of PLMN*/
+       if (strlen(network_plmn) == 5) {
+               if (tcore_util_is_country_NA(network_plmn) == TRUE) {
+                       char buf[7] = { 0, };
+                       strcpy(buf, network_plmn);
+                       strcat(buf, "0");
+                       g_free(network_plmn);
+                       network_plmn = g_strdup(buf);
+
+                       is_na_plmn = TRUE;
+               }
+       }
+
+       tcore_network_get_lac(npi->co_network, &cur_lac);
+
+       info("network_plmn:[%s], use_lac:[%d] cur_lac:[%d], opl_count:[%d], pnn_count:[%d]",
+            network_plmn, use_lac, cur_lac, npi->eons_data->opl->opl_count, npi->eons_data->pnn->pnn_count);
+
+       for (i = 0; i < npi->eons_data->opl->opl_count; i++) {
+               is_plmn_matched = TRUE;
+               ref_pnn_id = npi->eons_data->opl->list[i].rec_identifier - 1;
+
+               /* if NA PLMN & the length is 5 then add '0' at 6th digit of PLMN*/
+               if (is_na_plmn && strlen((char *)npi->eons_data->opl->list[i].plmn) == 5) {
+                       if (tcore_util_is_country_NA((char *)npi->eons_data->opl->list[i].plmn) == TRUE) {
+                               npi->eons_data->opl->list[i].plmn[5] = '0';
+                               npi->eons_data->opl->list[i].plmn[6] = 0x00;
+                       }
+               }
+
+               info("opl[%d] - plmn[%s], ref_pnn_id[%d], lac_from[%d]~lac_to[%d]",
+                    i,
+                    npi->eons_data->opl->list[i].plmn,
+                    ref_pnn_id,
+                    npi->eons_data->opl->list[i].lac_from,
+                    npi->eons_data->opl->list[i].lac_to);
+
+               /* Check 'PLMN in EF-OPL' and 'current PLMN' are matched*/
+               for (j = 0; j < (int)strlen(network_plmn); j++) {
+                       if (npi->eons_data->opl->list[i].plmn[j] == 'D') {
+                               /* 'D' is wild character*/
+                               continue;
+                       }
+                       if (npi->eons_data->opl->list[i].plmn[j] != network_plmn[j]) {
+                               is_plmn_matched = FALSE;
+                               break;
+                       }
+               }
+               if (is_plmn_matched == FALSE)
+                       continue;
+
+               /* Check 'PNN record id in EF-OPL' is valid*/
+               if (ref_pnn_id < 0 || ref_pnn_id >= npi->eons_data->pnn->pnn_count) {
+                       info("pnn_id(%d) is not vaild. use NITZ name", ref_pnn_id);
+                       continue; /* Check next opl */
+               }
+
+               if (use_lac) {
+                       /* Check Current LAC is present in the LAC range in the opl list */
+                       if (cur_lac >= npi->eons_data->opl->list[i].lac_from && cur_lac <= npi->eons_data->opl->list[i].lac_to) {
+                               if (ref_pnn_id < 0 || ref_pnn_id >= npi->eons_data->pnn->pnn_count) {
+                                       /* Check 'PNN record id in EF-OPL' is valid */
+                                       info("LAC and PLMN are matched. But, invalid pnn_id(%d). use NITZ name", ref_pnn_id);
+                               } else if (strlen((char *)npi->eons_data->pnn->list[ref_pnn_id].short_name) != 0
+                                          || strlen((char *)npi->eons_data->pnn->list[ref_pnn_id].full_name) != 0) {
+                                       dbg("LAC matched with EF-PNN record[%d].", ref_pnn_id);
+                                       is_opl_matched = TRUE;
+                               } else {
+                                       dbg("LAC matched with EF-PNN record[%d] but names aren't valid.", ref_pnn_id);
+                               }
+                               break;
+                       } else {
+                               /* LAC is not matched. Check Next OPL*/
+                               continue;
+                       }
+               } else {
+                       /* Check 'PNN record id in EF-OPL' is valid */
+                       if (ref_pnn_id < 0 || ref_pnn_id >= npi->eons_data->pnn->pnn_count)
+                               warn("PLMN are matched. But, invalid pnn_id(%d). use NITZ name", ref_pnn_id);
+                       else
+                               is_opl_matched = TRUE;
+
+                       break;
+               }
+       }
+       g_free(network_plmn);
+
+       if (is_opl_matched) {
+               unsigned short short_buf_len, long_buf_len;
+               unsigned char short_buf[255] = { 0, };
+               unsigned char long_buf[255] = { 0, };
+
+               tcore_util_convert_string_to_utf8(short_buf, &short_buf_len, ALPHABET_FORMAT_8BIT_DATA,
+                                                 (const unsigned char *)npi->eons_data->pnn->list[ref_pnn_id].short_name,
+                                                 strlen((const char *)npi->eons_data->pnn->list[ref_pnn_id].short_name));
+               tcore_util_convert_string_to_utf8(long_buf, &long_buf_len, ALPHABET_FORMAT_8BIT_DATA,
+                                                 (const unsigned char *)npi->eons_data->pnn->list[ref_pnn_id].full_name,
+                                                 strlen((const char *)npi->eons_data->pnn->list[ref_pnn_id].full_name));
+
+               if (strlen((const char *)long_buf) != 0)
+                       return g_strdup((const char *)long_buf);
+               else if (strlen((const char *)short_buf) != 0)
+                       return g_strdup((const char *)short_buf);
+       }
+
+       return NULL;
+}
+
+static char *__network_get_override_spn_display_rule(NetworkPrivateInfo *npi)
+{
+       char *xml_spn_display_rule = NULL;
+
+       do {
+               if (G_UNLIKELY(!npi || !npi->eons_data))
+                       break;
+
+               if (!npi->eons_data->spn_override_info)
+                       manager_network_load_spn_override_info(npi);
+
+               if (npi->eons_data->spn_override_info)
+                       xml_spn_display_rule = npi->eons_data->spn_override_info->spn_display_rule;
+
+       } while (0);
+       return xml_spn_display_rule;
+}
+
+static gboolean __network_get_override_name_priority(NetworkPrivateInfo *npi, enum tcore_network_name_priority *priority)
+{
+       char *spn_display_rule = __network_get_override_spn_display_rule(npi);
+
+       if (!spn_display_rule)
+               return FALSE;
+
+       if (g_strcmp0(spn_display_rule, "SPN_RULE_SHOW_SPN") == 0)
+               *priority = TCORE_NETWORK_NAME_PRIORITY_SPN;
+       else if (g_strcmp0(spn_display_rule, "SPN_RULE_SHOW_PLMN") == 0)
+               *priority = TCORE_NETWORK_NAME_PRIORITY_NETWORK;
+       else
+               return FALSE;
+
+       return TRUE;
+}
+
+static void __network_get_china_spn_display_priority(CoreObject *co_network, char *sim_plmn,
+                                                    char *spn_name, gboolean is_roaming, enum tcore_network_name_priority *new_priority, enum tcore_network_name_priority *current_priority)
+{
+       enum tcore_network_name_priority priority;
+
+       tcore_network_get_network_name_priority(co_network, &priority);
+       *new_priority = *current_priority = priority;
+
+       if (sim_plmn) {
+               if (((g_strcmp0(sim_plmn, "45400") == 0) || (g_strcmp0(sim_plmn, "45402") == 0) ||
+                    (g_strcmp0(sim_plmn, "45410") == 0) || (g_strcmp0(sim_plmn, "45418") == 0)) && spn_name && !is_roaming) {
+                       dbg("Setting priority to SPN. sim_plmn:[%s], is_roaming:[%d]", sim_plmn, is_roaming);
+                       *new_priority = TCORE_NETWORK_NAME_PRIORITY_SPN;
+               } else {
+                       dbg("Setting priority to NETWORK. sim_plmn:[%s], is_roaming:[%d]", sim_plmn, is_roaming);
+                       *new_priority = TCORE_NETWORK_NAME_PRIORITY_NETWORK;
+               }
+       } else {
+               dbg("No sim plmn. Set to Current priority (%d)", priority);
+       }
+
+}
+
+void __network_update_lac_netname(NetworkPrivateInfo *npi)
+{
+       char *new_name = NULL, *old_name = NULL;
+       gboolean is_updated = FALSE;
+       unsigned int lac = 0;
+
+       MANAGER_NET_CHECK_NPI_EONS(npi);
+
+       if (!npi->eons_data->lac_netname_info)
+               return;
+
+       /* Do not set lac_netname in roaming Area */
+       if (tcore_network_get_roaming_state(npi->co_network) == TRUE)
+               new_name = NULL;
+       else {
+               tcore_network_get_lac(npi->co_network, &lac);
+               new_name = __network_get_lac_netname(npi, lac);
+       }
+
+       old_name = npi->eons_data->lac_netname_info->lac_netname;
+
+       if (new_name) {
+               if (!old_name || g_strcmp0(old_name, new_name))
+                       is_updated = TRUE;
+       } else {
+               if (old_name)
+                       is_updated = TRUE;
+       }
+
+       if (is_updated) {
+               info("[LACNETNAME] name updated (%s) -> (%s)", old_name ? old_name : "", new_name ? new_name : "");
+               g_free(npi->eons_data->lac_netname_info->lac_netname);
+
+               if (new_name) {
+                       npi->eons_data->lac_netname_info->lac_netname = g_strdup(new_name);
+                       if (vconf_set_str(VCONFKEY_TELEPHONY_LAC_NETNAME, new_name) < 0)
+                               warn("[LACNETNAME] Fail to set lac netname");
+               } else {
+                       npi->eons_data->lac_netname_info->lac_netname = NULL;
+                       if (vconf_set_str(VCONFKEY_TELEPHONY_LAC_NETNAME, "") < 0)
+                               warn("[LACNETNAME] Fail to set lac netname");
+               }
+       }
+       g_free(new_name);
+}
+
+static void __network_update_nwname(NetworkPrivateInfo *npi,
+                                   NetworkNameType type, const char *short_name, const char *long_name)
+{
+       gboolean name_present = FALSE;
+
+       MANAGER_NET_CHECK_NPI_EONS(npi);
+
+       if (type > npi->eons_data->name_type) {
+               warn("low priority name setting request.(req type[%d] saved nw_name_type[%d])",
+                    type, npi->eons_data->name_type);
+               return;
+       }
+
+       dbg("saved network name(short[%s] long[%s]). nw_name_type[%d]",
+           short_name, long_name, npi->eons_data->name_type);
+
+       if (short_name && strlen(short_name) != 0) {
+               tcore_network_set_network_name(npi->co_network, TCORE_NETWORK_NAME_TYPE_SHORT, short_name);
+               name_present = TRUE;
+       }
+
+       if (long_name && strlen(long_name) != 0) {
+               tcore_network_set_network_name(npi->co_network, TCORE_NETWORK_NAME_TYPE_FULL, long_name);
+               name_present = TRUE;
+       } else {
+               /*
+                * If long name is empty, set short name to long name
+                * (long name is default)
+                */
+               tcore_network_set_network_name(npi->co_network, TCORE_NETWORK_NAME_TYPE_FULL, short_name);
+       }
+
+       if (name_present)
+               npi->eons_data->name_type = type;
+}
+
+static void __network_update_eons(NetworkPrivateInfo *npi)
+{
+       char *network_plmn = NULL;
+       char *eonsname = NULL;
+
+       MANAGER_NET_CHECK_NPI_EONS(npi)
+
+       network_plmn = tcore_network_get_plmn(npi->co_network);
+       if (G_UNLIKELY(!network_plmn)) {
+               warn("network plmn is NULL");
+               return;
+       }
+
+       eonsname = __network_get_eons_name(npi, network_plmn, TRUE);
+       if (eonsname) {
+               if (tcore_sim_is_jio_sim(npi->co_sim) && __network_is_vowifi_registered(npi)) {
+                       info("VoWiFi registered. Change eons network name. [%s] -> [%s]", eonsname, "Jio WiFi");
+                       g_free(eonsname);
+                       eonsname = g_strdup("Jio WiFi");
+               }
+               __network_update_nwname(npi, NETWORK_NAME_TYPE_EONS, (const char *)eonsname, (const char *)eonsname);
+               tcore_network_update_mcc_mnc_oper_list(npi->co_network, network_plmn, eonsname, TCORE_NETWORK_OPERATOR_INFO_TYPE_EONS);
+               g_free(eonsname);
+       } else {
+               if (npi->eons_data->name_type == NETWORK_NAME_TYPE_EONS) {
+                       char mcc[4] = { 0, };
+                       const char *mnc;
+                       struct tcore_network_operator_info *noi = NULL;
+
+                       memcpy(mcc, network_plmn, 3);
+                       mnc = network_plmn + 3;
+
+                       noi = tcore_network_operator_info_find(npi->co_network, mcc, mnc);
+                       if (noi && noi->type == TCORE_NETWORK_OPERATOR_INFO_TYPE_EONS) {
+                               tcore_network_operator_info_remove(npi->co_network, noi);
+                               info("EONS noi was removed");
+                       }
+
+                       info("Current plmn is not eons range. change name type to NITZ");
+                       npi->eons_data->name_type = NETWORK_NAME_TYPE_NITZ;
+               }
+       }
+
+       g_free(network_plmn);
+}
+
+static void __network_update_plmn_name(NetworkPrivateInfo *npi)
+{
+       char name[NETWORK_MAX_NETWORK_NAME_LEN + 1] = { 0, };
+       const char *plmn;
+
+       MANAGER_NET_CHECK_NPI_CACHE(npi);
+
+       plmn = npi->cache_data ? (const char *)npi->cache_data->current_plmn : NULL;
+       manager_network_get_name_from_plmn(npi->co_network, name, plmn);
+       if (tcore_sim_is_jio_sim(npi->co_sim) && __network_is_vowifi_registered(npi)) {
+               if (g_strcmp0(name, "Jio WiFi") != 0) {
+                       info("VoWiFi registered. Change nitz network name. [%s] -> [%s]", name, "Jio WiFi");
+                       g_strlcpy(name, "Jio WiFi", strlen("Jio WiFi")+1);
+               } else {
+                       info("VoWiFi registered. Nitz network name is already changed to [Jio WiFi]");
+               }
+       }
+       __network_update_nwname(npi, NETWORK_NAME_TYPE_NITZ, name, "");
+}
+
+static void __network_update_spn_name(NetworkPrivateInfo *npi,
+                                     NetworkSpnNameType type, const char *name)
+{
+       MANAGER_NET_CHECK_NPI_EONS(npi);
+
+       if (type > npi->eons_data->spn_name_type) {
+               warn("low priority name setting request.(req type[%d] saved type[%d])", type, npi->eons_data->spn_name_type);
+               return;
+       }
+       npi->eons_data->spn_name_type = type;
+       dbg("saved spn name[%s]. type[%d]", name, npi->eons_data->spn_name_type);
+
+       tcore_network_set_network_name(npi->co_network, TCORE_NETWORK_NAME_TYPE_SPN, name);
+}
+
+static void __network_update_name_priority(NetworkPrivateInfo *npi)
+{
+       enum tcore_network_name_priority priority = TCORE_NETWORK_NAME_PRIORITY_UNKNOWN;
+       int is_hplmn;
+       struct tel_sim_spn *spn = NULL;
+
+       MANAGER_NET_CHECK_NPI_EONS(npi);
+
+       spn = tcore_sim_get_spn(npi->co_sim);
+       if (!spn) {
+               warn("Cannot get spn[%s]", spn ? spn : NULL);
+               goto out;
+       }
+
+       if (strlen((char *)spn->spn) == 0) {
+               dbg("no spn name. set priority to network name only");
+               g_free(spn);
+               goto out;
+       }
+
+       if (tcore_sim_is_jio_sim(npi->co_sim) && __network_is_vowifi_registered(npi)) {
+               info("VoWiFi registered. Update priority to network");
+               g_free(spn);
+               goto out;
+       }
+
+       is_hplmn = __network_is_hplmn(npi);
+       dbg("is home plmn[%d]", is_hplmn);
+
+       /**
+        * display condition
+        *  bit[0]: 0 = display of registered PLMN name not required when registered
+        *                              PLMN is either HPLMN or a PLMN in the service provider PLMN
+        *                              list
+        *              1 = display of registered PLMN name required when registered
+        *                              PLMN is either HPLMN or a PLMN in the service provider PLMN
+        *                              list
+        *  bit[1]: 0 = display of the service provider name is required when
+        *                              registered PLMN is neither HPLMN nor a PLMN in the service
+        *                              provider PLMN list
+        *          1 = display of the service provider name is not required when
+        *                              registered PLMN is neither HPLMN nor a PLMN in the service
+        *                              provider PLMN list
+        *
+        * 0x1 => HOME PLMN BIT
+        * 0x2 => ROAMING SPN BIT
+        */
+
+       switch (spn->display_condition) {
+       case 0x0:
+               if (is_hplmn) {
+                       /* not display nwname */
+                       tcore_network_set_network_name_priority(npi->co_network, TCORE_NETWORK_NAME_PRIORITY_SPN);
+               } else {
+                       /* display spn */
+                       tcore_network_set_network_name_priority(npi->co_network, TCORE_NETWORK_NAME_PRIORITY_ANY);
+               }
+               break;
+
+       case 0x1:
+               tcore_network_set_network_name_priority(npi->co_network, TCORE_NETWORK_NAME_PRIORITY_ANY);
+               break;
+
+       case 0x2:
+               if (is_hplmn) {
+                       /* not display nwname */
+                       tcore_network_set_network_name_priority(npi->co_network, TCORE_NETWORK_NAME_PRIORITY_SPN);
+               } else {
+                       /* not display spn */
+                       tcore_network_set_network_name_priority(npi->co_network, TCORE_NETWORK_NAME_PRIORITY_NETWORK);
+               }
+               break;
+
+       case 0x3:
+               if (is_hplmn) {
+                       /* display nwname */
+                       tcore_network_set_network_name_priority(npi->co_network, TCORE_NETWORK_NAME_PRIORITY_ANY);
+               } else {
+                       /* not display spn */
+                       tcore_network_set_network_name_priority(npi->co_network, TCORE_NETWORK_NAME_PRIORITY_NETWORK);
+               }
+               break;
+       }
+
+       if (__network_get_override_name_priority(npi, &priority)) {
+               info("[SPN_OVERRIDE] Apply priority by overriden rule [%d]", priority);
+               tcore_network_set_network_name_priority(npi->co_network, priority);
+       }
+
+       if (tcore_network_get_network_name_priority(npi->co_network, &priority) == TCORE_RETURN_SUCCESS)
+               info("is_hplmn[%d] priority[%d]", is_hplmn, priority);
+
+       g_free(spn);
+       return;
+
+ out:
+       tcore_network_set_network_name_priority(npi->co_network, TCORE_NETWORK_NAME_PRIORITY_NETWORK);
+}
+
+void __network_update_china_spn_display(NetworkPrivateInfo *npi)
+{
+       struct tel_sim_imsi *imsi = NULL;
+       struct tel_sim_spn *spn = NULL;
+       gboolean is_roaming = FALSE;
+       char *sim_plmn = NULL;
+       char *spn_name = NULL;
+       enum tcore_network_name_priority current_priority, new_priority;
+
+       MANAGER_NET_CHECK_NPI_EONS(npi);
+
+       is_roaming = tcore_network_get_roaming_state(npi->co_network);
+       imsi = tcore_sim_get_imsi(npi->co_sim);
+       if (G_UNLIKELY(!imsi) || (strlen(imsi->plmn) == 0)) {
+               warn("Cannot get PLMN from IMSI");
+               goto OUT;
+       } else {
+               sim_plmn = imsi->plmn;
+       }
+
+       spn = tcore_sim_get_spn(npi->co_sim);
+       if (G_UNLIKELY(!spn) || (strlen((char *)spn->spn) == 0))
+               warn("Cannot get spn");
+       else
+               spn_name = (char *)spn->spn;
+
+       dbg("sim_plmn:[%s], spn_name:[%s], is_roaming:[%d]", sim_plmn, spn_name ? spn_name : "None", is_roaming);
+       /* China PLMN */
+       if ((g_strcmp0(sim_plmn, "46000") == 0) || (g_strcmp0(sim_plmn, "46001") == 0) || (g_strcmp0(sim_plmn, "46002") == 0)
+           || (g_strcmp0(sim_plmn, "46007") == 0) || (g_strcmp0(sim_plmn, "46008") == 0)) {
+               if (!is_roaming) {
+                       if (g_strcmp0(sim_plmn, "46001") == 0)
+                               dbg("CU operator name. (will be converted by Application)");
+                       else
+                               dbg("CMCC operator name. (will be converted by Application)");
+
+                       if (spn_name && (g_strcmp0(spn_name, "CMCC") != 0) && (g_strcmp0(spn_name, "CU") != 0)) {
+                               dbg("NW_NAME set to SPN(%s)", spn_name);
+                               __network_update_nwname(npi, NETWORK_NAME_TYPE_NITZ, spn_name, "");
+                       }
+               }
+       }
+       /* Taiwan PLMN */
+       else if ((g_strcmp0(sim_plmn, "46692") == 0) || (g_strcmp0(sim_plmn, "46601") == 0) || (g_strcmp0(sim_plmn, "46688") == 0)
+                || (g_strcmp0(sim_plmn, "46697") == 0) || (g_strcmp0(sim_plmn, "46693") == 0) || (g_strcmp0(sim_plmn, "46699") == 0)
+                || (g_strcmp0(sim_plmn, "46689") == 0)) {
+               if (!is_roaming)
+                       dbg("Taiwan nwname will be converted by Application");
+       }
+       /* Hong Kong PLMN */
+       else if ((g_strcmp0(sim_plmn, "45412") == 0) || (g_strcmp0(sim_plmn, "45413") == 0) || (g_strcmp0(sim_plmn, "45416") == 0)
+                || (g_strcmp0(sim_plmn, "45419") == 0)) {
+               if (!is_roaming)
+                       dbg("HK nwname will be converted by Application");
+
+       } else if (g_strcmp0(sim_plmn, "45407") == 0) {
+               char *plmn = NULL;
+               plmn = tcore_network_get_plmn(npi->co_network);
+               if (plmn) {
+                       if (strncmp(plmn, "460", 3) == 0)
+                               dbg("CU HK SIM card in CHINA network case. nwname will be converted by Application");
+
+                       g_free(plmn);
+               }
+       }
+
+ OUT:
+       __network_get_china_spn_display_priority(npi->co_network, sim_plmn, spn_name, is_roaming, &new_priority, &current_priority);
+       if (current_priority != new_priority) {
+               tcore_network_set_network_name_priority(npi->co_network, new_priority);
+               dbg("name priority was changed to (%d) to (%d)", current_priority, new_priority);
+       }
+
+       g_free(imsi);
+       g_free(spn);
+       return;
+}
+
+static void __network_reset_sim_network_name(CoreObject *co_network, NetworkPrivateInfo *npi)
+{
+       /* SPN */
+       tcore_network_set_network_name(co_network, TCORE_NETWORK_NAME_TYPE_SPN, NULL);
+
+       /* SPDI */
+       if (npi->eons_data->spdi == NULL) {
+               npi->eons_data->spdi = g_malloc0(sizeof(struct tel_sim_spdi));
+       } else {
+               memset(npi->eons_data->spdi, 0x0, sizeof(struct tel_sim_spdi));
+       }
+
+       /* OPL */
+       if (npi->eons_data->opl == NULL) {
+               npi->eons_data->opl = g_malloc0(sizeof(struct tel_sim_opl_list));
+       } else {
+               if (npi->eons_data->opl->list)
+                       g_free(npi->eons_data->opl->list);
+               memset(npi->eons_data->opl, 0x0, sizeof(struct tel_sim_opl_list));
+       }
+
+       /* PNN */
+       if (npi->eons_data->pnn == NULL) {
+               npi->eons_data->pnn = g_malloc0(sizeof(struct tel_sim_pnn_list));
+       } else {
+               if (npi->eons_data->pnn->list)
+                       g_free(npi->eons_data->pnn->list);
+               memset(npi->eons_data->pnn, 0x0, sizeof(struct tel_sim_pnn_list));
+       }
+
+       /* Private Info */
+       npi->eons_data->name_type = NETWORK_NAME_TYPE_NONE;
+       npi->eons_data->spn_name_type = NETWORK_SPN_NAME_TYPE_NONE;
+       npi->eons_data->sim_network_name_state = 0;
+       npi->eons_data->sim_network_name_support_list = 0;
+       npi->eons_data->is_eons_ready = FALSE;
+       info("[NETINFO] network sim memory clear");
+}
+
+void manager_network_apply_operator_name_rule(const char *plmn,
+                                             char **name_delta, char **name_long, char **name_short)
+{
+       if (tfeature_is_supported(TFEATURE_FUNCTION_DISPLAY_DELTA_AND_SHORT_NAME)) {
+               /*
+                * Basic rule is "Full Name" > "Short Name" > "TS25 List" > "PLMN"
+                * Feature rule is "Delta List" > "Short Name" > "Full Name" > "TS25 List" > "PLMN"
+                * Applications display network name base on basic rule.
+                * So, We should replace "Full Name" to "Delta" or  "Full Name" to "Short Name".
+                */
+               if (*name_delta) {
+                       dbg("Change Name priority (Delta[%s] > Short[%s] > Long[%s])",
+                           *name_delta, *name_short ? *name_short : "", *name_long ? *name_long : "");
+                       g_free(*name_long);
+                       g_free(*name_short);
+                       *name_long = g_strdup(*name_delta);
+                       *name_short = NULL;
+               } else {
+                       char *name_tmp = NULL;
+                       dbg("Change Name priority (Short > Long)");
+                       name_tmp = *name_long;
+                       *name_long = *name_short;
+                       *name_short = name_tmp;
+               }
+       } else if (tfeature_is_supported(TFEATURE_FUNCTION_DISPLAY_PLMN_FAKING_4MVNO)) {
+               if (*name_delta) {
+                       info("Change Name priority. Display Delta[%s] (ignore previous Short[%s], Long[%s])",
+                            *name_delta, *name_short ? *name_short : "", *name_long ? *name_long : "");
+                       g_free(*name_long);
+                       g_free(*name_short);
+                       *name_long = g_strdup(*name_delta);
+                       *name_short = NULL;
+               }
+       }
+}
+
+void manager_network_load_spn_override_info(NetworkPrivateInfo *npi)
+{
+       xmlNode *cur_node = NULL;
+       xmlNodePtr cur;
+       void *xml_doc = NULL, *xml_root_node = NULL;
+       char *xml_spn = NULL, *xml_imsi_subset = NULL, *xml_plmn = NULL, *xml_fake_home_on = NULL, *xml_fake_roaming_on = NULL, *xml_spn_display_rule = NULL;
+       struct tel_sim_imsi *imsi = NULL;
+       gboolean key_matched = FALSE;
+
+       MANAGER_NET_CHECK_NPI_EONS(npi);
+
+       if (npi->eons_data->spn_override_info) {
+               dbg("already loaded");
+               return;
+       }
+
+       imsi = tcore_sim_get_imsi(npi->co_sim);
+       if (!imsi || strlen(imsi->plmn) == 0) {
+               info("[SPN_OVERRIDE] Cannot find SIM plmn");
+               g_free(imsi);
+               return;
+       }
+
+       __network_load_spn_conf_xml(SPN_DATABASE_PATH, "spnOverrides", &xml_doc, &xml_root_node);
+       if (!xml_root_node) {
+               err("[SPN_OVERRIDE] Load error - Root node is NULL.");
+               g_free(imsi);
+               return;
+       }
+
+       npi->eons_data->spn_override_info = g_malloc0(sizeof(SpnOverrideInfo));
+
+       cur = xml_root_node;
+       /* Compare and update */
+       for (cur_node = cur; cur_node; cur_node = cur_node->next) {
+               if (cur_node->type == XML_ELEMENT_NODE) {
+                       xml_plmn = (char *)xmlGetProp(cur_node, (const xmlChar *)"numeric");
+                       if (xml_plmn && !g_strcmp0(xml_plmn, imsi->plmn)) {
+                               xml_spn = (char *)xmlGetProp(cur_node, (const xmlChar *)"spn");
+                               xml_imsi_subset = (char *)xmlGetProp(cur_node, (const xmlChar *)"imsi_subset");
+                               xml_fake_home_on = (char *)xmlGetProp(cur_node, (const xmlChar *)"fake_home_on");
+                               xml_fake_roaming_on = (char *)xmlGetProp(cur_node, (const xmlChar *)"fake_roaming_on");
+                               xml_spn_display_rule = (char *)xmlGetProp(cur_node, (const xmlChar *)"spn_display_rule");
+
+                               info("[SPN_OVERRIDE] [%s] - spn:[%s] subset:[%s] fakehome:[%s] fakeroam:[%s] rule:[%s] key[%s]",
+                                    xml_plmn, xml_spn, xml_imsi_subset, xml_fake_home_on, xml_fake_roaming_on, xml_spn_display_rule, imsi->msin);
+
+                               if (xml_imsi_subset) {
+                                       if (g_str_has_prefix(imsi->msin, xml_imsi_subset)) {
+                                               info("[SPN_OVERRIDE] matched subset. Use this info");
+                                               key_matched = TRUE;
+                                               g_free(npi->eons_data->spn_override_info->imsi_subset);
+                                               npi->eons_data->spn_override_info->imsi_subset = g_strdup(xml_imsi_subset);
+                                       } else {
+                                               info("[SPN_OVERRIDE] is not matched. check another field");
+                                               continue;
+                                       }
+                               } else {
+                                       info("[SPN_OVERRIDE] We don't need to check key matching. This is candidate info");
+                               }
+
+                               if (xml_spn) {
+                                       g_free(npi->eons_data->spn_override_info->spn);
+                                       npi->eons_data->spn_override_info->spn = g_strdup(xml_spn);
+                               }
+
+                               if (xml_fake_home_on) {
+                                       g_free(npi->eons_data->spn_override_info->fake_home_on);
+                                       npi->eons_data->spn_override_info->fake_home_on = g_strdup(xml_fake_home_on);
+                               }
+
+                               if (xml_fake_roaming_on) {
+                                       g_free(npi->eons_data->spn_override_info->fake_roaming_on);
+                                       npi->eons_data->spn_override_info->fake_roaming_on = g_strdup(xml_fake_roaming_on);
+                               }
+
+                               if (xml_spn_display_rule) {
+                                       g_free(npi->eons_data->spn_override_info->spn_display_rule);
+                                       npi->eons_data->spn_override_info->spn_display_rule = g_strdup(xml_spn_display_rule);
+                               }
+
+                               if (key_matched)
+                                       break;
+                       }
+               }
+       }
+
+       __network_unload_spn_conf_xml(&xml_doc, &xml_root_node);
+       g_free(imsi);
+}
+
+gboolean manager_network_is_duplicated_name(NetworkPrivateInfo *npi, char *long_name, char *short_name)
+{
+       gboolean is_new = FALSE;
+
+       MANAGER_NET_CHECK_NPI_EONS_RET(npi);
+
+       info("[NETINFO] Saved:(L[%s] S[%s]) Received:(L[%s]S[%s])",
+            npi->eons_data->long_nitz_name ? npi->eons_data->long_nitz_name : "", npi->eons_data->short_nitz_name ? npi->eons_data->short_nitz_name : "",
+            long_name ? long_name : "", short_name ? short_name : "");
+
+       if (long_name) {
+               if (npi->eons_data->long_nitz_name && strcmp(long_name, npi->eons_data->long_nitz_name)) {
+                       g_free(npi->eons_data->long_nitz_name);
+                       npi->eons_data->long_nitz_name = NULL;
+               }
+
+               if (!npi->eons_data->long_nitz_name) {
+                       npi->eons_data->long_nitz_name = g_strdup(long_name);
+                       is_new = TRUE;
+               }
+       } else {
+               if (npi->eons_data->long_nitz_name) {
+                       g_free(npi->eons_data->long_nitz_name);
+                       npi->eons_data->long_nitz_name = NULL;
+                       is_new = TRUE;
+               }
+       }
+
+       if (short_name) {
+               if (npi->eons_data->short_nitz_name && strcmp(short_name, npi->eons_data->short_nitz_name)) {
+                       g_free(npi->eons_data->short_nitz_name);
+                       npi->eons_data->short_nitz_name = NULL;
+               }
+
+               if (!npi->eons_data->short_nitz_name) {
+                       npi->eons_data->short_nitz_name = g_strdup(short_name);
+                       is_new = TRUE;
+               }
+       } else {
+               if (npi->eons_data->short_nitz_name) {
+                       g_free(npi->eons_data->short_nitz_name);
+                       npi->eons_data->short_nitz_name = NULL;
+                       is_new = TRUE;
+               }
+       }
+
+       if (npi->eons_data->is_eons_updated) {
+               info("[NETINFO] EONS updated. skip checking duplicated");
+               is_new = TRUE;
+       }
+
+       return !is_new;
+}
+
+void manager_network_get_name_from_plmn(CoreObject *co_network, 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;
+       }
+
+       /* Copy Network operator name from DB to memory */
+       __network_load_network_operator_info(co_network, plmn);
+       noi = tcore_network_operator_info_find(co_network, 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);
+}
+
+void manager_network_get_all_eons_name_from_plmn(NetworkPrivateInfo *npi, char *name, const char *plmn)
+{
+       char *eonsname = NULL;
+
+       MANAGER_NET_CHECK_NPI_EONS(npi);
+
+       if (G_UNLIKELY(!plmn) || G_UNLIKELY(strlen(plmn) < 4)) {
+               dbg("Invalid plmn");
+               return;
+       }
+
+       if (tfeature_is_supported(TFEATURE_FUNCTION_REFER_EONS_ON_MANUAL_SEARCH)) {
+               dbg("Fetch name using EONS");
+               if (tfeature_is_supported(TFEATURE_FUNCTION_REFER_EONS_WITHOUT_LAC))
+                       eonsname = __network_get_eons_name(npi, plmn, FALSE);
+               else
+                       eonsname = __network_get_eons_name(npi, plmn, TRUE);
+
+               if (tfeature_is_supported(TFEATURE_FUNCTION_REFER_SPN_ON_MANUAL_SEARCH)) {
+                       struct tel_sim_spn *spn = tcore_sim_get_spn(npi->co_sim);
+
+                       if (spn && strlen((char *)spn->spn) > 0) {
+                               struct tel_sim_imsi *imsi = tcore_sim_get_imsi(npi->co_sim);
+                               if (imsi && strlen(imsi->plmn) > 0) {
+                                       if (__network_is_plmn_matched(npi) && g_strcmp0("50503", imsi->plmn) == 0) {
+                                               warn("change eonsname with spn name. EONS[%s] -> SPN[%s]", eonsname, spn);
+                                               g_free(eonsname);
+                                               eonsname = g_strdup((gchar *)(spn->spn));
+                                       }
+                               } else
+                                       warn("Cannot get PLMN from IMSI");
+
+                               g_free(imsi);
+                       } else
+                               warn("Cannot get spn");
+
+                       g_free(spn);
+               }
+
+               if (eonsname) {
+                       memset(name, 0, NETWORK_MAX_NETWORK_NAME_LEN + 1);
+                       if (tfeature_is_supported(TFEATURE_FUNCTION_DISPLAY_RATINFO_MANUALSEARCH) == FALSE)
+                               g_strlcpy(name, eonsname, NETWORK_MAX_NETWORK_NAME_LEN + 1);
+                       else if (tfeature_is_supported(TFEATURE_FUNCTION_SKIP_EONS_INFO) == FALSE)
+                               g_strlcpy(name, eonsname, NETWORK_MAX_NETWORK_NAME_LEN + 1);
+
+                       dbg("Name from EONS[%s] plmn:[%s]", name, plmn);
+                       g_free(eonsname);
+               } else {
+                       manager_network_get_name_from_plmn(npi->co_network, name, plmn);
+               }
+       } else {
+               dbg("Fetch name from CSC/TS25 DB");
+               manager_network_get_name_from_plmn(npi->co_network, name, plmn);
+       }
+       __network_get_exceptional_name_from_plmn(npi, name, plmn);
+}
+
+void manager_network_update_spn_display(NetworkPrivateInfo *npi)
+{
+       MANAGER_NET_CHECK_NPI_EONS(npi);
+
+       if (!npi->eons_data->is_eons_ready) {
+               info("eons is not ready");
+               return;
+       }
+
+       __network_update_eons(npi);
+       __network_update_plmn_name(npi);
+       __network_update_name_priority(npi);
+       __network_apply_operator_features(npi);
+}
+
+static void manager_network_on_sim_resp_get_spn(NetworkPrivateInfo *npi,
+                                               const struct tresp_sim_read *resp, unsigned int data_len)
+{
+       if (G_LIKELY((data_len > 0) && (resp->result == SIM_ACCESS_SUCCESS))) {
+               char *final_spn;
+               struct tel_sim_imsi *imsi = NULL;
+
+               MANAGER_NET_CHECK_NPI_EONS(npi);
+
+               /* Get imsi to use its PLMN */
+               imsi = tcore_sim_get_imsi(npi->co_sim);
+
+               /* Get imsi plmn failed. Use EF_SPN */
+               if (!imsi || strlen(imsi->plmn) == 0 || strlen(imsi->msin) == 0) {
+                       info("imsi plmn cannot be retrieved. So spn cannot be overridden. spn.display_condition[0x%x] spn [%s]", resp->data.spn.display_condition, (char *)resp->data.spn.spn);
+                       __network_update_spn_name(npi, NETWORK_SPN_NAME_TYPE_SPN, (char *)resp->data.spn.spn);
+                       g_free(imsi);
+                       return;
+               }
+
+               /* Override SPN */
+               final_spn = __network_get_override_spn(npi, (char *)resp->data.spn.spn, imsi);
+               g_free(imsi);
+
+               info("[NETINFO] spn.display_condition[0x%x] ef_spn[%s] updated_spn[%s]",
+                    resp->data.spn.display_condition, resp->data.spn.spn, final_spn);
+               __network_update_spn_name(npi, NETWORK_SPN_NAME_TYPE_SPN, final_spn);
+       } else {
+               err("get spn failed. result[0x%x]", resp->result);
+       }
+}
+
+static void manager_network_on_sim_resp_get_pnn(NetworkPrivateInfo *npi,
+                                               const struct tresp_sim_read *resp, unsigned int data_len)
+{
+       memset(npi->eons_data->pnn, 0, sizeof(struct tel_sim_pnn_list));
+
+       if ((data_len > 0) && (resp->result == SIM_ACCESS_SUCCESS)) {
+               npi->eons_data->pnn->pnn_count = resp->data.pnn.pnn_count;
+               dbg("pnn count[%d]", npi->eons_data->pnn->pnn_count);
+               if (npi->eons_data->pnn->pnn_count > 0) {
+                       int i = 0;
+                       npi->eons_data->pnn->list = g_malloc0(sizeof(struct tel_sim_pnn) * npi->eons_data->pnn->pnn_count);
+                       for (i = 0; i < npi->eons_data->pnn->pnn_count; i++) {
+                               memcpy(&npi->eons_data->pnn->list[i], &resp->data.pnn.list[i], sizeof(struct tel_sim_pnn));
+                               info("[NETINFO] pnn[%d] : short_name[%s] full_name[%s]",
+                                    i, npi->eons_data->pnn->list[i].short_name, npi->eons_data->pnn->list[i].full_name);
+                       }
+               }
+       } else {
+               err("get pnn failed. result[0x%x]", resp->result);
+       }
+}
+
+static void manager_network_on_sim_resp_get_opl(NetworkPrivateInfo *npi,
+                                               const struct tresp_sim_read *resp, unsigned int data_len)
+{
+       memset(npi->eons_data->opl, 0, sizeof(struct tel_sim_opl_list));
+
+       if ((data_len > 0) && (resp->result == SIM_ACCESS_SUCCESS)) {
+               npi->eons_data->opl->opl_count = resp->data.opl.opl_count;
+               dbg("opl count[%d]", npi->eons_data->opl->opl_count);
+               if (npi->eons_data->opl->opl_count > 0) {
+                       int i = 0;
+                       npi->eons_data->opl->list = g_malloc0(sizeof(struct tel_sim_opl) * npi->eons_data->opl->opl_count);
+                       for (i = 0; i < npi->eons_data->opl->opl_count; i++) {
+                               memcpy(&npi->eons_data->opl->list[i], &resp->data.opl.list[i], sizeof(struct tel_sim_opl));
+                               info("[NETINFO] opl[%d] : plmn[%s] lac_from[%d] lac_to[%d] pnn_index[%d]",
+                                    i, npi->eons_data->opl->list[i].plmn, npi->eons_data->opl->list[i].lac_from,
+                                    npi->eons_data->opl->list[i].lac_to, npi->eons_data->opl->list[i].rec_identifier);
+                       }
+               }
+       } else {
+               err("get opl failed. result[0x%x]", resp->result);
+       }
+}
+
+static void manager_network_on_sim_resp_get_spdi(NetworkPrivateInfo *npi,
+                                                const struct tresp_sim_read *resp, unsigned int data_len)
+{
+       memset(npi->eons_data->spdi, 0, sizeof(struct tel_sim_spdi));
+
+       if ((data_len > 0) && (resp->result == SIM_ACCESS_SUCCESS)) {
+               memcpy(npi->eons_data->spdi, &resp->data.spdi, sizeof(struct tel_sim_spdi));
+               info("[NETINFO] spdi count[%d]", npi->eons_data->spdi->plmn_count);
+       } else {
+               err("get spdi failed. result[0x%x]", resp->result);
+       }
+}
+
+static void manager_network_on_sim_resp_get_cphs_netname(NetworkPrivateInfo *npi,
+                                                        const struct tresp_sim_read *resp, unsigned int data_len)
+{
+       if ((data_len > 0) && (resp->result == SIM_ACCESS_SUCCESS)) {
+               info("[NETINFO] cphs full name[%s] cphs short name[%s]", resp->data.cphs_net.full_name, resp->data.cphs_net.short_name);
+
+               if (strlen((char *)resp->data.cphs_net.full_name) > 0)
+                       __network_update_spn_name(npi, NETWORK_SPN_NAME_TYPE_ONS, (char *)resp->data.cphs_net.full_name);
+               else
+                       __network_update_spn_name(npi, NETWORK_SPN_NAME_TYPE_ONS, (char *)resp->data.cphs_net.short_name);
+
+       } else {
+               warn("GET_CPHS_NETNAME failed. result[0x%x]", resp->result);
+       }
+}
+
+static void manager_network_resp_hook_get_sim_network_name(UserRequest *ur,
+                                                          enum tcore_response_command command, unsigned int data_len,
+                                                          const void *data, void *user_data)
+{
+       const struct tresp_sim_read *resp = data;
+       TcorePlugin *modem_plugin = user_data;
+       NetworkPrivateInfo *npi = manager_network_ref_npi_by_plugin(modem_plugin);
+
+       MANAGER_NET_CHECK_NPI_EONS(npi);
+
+       switch (command) {
+       case TRESP_SIM_GET_SPDI:
+               npi->eons_data->sim_network_name_state |= NETWORK_SIM_NETWORK_NAME_SPDI;
+               dbg("Receive TRESP_SIM_GET_SPDI response");
+               manager_network_on_sim_resp_get_spdi(npi, resp, data_len);
+               break;
+
+       case TRESP_SIM_GET_SPN:
+               npi->eons_data->sim_network_name_state |= NETWORK_SIM_NETWORK_NAME_SPN;
+               dbg("Receive TRESP_SIM_GET_SPN response");
+               manager_network_on_sim_resp_get_spn(npi, resp, data_len);
+               break;
+
+       case TRESP_SIM_GET_CPHS_NETNAME:
+               npi->eons_data->sim_network_name_state |= NETWORK_SIM_NETWORK_NAME_CPHS_NAME;
+               dbg("Receive TRESP_SIM_GET_CPHS_NETNAME response");
+               manager_network_on_sim_resp_get_cphs_netname(npi, resp, data_len);
+               break;
+
+       case TRESP_SIM_GET_PNN:
+               npi->eons_data->sim_network_name_state |= NETWORK_SIM_NETWORK_NAME_PNN;
+               dbg("Receive TRESP_SIM_GET_PNN response");
+               manager_network_on_sim_resp_get_pnn(npi, resp, data_len);
+               break;
+
+       case TRESP_SIM_GET_OPL:
+               npi->eons_data->sim_network_name_state |= NETWORK_SIM_NETWORK_NAME_OPL;
+               dbg("Receive TRESP_SIM_GET_OPL response");
+               manager_network_on_sim_resp_get_opl(npi, resp, data_len);
+               break;
+
+       default:
+               err("Unsupported cmd");
+       }
+
+       if (npi->eons_data->sim_network_name_state == npi->eons_data->sim_network_name_support_list) {
+               info("[NETINFO] eons is ready");
+               npi->eons_data->is_eons_ready = TRUE;
+               npi->eons_data->is_eons_updated = TRUE;
+               __network_post_network_identity(npi);
+               npi->eons_data->is_eons_updated = FALSE;
+       }
+}
+
+void manager_network_get_sim_network_name(CoreObject *co_sim)
+{
+       TcorePlugin *modem_plugin = tcore_object_ref_plugin(co_sim);
+       NetworkPrivateInfo *npi = manager_network_ref_npi_by_plugin(modem_plugin);
+       UserRequest *ur = NULL;
+       int req_name_type = NETWORK_SIM_NETWORK_NAME_ALL;
+       int cur_name_type;
+       enum tcore_request_command command;
+       TReturn ret;
+
+       MANAGER_NET_CHECK_NPI_EONS(npi);
+
+       info("req_name_type:[0x%x]", req_name_type);
+       while (req_name_type) {
+               if (req_name_type & NETWORK_SIM_NETWORK_NAME_SPDI) {
+                       command = TREQ_SIM_GET_SPDI;
+                       cur_name_type = NETWORK_SIM_NETWORK_NAME_SPDI;
+                       dbg("Dispatch TREQ_SIM_GET_SPDI");
+               } else if (req_name_type & NETWORK_SIM_NETWORK_NAME_SPN) {
+                       command = TREQ_SIM_GET_SPN;
+                       cur_name_type = NETWORK_SIM_NETWORK_NAME_SPN;
+                       dbg("Dispatch NETWORK_SIM_NETWORK_NAME_SPN");
+               } else if (req_name_type & NETWORK_SIM_NETWORK_NAME_CPHS_NAME) {
+                       command = TREQ_SIM_GET_CPHS_NETNAME;
+                       cur_name_type = NETWORK_SIM_NETWORK_NAME_CPHS_NAME;
+                       dbg("Dispatch NETWORK_SIM_NETWORK_NAME_CPHS_NAME");
+               } else if (req_name_type & NETWORK_SIM_NETWORK_NAME_PNN) {
+                       command = TREQ_SIM_GET_PNN;
+                       cur_name_type = NETWORK_SIM_NETWORK_NAME_PNN;
+                       dbg("Dispatch NETWORK_SIM_NETWORK_NAME_PNN");
+               } else if (req_name_type & NETWORK_SIM_NETWORK_NAME_OPL) {
+                       command = TREQ_SIM_GET_OPL;
+                       cur_name_type = NETWORK_SIM_NETWORK_NAME_OPL;
+                       dbg("Dispatch NETWORK_SIM_NETWORK_NAME_OPL");
+               } else {
+                       err("Not supported SIM command");
+                       return;
+               }
+
+               req_name_type &= ~cur_name_type;
+
+               ur = tcore_user_request_new(NULL, NULL);
+               tcore_user_request_set_command(ur, command);
+               tcore_user_request_set_response_hook(ur, manager_network_resp_hook_get_sim_network_name, modem_plugin);
+               ret = tcore_object_dispatch_request(co_sim, ur);
+               if (ret == TCORE_RETURN_SUCCESS)
+                       npi->eons_data->sim_network_name_support_list |= cur_name_type;
+               else {
+                       err("Request [0x%x] dispatch failed", command);
+                       tcore_user_request_unref(ur);
+               }
+       }
+}
+
+void manager_network_process_sim_refreshed(CoreObject *co_sim)
+{
+       TcorePlugin *plugin = tcore_object_ref_plugin(co_sim);
+       CoreObject *co_network = tcore_plugin_ref_core_object(plugin, CORE_OBJECT_TYPE_NETWORK);
+       NetworkPrivateInfo *npi = NULL;
+
+       dbg("Enter");
+
+       npi = manager_network_ref_npi_by_plugin(plugin);
+       if (G_UNLIKELY(!npi || !npi->eons_data)) {
+               err("NULL data : npi[%p]", npi);
+               return;
+       }
+
+       /* Reset Network name */
+       __network_reset_sim_network_name(co_network, npi);
+
+       /* Update Private Info */
+       npi->eons_data->is_sim_refreshed = TRUE;
+}
+
+TReturn manager_network_process_nitz_name(struct tnoti_network_identity *data,
+                                         NetworkPrivateInfo *npi)
+{
+       struct tnoti_network_identity noti = { { 0 }, };
+       char mcc[4] = { 0, };
+       char mnc[4] = { 0, };
+       char *name_ts25 = NULL;
+       char *name_short = NULL;
+       char *name_long = NULL;
+       char *name_delta = NULL;
+       char *nitz_name = NULL;
+       TcorePlugin *plugin = NULL;
+
+       if (G_UNLIKELY(!npi->eons_data))
+               return TCORE_MANAGER_RETURN_CONTINUE;
+
+       /* check eons ready */
+       if (!npi->eons_data->is_eons_ready) {
+               info("EONS is not ready yet. Backup NITZ IDENTITY message");
+               g_free(npi->eons_data->backup_name_ind_msg);
+               npi->eons_data->backup_name_ind_msg = g_memdup(data, sizeof(struct tnoti_network_identity));
+               return TCORE_MANAGER_RETURN_STOP;
+       }
+
+       /* check duplicated */
+       name_short = g_strdup(data->short_name);
+       name_long = g_strdup(data->full_name);
+
+       if (manager_network_is_duplicated_name(npi, name_long, name_short) == TRUE) {
+               if (!npi->eons_data->is_sim_refreshed) {
+                       dbg("Ignore duplicated!");
+                       g_free(name_long);
+                       g_free(name_short);
+                       return TCORE_MANAGER_RETURN_STOP;
+               }
+       }
+
+       /* Read name from mcc-mnc name table*/
+       if (strlen(data->plmn) != 0) {
+               struct tcore_network_operator_info *noi = NULL;
+
+               if (memcmp(npi->cache_data->current_plmn, data->plmn, NETWORK_MAX_PLMN_LEN) != 0)
+                       __network_load_network_operator_info(npi->co_network, data->plmn);
+
+               g_strlcpy(mcc, data->plmn, 4);
+               g_strlcpy(mnc, data->plmn + 3, 4);
+               noi = tcore_network_operator_info_find(npi->co_network, mcc, mnc);
+               if (noi) {
+                       name_ts25 = g_strdup(noi->name);
+                       if (noi->type == TCORE_NETWORK_OPERATOR_INFO_TYPE_DELTA_DB)
+                               name_delta = g_strdup(noi->name);
+               }
+       }
+
+       manager_network_apply_operator_name_rule(data->plmn, &name_delta, &name_long, &name_short);
+       plugin = tcore_object_ref_plugin(npi->co_network);
+
+       /* Update mcc-mnc name table */
+       do {
+               if (name_long && strlen(name_long) != 0) {
+                       nitz_name = name_long;
+               } else if (name_short && strlen(name_short) != 0) {
+                       nitz_name = name_short;
+               }
+
+               if (!nitz_name) {
+                       info("No NITZ name. Nothing to update mcc-mnc name table");
+                       break;
+               }
+
+               if (name_ts25 && !strcmp(nitz_name, name_ts25)) {
+                       info("We already have name. Nothing to update mcc-mnc name table");
+                       break;
+               }
+
+               tcore_network_update_mcc_mnc_oper_list(npi->co_network, data->plmn, nitz_name, TCORE_NETWORK_OPERATOR_INFO_TYPE_NITZ);
+
+               if (npi->eons_data->name_type == NETWORK_NAME_TYPE_EONS) {
+                       info("Current Name type(%d) is not NITZ. Nothing to update mcc-mnc name db.", npi->eons_data->name_type);
+                       break;
+               }
+               tcore_network_update_mcc_mnc_oper_list_db(plugin, mcc, mnc, nitz_name);
+       } while (0);
+
+       if (!nitz_name) {
+               info("No NITZ name. Use ts25:[%s] or PLMN string:[%s]", name_ts25 ? name_ts25 : "", data->plmn);
+               g_free(name_short);
+               name_short = NULL;
+
+               if (name_ts25)
+                       name_short = g_strdup(name_ts25);
+               else if (strlen(data->plmn) != 0)
+                       name_short = g_strdup(data->plmn);
+       }
+
+       /* Updates the Network name */
+       __network_update_nwname(npi, NETWORK_NAME_TYPE_NITZ, name_short, name_long);
+       manager_network_update_spn_display(npi);
+
+       g_free(name_long);
+       g_free(name_short);
+       g_free(name_ts25);
+       g_free(name_delta);
+
+       /* Reset SIM refresh flag */
+       if (npi->eons_data->is_sim_refreshed)
+               npi->eons_data->is_sim_refreshed = FALSE;
+
+       name_short = tcore_network_get_network_name(npi->co_network, TCORE_NETWORK_NAME_TYPE_SHORT);
+       if (name_short) {
+               snprintf(data->short_name, 16, "%s", name_short);
+               g_free(name_short);
+       }
+
+       name_long = tcore_network_get_network_name(npi->co_network, TCORE_NETWORK_NAME_TYPE_FULL);
+       if (name_long) {
+               snprintf(noti.full_name, 32, "%s", name_long);
+               g_free(name_long);
+       }
+
+       g_strlcpy(noti.plmn, data->plmn, NETWORK_MAX_PLMN_LEN + 1);
+
+       info("Updated TNOTI : short_name[%s], full_name[%s], plmn[%s]",
+            noti.short_name, noti.full_name, noti.plmn);
+
+       /* Send Notification - Network Identity */
+       tcore_server_broadcast_notification(tcore_plugin_ref_server(plugin),
+                                           npi->co_network, TNOTI_NETWORK_IDENTITY, sizeof(struct tnoti_network_identity), &noti);
+
+       return TCORE_MANAGER_RETURN_STOP;
+}
+
diff --git a/src/network_name/manager_network_name.h b/src/network_name/manager_network_name.h
new file mode 100644 (file)
index 0000000..20c4706
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * tel-plugin-manager
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Imran Mohammed <md.imran@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.
+ */
+
+#ifndef __MANAGER_NETWORK_NAME_H__
+#define __MANAGER_NETWORK_NAME_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "manager_types.h"
+
+#define SPN_DATABASE_PATH "/opt/data/etc/spn-conf.xml"
+
+#define NETWORK_SIM_NETWORK_NAME_SPN       0x000001
+#define NETWORK_SIM_NETWORK_NAME_PNN       0x000010
+#define NETWORK_SIM_NETWORK_NAME_OPL       0x000100
+#define NETWORK_SIM_NETWORK_NAME_SPDI      0x001000
+#define NETWORK_SIM_NETWORK_NAME_CPHS_NAME 0x010000
+#define NETWORK_SIM_NETWORK_NAME_ALL \
+       (NETWORK_SIM_NETWORK_NAME_SPN \
+        | NETWORK_SIM_NETWORK_NAME_PNN \
+        | NETWORK_SIM_NETWORK_NAME_OPL \
+        | NETWORK_SIM_NETWORK_NAME_SPDI \
+        | NETWORK_SIM_NETWORK_NAME_CPHS_NAME)
+#define NETWORK_SIM_NETWORK_NAME_DB_VALID  0x100000
+
+typedef enum {
+       NETWORK_NAME_TYPE_EONS = 1,
+       NETWORK_NAME_TYPE_NITZ,
+       NETWORK_NAME_TYPE_NONE
+} NetworkNameType;
+
+typedef enum {
+       NETWORK_SPN_NAME_TYPE_SPN = 1,
+       NETWORK_SPN_NAME_TYPE_ONS,
+       NETWORK_SPN_NAME_TYPE_NONE
+} NetworkSpnNameType;
+
+typedef struct area_code_info_t {
+       char areacode[2 + 1];
+       char state[2 + 1];
+} AreaCodeInfo;
+
+typedef struct spn_override_info_t {
+       char *spn;
+       char *imsi_subset;
+       char *fake_home_on;
+       char *fake_roaming_on;
+       char *spn_display_rule;
+} SpnOverrideInfo;
+
+typedef struct lac_netname_info_t {
+       char *lac_netname;
+       GHashTable *lac_netname_hash;
+} LacNetnameInfo;
+
+struct manager_network_eons_info {
+       struct tel_sim_spdi *spdi;
+       struct tel_sim_opl_list *opl;
+       struct tel_sim_pnn_list *pnn;
+       struct tnoti_network_identity *backup_name_ind_msg;
+       gboolean is_eons_ready;
+       gboolean is_sim_refreshed;
+       gboolean is_eons_updated;
+       char *long_nitz_name;
+       char *short_nitz_name;
+       int sim_network_name_state;
+       int sim_network_name_support_list;
+       NetworkNameType name_type;
+       NetworkSpnNameType spn_name_type;
+       SpnOverrideInfo *spn_override_info;
+       LacNetnameInfo *lac_netname_info;
+};
+
+void manager_network_process_sim_refreshed(CoreObject *co_sim);
+void     manager_network_get_sim_network_name(CoreObject *co_sim);
+void     manager_network_apply_operator_name_rule(const char *plmn, char **name_delta, char **name_long, char **name_short);
+void     manager_network_load_spn_override_info(NetworkPrivateInfo *npi);
+gboolean manager_network_is_duplicated_name(NetworkPrivateInfo *npi, char *long_name, char *short_name);
+void     manager_network_get_name_from_plmn(CoreObject *co_network, char *name, const char *plmn);
+void     manager_network_get_all_eons_name_from_plmn(NetworkPrivateInfo *npi, char *name, const char *plmn);
+void     manager_network_update_spn_display(NetworkPrivateInfo *npi);
+
+TReturn manager_network_process_nitz_name(struct tnoti_network_identity *data, NetworkPrivateInfo *npi);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MANAGER_NETWORK_NAME_H__ */
diff --git a/tel-plugin-manager.manifest b/tel-plugin-manager.manifest
new file mode 100644 (file)
index 0000000..97e8c31
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_"/>
+       </request>
+</manifest>