+//
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Flora License, Version 1.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://floralicense.org/license/
+//
+// 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.
+//
+
+/**
+ * @file CallTelephonyManager.cpp
+ * @brief Call log item provider
+ */
+#include <stdio.h>
+#include <FBaseSys.h>
+#include <FSystem.h>
+#include "ITapiModem.h"
+#include "ITapiSim.h"
+#include "CallInfo.h"
+#include "CallTelephonyManager.h"
+#include "CallSettingsManager.h"
+#include "CallTypes.h"
+
+using namespace Tizen::Base;
+using namespace Tizen::Graphics;
+using namespace Tizen::Social;
+using namespace Tizen::System;
+using namespace Tizen::Base::Collection;
+
+const char* callEventList[] = {
+ TAPI_NOTI_VOICE_CALL_STATUS_IDLE,
+ TAPI_NOTI_VOICE_CALL_STATUS_ACTIVE,
+ TAPI_NOTI_VOICE_CALL_STATUS_HELD,
+ TAPI_NOTI_VOICE_CALL_STATUS_DIALING,
+ TAPI_NOTI_VOICE_CALL_STATUS_ALERT,
+ TAPI_NOTI_VOICE_CALL_STATUS_WAITING,
+ TAPI_NOTI_CALL_INFO_CALL_CONNECTED_LINE,
+ TAPI_NOTI_CALL_INFO_WAITING,
+ TAPI_NOTI_CALL_INFO_CUG,
+ TAPI_NOTI_CALL_INFO_FORWARDED,
+ TAPI_NOTI_CALL_INFO_BARRED_INCOMING,
+ TAPI_NOTI_CALL_INFO_BARRED_OUTGOING,
+ TAPI_NOTI_CALL_INFO_DEFLECTED,
+ TAPI_NOTI_CALL_INFO_CLIR_SUPPRESSION_REJECT,
+ TAPI_NOTI_CALL_INFO_FORWARD_UNCONDITIONAL,
+ TAPI_NOTI_CALL_INFO_FORWARD_CONDITIONAL,
+ TAPI_NOTI_CALL_INFO_CALL_LINE_IDENTITY,
+ TAPI_NOTI_CALL_INFO_CALL_NAME_INFORMATION,
+ TAPI_NOTI_CALL_INFO_FORWARDED_CALL,
+ TAPI_NOTI_CALL_INFO_CUG_CALL,
+ TAPI_NOTI_CALL_INFO_DEFLECTED_CALL,
+ TAPI_NOTI_CALL_INFO_TRANSFERED_CALL,
+ TAPI_NOTI_CALL_INFO_HELD,
+ TAPI_NOTI_CALL_INFO_ACTIVE,
+ TAPI_NOTI_CALL_INFO_JOINED,
+ TAPI_NOTI_CALL_INFO_RELEASED_ON_HOLD,
+ TAPI_NOTI_CALL_INFO_TRANSFER_ALERT,
+ TAPI_NOTI_CALL_INFO_TRANSFERED,
+ TAPI_NOTI_CALL_INFO_CF_CHECK_MESSAGE,
+};
+
+TelephonyManager* TelephonyManager::__pManager = null;
+
+TelephonyManager::TelephonyManager(ITelephonyEventListener* pEventListener)
+: __pEventListener(pEventListener)
+{
+ __pDialedCall = null;
+ __pIncomingCall = null;
+ __pActiveCallList = null;
+ __pSettingsManager = null;
+ __pTapiHandle = null;
+ __pAddressBook = null;
+ __pCachedContact = null;
+ __isMuted = false;
+ __isSpeakerOn = false;
+ __pSoundManager = null;
+ __pCalllogMgr = null;
+}
+
+TelephonyManager::~TelephonyManager(void)
+{
+ if (__pActiveCallList != null)
+ {
+ delete __pActiveCallList;
+ }
+
+ if (__pDialedCall != null)
+ {
+ delete __pDialedCall;
+ __pDialedCall = null;
+ }
+
+ if (__pIncomingCall != null)
+ {
+ delete __pIncomingCall;
+ __pIncomingCall = null;
+ }
+
+ if (__pAddressBook != null)
+ {
+ delete __pAddressBook;
+ __pAddressBook = null;
+ }
+ if (__pCachedContact != null)
+ {
+ delete __pCachedContact;
+ __pCachedContact = null;
+ }
+
+ //unregister for events from TAPI Lib.
+ UnregisterEvents();
+
+ //De-initialize the TAPI Library
+ if(__pTapiHandle != null)
+ {
+ tel_deinit(__pTapiHandle);
+ }
+
+ if (__pSoundManager != null)
+ {
+ delete __pSoundManager;
+ }
+
+ if (__pCalllogMgr != null)
+ {
+ __pCalllogMgr = null;
+ }
+}
+
+TelephonyManager*
+TelephonyManager::GetInstance(ITelephonyEventListener* pEventListener)
+{
+ if (__pManager == null)
+ {
+ CreateInstance(pEventListener);
+ }
+ return __pManager;
+}
+
+void
+TelephonyManager::CreateInstance(ITelephonyEventListener* pEventListener)
+{
+ __pManager = new (std::nothrow) TelephonyManager(pEventListener);
+ result r = __pManager->Initialize();
+ if (IsFailed(r))
+ {
+ delete __pManager;
+ __pManager = null;
+ }
+ atexit(&(TelephonyManager::DestroyInstance));
+}
+
+void
+TelephonyManager::DestroyInstance(void)
+{
+ if (__pManager != null)
+ {
+ __pManager->EndAllCalls();
+ delete __pManager;
+ __pManager = null;
+ }
+}
+
+result
+TelephonyManager::Initialize(void)
+{
+ //Initialize telephony library
+ result r = InitializeTelephonyLibrary();
+ if (IsFailed(r))
+ {
+ return r;
+ }
+ __pActiveCallList = new (std::nothrow) HashMapT<long, CallInfo>();
+ __pActiveCallList->Construct(IDI_MAX_ACTIVE_CALLS);
+
+ //Initialize the Settings Manager to fetch call settings
+ __pSettingsManager = SettingsManager::GetInstance();
+
+ __pSoundManager = new (std::nothrow) SoundManager();
+ __pCalllogMgr = CallLogManager::GetInstance();
+
+ //initialize address book to fetch contacts information
+ __pAddressBook = AddressbookManager::GetInstance()->GetAddressbookN();
+ if(__pAddressBook == null)
+ {
+ return E_FAILURE;
+ }
+ return r;
+}
+
+result
+TelephonyManager::InitializeTelephonyLibrary(void)
+{
+ result r = E_FAILURE;
+
+ __pTapiHandle = tel_init(null);
+ if (__pTapiHandle != null)
+ {
+ //register telephony events
+ int errorCode = RegisterEvents();
+ if (errorCode == TAPI_CAUSE_SUCCESS)
+ {
+ r = E_SUCCESS;
+ }
+ }
+ //TAPI Library is initialized and events registered successfully
+ return r;
+}
+
+int
+TelephonyManager::RegisterEvents(void)
+{
+ int errCode = -1;
+ int eventCount = sizeof(callEventList) / sizeof(char *);
+ for (int index = 0; index < eventCount; index++)
+ {
+ errCode = tel_register_noti_event(__pTapiHandle, callEventList[index], &HandleCallback, this);
+ if (errCode != TAPI_API_SUCCESS)
+ {
+ return errCode;
+ }
+ }
+ return errCode;
+}
+
+void
+TelephonyManager::UnregisterEvents(void)
+{
+ int eventCount = sizeof(callEventList) / sizeof(char *);
+ for (int index = 0; index < eventCount; index++)
+ {
+ tel_deregister_noti_event(__pTapiHandle, callEventList[index]);
+ }
+}
+
+ErrorCodes
+TelephonyManager::SetupMoCall(String& contactNumber, bool isEmergency)
+{
+ result res = E_SUCCESS;
+ //check if valid phone number exist
+ res = CheckValidTelePhoneNumber(contactNumber);
+ if (IsFailed(res))
+ {
+ return ERROR_INVALID_NUMBER;
+ }
+
+ //if dialing an emergency call and active calls exist
+ //then end all active calls.
+ if (isEmergency && __pActiveCallList->GetCount() > 0)
+ {
+ //Get first call handle
+ CallInfo endCallInfo;
+ IListT<CallInfo>* pCallList = __pActiveCallList->GetValuesN();
+ pCallList->GetAt(0, endCallInfo);
+ int callHandle = endCallInfo.GetCallHandle()->ToLong();
+ delete pCallList;
+ pCallList = null;
+
+ //release all active or held calls
+ int tapiRes = tel_end_call(__pTapiHandle, callHandle, TAPI_CALL_END_ALL, &HandleCallbackResponse, this);
+ if (tapiRes == TAPI_CAUSE_SUCCESS)
+ {
+ __pActiveCallList->RemoveAll();
+ res = E_SUCCESS;
+ }
+ else
+ {
+ res = E_FAILURE;
+ }
+ }
+ else if (__pActiveCallList->GetCount() == 1)
+ {
+ //Check if there is already an active call,
+ //Put the already active call on hold.
+ CallInfo holdCallInfo;
+ IListT<CallInfo>* pCallList = __pActiveCallList->GetValuesN();
+
+ pCallList->GetAt(0, holdCallInfo);
+ //Check if call is active, then put on hold
+ if (holdCallInfo.IsOnHold() == false)
+ {
+ res = HoldActiveCall(&holdCallInfo, true);
+ }
+ delete pCallList;
+ pCallList = null;
+ }
+
+ //make the next call, only if any existing active call
+ //is successfully put on hold or is already on hold.
+ if (res == E_SUCCESS)
+ {
+ res = DialOutgoingCall(contactNumber, isEmergency);
+ }
+
+ if(res == E_SUCCESS)
+ {
+ return ERROR_NONE;
+ }
+ else
+ {
+ return ERROR_TAPI_ERROR;
+ }
+}
+
+void
+TelephonyManager::EndAllCalls(void)
+{
+ if(__pDialedCall != null)
+ {
+ if(__pDialedCall->GetCallHandle() != null)
+ {
+ tel_end_call(__pTapiHandle, __pDialedCall->GetCallHandle()->ToLong(), TAPI_CALL_END, &HandleCallbackResponse, this);
+ }
+ }
+ tel_end_call(__pTapiHandle, -1, TAPI_CALL_END_HOLD_ALL, &HandleCallbackResponse, this);
+ //end all active calls before terminating application
+ tel_end_call(__pTapiHandle, -1, TAPI_CALL_END_ALL, &HandleCallbackResponse, this);
+ __pSettingsManager->SetCallState(CALL_STATE_CALL_OFF);
+}
+
+result
+TelephonyManager::EndActiveCall(Long callHandle)
+{
+ result r = E_FAILURE;
+
+ //fetch ended callInfo from active call list
+ CallInfo endCall;
+ r = __pActiveCallList->GetValue(callHandle.ToLong(), endCall);
+ if (r == E_SUCCESS)
+ {
+ r = EndCall(endCall);
+ }
+ return r;
+}
+
+result
+TelephonyManager::EndDialingCall(String& contactNumber)
+{
+ result r = E_FAILURE;
+ //This is because for a dialing call, call handle is updated with some delay in telephony manager.
+ //And it is not available with outgoing call screen.
+ if (contactNumber.IsEmpty())
+ {
+ return r;
+ }
+
+ //Check If Ended call matches Dialed Call.
+ CallInfo endCall;
+ if (__pDialedCall != null && __pDialedCall->GetContactNumber().Equals(contactNumber))
+ {
+ endCall = *__pDialedCall;
+ r = EndCall(endCall);
+ }
+ return r;
+}
+
+result
+TelephonyManager::EndCall(CallInfo& endCallInfo)
+{
+ result r = E_FAILURE;
+
+ if (endCallInfo.GetCallHandle() != null)
+ {
+ unsigned int callHandle = endCallInfo.GetCallHandle()->ToLong();
+ //end "dialed but unconnected" call or active call - processing to be handled in HandleIdleCallback().
+ int res = tel_end_call(__pTapiHandle, callHandle, TAPI_CALL_END, &HandleCallbackResponse, this);
+ if (res == TAPI_CAUSE_SUCCESS)
+ {
+ r = E_SUCCESS;
+ }
+ }
+ return r;
+}
+
+result
+TelephonyManager::AnswerCall(int callHandle, bool acceptCall)
+{
+ result r = E_FAILURE;
+ __pSoundManager->StopAlert();
+ TelCallAnswerType_t answerType = TAPI_CALL_ANSWER_ACCEPT;
+ int res = -1;
+ if (acceptCall == true)
+ {
+ answerType = TAPI_CALL_ANSWER_ACCEPT;
+ // redirect to dummy call back handler as the flow already handled in registered event callback
+ res = tel_answer_call(__pTapiHandle, callHandle, answerType, &HandleCallbackResponse, this);
+ }
+ else
+ {
+ answerType = TAPI_CALL_ANSWER_REJECT;
+ // redirect to reject call back handler as the flow has to be handled
+ res = tel_answer_call(__pTapiHandle, callHandle, answerType, &HandleRejectCallbackResponse, this);
+ }
+
+ if (res == TAPI_CAUSE_SUCCESS)
+ {
+ r = E_SUCCESS;
+ }
+ else
+ {
+ r = E_FAILURE;
+ }
+ return r;
+}
+
+result
+TelephonyManager::AcceptCall(CallAnsweringOptions answerOptions,int callHandle)
+{
+ result r = E_FAILURE;
+ __pSoundManager->StopAlert();
+ __pSoundManager->SetSoundMode(SOUND_MODE_VOICE);
+
+ //Check if this is a new incoming call
+ if(__pIncomingCall == null || (callHandle != (unsigned int)__pIncomingCall->GetCallHandle()->ToLong()))
+ {
+ //construct and fetch new Incoming call Info
+ String incomingHandle;
+ incomingHandle.Append(callHandle);
+ CallInfo* pDuplicateCallInfo = FetchIncomingCallHandleN(incomingHandle, String(L""));
+ if(pDuplicateCallInfo == null)
+ {
+ r = E_FAILURE;
+ return r;
+ }
+ delete pDuplicateCallInfo;
+ pDuplicateCallInfo = null;
+ }
+
+ switch(answerOptions)
+ {
+ case ANSERWING_OPTION_HOLD_SINGLE_CALL:
+ case ANSERWING_OPTION_END_SINGLE_CALL:
+ {
+ r = AcceptSecondCall(answerOptions, callHandle);
+ }
+ break;
+
+ case ANSERWING_OPTION_REPLACE_ACTIVE_CALL:
+ case ANSERWING_OPTION_REPLACE_HELD_CALL:
+ case ANSERWING_OPTION_END_ALL_CALLS:
+ {
+ r = AcceptMultipleCall(answerOptions, callHandle);
+ }
+ break;
+
+ default:
+ break;
+ }
+ return r;
+}
+
+result
+TelephonyManager::AcceptSecondCall(CallAnsweringOptions answerOptions, const int incomingCallHandle)
+{
+ result r = E_FAILURE;
+
+ switch (answerOptions)
+ {
+ case ANSERWING_OPTION_HOLD_SINGLE_CALL:
+ {
+ //accept incoming call by putting active call on Hold with 'TAPI_CALL_ANSWER_HOLD_AND_ACCEPT'
+ int res = tel_answer_call(__pTapiHandle, incomingCallHandle, TAPI_CALL_ANSWER_HOLD_AND_ACCEPT, &HandleCallbackResponse, this);
+ if (res != 0)
+ {
+ r = E_FAILURE;
+ break;
+ }
+
+ //Call connected successfully
+ r = E_SUCCESS;
+ //update status of first call to "OnHold"
+ IListT<CallInfo>* pCallList = __pActiveCallList->GetValuesN();
+ CallInfo firstCallInfo;
+ pCallList->GetAt(0, firstCallInfo);
+ //replace old object with update CallInfo
+ CallInfo* pHeldCallInfo = new (std::nothrow) CallInfo();
+ *pHeldCallInfo = firstCallInfo;
+ pHeldCallInfo->SetOnHold(true);
+ __pActiveCallList->Remove(firstCallInfo.GetCallHandle()->ToLong());
+ __pActiveCallList->Add(pHeldCallInfo->GetCallHandle()->ToLong(), *pHeldCallInfo);
+ delete pCallList;
+ pCallList = null;
+ }
+ break;
+
+ case ANSERWING_OPTION_END_SINGLE_CALL:
+ {
+ //Transfer Old active calls to a separate list to avoid any processing in HandleIdleCallback().
+ HashMapT<long, CallInfo>* pEndCallsList = __pActiveCallList;
+ //create a new ActiveCallList
+ __pActiveCallList = new (std::nothrow) HashMapT<long, CallInfo>();
+ __pActiveCallList->Construct(IDI_MAX_ACTIVE_CALLS);
+
+ //accept call and reject all active calls with 'TAPI_CALL_ANSWER_REPLACE'
+ int res = tel_answer_call(__pTapiHandle, incomingCallHandle, TAPI_CALL_ANSWER_REPLACE, &HandleCallbackResponse, this);
+ if (res != 0)
+ {
+ r = E_FAILURE;
+ //delete newly constructed list and gain ownership of old list
+ delete __pActiveCallList;
+ __pActiveCallList = pEndCallsList;
+ break;
+ }
+
+ //Call connected successfully
+ r = E_SUCCESS;
+ //Add calls information to call log before deleting from active call list.
+ IListT<CallInfo>* pCallList = pEndCallsList->GetValuesN();
+ if(pCallList != null)
+ {
+ CallInfo endCallInfo;
+ if (pCallList->GetAt(0, endCallInfo) == E_SUCCESS)
+ {
+ SaveCallInfoToLogsDb(endCallInfo);
+ }
+ delete pCallList;
+ }
+ pEndCallsList->RemoveAll();
+ delete pEndCallsList;
+ }
+ break;
+
+ default:
+ break;
+ }
+ return r;
+}
+
+result
+TelephonyManager::AcceptMultipleCall(CallAnsweringOptions answerOptions, const int incomingCallHandle)
+{
+ result r = E_FAILURE;
+
+ switch (answerOptions)
+ {
+ case ANSERWING_OPTION_REPLACE_ACTIVE_CALL:
+ {
+ //Replace "Active" call by incoming call and save ended call to call logs db.
+ IListT<CallInfo>* pCallList = __pActiveCallList->GetValuesN();
+ CallInfo callToBeEnded;
+ pCallList->GetAt(0, callToBeEnded);
+ //Check if the call is on "Hold", then fetch 2nd callInfo
+ if (callToBeEnded.IsOnHold() == true)
+ {
+ pCallList->GetAt(1, callToBeEnded);
+ }
+ delete pCallList;
+ pCallList = null;
+
+ //remove "CallToBeEnded" from Active call list to avoid processing in HandleIdleCallback().
+ __pActiveCallList->Remove(callToBeEnded.GetCallHandle()->ToLong());
+
+ //Accept incoming call by End Active call with 'TAPI_CALL_ANSWER_REPLACE'
+ int res = tel_answer_call(__pTapiHandle, incomingCallHandle, TAPI_CALL_ANSWER_REPLACE, &HandleCallbackResponse, this);
+ if (res != 0)
+ {
+ r = E_FAILURE;
+ //save the previous call back to active call list
+ __pActiveCallList->Add(callToBeEnded.GetCallHandle()->ToLong(), callToBeEnded);
+ break;
+ }
+
+ //Incoming Call connected successfully
+ r = E_SUCCESS;
+ //save to ended call to call logs db.
+ SaveCallInfoToLogsDb(callToBeEnded);
+ }
+ break;
+
+ case ANSERWING_OPTION_REPLACE_HELD_CALL:
+ {
+ //Replace "Held" call by incoming call and save ended call to call logs db.
+ IListT<CallInfo>* pCallList = __pActiveCallList->GetValuesN();
+ //"Held" call is to be ended
+ CallInfo callToBeEnded;
+ //"Active" call will be put on Hold
+ CallInfo callToPutOnHold;
+ pCallList->GetAt(0, callToBeEnded);
+ //Check if the call is NOT "Held", then fetch 2nd callInfo
+ if (callToBeEnded.IsOnHold() == false)
+ {
+ callToPutOnHold = callToBeEnded;
+ pCallList->GetAt(1, callToBeEnded);
+ }
+ else
+ {
+ pCallList->GetAt(1, callToPutOnHold);
+ }
+ delete pCallList;
+ pCallList = null;
+
+ //remove "CallToBeEnded" from Active call list to avoid processing in HandleIdleCallback().
+ __pActiveCallList->Remove(callToBeEnded.GetCallHandle()->ToLong());
+
+ //End "Held" Call using 'TAPI_CALL_END'.
+ int res = -1;
+ if (callToBeEnded.IsConferenceCall() == false)
+ {
+ res = tel_end_call(__pTapiHandle, callToBeEnded.GetCallHandle()->ToLong(), TAPI_CALL_END, &HandleCallbackResponse, this);
+ }
+ else
+ {
+ IListT<CallInfo>* pParticipantsInfo = callToBeEnded.GetCallerList();
+ //need to end every participant individually for conference call
+ for (int index = 0; index < pParticipantsInfo->GetCount(); index++)
+ {
+ CallInfo memberCallInfo;
+ pParticipantsInfo->GetAt(index, memberCallInfo);
+ res = tel_end_call(__pTapiHandle, memberCallInfo.GetCallHandle()->ToLong(), TAPI_CALL_END, &HandleCallbackResponse, this);
+ }
+ }
+
+ if (res != 0)
+ {
+ r = E_FAILURE;
+ //save the previous "callToBeEnded" call back to active call list
+ __pActiveCallList->Add(callToBeEnded.GetCallHandle()->ToLong(), callToBeEnded);
+ break;
+ }
+ //"Held" call successfully ended - Add call ended to call log database
+ SaveCallInfoToLogsDb(callToBeEnded);
+
+ //accept incoming call by Holding "Active" call using "TAPI_CALL_ANSWER_HOLD_AND_ACCEPT".
+ res = tel_answer_call(__pTapiHandle, incomingCallHandle, TAPI_CALL_ANSWER_HOLD_AND_ACCEPT, &HandleCallbackResponse, this);
+ if (res != 0)
+ {
+ r = E_FAILURE;
+ break;
+ }
+
+ //Call connected successfully and active call is "Onhold"
+ r = E_SUCCESS;
+ //replace old object with update CallInfo
+ CallInfo* pHeldCallInfo = new (std::nothrow) CallInfo();
+ *pHeldCallInfo = callToPutOnHold;
+ pHeldCallInfo->SetOnHold(true);
+ __pActiveCallList->Remove(callToPutOnHold.GetCallHandle()->ToLong());
+ __pActiveCallList->Add(pHeldCallInfo->GetCallHandle()->ToLong(), *pHeldCallInfo);
+ }
+ break;
+
+ case ANSERWING_OPTION_END_ALL_CALLS:
+ {
+ //End all active and Held calls after saving to call log. Incoming call is automatically accepted by TAPI engine,
+ // and processing of Incoming call is handled in HandleActiveCallback().
+
+ //Transfer Old active calls to a separate list to avoid any processing in HandleIdleCallback().
+ HashMapT<long, CallInfo>* pEndCallsList = __pActiveCallList;
+ //create a new ActiveCallList
+ __pActiveCallList = new (std::nothrow) HashMapT<long, CallInfo>();
+ __pActiveCallList->Construct(IDI_MAX_ACTIVE_CALLS);
+
+ //End all active calls and all hold calls
+ int res = tel_end_call(__pTapiHandle, -1, TAPI_CALL_END_ACTIVE_ALL, &HandleCallbackResponse, this);
+ if(res == 0)
+ {
+ res = tel_end_call(__pTapiHandle, -1, TAPI_CALL_END_HOLD_ALL, &HandleCallbackResponse, this);
+ }
+
+ if (res != 0)
+ {
+ r = E_FAILURE;
+ //delete newly constructed list and gain ownership of old list
+ delete __pActiveCallList;
+ __pActiveCallList = pEndCallsList;
+ break;
+ }
+
+ //all calls ended successfully, Incoming call is automatically accepted.
+ r = E_SUCCESS;
+
+ //Add calls information to call log before deleting from active call list.
+ IListT<CallInfo>* pCallList = pEndCallsList->GetValuesN();
+ if(pCallList != null)
+ {
+ int callCount = pCallList->GetCount();
+ for (int index = 0; index < callCount; index++)
+ {
+ CallInfo endCallInfo;
+ if (pCallList->GetAt(index, endCallInfo) == E_SUCCESS)
+ {
+ SaveCallInfoToLogsDb(endCallInfo);
+ }
+ }
+ delete pCallList;
+ pCallList = null;
+ }
+ pEndCallsList->RemoveAll();
+ delete pEndCallsList;
+ pEndCallsList = null;
+ }
+ break;
+
+ default:
+ break;
+ }
+ return r;
+}
+
+result
+TelephonyManager::HoldCall(Tizen::Base::Long callHandle, bool holdCall)
+{
+ result r = E_SUCCESS;
+ //Check if there are any existing active calls
+ if (__pActiveCallList->GetCount())
+ {
+ IListT<CallInfo>* pCallList = __pActiveCallList->GetValuesN();
+ int callCount = pCallList->GetCount();
+ for (int index = 0; index < callCount; index++)
+ {
+ CallInfo holdCallInfo;
+
+ r = pCallList->GetAt(index, holdCallInfo);
+ //check if an active call is found with matching contact no.
+ if ((r == E_SUCCESS) && (holdCallInfo.GetCallHandle()->Equals(callHandle)))
+ {
+ r = HoldActiveCall(&holdCallInfo, holdCall);
+ break;
+ }
+ }
+ delete pCallList;
+ pCallList = null;
+ }
+
+ return r;
+}
+
+result
+TelephonyManager::EndConferenceCall(void)
+{
+ result r = E_FAILURE;
+ //fetch conference callInfo to end
+ CallInfo confCallToEnd;
+ bool isConferenceCallFound = false;
+
+ IListT<CallInfo>* pCallList = __pActiveCallList->GetValuesN();
+ int callCount = pCallList->GetCount();
+ for (int index = 0; index < callCount; index++)
+ {
+ pCallList->GetAt(index, confCallToEnd);
+ if (confCallToEnd.IsConferenceCall() == true)
+ {
+ isConferenceCallFound = true;
+ break;
+ }
+ }
+ delete pCallList;
+ pCallList = null;
+
+ if (isConferenceCallFound == true)
+ {
+ //End conference call
+ TelCallEndType_t callEndType = TAPI_CALL_END_ACTIVE_ALL;
+ if (confCallToEnd.IsOnHold() == true)
+ {
+ callEndType = TAPI_CALL_END_HOLD_ALL;
+ }
+ int res = tel_end_call(__pTapiHandle, confCallToEnd.GetCallHandle()->ToLong(), callEndType, &HandleEndConferenceCallbackResponse, this);
+ if (res == TAPI_CAUSE_SUCCESS)
+ {
+ r = E_SUCCESS;
+ }
+ }
+ return r;
+}
+
+result
+TelephonyManager::HoldConferenceCall(bool holdCall)
+{
+ result r = E_FAILURE;
+ int confCallIndex = -1;
+ CallInfo confCallToHold;
+ bool isConferenceCallFound = false;
+
+ IListT<CallInfo>* pCallList = __pActiveCallList->GetValuesN();
+ int confCallCount = pCallList->GetCount();
+
+ for (int index = 0; index < confCallCount; index++)
+ {
+ pCallList->GetAt(index, confCallToHold);
+ if (confCallToHold.IsConferenceCall() == true)
+ {
+ isConferenceCallFound = true;
+ confCallIndex = index;
+ //Found the Conference call to be ended.
+ break;
+ }
+ }
+
+ if (isConferenceCallFound == false)
+ {
+ delete pCallList;
+ pCallList = null;
+ return r;
+ }
+
+ unsigned int callHandle = confCallToHold.GetCallHandle()->ToLong();
+ int res = TAPI_API_INVALID_INPUT;
+ if (holdCall == true)
+ {
+ res = tel_hold_call(__pTapiHandle, callHandle, &HandleCallbackResponse, this);
+ }
+ else
+ {
+ res = tel_active_call(__pTapiHandle, callHandle, &HandleCallbackResponse, this);
+ }
+ if (res == TAPI_API_SUCCESS)
+ {
+ r = E_SUCCESS;
+ if (holdCall == true)
+ {
+ confCallToHold.SetOnHold(true);
+ }
+ else
+ {
+ confCallToHold.SetOnHold(false);
+ }
+ CallInfo* pConfCallInfo = new (std::nothrow) CallInfo();
+ *pConfCallInfo = confCallToHold;
+ __pActiveCallList->Remove(callHandle);
+ __pActiveCallList->Add(callHandle, *pConfCallInfo);
+ }
+ else
+ {
+ r = E_FAILURE;
+ }
+
+ delete pCallList;
+ pCallList = null;
+ return r;
+}
+
+result
+TelephonyManager::JoinCall(void)
+{
+ result r = E_FAILURE;
+ int res = -1;
+ CallInfo activeCall;
+ CallInfo heldCall;
+ // Use enumerator to access elements in the map
+ IListT<CallInfo>* pCallList = __pActiveCallList->GetValuesN();
+ r = pCallList->GetAt(0, activeCall);
+
+ if (r == E_SUCCESS)
+ {
+ r = pCallList->GetAt(1, heldCall);
+ if (r == E_SUCCESS)
+ {
+ unsigned int activeCallHandle = activeCall.GetCallHandle()->ToLong();
+ unsigned int heldCallHandle = heldCall.GetCallHandle()->ToLong();
+
+ //Check if participants in conference call are under limit.
+ if ((heldCall.IsConferenceCall() == true) && (heldCall.GetCallerListCount() < IDI_MAX_CONF_CALL_PARTICIPANTS))
+ {
+ res = tel_join_call(__pTapiHandle, heldCallHandle, activeCallHandle, &HandleJoinCallbackResponse, this);
+ }
+ else if (activeCall.GetCallerListCount() < IDI_MAX_CONF_CALL_PARTICIPANTS)
+ {
+ res = tel_join_call(__pTapiHandle, activeCallHandle, heldCallHandle, &HandleJoinCallbackResponse, this);
+ }
+ }
+ }
+ delete pCallList;
+ pCallList = null;
+ if (res == TAPI_API_SUCCESS)
+ {
+ r = E_SUCCESS;
+ }
+ else
+ {
+ r = E_FAILURE;
+ }
+ return r;
+}
+
+result
+TelephonyManager::HoldActiveCall(CallInfo* pActiveCallInfo, bool holdCall)
+{
+ unsigned int callHandle = pActiveCallInfo->GetCallHandle()->ToLong();
+ int retStatus = -1;
+ if (holdCall == true)
+ {
+ retStatus = tel_hold_call(__pTapiHandle, callHandle, &HandleCallbackResponse, this);
+ }
+ else
+ {
+ retStatus = tel_active_call(__pTapiHandle, callHandle, &HandleCallbackResponse, this);
+ }
+
+ if (retStatus == TAPI_CAUSE_SUCCESS)
+ {
+ CallInfo* pHeldCallInfo = new (std::nothrow) CallInfo();
+ //copy state into new callinfo object
+ *pHeldCallInfo = *pActiveCallInfo;
+
+ //set call to hold state
+ pHeldCallInfo->SetOnHold(holdCall);
+
+ __pActiveCallList->Remove(callHandle);
+ //replace old object with new
+ __pActiveCallList->Add(callHandle, *pHeldCallInfo);
+ return E_SUCCESS;
+ }
+ else
+ {
+ return E_FAILURE;
+ }
+}
+
+result
+TelephonyManager::DialOutgoingCall(String& contactNumber, bool isEmergency)
+{
+ TelCallDial_t structDialCall;
+
+ //conversion "contactNumber" to char*
+ const wchar_t* pContact = contactNumber.GetPointer();
+ int len = contactNumber.GetLength()+1;
+ char* pNumber = new (std::nothrow) char[len];
+ wcstombs(pNumber, pContact, len);
+
+
+ //initialize request parameter
+ memset(&structDialCall, '\0', sizeof(TelCallDial_t));
+ memcpy(structDialCall.szNumber, pNumber, strlen(pNumber));
+ AppLogDebug("%s",structDialCall.szNumber);
+ if(isEmergency == true)
+ {
+ structDialCall.CallType = TAPI_CALL_TYPE_E911;
+ }
+ else
+ {
+ structDialCall.CallType = TAPI_CALL_TYPE_VOICE;
+ }
+
+ int res = tel_dial_call(__pTapiHandle, &structDialCall, &HandleDialCallbackResponse, this);
+ if (__pSoundManager == null)
+ {
+ __pSoundManager = new (std::nothrow) SoundManager();
+ }
+ __pSoundManager->StartSession();
+ delete[] pNumber;
+ pNumber = null;
+
+ if (res == TAPI_CAUSE_SUCCESS)
+ {
+ if (__pDialedCall != null)
+ {
+ delete __pDialedCall;
+ __pDialedCall = null;
+ }
+ __pDialedCall = new (std::nothrow) CallInfo();
+ __pDialedCall->SetContactNumber(contactNumber);
+ __pDialedCall->SetEmergency(isEmergency);
+ result r = FetchContactInfoForNumber(contactNumber);
+ if (!IsFailed(r))
+ {
+ __pDialedCall->SetContactInfo(*__pCachedContact);
+ }
+ return E_SUCCESS;
+ }
+ else
+ {
+ return E_FAILURE;
+ }
+}
+
+result
+TelephonyManager::SwapCalls(void)
+{
+ result r = E_FAILURE;
+
+ //check if there are atleast 2 active calls
+ if (__pActiveCallList->GetCount() == IDI_MAX_ACTIVE_CALLS)
+ {
+ int retStatus = 0;
+
+ //fetch call handles
+ IListT<long>* pCallHandleList = __pActiveCallList->GetKeysN();
+ long callHandle1 = 0;
+ pCallHandleList->GetAt(0, callHandle1);
+ long callHandle2 = 0;
+ pCallHandleList->GetAt(1, callHandle2);
+
+ retStatus = tel_swap_call(__pTapiHandle, callHandle1, callHandle2, &HandleSwapCallbackResponse, this);
+
+ if (retStatus == TAPI_CAUSE_SUCCESS)
+ {
+ r = E_SUCCESS;
+ }
+ delete pCallHandleList;
+ pCallHandleList = null;
+ }
+
+ return r;
+}
+
+result
+TelephonyManager::SendCallDTMF(String& textToBeSent)
+{
+ result r = E_FAILURE;
+ //check if there is an active Call
+ if (__pActiveCallList->GetCount() > 0)
+ {
+ //conversion "textToBeSent" to char*
+ const wchar_t* pTextToBeSent = textToBeSent.GetPointer();
+ int len = textToBeSent.GetLength() + 1;
+ char* pNumber = new (std::nothrow) char[len];
+ wcstombs(pNumber, pTextToBeSent, len);
+ int retStatus = tel_call_dtmf(__pTapiHandle, pNumber, &HandleCallbackResponse, this);
+ delete []pNumber;
+ pNumber = null;
+ if (retStatus == TAPI_CAUSE_SUCCESS)
+ {
+ r = E_SUCCESS;
+ }
+ }
+ return r;
+}
+
+result
+TelephonyManager::EndFromConference(int callHandle)
+{
+ result r = E_FAILURE;
+ int confCallIndex = -1;
+ CallInfo endConfCall;
+ bool isConferenceCallFound = false;
+
+ IListT<CallInfo>* pCallList = __pActiveCallList->GetValuesN();
+ int callCount = pCallList->GetCount();
+ for (int index = 0; index < callCount; index++)
+ {
+ pCallList->GetAt(index, endConfCall);
+ if (endConfCall.IsConferenceCall() == true)
+ {
+ isConferenceCallFound = true;
+ confCallIndex = index;
+ //Found the Conference call to be ended.
+ break;
+ }
+ }
+
+ delete pCallList;
+ pCallList = null;
+
+ if (isConferenceCallFound == false)
+ {
+ //no conference call found
+ return r;
+ }
+
+ //Identify the call to be ended and remove from list on API success
+ CallInfo callToBeEnded;
+ IListT<CallInfo>* pParticipantList = endConfCall.GetCallerList();
+ int participantCount = pParticipantList->GetCount();
+ for (int index = 0; index < participantCount; index++)
+ {
+ pParticipantList->GetAt(index, callToBeEnded);
+ if (callToBeEnded.GetCallHandle()->ToLong() == callHandle)
+ {
+ //Identify the call to be ended and remove from list on API success
+ TelCallEndType_t endType = TAPI_CALL_END;
+
+ int res = tel_end_call(__pTapiHandle, callHandle, endType, &HandleEndFromConferenceCallbackResponse, this);
+ if (res == TAPI_CAUSE_SUCCESS)
+ {
+ r = E_SUCCESS;
+ }
+ else
+ {
+ r = E_FAILURE;
+ }
+ break;
+ }
+ }
+
+ return r;
+}
+
+result
+TelephonyManager::SplitFromConference(int callHandle)
+{
+ result r = E_FAILURE;
+ int confCallIndex = -1;
+ CallInfo endConfCall;
+ bool isConferenceCallFound = false;
+
+ IListT<CallInfo>* pCallList = __pActiveCallList->GetValuesN();
+ int callCount = pCallList->GetCount();
+ for (int index = 0; index < callCount; index++)
+ {
+ pCallList->GetAt(index, endConfCall);
+ if (endConfCall.IsConferenceCall() == true)
+ {
+ isConferenceCallFound = true;
+ confCallIndex = index;
+ //Found the Conference call to be ended.
+ break;
+ }
+ }
+ delete pCallList;
+ pCallList = null;
+ if (isConferenceCallFound == false)
+ {
+ //no conference call found
+ return r;
+ }
+
+ //Identify the call to be ended and remove from list on API success
+ CallInfo callToBeEnded;
+ pCallList = endConfCall.GetCallerList();
+ callCount = pCallList->GetCount();
+ for (int index = 0; index < callCount; index++)
+ {
+ pCallList->GetAt(index, callToBeEnded);
+ if (callToBeEnded.GetCallHandle()->ToLong() == callHandle)
+ {
+ int res = tel_split_call(__pTapiHandle, callHandle, &HandleSplitFromConferenceCallbackResponse, this);
+ if (res == TAPI_CAUSE_SUCCESS)
+ {
+ r = E_SUCCESS;
+ }
+ else
+ {
+ r = E_FAILURE;
+ }
+ break;
+ }
+ }
+ return r;
+}
+
+result
+TelephonyManager::SetMuteStatus(bool setMute)
+{
+ TelSoundMuteStatus_t muteStatus;
+ result r = E_FAILURE;
+ if (setMute == true)
+ {
+ muteStatus = TAPI_SOUND_MUTE_STATUS_ON;
+ }
+ else
+ {
+ muteStatus = TAPI_SOUND_MUTE_STATUS_OFF;
+ }
+ int res = tel_set_call_mute_status(__pTapiHandle, muteStatus, &HandleCallbackResponse, this);
+ if (res == TAPI_CAUSE_SUCCESS)
+ {
+ __isMuted = setMute;
+ r = E_SUCCESS;
+ }
+ else
+ {
+ r = E_FAILURE;
+ }
+ return r;
+}
+
+bool
+TelephonyManager::IsCallMuted(void)
+{
+ return __isMuted;
+}
+
+result
+TelephonyManager::SetSpeakerStatus(bool setSpeaker)
+{
+ result r = E_FAILURE;
+ TelCallSoundPathInfo_t callSoundPathInfo;
+ __pSoundManager->SetSpeakerStatus(setSpeaker);
+ if (setSpeaker == true)
+ {
+ callSoundPathInfo.path = TAPI_SOUND_PATH_SPK_PHONE;
+ }
+ else
+ {
+ callSoundPathInfo.path = TAPI_SOUND_PATH_HANDSET;
+ }
+ callSoundPathInfo.ex_volume = TelCallSoundPathInfo_t::TAPI_SOUND_EX_VOLUME_ON;
+
+ int res = tel_set_call_sound_path(__pTapiHandle, &callSoundPathInfo, &HandleCallbackResponse, this);
+
+ if (res == TAPI_CAUSE_SUCCESS)
+ {
+ __isSpeakerOn = setSpeaker;
+ r = E_SUCCESS;
+ }
+ else
+ {
+ r = E_FAILURE;
+ }
+ return r;
+}
+
+bool
+TelephonyManager::IsSpeakerOn(void)
+{
+ return __isSpeakerOn;
+}
+
+bool
+TelephonyManager::IsSplitAllowed(void)
+{
+ // Split functionality is allowed only if a one call is present.
+ // The call can be a single call or a conference call
+ if (__pActiveCallList->GetCount() == 1)
+ {
+ return true;
+ }
+ return false;
+}
+
+void
+TelephonyManager::HandleCallbackResponse(TapiHandle* pHandle, int callBackResult, void* pData, void* pUserData)
+{
+ //should not do anything here.
+}
+
+void
+TelephonyManager::HandleDialCallbackResponse(TapiHandle* pHandle, int callBackResult, void* pData, void* pUserData)
+{
+ TelephonyManager* pTelManager = (TelephonyManager*) pUserData;
+ if (callBackResult != TAPI_CAUSE_SUCCESS)
+ {
+ if (pTelManager->__pDialedCall != null)
+ {
+ delete pTelManager->__pDialedCall;
+ pTelManager->__pDialedCall = null;
+ }
+ pTelManager->__pEventListener->HandleTelephonyError(ERROR_DIAL_FAILED);
+ }
+}
+
+void
+TelephonyManager::HandleRejectCallbackResponse(TapiHandle* pHandle, int callBackResult, void* pData, void* pUserData)
+{
+ AppLogDebug("ENTER");
+ // This callback comes only if user has either rejected an incoming call from IncomingCallForm.
+ // or the incoming call was automatically blocked.
+ TelephonyManager* pTelManager = (TelephonyManager*) pUserData;
+ if (pData != null && callBackResult == TAPI_API_SUCCESS)
+ {
+ unsigned int rejectedCallHandle = 0;
+ memcpy(&rejectedCallHandle, pData, sizeof(TS_UINT));
+
+ //Check if incoming call is rejected
+ if (pTelManager->__pIncomingCall != null && (rejectedCallHandle == (unsigned int) pTelManager->__pIncomingCall->GetCallHandle()->ToLong()))
+ {
+ CallInfo rejectedCallInfo;
+ rejectedCallInfo = *(pTelManager->__pIncomingCall);
+ delete pTelManager->__pIncomingCall;
+ pTelManager->__pIncomingCall = null;
+
+ //Check if number was automatically rejected using settings, then don't give any notification to user.
+ bool showIncomingCallRejectedNotification = true;
+ if (((pTelManager->__pSettingsManager->GetUnknownRejectStatus() == true) && (rejectedCallInfo.GetContactInfo() == null))
+ || (pTelManager->__pSettingsManager->IsCallToBeRejected(rejectedCallInfo.GetContactNumber()) == true))
+ {
+ //blocked
+ AppLogDebug("Call blocked");
+ showIncomingCallRejectedNotification = false;
+ rejectedCallInfo.SetCalllogType(CALL_LOG_TYPE_VOICE_BLOCKED);
+ }
+ else
+ {
+ AppLogDebug("Call rejected");
+ //rejected by user from incoming call form
+ showIncomingCallRejectedNotification = true;
+ rejectedCallInfo.SetCalllogType(CALL_LOG_TYPE_VOICE_REJECTED);
+ }
+ //Save rejected incoming call to call log db.
+ pTelManager->SaveCallInfoToLogsDb(rejectedCallInfo);
+
+ if (showIncomingCallRejectedNotification == true)
+ {
+ //check if the ended call was the last call
+ bool isLastCall = (pTelManager->__pActiveCallList->GetCount() == 0);
+ //Stop alert - started only for incoming calls which are not blocked.
+ if(pTelManager->__pSoundManager != null)
+ {
+ pTelManager->__pSoundManager->StopAlert();
+ //Do not call stop session if there is already a call going on
+ if(isLastCall == true)
+ {
+ pTelManager->__pSoundManager->StopSession();
+ }
+ }
+ //Send notification to user
+ ArrayListT<CallInfo>* pCallList = null;
+ if (isLastCall)
+ {
+ //save 'RejectedCall' to list to show on EndCallForm
+ pCallList = new (std::nothrow) ArrayListT<CallInfo>();
+ pCallList->Construct(1);
+ CallInfo* pRejectedCall = new (std::nothrow) CallInfo();
+ *pRejectedCall = rejectedCallInfo;
+ pCallList->Add(*pRejectedCall);
+ }
+ else
+ {
+ //fetch active calls to show appropriate scene
+ pCallList = static_cast<ArrayListT<CallInfo>*>(pTelManager->__pActiveCallList->GetValuesN());
+ }
+ pTelManager->__pEventListener->HandleCallDisconnected(isLastCall, *pCallList);
+ delete pCallList;
+ pCallList = null;
+ }
+ }
+ }
+ else
+ {
+ pTelManager->__pEventListener->HandleTelephonyError(ERROR_REJECT_FAILED);
+ }
+ AppLogDebug("EXIT");
+}
+
+void
+TelephonyManager::HandleJoinCallbackResponse(TapiHandle* pHandle, int callBackResult, void* pData, void* pUserData)
+{
+ TelephonyManager* pTelManager = (TelephonyManager*) pUserData;
+ if (callBackResult == TAPI_API_SUCCESS && pData != null)
+ {
+ unsigned int tempHandle = 0;
+ TelCallInfoJoinedNoti_t joinedInfoNotification;
+ CallInfo confCallInfo;
+
+ memcpy(&tempHandle, pData, sizeof(TS_UINT));
+ joinedInfoNotification.id = tempHandle;
+ CallInfo activeCall;
+ CallInfo heldCall;
+ // Use enumerator to access elements in the map
+ IListT<CallInfo>* pCallList = pTelManager->__pActiveCallList->GetValuesN();
+ result r = pCallList->GetAt(0, activeCall);
+
+ if (r == E_SUCCESS)
+ {
+ r = pCallList->GetAt(1, heldCall);
+ if (r == E_SUCCESS)
+ {
+ CallInfo* pConfCallInfo = new (std::nothrow) CallInfo();
+ unsigned int activeCallHandle = activeCall.GetCallHandle()->ToLong();
+ unsigned int heldCallHandle = heldCall.GetCallHandle()->ToLong();
+ if (activeCall.IsConferenceCall() == true)
+ {
+ r = E_SUCCESS;
+ //When joined both become active
+ activeCall.SetOnHold(false);
+ heldCall.SetOnHold(false);
+ *pConfCallInfo = activeCall;
+ pConfCallInfo->AddCallToCallerList(heldCall);
+ pConfCallInfo->SetCallHandle(activeCallHandle);
+ //Set call start time
+ if (pConfCallInfo->GetCallConnectTime() > heldCall.GetCallConnectTime())
+ {
+ pConfCallInfo->SetCallConnectTime(heldCall.GetCallConnectTime());
+ pConfCallInfo->SetCallNotificationTime(heldCall.GetCallNotificationTime());
+ }
+ }
+ else if (heldCall.IsConferenceCall() == true)
+ {
+ r = E_SUCCESS;
+ heldCall.SetOnHold(false);
+ activeCall.SetOnHold(false);
+ *pConfCallInfo = heldCall;
+ pConfCallInfo->AddCallToCallerList(activeCall);
+ pConfCallInfo->SetCallHandle(heldCallHandle);
+ //Set call start time
+ if (pConfCallInfo->GetCallConnectTime() > activeCall.GetCallConnectTime())
+ {
+ pConfCallInfo->SetCallConnectTime(activeCall.GetCallConnectTime());
+ pConfCallInfo->SetCallNotificationTime(activeCall.GetCallNotificationTime());
+ }
+ }
+ else
+ {
+ r = E_SUCCESS;
+ pConfCallInfo->SetConference(true);
+ heldCall.SetOnHold(false);
+ activeCall.SetOnHold(false);
+ pConfCallInfo->AddCallToCallerList(activeCall);
+ pConfCallInfo->AddCallToCallerList(heldCall);
+ pConfCallInfo->SetCallHandle(activeCallHandle);
+ //Set call start time
+ if (activeCall.GetCallConnectTime() > heldCall.GetCallConnectTime())
+ {
+ pConfCallInfo->SetCallConnectTime(heldCall.GetCallConnectTime());
+ pConfCallInfo->SetCallNotificationTime(heldCall.GetCallNotificationTime());
+ }
+ else
+ {
+ pConfCallInfo->SetCallConnectTime(activeCall.GetCallConnectTime());
+ pConfCallInfo->SetCallNotificationTime(activeCall.GetCallNotificationTime());
+ }
+ }
+ pConfCallInfo->SetCallHandle(joinedInfoNotification.id);
+ pTelManager->__pActiveCallList->RemoveAll();
+ //only one call in the list
+ pTelManager->__pActiveCallList->Add(joinedInfoNotification.id, *pConfCallInfo);
+ //notify listener that call is connected.
+ pTelManager->__pEventListener->HandleConferenceCall(*pConfCallInfo);
+ delete pCallList;
+ pCallList = null;
+ }
+ }
+ }
+ else
+ {
+ pTelManager->__pEventListener->HandleTelephonyError(ERROR_JOIN_FAILED);
+ }
+}
+
+void
+TelephonyManager::HandleSwapCallbackResponse(TapiHandle* pHandle, int callBackResult, void* pData, void* pUserData)
+{
+ TelephonyManager* pTelManager = (TelephonyManager*) pUserData;
+ if (callBackResult == TAPI_CAUSE_SUCCESS)
+ {
+ IListT<CallInfo>* pCallList = pTelManager->__pActiveCallList->GetValuesN();
+ IListT<long>* pKeyList = pTelManager->__pActiveCallList->GetKeysN();
+ int callCount = pTelManager->__pActiveCallList->GetCount();
+ for (int index = 0; index < callCount; index++)
+ {
+ CallInfo* pTempCallInfo = new (std::nothrow) CallInfo();
+ pCallList->GetAt(index, *pTempCallInfo);
+ (pTempCallInfo->IsOnHold() == false) ? pTempCallInfo->SetOnHold(true) : pTempCallInfo->SetOnHold(false);
+ long callHandle;
+ pKeyList->GetAt(index, callHandle);
+ pTelManager->__pActiveCallList->SetValue(callHandle, *pTempCallInfo);
+ }
+ delete pCallList;
+ pCallList = null;
+ delete pKeyList;
+ pKeyList = null;
+ pCallList = pTelManager->__pActiveCallList->GetValuesN();
+ pTelManager->__pEventListener->HandleCallSwapOccured(*pCallList);
+ }
+ else
+ {
+ pTelManager->__pEventListener->HandleTelephonyError(ERROR_SWAP_FAILED);
+ }
+}
+
+void
+TelephonyManager::HandleEndFromConferenceCallbackResponse(TapiHandle* pHandle, int callBackResult, void* pData, void* pUserData)
+{
+ AppLogDebug("ENTER");
+ //This callback comes if a single call is ended from Conference call.
+ TelephonyManager* pTelManager = (TelephonyManager*) pUserData;
+ bool isParticipantCallEnded = false;
+
+ if (callBackResult == TAPI_CAUSE_SUCCESS && pData != null)
+ {
+ //fetch end call handle
+ TelCallEndCnf_t callEndNotification;
+ memcpy(&callEndNotification, pData, sizeof(TelCallEndCnf_t));
+ //Fetch conference call
+ CallInfo endConfCall;
+ bool isConferenceCallFound = false;
+ IListT<CallInfo>* pCallList = pTelManager->__pActiveCallList->GetValuesN();
+ int callCount = pCallList->GetCount();
+ for (int index = 0; index < callCount; index++)
+ {
+ pCallList->GetAt(index, endConfCall);
+ if (endConfCall.IsConferenceCall() == true)
+ {
+ isConferenceCallFound = true;
+ //Found the Conference call to be changed.
+ break;
+ }
+ }
+ delete pCallList;
+ pCallList = null;
+
+ //Identify the call to be ended and remove from list.
+ if (isConferenceCallFound == true)
+ {
+ isParticipantCallEnded = pTelManager->HandleParticipantEndedFromConference(callEndNotification.id, endConfCall);
+ }
+ }
+
+ //Check if participant call or Conference call was not found, then show error
+ if (isParticipantCallEnded == false)
+ {
+ pTelManager->__pEventListener->HandleTelephonyError(ERROR_END_FROM_CONFERENCE_FAILED);
+ }
+ AppLogDebug("EXIT");
+}
+
+bool
+TelephonyManager::HandleParticipantEndedFromConference(unsigned int participantCallHandle, CallInfo& conferenceCall)
+{
+ AppLogDebug("ENTER");
+ //to check if participant call was found and ended.
+ bool isParticipantCallEnded = false;
+ //Identify the call to be ended and remove from list.
+ CallInfo callToBeEnded;
+ IListT<CallInfo>* pCallerList = conferenceCall.GetCallerList();
+ int callerCount = pCallerList->GetCount();
+ for (int index = 0; index < callerCount; index++)
+ {
+ pCallerList->GetAt(index, callToBeEnded);
+ if ((unsigned int)callToBeEnded.GetCallHandle()->ToLong() == participantCallHandle)
+ {
+ //Identify the call to be ended and remove from conference list
+ conferenceCall.RemoveCallFromCallerList(index);
+ //update its status to individual call before saving to database
+ callToBeEnded.SetConference(false);
+ SaveCallInfoToLogsDb(callToBeEnded);
+ isParticipantCallEnded = true;
+ break;
+ }
+ }
+
+ if(isParticipantCallEnded == false)
+ {
+ //participant call not found and not ended
+ return isParticipantCallEnded;
+ }
+
+ unsigned int confCallHandle = (unsigned int)conferenceCall.GetCallHandle()->ToLong();
+ //Check if last participant removed. If yes, switch to single active view
+ if (conferenceCall.GetCallerListCount() == 1)
+ {
+ CallInfo callFromList;
+ pCallerList = conferenceCall.GetCallerList();
+ pCallerList->GetAt(0, callFromList);
+ //construct a new single active call
+ CallInfo* pActiveCall = new (std::nothrow) CallInfo();
+ *pActiveCall = callFromList;
+ //update conference status and Hold status
+ pActiveCall->SetConference(false);
+ pActiveCall->SetOnHold(conferenceCall.IsOnHold());
+
+ __pActiveCallList->Remove(confCallHandle);
+ __pActiveCallList->Add(pActiveCall->GetCallHandle()->ToLong(), *pActiveCall);
+ pActiveCall = null;
+ //using the callConnected to switch to single active screen
+ //or update multiple active call screen
+ IListT<CallInfo>* pActiveCallList = __pActiveCallList->GetValuesN();
+ __pEventListener->HandleCallConnected(*pActiveCallList);
+ delete pActiveCallList;
+ pActiveCallList = null;
+ }
+ else
+ {
+ CallInfo callFromList;
+ pCallerList = conferenceCall.GetCallerList();
+ pCallerList->GetAt(0, callFromList);
+ //construct a new conference call
+ CallInfo* pConfCallInfo = new (std::nothrow) CallInfo();
+ *pConfCallInfo = conferenceCall;
+ if (confCallHandle == participantCallHandle)
+ {
+ //Call Handle is same as conf call handle, so need to change conf call handle
+ __pActiveCallList->Remove(confCallHandle);
+ int newConfCallHandle = callFromList.GetCallHandle()->ToLong();
+ pConfCallInfo->SetCallHandle(newConfCallHandle);
+ __pActiveCallList->Add(newConfCallHandle, *pConfCallInfo);
+ }
+ else
+ {
+ __pActiveCallList->SetValue(confCallHandle, *pConfCallInfo);
+ }
+ __pEventListener->HandleConferenceChange();
+ }
+ AppLogDebug("EXIT");
+ return isParticipantCallEnded;
+}
+
+void
+TelephonyManager::HandleSplitFromConferenceCallbackResponse(TapiHandle* pHandle, int callBackResult, void* pData, void* pUserData)
+{
+ TelephonyManager* pTelManager = (TelephonyManager*) pUserData;
+ if (callBackResult == TAPI_CAUSE_SUCCESS && pData != null)
+ {
+ TelCallSplitCnf_t callSplitNotification;
+ memcpy(&callSplitNotification, pData, sizeof(TelCallSplitCnf_t));
+ int confCallIndex = -1;
+ CallInfo endConfCall;
+ bool isConferenceCallFound = false;
+
+ IListT<CallInfo>* pCallList = pTelManager->__pActiveCallList->GetValuesN();
+ int callCount = pCallList->GetCount();
+ for (int index = 0; index < callCount; index++)
+ {
+ pCallList->GetAt(index, endConfCall);
+ if (endConfCall.IsConferenceCall() == true)
+ {
+ isConferenceCallFound = true;
+ confCallIndex = index;
+ //Found the Conference call to be ended.
+ break;
+ }
+ }
+
+ if (isConferenceCallFound == false)
+ {
+ delete pCallList;
+ pCallList = null;
+ return;
+ }
+ delete pCallList;
+ pCallList = null;
+ //Identify the call to be ended and remove from list on API success
+ CallInfo callToBeEnded;
+ pCallList = endConfCall.GetCallerList();
+ callCount = pCallList->GetCount();
+ for (int index = 0; index < callCount; index++)
+ {
+ pCallList->GetAt(index, callToBeEnded);
+ if ((unsigned int)callToBeEnded.GetCallHandle()->ToLong() == callSplitNotification.id)
+ {
+ //Identified the call to be ended and remove from conference list
+ //Add this to the active call list
+ endConfCall.RemoveCallFromCallerList(index);
+ break;
+ }
+ }
+ unsigned int confCallHandle = (unsigned int)endConfCall.GetCallHandle()->ToLong();
+ //Set the hold flags correctly and make the changes to the active call list
+ if (endConfCall.GetCallerListCount() == 1)
+ {
+ //Set hold for the other single call
+ // and add to the list
+ CallInfo callFromList;
+ pCallList = endConfCall.GetCallerList();
+ pCallList->GetAt(0, callFromList);
+ CallInfo* pHeldCall = new (std::nothrow) CallInfo();
+ *pHeldCall = callFromList;
+ pHeldCall->SetConference(false);
+ pHeldCall->SetOnHold(true);
+ pTelManager->__pActiveCallList->Remove(confCallHandle);
+ pTelManager->__pActiveCallList->Add(pHeldCall->GetCallHandle()->ToLong(), *pHeldCall);
+ pHeldCall = null;
+ }
+ else
+ {
+ //Set hold flag for conference call
+ endConfCall.SetOnHold(true);
+ CallInfo callFromList;
+ pCallList = endConfCall.GetCallerList();
+ pCallList->GetAt(0, callFromList);
+
+ CallInfo* pConfCallInfo = new (std::nothrow) CallInfo();
+ *pConfCallInfo = endConfCall;
+ if (confCallHandle == callSplitNotification.id)
+ {
+ //Call Handle is same as conf call handle.
+ //Change conf call handle
+ pTelManager->__pActiveCallList->Remove(confCallHandle);
+ int tmpCallHandle = callFromList.GetCallHandle()->ToLong();
+ pConfCallInfo->SetCallHandle(tmpCallHandle);
+ pTelManager->__pActiveCallList->Add(callFromList.GetCallHandle()->ToLong(), *pConfCallInfo);
+ }
+ else
+ {
+ pTelManager->__pActiveCallList->Remove(confCallHandle);
+ pTelManager->__pActiveCallList->Add(confCallHandle, *pConfCallInfo);
+ }
+ }
+ //Add the new active call to active call list
+ CallInfo* pActiveCall = new (std::nothrow) CallInfo();
+ *pActiveCall = callToBeEnded;
+ pActiveCall->SetConference(false);
+ pActiveCall->SetOnHold(false);
+ pTelManager->__pActiveCallList->Remove(pActiveCall->GetCallHandle()->ToLong());
+ pTelManager->__pActiveCallList->Add(pActiveCall->GetCallHandle()->ToLong(), *pActiveCall);
+ pActiveCall = null;
+ //using the callConnected to switch to Multiple active screen
+ pCallList = pTelManager->__pActiveCallList->GetValuesN();
+ pTelManager->__pEventListener->HandleCallConnected(*pCallList);
+ pCallList = null;
+ }
+ else
+ {
+ pTelManager->__pEventListener->HandleTelephonyError(ERROR_SPLIT_FROM_CONFERENCE_FAILED);
+ }
+}
+
+void
+TelephonyManager::HandleEndConferenceCallbackResponse(TapiHandle* pHandle, int callBackResult, void* pData, void* pUserData)
+{
+ AppLog("ENTER");
+ //This callback comes only if a conference call is ended by user.
+ TelephonyManager* pTelManager = (TelephonyManager*) pUserData;
+ if (callBackResult == TAPI_CAUSE_SUCCESS && pData != null)
+ {
+ //fetch ended confCall details
+ result r = E_FAILURE;
+ CallInfo endConfCallInfo;
+ IListT<CallInfo>* pActiveCallList = pTelManager->__pActiveCallList->GetValuesN();
+ if(pActiveCallList != null && pActiveCallList->GetCount() > 0)
+ {
+ for (int index = 0; index < pActiveCallList->GetCount(); index++)
+ {
+ r = pActiveCallList->GetAt(index, endConfCallInfo);
+ if(r == E_SUCCESS && endConfCallInfo.IsConferenceCall() == true)
+ {
+ //conference call found.
+ r = E_SUCCESS;
+ break;
+ }
+ else
+ {
+ r = E_FAILURE;
+ }
+ }
+ }
+ delete pActiveCallList;
+ pActiveCallList = null;
+
+ //check if no conference call found, then return.
+ if(r == E_FAILURE)
+ {
+ return;
+ }
+ //remove the conference call handle from active call list to avoid any processing in HandleIdleCallback().
+ pTelManager->__pActiveCallList->Remove(endConfCallInfo.GetCallHandle()->ToLong());
+ //Save "End" Conf. call info to call log database
+ pTelManager->SaveCallInfoToLogsDb(endConfCallInfo);
+
+ //check if the ended call was the last call and show notification to user
+ bool isLastCall = (pTelManager->__pActiveCallList->GetCount() == 0);
+ ArrayListT<CallInfo>* pCallList = null;
+ if (isLastCall)
+ {
+ pTelManager->__pSoundManager->SetlastEndedConferenceCall();
+ //stop sound session
+ pTelManager->__pSoundManager->StopSession();
+ //send empty call list to show dialer or call log screen
+ pCallList = new (std::nothrow) ArrayListT<CallInfo>();
+ }
+ else
+ {
+ //fetch active calls to show appropriate scene
+ pCallList = static_cast<ArrayListT<CallInfo>*>(pTelManager->__pActiveCallList->GetValuesN());
+ }
+ //notify listener that call is disconnected.
+ pTelManager->__pEventListener->HandleCallDisconnected(isLastCall, *pCallList);
+ delete pCallList;
+ pCallList = null;
+ }
+ else
+ {
+ pTelManager->__pEventListener->HandleTelephonyError(ERROR_END_CALL_FAILED);
+ }
+ AppLog("EXIT");
+}
+
+void
+TelephonyManager::HandleIdleCallBack(void* pData)
+{
+ AppLogDebug("ENTER");
+ //This callback comes when any type of calls are ended
+ //We do NOT handle below scenarios here -
+ //1) In incoming call scenarios, if we end any active calls - handled in "AcceptCall()".
+ //2) Incoming call automatically blocked and rejection by user scenarios are handled in "HandleRejectCallbackResponse()".
+ //3) End conference call is handled in "HandleEndConferenceCallbackResponse()".
+ //4) End Single Call from Conference call by user is handled in "HandleEndFromConferenceCallbackResponse()".
+ //5) End Single Call from Conference call using eventInjector is diverted to "HandleParticipantEndedFromConference()".
+ //BUT, we do handle below scenarios here -
+ //1) "MISSED" incoming call scenario here i.e incoming call is rejected by other caller.
+ //2) an "unconnected" dialed call is ended by caller or other party.
+ //3) Any normal active calls(NOT conference calls) ended by user or by other party.
+
+ if(__pSoundManager->GetLastConferenceCall() == false)
+ {
+ __pSoundManager->SetDisconnectTone();
+ }
+
+ TelCallStatusIdleNoti_t idleNotification;
+ memcpy(&idleNotification, pData, sizeof(TelCallStatusIdleNoti_t));
+ //handle end call event, show next screen
+ unsigned int endCallHandle = idleNotification.id;
+
+ //empty active call list or no dialed or incoming calls - ignore this event
+ IListT<CallInfo>* pActiveCallList = __pActiveCallList->GetValuesN();
+ if((pActiveCallList == null || pActiveCallList->GetCount() <= 0) && __pDialedCall == null && __pIncomingCall == null)
+ {
+ delete pActiveCallList;
+ AppLogDebug("EXIT - no calls exist");
+ return;
+ }
+
+ //Check if ended call was among conference caller list,
+ //then divert event to "HandleParticipantEndedFromConference()"
+ CallInfo confCallInfo;
+ bool isConferenceCallChanged = false;
+ for (int index = 0; index < pActiveCallList->GetCount(); index++)
+ {
+ //fetch conference call
+ result r = pActiveCallList->GetAt(index, confCallInfo);
+ if (r == E_SUCCESS && confCallInfo.IsConferenceCall() == true)
+ {
+ //Conference call found - check if ended call is a participant
+ isConferenceCallChanged = HandleParticipantEndedFromConference(endCallHandle, confCallInfo);
+ break;
+ }
+ }
+ delete pActiveCallList;
+ pActiveCallList = null;
+ if (isConferenceCallChanged == true)
+ {
+ //end call event handled - conference call will now either remain as conf. call
+ //or become single active call, if it has only 1 participant left.
+ __pSoundManager->SetSoundMode(SOUND_MODE_VOICE);
+ return;
+ }
+
+ //check if ended call was among the active call list and not a conference call
+ CallInfo endCallInfo;
+ result r = __pActiveCallList->GetValue(endCallHandle, endCallInfo);
+ if (r == E_SUCCESS)
+ {
+ bool isHandled = HandleEndNormalActiveCall(endCallInfo);
+ if (isHandled == true)
+ {
+ __pSoundManager->SetSoundMode(SOUND_MODE_VOICE);
+ return;
+ }
+ }
+
+ //Check if dialed call is rejected by other party
+ bool isDialedCallEnded = ((__pDialedCall != null) && (((unsigned int)__pDialedCall->GetCallHandle()->ToLong()) == idleNotification.id));
+ //Check if "missed" incoming call is ended
+ bool isMissedIncomingCallEnded = (__pIncomingCall != null && ((unsigned int)__pIncomingCall->GetCallHandle()->ToLong() == idleNotification.id));
+ if (isDialedCallEnded == true || isMissedIncomingCallEnded == true)
+ {
+ //It comes here only if the ended call was either a "unconnected" dialed call or an "Missed" incoming call.
+ bool isLastCall = (__pActiveCallList->GetCount() == 0);
+
+ ArrayListT<CallInfo>* pCallList = null;
+ //Check if dialed call was ended
+ if (isDialedCallEnded == true)
+ {
+ AppLogDebug("Dialed Call Ended");
+ //Call Ended is the dialed call
+ endCallInfo = *(__pDialedCall);
+ delete __pDialedCall;
+ __pDialedCall = null;
+ }
+ else
+ {
+ //Here, only "Missed" Incoming call ended by other caller is handled.
+ AppLogDebug("Missed Call Ended");
+ __pSoundManager->StopAlert();
+ endCallInfo = *(__pIncomingCall);
+ delete __pIncomingCall;
+ __pIncomingCall = null;
+ //update missed status
+ endCallInfo.SetCalllogType(CALL_LOG_TYPE_VOICE_MISSED);
+ }
+ //save ended call to call log db.
+ SaveCallInfoToLogsDb(endCallInfo);
+
+ //notify listener that call is disconnected.
+ if (isLastCall == true)
+ {
+ __pSoundManager->StopSession();
+ pCallList = new (std::nothrow) ArrayListT<CallInfo>();
+ pCallList->Construct(1);
+ if (isMissedIncomingCallEnded == false)
+ {
+ //save to list to show EndCallForm
+ pCallList->Add(endCallInfo);
+ }
+ __pSoundManager->GetTimer()->Cancel();
+
+ }
+ else
+ {
+ pCallList = static_cast<ArrayListT<CallInfo>*>(__pActiveCallList->GetValuesN());
+ }
+ __pEventListener->HandleCallDisconnected(isLastCall, *pCallList);
+ delete pCallList;
+ pCallList = null;
+ }
+ __pSoundManager->SetSoundMode(SOUND_MODE_VOICE);
+ AppLogDebug("EXIT");
+}
+
+bool
+TelephonyManager::HandleEndNormalActiveCall(CallInfo& endCallInfo)
+{
+ // This function gets called only from HandleIdleCallback(),
+ // to handle disconnection of normal active calls.
+ if (endCallInfo.IsConferenceCall() == false)
+ {
+ //remove the call handle from active call list
+ __pActiveCallList->Remove(endCallInfo.GetCallHandle()->ToLong());
+ //check if the ended call was the last call and show notification to user
+ bool isLastCall = (__pActiveCallList->GetCount() == 0);
+ ArrayListT<CallInfo>* pCallList = null;
+ if (isLastCall)
+ {
+ //stop sound session
+ __pSoundManager->StopSession();
+ //save "End" CallInfo to list to show EndCallForm
+ pCallList = new (std::nothrow) ArrayListT<CallInfo>();
+ pCallList->Construct(1);
+ pCallList->Add(endCallInfo);
+ }
+ else
+ {
+ //fetch active calls to show appropriate scene
+ pCallList = static_cast<ArrayListT<CallInfo>*>(__pActiveCallList->GetValuesN());
+ }
+
+ //Save "End" call info to call log database
+ SaveCallInfoToLogsDb(endCallInfo);
+ //notify listener that call is disconnected.
+ __pEventListener->HandleCallDisconnected(isLastCall, *pCallList);
+ delete pCallList;
+ pCallList = null;
+ return true;
+ }
+ return false;
+}
+
+void
+TelephonyManager::HandleDialingCallBack(void* pData)
+{
+ unsigned int tempHandle = 0;
+ TelCallStatusDialingNoti_t dialingNotification;
+ memcpy(&tempHandle, pData, sizeof(TS_UINT));
+ dialingNotification.id = tempHandle;
+ //check if callback is for different dialed call
+ //Dont check for call handle, since this is the first time, we get call handle for a dialed call.
+ if (__pDialedCall == null)
+ {
+ //construct new dialed call
+ __pDialedCall = new (std::nothrow) CallInfo();
+
+ TelCallStatus_t callStatus;
+ int res = tel_get_call_status(__pTapiHandle, dialingNotification.id, &callStatus);
+ if (res == TAPI_CAUSE_SUCCESS)
+ {
+ //save phone number
+ String contactNumber(callStatus.pNumber);
+ __pDialedCall->SetContactNumber(contactNumber);
+ //set emergency state
+ if(callStatus.CallType == TAPI_CALL_TYPE_E911)
+ {
+ __pDialedCall->SetEmergency(true);
+ }
+ else
+ {
+ __pDialedCall->SetEmergency(false);
+ }
+ //save contact info
+ FetchContactInfoForNumber(__pDialedCall->GetContactNumber());
+ if (__pCachedContact != null)
+ {
+ __pDialedCall->SetContactInfo(*(__pCachedContact));
+ }
+ }
+ }
+ //set call handle for dialed call
+ __pDialedCall->SetCallHandle(dialingNotification.id);
+ __pDialedCall->SetCalllogType(CALL_LOG_TYPE_VOICE_OUTGOING);
+
+ //set call notification time.
+ long long startTime = 0;
+ SystemTime::GetTicks(startTime);
+ __pDialedCall->SetCallNotificationTime(startTime);
+}
+
+void
+TelephonyManager::HandleActiveCallBack(void* pData)
+{
+ // This callback comes whenever any new call is connected
+ // Or, any "Held" call is activated (we ignore activation of "Held" calls).
+ unsigned int newCallHandle = 0;
+ TelCallStatusActiveNoti_t activeNotification;
+ memcpy(&newCallHandle, pData, sizeof(TS_UINT));
+ activeNotification.id = newCallHandle;
+ IListT<CallInfo>* pCallList = __pActiveCallList->GetValuesN();
+
+ //Check if the "Held" call was activated, i.e it is already present in already activated calls list.
+ bool toHandleEvent = true;
+ for (int callIndex = 0; (callIndex < pCallList->GetCount() && toHandleEvent == true); callIndex++ )
+ {
+ CallInfo tempCallInfo;
+ pCallList->GetAt(callIndex, tempCallInfo);
+ unsigned int tempCallHandle = tempCallInfo.GetCallHandle()->ToLong();
+ //Check if active callback came for "HandleJoinCallbackResponse"
+ //or for "UnHold Conference Call or normal call".
+ if(tempCallInfo.IsConferenceCall() == true)
+ {
+ if (tempCallHandle == activeNotification.id)
+ {
+ toHandleEvent = false;
+ }
+ else
+ {
+ //check individual participants of conf call
+ IListT<CallInfo>* pConfCallList = tempCallInfo.GetCallerList();
+ int confCallCount = pConfCallList->GetCount();
+ for (int callIndex = 0; (callIndex < confCallCount && toHandleEvent == true); callIndex++)
+ {
+ CallInfo confCallerInfo;
+ pConfCallList->GetAt(callIndex, confCallerInfo);
+ unsigned int confCallerHandle = confCallerInfo.GetCallHandle()->ToLong();
+ if (confCallerHandle == activeNotification.id)
+ {
+ toHandleEvent = false;
+ }
+ }
+ }
+ }
+ else if(tempCallHandle == activeNotification.id)
+ {
+ //If normal call is UnHold
+ toHandleEvent = false;
+ }
+ }
+
+ //check if we need to handle this event.
+ if(toHandleEvent == true)
+ {
+ //Here it comes, only if either new dialed or incoming call was connected.
+ HandleCallConnected( activeNotification.id);
+ }
+ delete pCallList;
+ pCallList = null;
+}
+
+void
+TelephonyManager::HandleCallConnected(unsigned int connectedCallHandle)
+{
+ //Here it comes, only if either new dialed or incoming call was connected.
+ //This function should be called only from "HandleActiveCallback()".
+ CallInfo* pConnectedCall = null;
+ //to check if incoming call was connected
+ bool isIncomingCallConnected = false;
+
+ __pSoundManager->SetConnectTone();
+ //Check if dialed call is connected.
+ if ((__pDialedCall != null) && (connectedCallHandle == (unsigned int)__pDialedCall->GetCallHandle()->ToLong()))
+ {
+ pConnectedCall = __pDialedCall;
+ __pDialedCall = null;
+ }
+ //Check if connected call is incoming call.
+ else if (__pIncomingCall != null && (connectedCallHandle == (unsigned int)__pIncomingCall->GetCallHandle()->ToLong()))
+ {
+ pConnectedCall = __pIncomingCall;
+ __pIncomingCall = null;
+ isIncomingCallConnected = true;
+ }
+ else
+ {
+ // this is just for safety. This scenario should never come.
+ // Otherwise Correct the code in some other function, if it comes here.
+ AppLogDebug("Error - Connected call was neither one of active calls nor it was dialed or incoming call");
+ //Construct a new CallInfo object for call
+ pConnectedCall = new (std::nothrow) CallInfo();
+ pConnectedCall->SetCallHandle(connectedCallHandle);
+
+ TelCallStatus_t callStatus;
+ int res = tel_get_call_status(__pTapiHandle, connectedCallHandle, &callStatus);
+ if (res == TAPI_CAUSE_SUCCESS)
+ {
+ String contactNumber(callStatus.pNumber);
+ pConnectedCall->SetContactNumber(contactNumber);
+ //set emergency state
+ if(callStatus.CallType == TAPI_CALL_TYPE_E911)
+ {
+ pConnectedCall->SetEmergency(true);
+ }
+ else
+ {
+ pConnectedCall->SetEmergency(false);
+ }
+ //set call notification time
+ long long startTime = 0;
+ SystemTime::GetTicks(startTime);
+ pConnectedCall->SetCallNotificationTime(startTime);
+ if (callStatus.bMoCall == true)
+ {
+ pConnectedCall->SetCalllogType(CALL_LOG_TYPE_VOICE_OUTGOING);
+ }
+ else
+ {
+ pConnectedCall->SetCalllogType(CALL_LOG_TYPE_VOICE_INCOMING);
+ isIncomingCallConnected = true;
+ }
+ }
+ //delete any dialed or incoming call objects
+ delete __pDialedCall;
+ __pDialedCall = null;
+ delete __pIncomingCall;
+ __pIncomingCall = null;
+ }
+
+ //fetch contact info for connected call & it is not a hidden call
+ if (pConnectedCall->GetContactInfo() == null && pConnectedCall->GetContactNumber().IsEmpty() == false)
+ {
+ FetchContactInfoForNumber(pConnectedCall->GetContactNumber());
+ if (__pCachedContact != null)
+ {
+ pConnectedCall->SetContactInfo(*(__pCachedContact));
+ }
+ }
+ //set Call connect time for newly connected call
+ long long startTime = 0;
+ SystemTime::GetTicks(startTime);
+ pConnectedCall->SetCallConnectTime(startTime);
+ if(GetCurrentCallCount() == 0)
+ {
+ __pSoundManager->SetMinuteReminderTone();
+ }
+
+
+ //transfer ownership to Active calls list
+ __pActiveCallList->Add(connectedCallHandle, *(pConnectedCall));
+ pConnectedCall = null;
+
+ //notify listener that call is connected.
+ IListT<CallInfo>* pCallList = __pActiveCallList->GetValuesN();
+ __pSoundManager->SetSoundMode(SOUND_MODE_VOICE);
+ __pEventListener->HandleCallConnected(*pCallList);
+ if (isIncomingCallConnected == true)
+ {
+ __pSoundManager->StopAlert();
+ }
+ delete pCallList;
+ pCallList = null;
+}
+
+bool
+TelephonyManager::CheckIncomingCallToBeRejected(CallInfo* pIncomingCallInfo)
+{
+ int callHandle = pIncomingCallInfo->GetCallHandle()->ToLong();
+ String contactNumber(L"");
+ contactNumber.Append(pIncomingCallInfo->GetContactNumber());
+ //Check if "reject unknown calls" is set and contact number is not present in AddressBook
+ //or if contact number is blacklisted
+ if (((__pSettingsManager->GetUnknownRejectStatus() == true) && (pIncomingCallInfo->GetContactInfo() == null))
+ || (__pSettingsManager->IsCallToBeRejected(contactNumber) == true))
+ {
+ AnswerCall(callHandle,false);
+ return true;
+ }
+ return false;
+}
+
+void
+TelephonyManager::HandleCallback(TapiHandle* pHandle, const char* pNotiId, void* pData, void* pUserData)
+{
+ unsigned int tempHandle = 0;
+ TelephonyManager* pTelManager = (TelephonyManager*) pUserData;
+ if (pTelManager->__pSoundManager == null)
+ {
+ AppLog("Creating Sound Manager");
+ pTelManager->__pSoundManager = new (std::nothrow) SoundManager();
+ }
+ //Handle telephony events
+ if (strcmp(pNotiId, TAPI_NOTI_VOICE_CALL_STATUS_IDLE) == 0)
+ {
+ pTelManager->HandleIdleCallBack(pData);
+ }
+ else if (strcmp(pNotiId, TAPI_NOTI_VOICE_CALL_STATUS_ACTIVE) == 0)
+ {
+ pTelManager->__pSoundManager->StartSession();
+ pTelManager->HandleActiveCallBack(pData);
+ }
+ else if (strcmp(pNotiId, TAPI_NOTI_VOICE_CALL_STATUS_DIALING) == 0)
+ {
+ pTelManager->HandleDialingCallBack(pData);
+ }
+ else
+ {
+ memcpy(&tempHandle, pData, sizeof(TS_UINT));
+ }
+}
+
+CallInfo*
+TelephonyManager::GetConferenceCallInfoN(void)
+{
+ CallInfo* pConfCallInfo = null;
+
+ IListT<CallInfo>* pCallList = __pActiveCallList->GetValuesN();
+ int callCount = pCallList->GetCount();
+ for (int index = 0; index < callCount; index++)
+ {
+ CallInfo callInfo;
+ pCallList->GetAt(index, callInfo);
+ if (callInfo.IsConferenceCall() == true)
+ {
+ pConfCallInfo = new (std::nothrow) CallInfo();
+ *pConfCallInfo = callInfo;
+ //Found the Conference call
+ break;
+ }
+ }
+ delete pCallList;
+ pCallList = null;
+
+ return pConfCallInfo;
+}
+
+IListT<CallInfo>*
+TelephonyManager::GetCallListN(void)
+{
+ ArrayListT<CallInfo>* pCallList = null;
+ if (__pActiveCallList != null)
+ {
+ pCallList = static_cast<ArrayListT<CallInfo>*>(__pActiveCallList->GetValuesN());
+ }
+ return pCallList;
+}
+
+int
+TelephonyManager::GetCurrentCallCount(void)
+{
+ if (__pActiveCallList != null)
+ {
+ return __pActiveCallList->GetCount();
+ }
+ return 0;
+}
+
+void
+TelephonyManager::StartAlert(CallInfo& incomingCallInfo)
+{
+ String contactRingTone(L"");
+ String contactNumber = incomingCallInfo.GetContactNumber();
+ //check if not hidden call
+ if(contactNumber.IsEmpty() == false)
+ {
+ //fetch contact info from Db
+ Contact* foundContact = GetContactN(contactNumber);
+ if(foundContact != null)
+ {
+ //fetch custom ringtone for contact
+ result r = foundContact->GetValue(CONTACT_PROPERTY_ID_RINGTONE, contactRingTone);
+ AppLog("ringtone fetched - r = %d", r);
+ delete foundContact;
+ foundContact = null;
+ }
+ }
+ __pSoundManager->StartAlert(contactRingTone);
+}
+
+void
+TelephonyManager::StopAlert(void)
+{
+ __pSoundManager->StopAlert();
+}
+
+result
+TelephonyManager::CheckValidTelePhoneNumber(const String& contactNumber)
+{
+ result r = E_SUCCESS;
+ if (contactNumber.GetLength() > TAPI_CALL_DIALDIGIT_LEN_MAX)
+ {
+ r = E_FAILURE;
+ }
+ //TODO: check if valid phone number else return error message
+ return r;
+}
+
+result
+TelephonyManager::CheckIfMOCallIsPossible()
+{
+ result r = E_SUCCESS;
+
+ //Check modem power status
+ int modemStatus = 0;
+ int errorCode = tel_check_modem_power_status(__pTapiHandle, &modemStatus);
+ if (errorCode != TAPI_API_SUCCESS || modemStatus == TAPI_PHONE_POWER_STATUS_OFF
+ || modemStatus == TAPI_PHONE_POWER_STATUS_ERROR)
+ {
+ r = E_FAILURE;
+ }
+ else
+ {
+ TelSimCardStatus_t simStatus;
+ int simChangedStatus;
+ //fetch sim initialization status
+ int errorCode = tel_get_sim_init_info(__pTapiHandle, &simStatus, &simChangedStatus);
+ if (errorCode != TAPI_API_SUCCESS)
+ {
+ r = E_FAILURE;
+ }
+ else
+ {
+ switch (simStatus)
+ {
+ case TAPI_SIM_STATUS_SIM_INIT_COMPLETED: // Sim Initialization ok
+ r = E_SUCCESS;
+ break;
+
+ case TAPI_SIM_STATUS_UNKNOWN: //initial state
+ case TAPI_SIM_STATUS_CARD_NOT_PRESENT: //Card not present
+ case TAPI_SIM_STATUS_CARD_REMOVED: //Card removed
+ case TAPI_SIM_STATUS_CARD_ERROR: // Bad card / On the fly, SIM gone bad
+ //TODO: might want to set different error code, to give proper message to user
+ r = E_FAILURE;
+ break;
+ default:
+ r = E_FAILURE;
+ break;
+ }
+ }
+ }
+ return r;
+}
+
+bool
+TelephonyManager::CheckIfMOCallIsEmergency(const String& contactNumber, bool isSimInitialized)
+{
+ //TODO: extract actual telephone number from contactNumber
+ //by deleting prefix,'P','W', etx.
+
+ bool isEmergency = false;
+ //conversion "contactNumber" to char*
+ const wchar_t* pContact = contactNumber.GetPointer();
+ int len = contactNumber.GetLength() + 1;
+ char* pNumber = new (std::nothrow) char[len];
+ wcstombs(pNumber, pContact, len);
+
+ if(isSimInitialized)
+ {
+ //used to get Ecc information for 2G and 3G.
+ TelSimEccList_t simEccList;
+ memset(&simEccList, 0x00, sizeof(TelSimEccList_t));
+ //Check if given number matches the sim card's emergency numbers
+ int errorCode = tel_get_sim_ecc(__pTapiHandle, &simEccList);
+ if (errorCode == TAPI_API_SUCCESS && simEccList.ecc_count > 0)
+ {
+ for (int index = 0; index < simEccList.ecc_count; index++)
+ {
+ if ((strcmp(pNumber, simEccList.list[index].number) == 0))
+ {
+ isEmergency = true;
+ }
+ }
+ }
+ }
+ else
+ {
+ //TODO: check if we need to also check SOS call numbers, if sim not present.
+ }
+
+ delete[] pNumber;
+ pNumber = null;
+ return isEmergency;
+}
+
+result
+TelephonyManager::FetchContactInfoForNumber(const String& phoneNumberStr)
+{
+ result r = E_FAILURE;
+
+ //delete previously cached data
+ if (__pCachedContact != null)
+ {
+ delete __pCachedContact;
+ __pCachedContact = null;
+ }
+
+ //Searches contacts by phone number.
+ IList* pContactList = __pAddressBook->SearchContactsByPhoneNumberN(phoneNumberStr);
+ if (pContactList == null || IsFailed(GetLastResult()))
+ {
+ return r;
+ }
+
+ //Fetch the contact's info to be displayed
+ IEnumerator* pContactEnum = pContactList->GetEnumeratorN();
+ while ((E_SUCCESS == pContactEnum->MoveNext()) && (__pCachedContact == null))
+ {
+ Contact* pContact = static_cast<Contact*>(pContactEnum->GetCurrent());
+
+ IList* pPhoneNumberList = pContact->GetValuesN(CONTACT_MPROPERTY_ID_PHONE_NUMBERS);
+ if (pPhoneNumberList != null)
+ {
+ IEnumerator* pPhoneEnum = pPhoneNumberList->GetEnumeratorN();
+ while (E_SUCCESS == pPhoneEnum->MoveNext())
+ {
+ PhoneNumber* pPhoneNumber = (PhoneNumber*) pPhoneEnum->GetCurrent();
+ //Check if this is the correct contact
+ if (pPhoneNumber->GetPhoneNumber().Equals(phoneNumberStr))
+ {
+ //save newly fetched contact info.
+ __pCachedContact = new (std::nothrow) Contact(*pContact);
+ r = E_SUCCESS;
+ break;
+ }
+ }
+ delete pPhoneEnum;
+ pPhoneNumberList->RemoveAll(true);
+ delete pPhoneNumberList;
+ }
+ }
+ delete pContactEnum;
+ pContactList->RemoveAll(true);
+ delete pContactList;
+
+ return r;
+}
+
+Contact*
+TelephonyManager::GetContactN(const String& phoneNumber)
+{
+ result r = FetchContactInfoForNumber(phoneNumber);
+ if (!IsFailed(r))
+ {
+ return new (std::nothrow) Contact(*__pCachedContact);
+ }
+ return null;
+}
+
+CallInfo*
+TelephonyManager::FetchIncomingCallHandleN(const String& callHandle, const String& contactNumber)
+{
+ if(__pIncomingCall != null)
+ {
+ delete __pIncomingCall;
+ __pIncomingCall = null;
+ }
+
+ if(callHandle.IsEmpty() == false)
+ {
+ int incomingHandle;
+ Integer::Parse(callHandle,incomingHandle);
+ //This API call is synchronous
+ TelCallStatus_t callStatus;
+ int errCode = tel_get_call_status(__pTapiHandle, incomingHandle, &callStatus);
+ if (errCode != TAPI_API_SUCCESS)
+ {
+ AppLogDebug("tel_get_call_status failed");
+ return null;
+ }
+ //construct incoming call info object
+ __pIncomingCall = new (std::nothrow) CallInfo();
+ __pIncomingCall->SetCallHandle(incomingHandle);
+
+ //contact number
+ String phoneNumber(contactNumber);
+ if(phoneNumber.IsEmpty() == true)
+ {
+ phoneNumber.Append(callStatus.pNumber);
+ }
+ __pIncomingCall->SetContactNumber(phoneNumber);
+ //set emergency state
+ if(callStatus.CallType == TAPI_CALL_TYPE_E911)
+ {
+ __pIncomingCall->SetEmergency(true);
+ }
+ else
+ {
+ __pIncomingCall->SetEmergency(false);
+ }
+ //set start time, when call is connected
+ long long startTime = 0;
+ SystemTime::GetTicks(startTime);
+ __pIncomingCall->SetCallNotificationTime(startTime);
+ __pIncomingCall->SetCalllogType(CALL_LOG_TYPE_VOICE_INCOMING);
+ }
+ else
+ {
+ //TODO: This 'else' block can be removed once AppControl request API is stabilized.
+ //This API call is synchronous and 'HandleIncomingCallStatusCallBack' is called for each active call.
+ int errCode = tel_get_call_status_all(__pTapiHandle, &HandleIncomingCallStatusCallBack, this);
+ if (errCode != TAPI_API_SUCCESS)
+ {
+ return null;
+ }
+ }
+
+ if(__pIncomingCall != null)
+ {
+ //set call notification time
+ long long startTime = 0;
+ SystemTime::GetTicks(startTime);
+ __pIncomingCall->SetCallNotificationTime(startTime);
+
+ if(__pIncomingCall->GetContactNumber().IsEmpty() == false)
+ {
+ //fetch contact info
+ FetchContactInfoForNumber(__pIncomingCall->GetContactNumber());
+ if (__pCachedContact != null)
+ {
+ __pIncomingCall->SetContactInfo(*__pCachedContact);
+ }
+ }
+
+ //construct a new callinfo object to pass its ownership to caller.
+ CallInfo* pNewIncomingCall = new (std::nothrow) CallInfo();
+ *pNewIncomingCall = *__pIncomingCall;
+ return pNewIncomingCall;
+ }
+ //return null, if no incoming call found
+ return null;
+}
+
+void
+TelephonyManager::HandleIncomingCallStatusCallBack(TelCallStatus_t* pCallStatus, void* pUserData)
+{
+ TelephonyManager* pTelManager = (TelephonyManager*) pUserData;
+ if (pCallStatus != null && pCallStatus->bMoCall == false
+ && ((pCallStatus->CallState == TAPI_CALL_STATE_INCOMING)
+ || (pCallStatus->CallState == TAPI_CALL_STATE_WAITING)))
+ {
+ //construct incoming call details
+ pTelManager->__pIncomingCall = new (std::nothrow) CallInfo();
+ pTelManager->__pIncomingCall->SetCallHandle(pCallStatus->CallHandle);
+ //contact number
+ String contactNumber(pCallStatus->pNumber);
+ pTelManager->__pIncomingCall->SetContactNumber(contactNumber);
+ //set emergency state
+ if(pCallStatus->CallType == TAPI_CALL_TYPE_E911)
+ {
+ pTelManager->__pIncomingCall->SetEmergency(true);
+ }
+ else
+ {
+ pTelManager->__pIncomingCall->SetEmergency(false);
+ }
+
+ pTelManager->__pIncomingCall->SetCalllogType(CALL_LOG_TYPE_VOICE_INCOMING);
+ }
+}
+
+void
+TelephonyManager::SaveCallInfoToLogsDb(CallInfo& endCallInfo)
+{
+ if (endCallInfo.IsConferenceCall() == false)
+ {
+ //single active call - Add call ended to call log database
+ __pCalllogMgr->AddCallogInfoToDatabase(&endCallInfo);
+ }
+ else
+ {
+ //Conference call
+ int confCallCount = endCallInfo.GetCallerListCount();
+ IListT<CallInfo>* pParticipantList = endCallInfo.GetCallerList();
+ for (int index = 0; index < confCallCount; index++)
+ {
+ CallInfo participantInfo;
+ if (pParticipantList->GetAt(index, participantInfo) == E_SUCCESS)
+ {
+ //Add call ended to call log database
+ __pCalllogMgr->AddCallogInfoToDatabase(&participantInfo);
+ }
+ }
+ }
+}