2 * Copyright 2012 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.tizenopensource.org/license
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "vc-core-callagent.h"
18 #include "vc-core-engine.h"
19 #include "vc-core-ccbs.h"
20 #include "vc-core-tapi-rqst.h"
21 #include "vc-core-tapi-evnt.h"
22 #include "vc-core-svcall.h"
25 /* For Debug Information, Inout state name string constant */
26 char *gszcall_vc_inout_state[VC_INOUT_STATE_MAX_NUM] = {
31 "OUTGOING_WAIT_ALERT",
32 "OUTGOING_WAIT_CONNECTED",
33 "OUTGOING_WAIT_RELEASE",
35 "OUTGOING_SHOW_REDIALCAUSE",
36 "OUTGOING_WAIT_REDIAL",
37 "OUTGOING_SHOW_RETRY_CALLBOX",
39 "INCOME_SELFEVENT_WAIT",
42 "INCOME_WAIT_REDIRECTCNF",
43 "INCOME_WAIT_REDIRECT_END",
44 "INCOME_WAIT_CONNECTED",
45 "INCOME_WAIT_HOLD_CONNECTED",
46 "INCOME_WAIT_RELEASE_ACTIVE_CONNECTED",
48 "INCOME_WAIT_RELEASE_ACTIVECALL",
49 "INCOME_WAIT_RELEASE_HOLDCALL",
50 "INCOME_WAIT_RELEASE",
54 /* For Debug Information, Call Agent State name string constant */
55 char *gszcall_vc_ca_state[CALL_VC_CA_STATE_MAX_NUM] = {
57 "CA_STATE_SPLIT_CALLBOX",
58 "CA_STATE_WAIT_SPLIT",
59 "CA_STATE_DROP_CALLBOX",
62 "CA_STATE_WAIT_SWAP_HOLD_OR_ACTIVATE",
63 "CA_STATE_WAIT_SWAP_HOLD",
64 "CA_STATE_WAIT_SWAP_ACTIVATE",
68 "CA_STATE_WAIT_UNHOLD",
70 "CA_STATE_WAIT_TRANSFER_CNF",
71 "CA_STATE_WAIT_TRANSFER_CALLEND",
72 "CA_STATE_WAIT_RELEASE_ALL_ACTIVECALL",
73 "CA_STATE_WAIT_RELEASE_ALL_HOLDCALL",
74 "CA_STATE_SENDMSG_CALLBOX",
75 "CA_STATE_VIEW_CONTACT_DETAIL_CALLBOX",
76 "CA_STATE_SAVE_TO_CONTACT_CALLBOX",
77 "CA_STATE_SS_WAIT_RELEASE_ALL_ACTIVECALL",
78 "CA_STATE_WAIT_RELEASE_ALL_CALLS",
79 "CA_STATE_WAIT_RELEASE_ALL_CALLS_TO_SETUP",
80 "CA_STATE_WAIT_RELEASE_ALL_CALLS_TO_SWITCH_TO_VIDEO_CALL"
84 * This function intializes the call agent
86 * @return Pointer to call agent state.
88 call_vc_callagent_state_t *_vc_core_ca_init_agent()
90 call_vc_callagent_state_t *pcall_agent = NULL;
91 pcall_agent = (call_vc_callagent_state_t *)calloc(1, sizeof(call_vc_callagent_state_t));
92 if (NULL == pcall_agent) {
93 CALL_ENG_DEBUG(ENG_DEBUG, "Voicecall Engine Initialization Failed: MEM ALLOC Failure");
97 /*Initialize Call Manager */
98 _vc_core_call_manager_init(&pcall_agent->call_manager);
100 /* Initialize Call Agent Flags */
101 _vc_core_ca_init_data(pcall_agent);
103 #ifdef _CCBS_DEFINED_
105 _vc_core_init_ccbs_info(pcall_agent);
109 #ifdef _CPHS_DEFINED_
110 _vc_core_svcall_init_cphs_info(pcall_agent);
116 * This function intializes the callagent data
119 * @param[in] pagent Pointer to the call agent structure
121 void _vc_core_ca_init_data(call_vc_callagent_state_t *pagent)
123 VOICECALL_RETURN_IF_FAIL(pagent != NULL);
124 pagent->callagent_state = CALL_VC_CA_STATE_NORMAL;
125 pagent->io_state = VC_INOUT_STATE_NONE;
126 pagent->bis_no_sim = FALSE;
127 pagent->aoc_ppm = VC_INVALID_PPM;
131 * This function finalizes the call agent
133 * @return Returns void
134 * @param[in] pcall_agent Pointer to the call agent structure
136 void _vc_core_ca_finish_agent(call_vc_callagent_state_t *pcall_agent)
138 if (NULL != pcall_agent) {
145 * This function changes the in out state of the call agent
147 * @return This function returns TRUE on success and FALSE on failure
148 * @param[in] pagent Pointer to the call agent structure
149 * @param[in] new_state The new i/o state that should be set
150 * @see _vc_core_ca_change_agent_state
152 gboolean _vc_core_ca_change_inout_state(call_vc_callagent_state_t *pagent, voicecall_inout_state_t new_state)
154 VOICECALL_RETURN_FALSE_IF_FAIL(pagent != NULL);
156 CALL_ENG_DEBUG(ENG_ERR, "%s(%d) --> %s(%d)", gszcall_vc_inout_state[pagent->io_state], pagent->io_state, gszcall_vc_inout_state[new_state], new_state);
157 pagent->io_state = new_state;
162 * This function changes the in call agent state
164 * @return This function returns TRUE on success and FALSE on failure
165 * @param[in] pAgent Pointer to the call agent structure
166 * @param[in] new_state The new call agent state that should be set
167 * @see _vc_core_ca_change_inout_state
169 gboolean _vc_core_ca_change_agent_state(call_vc_callagent_state_t *pAgent, call_vc_ca_state_t new_state)
171 VOICECALL_RETURN_FALSE_IF_FAIL((new_state >= CALL_VC_CA_STATE_NORMAL && new_state < CALL_VC_CA_STATE_MAX_NUM));
172 CALL_ENG_DEBUG(ENG_DEBUG, "%s(%d) --> %s(%d)", gszcall_vc_ca_state[pAgent->callagent_state], pAgent->callagent_state, gszcall_vc_ca_state[new_state], new_state);
173 pAgent->callagent_state = new_state;
178 * This function checks if all the call members have terminated or not
180 * @return Returns TRUE if no call members exist, FALSE otherwise
181 * @param[in] pAgent Pointer to the call agent structure
183 gboolean _vc_core_ca_check_end(call_vc_callagent_state_t *pAgent)
185 gboolean result = FALSE;
186 VOICECALL_RETURN_FALSE_IF_FAIL(pAgent != NULL);
187 if ((_vc_core_cm_get_call_member_count(&pAgent->call_manager) == 0) && (pAgent->io_state == VC_INOUT_STATE_NONE)) {
188 CALL_ENG_DEBUG(ENG_DEBUG, "TRUE");
193 CALL_ENG_DEBUG(ENG_DEBUG, "FALSE");
201 * This function sends the response to the SAT engine
203 * @return This function returns TRUE on success and FALSE on failure
204 * @param[in] pagent Pointer to the call agent structure
205 * @param[in] sat_rqst_resp_type sat rquest/response type used by the client
206 * @param[in] sat_response_type response to be sent to sat
208 gboolean _vc_core_ca_send_sat_response(call_vc_callagent_state_t *pagent, voicecall_engine_sat_rqst_resp_type sat_rqst_resp_type, call_vc_sat_reponse_type_t sat_response_type)
210 call_vc_satsetup_info_t *pcall_vc_satcall_info = (call_vc_satsetup_info_t *) &(pagent->call_manager.setupcall_info.satcall_setup_info);
211 TelSatAppsRetInfo_t call_vc_sat_response = {0,};
212 TapiResult_t error_code;
213 CALL_ENG_DEBUG(ENG_DEBUG, "sat_rqst_resp_type: %d, sat_response_type: %d", sat_rqst_resp_type, sat_response_type);
214 switch (sat_rqst_resp_type) {
215 case SAT_RQST_SETUP_CALL:
217 TelSatCallRetInfo_t sat_engine_ret_call = {0,};
218 switch (sat_response_type) {
219 case CALL_VC_ME_UNABLE_TO_PROCESS_COMMAND:
220 sat_engine_ret_call.resp = TAPI_SAT_R_ME_UNABLE_TO_PROCESS_COMMAND;
221 sat_engine_ret_call.bIsTapiCauseExist = FALSE;
222 sat_engine_ret_call.tapiCause = TAPI_CAUSE_UNKNOWN;
223 sat_engine_ret_call.meProblem = TAPI_SAT_ME_PROBLEM_ME_BUSY_ON_CALL;
224 sat_engine_ret_call.bIsOtherInfoExist = FALSE;
225 sat_engine_ret_call.permanentCallCtrlProblem = TAPI_SAT_CC_PROBLEM_NO_SPECIFIC_CAUSE;
227 case CALL_VC_NETWORK_UNABLE_TO_PROCESS_COMMAND:
228 sat_engine_ret_call.resp = TAPI_SAT_R_NETWORK_UNABLE_TO_PROCESS_COMMAND;
229 sat_engine_ret_call.bIsTapiCauseExist = TRUE;
230 sat_engine_ret_call.tapiCause = TAPI_CAUSE_BUSY;
231 sat_engine_ret_call.meProblem = TAPI_SAT_ME_PROBLEM_NO_SERVICE;
232 sat_engine_ret_call.bIsOtherInfoExist = FALSE;
233 sat_engine_ret_call.permanentCallCtrlProblem = TAPI_SAT_CC_PROBLEM_NO_SPECIFIC_CAUSE;
235 case CALL_VC_NETWORK_UNABLE_TO_PROCESS_COMMAND_WITHOUT_CAUSE:
236 sat_engine_ret_call.resp = TAPI_SAT_R_NETWORK_UNABLE_TO_PROCESS_COMMAND;
237 sat_engine_ret_call.bIsTapiCauseExist = FALSE;
238 sat_engine_ret_call.tapiCause = TAPI_CAUSE_UNKNOWN;
239 sat_engine_ret_call.meProblem = TAPI_SAT_ME_PROBLEM_NO_SPECIFIC_CAUSE;
240 sat_engine_ret_call.bIsOtherInfoExist = FALSE;
241 sat_engine_ret_call.permanentCallCtrlProblem = TAPI_SAT_CC_PROBLEM_NO_SPECIFIC_CAUSE;
243 case CALL_VC_ME_CONTROL_PERMANENT_PROBLEM:
244 sat_engine_ret_call.resp = TAPI_SAT_R_INTRCTN_WITH_CC_OR_SMS_CTRL_PRMNT_PRBLM;
245 sat_engine_ret_call.bIsTapiCauseExist = FALSE;
246 sat_engine_ret_call.tapiCause = TAPI_CAUSE_UNKNOWN;
247 sat_engine_ret_call.meProblem = TAPI_SAT_ME_PROBLEM_ACCESS_CONTROL_CLASS_BAR;
248 sat_engine_ret_call.bIsOtherInfoExist = FALSE;
249 sat_engine_ret_call.permanentCallCtrlProblem = TAPI_SAT_CC_PROBLEM_ACTION_NOT_ALLOWED;
251 case CALL_VC_ME_CLEAR_DOWN_BEFORE_CONN:
252 sat_engine_ret_call.resp = TAPI_SAT_R_USER_CLEAR_DOWN_CALL_BEFORE_CONN;
253 sat_engine_ret_call.bIsTapiCauseExist = FALSE;
254 sat_engine_ret_call.tapiCause = TAPI_CAUSE_UNKNOWN;
255 sat_engine_ret_call.meProblem = TAPI_SAT_ME_PROBLEM_ME_BUSY_ON_CALL;
256 sat_engine_ret_call.bIsOtherInfoExist = FALSE;
257 sat_engine_ret_call.permanentCallCtrlProblem = TAPI_SAT_CC_PROBLEM_NO_SPECIFIC_CAUSE;
259 case CALL_VC_ME_RET_SUCCESS:
260 sat_engine_ret_call.resp = TAPI_SAT_R_SUCCESS;
261 sat_engine_ret_call.bIsTapiCauseExist = TRUE;
262 sat_engine_ret_call.tapiCause = TAPI_CAUSE_SUCCESS;
263 sat_engine_ret_call.meProblem = TAPI_SAT_ME_PROBLEM_NO_SPECIFIC_CAUSE;
264 sat_engine_ret_call.bIsOtherInfoExist = FALSE;
265 sat_engine_ret_call.permanentCallCtrlProblem = TAPI_SAT_CC_PROBLEM_NO_SPECIFIC_CAUSE;
271 call_vc_sat_response.commandType = TAPI_SAT_CMD_TYPE_SETUP_CALL;
272 call_vc_sat_response.commandId = pcall_vc_satcall_info->satengine_setupcall_data.commandId;
273 memset(&(call_vc_sat_response.appsRet.setupCall), 0, sizeof(call_vc_sat_response.appsRet.setupCall));
274 memcpy(&(call_vc_sat_response.appsRet.setupCall), &sat_engine_ret_call, sizeof(call_vc_sat_response.appsRet.setupCall));
277 case SAT_RQST_SEND_DTMF:
279 TelSatDtmfRetInfo_t sat_engine_ret_dtmf;
280 switch (sat_response_type) {
281 case CALL_VC_ME_UNABLE_TO_PROCESS_COMMAND:
282 sat_engine_ret_dtmf.resp = TAPI_SAT_R_ME_UNABLE_TO_PROCESS_COMMAND;
284 case CALL_VC_NETWORK_UNABLE_TO_PROCESS_COMMAND:
285 sat_engine_ret_dtmf.resp = TAPI_SAT_R_NETWORK_UNABLE_TO_PROCESS_COMMAND;
287 case CALL_VC_ME_CONTROL_PERMANENT_PROBLEM:
288 sat_engine_ret_dtmf.resp = TAPI_SAT_R_INTRCTN_WITH_CC_OR_SMS_CTRL_PRMNT_PRBLM;
290 case CALL_VC_ME_CLEAR_DOWN_BEFORE_CONN:
291 sat_engine_ret_dtmf.resp = TAPI_SAT_R_USER_CLEAR_DOWN_CALL_BEFORE_CONN;
293 case CALL_VC_ME_RET_SUCCESS:
294 sat_engine_ret_dtmf.resp = TAPI_SAT_R_SUCCESS;
300 call_vc_sat_response.commandType = TAPI_SAT_CMD_TYPE_SEND_DTMF;
301 call_vc_sat_response.commandId = pcall_vc_satcall_info->satengine_dtmf_data.commandId;
302 memset(&(call_vc_sat_response.appsRet.sendDtmf), 0, sizeof(call_vc_sat_response.appsRet.sendDtmf));
303 memcpy(&(call_vc_sat_response.appsRet.sendDtmf), &sat_engine_ret_dtmf, sizeof(call_vc_sat_response.appsRet.sendDtmf));
305 /*Reset SAT DATA after sending response */
306 pcall_vc_satcall_info->satengine_dtmf_data.bIsHiddenMode = FALSE;
307 CALL_ENG_DEBUG(ENG_ERR, "SAT Hidden mode has been reset");
311 CALL_ENG_DEBUG(ENG_DEBUG, "Invalid SAT Rquest Response Type");
315 error_code = tel_send_sat_app_exec_result(pagent->tapi_handle, &call_vc_sat_response);
316 if (error_code != TAPI_API_SUCCESS) {
317 CALL_ENG_DEBUG(ENG_DEBUG, "Error tel_send_sat_app_exec_result():%#X", error_code);
322 CALL_ENG_DEBUG(ENG_DEBUG, "tel_send_sat_app_exec_result: Success");
329 * This function checks whether outgoing call is possible
331 * @return This function returns TRUE if outgoing call is possible or else FALSE
332 * @param[in] pagent Pointer to the call agent structure
333 * @param[in] bemergency_number TRUE - if outgoing call being made is emergency call or else FALSE
335 gboolean _vc_core_ca_is_mocall_possible(call_vc_callagent_state_t *pagent, gboolean bemergency_number)
337 gboolean bactive_call = FALSE;
338 gboolean bheld_call = FALSE;
340 VOICECALL_RETURN_FALSE_IF_FAIL(pagent != NULL);
341 bactive_call = _vc_core_cm_isexists_active_call(&pagent->call_manager);
342 bheld_call = _vc_core_cm_isexists_held_call(&pagent->call_manager);
343 if (pagent->io_state != VC_INOUT_STATE_NONE) {
344 CALL_ENG_DEBUG(ENG_DEBUG, "io_state=%d with FALSE ..", pagent->io_state);
348 /* If it is emergency number, the call can be made by disconnecting all calls */
349 if (bemergency_number) {
350 CALL_ENG_DEBUG(ENG_DEBUG, "Emergency number with TRUE..");
354 /* Mo is impossile when both active and hold call exist */
355 if (bactive_call && bheld_call) {
356 CALL_ENG_DEBUG(ENG_DEBUG, "ended with FALSE ..");
361 member_num = _vc_core_cm_get_call_member_count(&pagent->call_manager);
363 #ifdef _CPHS_DEFINED_
364 if (bactive_call && _vc_core_svcall_cphs_csp_get_status(VC_CPHS_CSP_HOLD) == FALSE) {
365 CALL_ENG_DEBUG(ENG_DEBUG, "_vc_core_svcall_cphs_csp_get_status : Hold is not possible");
369 /* Mo is impossile when member is more than max */
370 if (member_num >= (VC_MAX_CALL_GROUP_MEMBER + 1)) {
371 CALL_ENG_DEBUG(ENG_DEBUG, "_vc_core_ca_is_mocall_possible: ended with FALSE ..");
376 CALL_ENG_DEBUG(ENG_DEBUG, "_vc_core_ca_is_mocall_possible: ended with TRUE ..");
384 * This function ends all the active calls
386 * @return Returns TRUE on success and FALSE on failure
387 * @param[in] pagent Handle to voicecall engine
389 gboolean _vc_core_ca_end_active_calls(call_vc_callagent_state_t *pagent)
391 gboolean result = FALSE;
392 VOICECALL_RETURN_FALSE_IF_FAIL(pagent != NULL);
393 if (TRUE == _vc_core_cm_isexists_active_call(&pagent->call_manager)) {
394 result = _vc_core_tapi_rqst_release_active_calls(pagent);
395 if (TRUE == result) {
396 _vc_core_ca_change_agent_state(pagent, CALL_VC_CA_STATE_WAIT_RELEASE_ALL_ACTIVECALL);
403 * This function ends all the calls
405 * @return Returns TRUE on success and FALSE on failure
406 * @param[in] pagent Handle to voicecall engine
408 gboolean _vc_core_ca_end_all_calls(call_vc_callagent_state_t *pagent)
410 gboolean result = FALSE;
411 VOICECALL_RETURN_FALSE_IF_FAIL(pagent != NULL);
412 result = _vc_core_tapi_rqst_release_all_calls(pagent);
413 if (TRUE == result) {
414 _vc_core_ca_change_agent_state(pagent, CALL_VC_CA_STATE_WAIT_RELEASE_ALL_CALLS);
420 * This function ends all the held calls
422 * @return Returns TRUE on success and FALSE on failure
423 * @param[in] pagent Handle to voicecall engine
425 gboolean _vc_core_ca_end_held_calls(call_vc_callagent_state_t *pagent)
427 gboolean result = FALSE;
428 VOICECALL_RETURN_FALSE_IF_FAIL(pagent != NULL);
429 if (TRUE == _vc_core_cm_isexists_held_call(&pagent->call_manager)) {
430 result = _vc_core_tapi_rqst_release_held_calls(pagent);
431 if (TRUE == result) {
432 _vc_core_ca_change_agent_state(pagent, CALL_VC_CA_STATE_WAIT_RELEASE_ALL_HOLDCALL);
439 * This function checks whether private call is possible or not
441 * @return This function returns TRUE if private is possible or else FALSE
442 * @param[in] pcall_agent Pointer to the call agent structure
444 gboolean _vc_core_ca_is_private_call_possible(call_vc_callagent_state_t *pcall_agent)
446 gboolean active_calls = FALSE, held_calls = FALSE;
447 int active_call_member = 0;
448 _vc_core_cm_isexists_call_ingroup(&pcall_agent->call_manager, &active_calls, &held_calls);
449 active_call_member = _vc_core_cm_get_active_call_count(&pcall_agent->call_manager);
450 if (TRUE == active_calls && FALSE == held_calls) {
451 if (active_call_member > 1) {
459 * This function checks whether call transfer is possible
461 * @return This function returns TRUE if transfer is possible or else FALSE
462 * @param[in] pcall_agent Pointer to the call agent structure
464 gboolean _vc_core_ca_is_transfer_call_possible(call_vc_callagent_state_t *pcall_agent)
466 gboolean active_calls = FALSE;
467 gboolean held_calls = FALSE;
468 int total_call_member = 0;
470 #ifdef _CPHS_DEFINED_
471 if (FALSE == _vc_core_svcall_cphs_csp_get_status(pcall_agent, VC_CPHS_CSP_CT)) {
475 _vc_core_cm_isexists_call_ingroup(&pcall_agent->call_manager, &active_calls, &held_calls);
476 total_call_member = _vc_core_cm_get_call_member_count(&pcall_agent->call_manager);
478 /* The Explicit Call Transfer (ECT) function should be invoked in association with two existing calls which 1) one is answered and in the held state and 2) the other is answered and active or alerting. */
479 if (3 == total_call_member) {
480 if ((TRUE == active_calls) && (TRUE == held_calls) && (VC_INVALID_CALL_INDEX != pcall_agent->call_manager.mtcall_index)) {
481 CALL_ENG_DEBUG(ENG_DEBUG, "Transfer possible..1 active, 1 held, 1 waiting..");
486 else if (2 == total_call_member) {
487 if ((TRUE == active_calls) && (TRUE == held_calls) && (VC_INVALID_CALL_INDEX == pcall_agent->call_manager.mtcall_index)) {
491 else if ((FALSE == active_calls) && (TRUE == held_calls) && (VC_INVALID_CALL_INDEX != pcall_agent->call_manager.mtcall_index)) {
495 else if ((FALSE == active_calls) && (TRUE == held_calls) && (-1 != pcall_agent->call_manager.setupcall_info.mocall_index) /*Outgoing call exists */
496 && (VC_INOUT_STATE_OUTGOING_WAIT_CONNECTED == pcall_agent->io_state)) {
504 * This function checks whether conference call is possible
506 * @return This function returns TRUE if transfer is possible or else FALSE
507 * @param[in] pcall_agent Pointer to the call agent structure
509 gboolean _vc_core_ca_is_conf_call_possible(call_vc_callagent_state_t *pcall_agent)
511 gboolean active_calls = FALSE;
512 gboolean held_calls = FALSE;
513 int total_call_member = 0;
515 #ifdef _CPHS_DEFINED_
516 if (FALSE == _vc_core_svcall_cphs_csp_get_status(pcall_agent, VC_CPHS_CSP_MPTY)) {
520 _vc_core_cm_isexists_call_ingroup(&pcall_agent->call_manager, &active_calls, &held_calls);
521 total_call_member = _vc_core_cm_get_call_member_count(&pcall_agent->call_manager);
523 /* Joining call is impossile when active or hold call doesn't exist */
524 if ((FALSE == active_calls) || (FALSE == held_calls)) {
525 CALL_ENG_DEBUG(ENG_DEBUG, "Join Impossible...");
531 /*Joining call is impossile when member is more than max
532 * if ( total_call_member >= (CALL_VC_CALL_GROUP_MEMBER_MAX + 1)) : Max Number in Group + Another Call*/
533 if (total_call_member > VC_MAX_CALL_GROUP_MEMBER) { /*Logic Changed from above line for same condition */
534 CALL_ENG_DEBUG(ENG_DEBUG, "Ended with FALSE...");
539 CALL_ENG_DEBUG(ENG_DEBUG, "Ended with TRUE...");
547 * This function clears the data of a connected call givenits call handle
549 * @return Returns TRUE on success and FALSE on failure
550 * @param[in] pcall_agent Handle to voicecall engine
551 * @param[in] call_handle Call handle of the connected call to be cleared
553 gboolean _vc_core_ca_clear_connected_call(call_vc_callagent_state_t *pcall_agent, int call_handle)
555 call_vc_call_objectinfo_t call_object;
556 gboolean remove = FALSE;
557 int group_index = -1;
560 VOICECALL_RETURN_FALSE_IF_FAIL(pcall_agent != NULL);
561 VOICECALL_RETURN_FALSE_IF_FAIL(call_handle >= 0);
562 CALL_ENG_DEBUG(ENG_DEBUG, "..");
563 _vc_core_cm_get_call_object(&pcall_agent->call_manager, call_handle, &call_object);
564 group_index = _vc_core_cm_get_group_index(&pcall_agent->call_manager, (call_vc_handle) call_handle);
565 if (group_index == -1) {
566 CALL_ENG_DEBUG(ENG_DEBUG, "ERROR: Not exist");
569 grp_mem_num = _vc_core_cm_get_member_count_ingroup(&pcall_agent->call_manager, group_index);
570 for (i = 0; i < grp_mem_num; i++) {
571 if ((_vc_core_cm_get_call_state_ingroup_byposition(&pcall_agent->call_manager, group_index, i) != VC_CALL_STATE_ENDED) && (_vc_core_cm_get_call_state_ingroup_byposition(&pcall_agent->call_manager, group_index, i) != VC_CALL_STATE_ENDED_FINISH)) {
576 _vc_core_cm_remove_call_object(&pcall_agent->call_manager, call_handle);
580 gboolean clear_end_call = TRUE;
581 _vc_core_cm_change_call_state(&call_object, VC_CALL_STATE_ENDED_FINISH);
582 _vc_core_cm_set_call_object(&pcall_agent->call_manager, &call_object);
583 for (i = 0; i < grp_mem_num; i++) {
584 if (_vc_core_cm_get_call_state_ingroup_byposition(&pcall_agent->call_manager, group_index, i) != VC_CALL_STATE_ENDED_FINISH)
585 clear_end_call = FALSE;
587 if (clear_end_call) {
588 _vc_core_cm_clear_endcall_member(&pcall_agent->call_manager);