add APIs for getting SIM init status and importing SIM contacts by sim slot no
[platform/core/pim/contacts-service.git] / client / ctsvc_client_service_helper.c
1 /*
2  * Contacts Service
3  *
4  * Copyright (c) 2010 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19 #include <errno.h>
20 #include <sys/socket.h>
21 #include <sys/un.h>
22 #include <unistd.h>
23
24 #include "contacts.h"
25 #include "ctsvc_internal.h"
26 #include "ctsvc_socket.h"
27 #include "ctsvc_mutex.h"
28 #include "ctsvc_inotify.h"
29 #include "ctsvc_client_ipc.h"
30 #include "ctsvc_client_utils.h"
31 #include "ctsvc_client_handle.h"
32 #include "ctsvc_client_service_helper.h"
33
34 static int _ctsvc_connection = 0;
35 static __thread int _ctsvc_connection_on_thread = 0;
36
37 int ctsvc_client_get_thread_connection_count()
38 {
39         return _ctsvc_connection_on_thread;
40 }
41
42 int ctsvc_client_connect_with_flags(contacts_h contact, unsigned int flags)
43 {
44         CTS_FN_CALL;
45         int ret = CONTACTS_ERROR_NONE;
46
47         /* If new flag is defined, errer check should be updated */
48         RETVM_IF(flags & 0x11111110, CONTACTS_ERROR_INVALID_PARAMETER, "flags is invalid");
49
50         ret = ctsvc_client_connect(contact);
51         if (ret == CONTACTS_ERROR_PERMISSION_DENIED)
52                 return ret;
53         else if (ret == CONTACTS_ERROR_NONE)
54                 return ret;
55
56         if (flags & CONTACTS_CONNECT_FLAG_RETRY) {
57                 int i;
58                 int waiting_time = 500;
59                 for (i = 0; i < 9; i++) {
60                         usleep(waiting_time * 1000);
61                         DBG("retry cnt=%d, ret=%x, %d", (i+1), ret, waiting_time);
62                         ret = ctsvc_client_connect(contact);
63                         if (ret == CONTACTS_ERROR_NONE)
64                                 break;
65                         if (6 < i)
66                                 waiting_time += 30000;
67                         else
68                                 waiting_time *= 2;
69                 }
70         }
71
72         return ret;
73 }
74
75 static void _ctsvc_ipc_initialized_cb(void *user_data)
76 {
77         CTS_FN_CALL;
78         if (true == ctsvc_ipc_get_disconnected()) {
79                 ctsvc_ipc_set_disconnected(false);
80                 ctsvc_ipc_recovery();
81                 ctsvc_ipc_recover_for_change_subscription();
82         }
83 }
84
85 int ctsvc_client_connect(contacts_h contact)
86 {
87         CTS_FN_CALL;
88         int ret;
89         ctsvc_base_s *base = (ctsvc_base_s*)contact;
90         RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
91
92         ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
93         if (0 == base->connection_count) {
94                 ret = ctsvc_ipc_connect(contact, ctsvc_client_get_pid());
95                 if (ret != CONTACTS_ERROR_NONE) {
96                         ERR("ctsvc_ipc_connect() Fail(%d)", ret);
97                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
98                         return ret;
99                 }
100         }
101         base->connection_count++;
102
103         if (0 == _ctsvc_connection) {
104                 ret = ctsvc_socket_init();
105                 if (ret != CONTACTS_ERROR_NONE) {
106                         ERR("ctsvc_socket_init() Fail(%d)", ret);
107                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
108                         return ret;
109                 }
110
111                 ret = ctsvc_inotify_init();
112                 if (ret != CONTACTS_ERROR_NONE) {
113                         ERR("ctsvc_inotify_init() Fail(%d)", ret);
114                         ctsvc_socket_final();
115                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
116                         return ret;
117                 }
118                 ctsvc_view_uri_init();
119         } else {
120                 DBG("Contacts service has been already connected(%d)", _ctsvc_connection + 1);
121         }
122
123         if (1 == base->connection_count)
124                 ctsvc_inotify_subscribe_ipc_ready(_ctsvc_ipc_initialized_cb, NULL);
125
126         _ctsvc_connection++;
127         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
128
129         return CONTACTS_ERROR_NONE;
130 }
131
132 int ctsvc_client_disconnect(contacts_h contact)
133 {
134         CTS_FN_CALL;
135         int ret;
136         ctsvc_base_s *base = (ctsvc_base_s*)contact;
137         RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
138
139         ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
140
141         if (1 == base->connection_count) {
142                 ret = ctsvc_ipc_disconnect(contact, ctsvc_client_get_pid(), _ctsvc_connection);
143                 if (ret != CONTACTS_ERROR_NONE) {
144                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
145                         ERR("ctsvc_ipc_disconnect() Fail(%d)", ret);
146                         return ret;
147                 }
148                 ctsvc_inotify_unsubscribe_ipc_ready();
149         }
150         base->connection_count--;
151
152         if (1 == _ctsvc_connection) {
153                 ctsvc_ipc_destroy_for_change_subscription(true);
154                 ctsvc_view_uri_deinit();
155                 ctsvc_inotify_close();
156                 ctsvc_socket_final();
157
158         } else if (1 < _ctsvc_connection) {
159                 DBG("connection count is %d", _ctsvc_connection);
160         } else {
161                 DBG("call contacts_connect(), connection count is %d", _ctsvc_connection);
162                 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
163                 return CONTACTS_ERROR_DB;
164         }
165
166         _ctsvc_connection--;
167
168         if (0 == base->connection_count) {
169                 INFO("connection_count is 0. remove handle");
170                 ret = ctsvc_client_handle_remove(ctsvc_client_get_pid(), contact);
171                 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_client_handle_remove() Fail(%d)", ret);
172         }
173         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
174
175         return CONTACTS_ERROR_NONE;
176 }
177
178 int ctsvc_client_connect_on_thread(contacts_h contact)
179 {
180         int ret;
181         ctsvc_base_s *base = (ctsvc_base_s*)contact;
182         RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
183
184         ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
185
186         if (0 == base->connection_count) {
187                 ret = ctsvc_ipc_connect(contact, ctsvc_client_get_tid());
188                 if (ret != CONTACTS_ERROR_NONE) {
189                         ERR("ctsvc_ipc_connect() Fail(%d)", ret);
190                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
191                         return ret;
192                 }
193         }
194         base->connection_count++;
195
196         if (0 == _ctsvc_connection_on_thread) {
197                 ret = ctsvc_socket_init();
198                 if (ret != CONTACTS_ERROR_NONE) {
199                         ERR("ctsvc_socket_init() Fail(%d)", ret);
200                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
201                         return ret;
202                 }
203
204                 ret = ctsvc_inotify_init();
205                 if (ret != CONTACTS_ERROR_NONE) {
206                         ERR("ctsvc_inotify_init() Fail(%d)", ret);
207                         ctsvc_socket_final();
208                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
209                         return ret;
210                 }
211                 ctsvc_view_uri_init();
212         } else if (0 < _ctsvc_connection_on_thread) {
213                 DBG("System : Contacts service has been already connected");
214         }
215
216         if (1 == base->connection_count)
217                 ctsvc_inotify_subscribe_ipc_ready(_ctsvc_ipc_initialized_cb, NULL);
218
219         _ctsvc_connection_on_thread++;
220
221         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
222
223         return CONTACTS_ERROR_NONE;
224 }
225
226 int ctsvc_client_disconnect_on_thread(contacts_h contact)
227 {
228         int ret;
229         ctsvc_base_s *base = (ctsvc_base_s*)contact;
230         RETV_IF(NULL == base, CONTACTS_ERROR_INVALID_PARAMETER);
231
232         ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
233
234         if (1 == base->connection_count) {
235                 ret = ctsvc_ipc_disconnect(contact, ctsvc_client_get_tid(),
236                                 _ctsvc_connection_on_thread);
237                 if (ret != CONTACTS_ERROR_NONE) {
238                         ERR("ctsvc_ipc_disconnect() Fail(%d)", ret);
239                         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
240                         return ret;
241                 }
242                 ctsvc_inotify_unsubscribe_ipc_ready();
243         }
244         base->connection_count--;
245
246         if (1 == _ctsvc_connection_on_thread) {
247                 if (0 == _ctsvc_connection)
248                         ctsvc_ipc_destroy_for_change_subscription(true);
249                 ctsvc_view_uri_deinit();
250                 ctsvc_inotify_close();
251                 ctsvc_socket_final();
252                 DBG("System : connection_on_thread was destroyed successfully");
253         } else if (1 < _ctsvc_connection_on_thread) {
254                 DBG("connection count is %d", _ctsvc_connection_on_thread);
255         } else {
256                 DBG("call contacts_connect_on_thread(), connection count is %d",
257                                 _ctsvc_connection_on_thread);
258                 ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
259                 return CONTACTS_ERROR_DB;
260         }
261
262         _ctsvc_connection_on_thread--;
263
264         if (0 == base->connection_count) {
265                 INFO("connection_count is 0. remove handle");
266                 ret = ctsvc_client_handle_remove(ctsvc_client_get_tid(), contact);
267                 WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_client_handle_remove() Fail(%d)", ret);
268         }
269         ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
270
271         return CONTACTS_ERROR_NONE;
272 }
273