Prevent issue fix. Nabi issues fixed
[apps/osp/Call.git] / src / CallPresentationModel.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
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
7 //
8 //     http://floralicense.org/license/
9 //
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.
15 //
16
17 /**
18  * @file        CallCallPresentationModel.cpp
19  * @brief       Call Presentation model class
20  */
21 #include <FApp.h>
22 #include <FUi.h>
23 #include <FMedia.h>
24 #include "CallApp.h"
25 #include "CallActiveCallForm.h"
26 #include "CallInfo.h"
27 #include "CallPresentationModel.h"
28 #include "CallSettingsPresentationModel.h"
29 #include "CallConfCallerListForm.h"
30 #include "CallTelephonyManager.h"
31 #include "CallSceneRegister.h"
32 #include "CallTypes.h"
33
34 using namespace Tizen::Base;
35 using namespace Tizen::Base::Collection;
36 using namespace Tizen::App;
37 using namespace Tizen::Graphics;
38 using namespace Tizen::Media;
39 using namespace Tizen::Social;
40 using namespace Tizen::Ui::Scenes;
41
42 CallPresentationModel* CallPresentationModel::__pInstance = null;
43
44 CallPresentationModel::CallPresentationModel(void)
45 {
46         __pTelephonyMgr = null;
47         __pTelEventListener = null;
48         __pSettingsPresentor = null;
49         __isMessageAppControlRunning = false;
50         __isDialAppControlRunning = false;
51 }
52
53 CallPresentationModel::~CallPresentationModel(void)
54 {
55         __pTelephonyMgr = null;
56         __pSettingsPresentor = null;
57 }
58
59 void
60 CallPresentationModel::CreateInstance(void)
61 {
62         __pInstance = new (std::nothrow) CallPresentationModel();
63         result r = __pInstance->Construct();
64         if(IsFailed(r))
65         {
66                 delete __pInstance;
67                 __pInstance = null;
68                 return;
69         }
70
71         std::atexit(DestroyInstance);
72 }
73
74 CallPresentationModel*
75 CallPresentationModel::GetInstance(void)
76 {
77         if (__pInstance == null)
78         {
79                 CreateInstance();
80         }
81         return __pInstance;
82 }
83
84 void
85 CallPresentationModel::DestroyInstance(void)
86 {
87         if (__pInstance != null)
88         {
89                 delete __pInstance;
90                 __pInstance = null;
91         }
92 }
93
94 result
95 CallPresentationModel::Construct(void)
96 {
97         //Fetch Telephony Manager
98         __pTelephonyMgr = TelephonyManager::GetInstance(this);
99         __pSettingsPresentor = SettingsPresentationModel::GetInstance();
100         return E_SUCCESS;
101 }
102
103 void
104 CallPresentationModel::SetTelEventListener(ITelephonyEventListener* pTelEventListener)
105 {
106         //set form as telephony event listener
107         __pTelEventListener = pTelEventListener;
108 }
109
110 void
111 CallPresentationModel::DialCall(String& contactNumber, bool isEmergency)
112 {
113         int errorCode = ERROR_NONE;
114         //Check if Telephony Manager is initialized
115         TryCatch(__pTelephonyMgr != null, (errorCode = ERROR_TAPI_INIT_FAILED), "TAPI initialization failed");
116
117         //check if phone is in flight mode
118         if(__pSettingsPresentor != null && __pSettingsPresentor->GetFlightModeStatus() == true)
119         {
120                 __pTelEventListener->HandleTelephonyError(ERROR_FLIGHT_MODE_SET);
121                 return;
122         }
123         //setup outgoing call
124         errorCode = __pTelephonyMgr->SetupMoCall(contactNumber, isEmergency);
125         TryCatch(errorCode == ERROR_NONE,,"Error occurred while setup MO call");
126         if(__pSettingsPresentor != null)
127         {
128                 __pSettingsPresentor->SetCallState(CALL_STATE_CALL_VOICE_CONNECTING);
129         }
130         return;
131
132 CATCH:
133         __pTelEventListener->HandleTelephonyError(errorCode);
134 }
135
136 void
137 CallPresentationModel::EndActiveCall(Long callHandle)
138 {
139         if(__pTelephonyMgr != null)
140         {
141                 __pTelephonyMgr->EndActiveCall(callHandle);
142         }
143 }
144
145 void
146 CallPresentationModel::EndDialingCall(String& contactNumber)
147 {
148         if(__pTelephonyMgr != null)
149         {
150                 __pTelephonyMgr->EndDialingCall(contactNumber);
151         }
152 }
153
154 bool
155 CallPresentationModel::EndConferenceCall(void)
156 {
157         result r = __pTelephonyMgr->EndConferenceCall();
158         if (IsFailed(r))
159         {
160                 //TODO: send proper error code
161                 __pTelEventListener->HandleTelephonyError(ERROR_GENERAL);
162                 return false;
163         }
164         return true;
165 }
166
167 void
168 CallPresentationModel::EndAllCall(void)
169 {
170         if(__pTelephonyMgr != null)
171         {
172                 __pTelephonyMgr->EndAllCalls();
173         }
174 }
175 bool
176 CallPresentationModel::HoldCall(Tizen::Base::Long callHandle)
177 {
178         result r = __pTelephonyMgr->HoldCall(callHandle, true);
179         return (!IsFailed(r));
180 }
181
182 bool
183 CallPresentationModel::UnHoldCall(Tizen::Base::Long callHandle)
184 {
185         result r = __pTelephonyMgr->HoldCall(callHandle, false);
186         return (!IsFailed(r));
187 }
188
189 bool
190 CallPresentationModel::HoldConferenceCall(void)
191 {
192         result r = __pTelephonyMgr->HoldConferenceCall(true);
193         return (!IsFailed(r));
194 }
195
196 bool
197 CallPresentationModel::ActivateConferenceCall(void)
198 {
199         result r = __pTelephonyMgr->HoldConferenceCall(false);
200         return (!IsFailed(r));
201 }
202
203 void
204 CallPresentationModel::JoinCall(void)
205 {
206         result r = __pTelephonyMgr->JoinCall();
207         if (IsFailed(r))
208         {
209                 __pTelEventListener->HandleTelephonyError(ERROR_JOIN_FAILED);
210         }
211 }
212
213 void
214 CallPresentationModel::SwapCalls(void)
215 {
216         result r = __pTelephonyMgr->SwapCalls();
217         if (IsFailed(r))
218         {
219                 __pTelEventListener->HandleTelephonyError(ERROR_SWAP_FAILED);
220         }
221 }
222
223 bool
224 CallPresentationModel::SetMuteStatus(bool setMute)
225 {
226         result r = __pTelephonyMgr->SetMuteStatus(setMute);
227         return (!IsFailed(r));
228 }
229
230 bool
231 CallPresentationModel::IsCallMuted(void)
232 {
233         return __pTelephonyMgr->IsCallMuted();
234 }
235
236 bool
237 CallPresentationModel::SetSpeakerStatus(bool setSpeaker)
238 {
239         result r = __pTelephonyMgr->SetSpeakerStatus(setSpeaker);
240         return (!IsFailed(r));
241 }
242
243 bool
244 CallPresentationModel::IsSpeakerOn(void)
245 {
246         return __pTelephonyMgr->IsSpeakerOn();
247 }
248 void
249 CallPresentationModel::SendDTMFSignal(String& textToBeSent)
250 {
251         __pTelephonyMgr->SendCallDTMF(textToBeSent);
252 }
253
254 AppCallInfo*
255 CallPresentationModel::GetConferenceCallInfoN(void)
256 {
257         return __pTelephonyMgr->GetConferenceCallInfoN();
258 }
259
260 bool
261 CallPresentationModel::SplitFromConference(SplitConfCallerCmdIds splitCallerCmdId, IListT<AppCallInfo>* pConfCallList)
262 {
263         int callIndex = -1;
264         AppCallInfo callToBeSpli;
265         switch (splitCallerCmdId)
266         {
267         case IDA_SPLIT_CALLER1:
268                 callIndex = 0;
269                 break;
270
271         case IDA_SPLIT_CALLER2:
272                 callIndex = 1;
273                 break;
274
275         case IDA_SPLIT_CALLER3:
276                 callIndex = 2;
277                 break;
278
279         case IDA_SPLIT_CALLER4:
280                 callIndex = 3;
281                 break;
282
283         case IDA_SPLIT_CALLER5:
284                 callIndex = 4;
285                 break;
286
287         default:
288         break;
289         }
290
291         result r = pConfCallList->GetAt(callIndex, callToBeSpli);
292         TryCatch(r == E_SUCCESS,,"conf. call list corrupted");
293         //split single call from conference
294         r = __pTelephonyMgr->SplitFromConference(callToBeSpli.GetCallHandle()->ToLong());
295         TryCatch(r == E_SUCCESS,,"Split from conf. call failed");
296         return true;
297
298 CATCH:
299         __pTelEventListener->HandleTelephonyError(ERROR_SPLIT_FROM_CONFERENCE_FAILED);
300         return false;
301 }
302
303 void
304 CallPresentationModel::EndCallFromConference(EndConfCallerCmdIds endCallerCmdId, IListT<AppCallInfo>* pConfCallList)
305 {
306         int callIndex = -1;
307         AppCallInfo callToBeEnded;
308         switch (endCallerCmdId)
309         {
310         case IDA_END_CALLER1:
311                 callIndex = 0;
312                 break;
313
314         case IDA_END_CALLER2:
315                 callIndex = 1;
316                 break;
317
318         case IDA_END_CALLER3:
319                 callIndex = 2;
320                 break;
321
322         case IDA_END_CALLER4:
323                 callIndex = 3;
324                 break;
325
326         case IDA_END_CALLER5:
327                 callIndex = 4;
328                 break;
329
330         default:
331         break;
332         }
333
334         result r = pConfCallList->GetAt(callIndex, callToBeEnded);
335         TryCatch(r == E_SUCCESS,,"conference call list corrupted");
336         //end single call
337         r = __pTelephonyMgr->EndFromConference(callToBeEnded.GetCallHandle()->ToLong());
338         TryCatch(r == E_SUCCESS,,"End single call from conference call failed");
339
340         return;
341
342 CATCH:
343         __pTelEventListener->HandleTelephonyError(ERROR_END_CALL_FAILED);
344         return;
345 }
346
347 bool
348 CallPresentationModel::IsSplitAllowed(void)
349 {
350         return __pTelephonyMgr->IsSplitAllowed();
351 }
352
353 void
354 CallPresentationModel::AcceptIncomingCall(CallAnsweringOptions answerOptions,int callHandle)
355 {
356         result r = E_FAILURE;
357         if (answerOptions == ANSERWING_OPTION_ACCEPT_CALL)
358         {
359                 r = __pTelephonyMgr->AnswerCall(callHandle, true);
360         }
361         else
362         {
363                 r = __pTelephonyMgr->AcceptCall(answerOptions,callHandle);
364         }
365         if (IsFailed(r))
366         {
367                 __pTelEventListener->HandleTelephonyError(ERROR_GENERAL);
368         }
369 }
370
371 IListT<AppCallInfo>*
372 CallPresentationModel::GetCallListN(void)
373 {
374         return __pTelephonyMgr->GetCallListN();
375 }
376
377
378 bool
379 CallPresentationModel::RejectCall(int callHandle, bool sendMsg, const String& contactNumber)
380 {
381         AppLogDebug("Enter");
382         result r = __pTelephonyMgr->AnswerCall(callHandle, false);
383         if (IsFailed(r))
384         {
385                 __pTelEventListener->HandleTelephonyError(ERROR_GENERAL);
386                 return false;
387         }
388
389         if (sendMsg == true)
390         {
391                 //launch message
392                 result r = E_SUCCESS;
393                 HashMap extraData;
394                 extraData.Construct();
395
396                 extraData.Add(new (std::nothrow) String(MESSAGE_TYPE), new (std::nothrow) String(MESSAGE_SMS_TYPE));
397                 extraData.Add(new (std::nothrow) String(MESSAGE_TO), new (std::nothrow) String(contactNumber));
398
399                 AppControl* pAc = AppManager::FindAppControlN(PROVIDER_ID_MESSAGE, OPERATION_ID_COMPOSE);
400                 if (pAc != null)
401                 {
402                         AppLogDebug("Start");
403                         r = pAc->Start(null, null, &extraData, this);
404                         __isMessageAppControlRunning = true;
405                         delete pAc;
406                 }
407
408                 extraData.RemoveAll(true);
409         }
410         AppLogDebug("Exit");
411         return true;
412 }
413
414 void CallPresentationModel::OnAppForeground(void)
415 {
416         if (__isMessageAppControlRunning == true)
417         {
418                 //This comes here, when Message AppControl is finished working.
419                 __isMessageAppControlRunning = false;
420                 //Check if this was the last call, then terminate application.
421                 //And if any calls are active, then those cases are already handled from Other places.
422                 if( GetCurrentCallCount() == 0)
423                 {
424                         CallApp* pPhoneApp = static_cast<CallApp*>(UiApp::GetInstance());
425                         pPhoneApp->Terminate();
426                 }
427         }
428 }
429
430 void
431 CallPresentationModel::OnAppControlCompleteResponseReceived(const AppId& appId, const String& operationId, AppCtrlResult appControlResult, const IMap* pExtraData)
432 {
433         if (__isMessageAppControlRunning == true)
434         {
435                 //This comes here, when Message AppControl is finished working.
436                 __isMessageAppControlRunning = false;
437                 //Check if this was the last call, then terminate application.
438                 //And if any calls are active, then those cases are already handled from Other places.
439                 if( GetCurrentCallCount() == 0)
440                 {
441                         CallApp* pPhoneApp = static_cast<CallApp*>(UiApp::GetInstance());
442                         pPhoneApp->Terminate();
443                 }
444         }
445         if(appId.Equals(PROVIDER_ID_PHONE,false) == true &&  operationId.Equals(OPERATION_ID_DIAL,false) == true)
446         {
447                 __isDialAppControlRunning = false;
448
449                 if(appControlResult == APP_CTRL_RESULT_SUCCEEDED)
450                 {
451                         String* pKey = new (std::nothrow) String(PARAM_PHONE_NUMBER);
452                         if (pExtraData->ContainsKey(*pKey) == true)
453                         {
454                                 const String* pPhoneNumber = static_cast<const String*>(pExtraData->GetValue(*pKey));
455                                 if(pPhoneNumber != null && pPhoneNumber->IsEmpty() == false)
456                                 {
457                                         AddCall(*pPhoneNumber);
458                                 }
459
460                         }
461
462                 }
463
464         }
465 }
466
467 void
468 CallPresentationModel::AddCall(const String& phoneNumber)
469 {
470         ArrayList* pLaunchArgs = null;
471         SceneManager* pSceneManager = SceneManager::GetInstance();
472         int currentActiveCallCount = GetCurrentCallCount();
473         if(currentActiveCallCount <= 1)
474         {
475                 //make an outgoing call with given number
476                 String* contactTxt = new (std::nothrow) String(phoneNumber);
477                 pLaunchArgs =  new (std::nothrow) ArrayList(SingleObjectDeleter);
478                 pLaunchArgs->Construct();
479                 pLaunchArgs->Add(contactTxt);
480                 bool isEmergencyCall = IsEmergencyNumber(*contactTxt, true);
481
482                 SceneId nextScene = IDSCN_SCENE_OUTCALL;
483                 if (isEmergencyCall)
484                 {
485                         nextScene = IDSCN_SCENE_OUT_EMERGENCYCALL;
486                 }
487                 pSceneManager->GoForward( ForwardSceneTransition( nextScene), pLaunchArgs);
488
489         }
490 }
491
492 int
493 CallPresentationModel::GetCurrentCallCount(void)
494 {
495         return __pTelephonyMgr->GetCurrentCallCount();
496 }
497
498 bool
499 CallPresentationModel::CheckSimInitializationIsCompleted()
500 {
501         result r = E_FAILURE;
502         if(__pTelephonyMgr != null)
503         {
504                 r = __pTelephonyMgr->CheckIfMOCallIsPossible();
505         }
506         return (!IsFailed(r));
507 }
508
509 bool
510 CallPresentationModel::IsEmergencyNumber(const Tizen::Base::String& phoneNumber, bool isSimInitialized)
511 {
512         return __pTelephonyMgr->CheckIfMOCallIsEmergency(phoneNumber, isSimInitialized);
513 }
514
515 void
516 CallPresentationModel::StartAlert(AppCallInfo& incomingCallInfo)
517 {
518         //Adding incoming call sate setting here
519         if(__pSettingsPresentor != null)
520         {
521                 __pSettingsPresentor->SetCallState(CALL_STATE_CALL_VOICE_CONNECTING);
522         }
523         __pTelephonyMgr->StartAlert(incomingCallInfo);
524 }
525
526 void
527 CallPresentationModel::StopAlert(void)
528 {
529         __pTelephonyMgr->StopAlert();
530 }
531
532 Contact*
533 CallPresentationModel::GetContactN(const String& phoneNumber)
534 {
535         return __pTelephonyMgr->GetContactN(phoneNumber);
536 }
537
538 AppCallInfo*
539 CallPresentationModel::FetchIncomingCallDetailsN(const String& callHandle, const String& contactNumber)
540 {
541
542         return __pTelephonyMgr->FetchIncomingCallHandleN(callHandle, contactNumber);
543 }
544
545 bool
546 CallPresentationModel::CheckIncomingCallToBeRejected(AppCallInfo* pIncomingCallInfo)
547 {
548         return __pTelephonyMgr->CheckIncomingCallToBeRejected(pIncomingCallInfo);
549 }
550
551 /////////////////////////////////////////////////////////////////
552 /////  Event Listener methods from ITelephonyEventListener  /////
553 /////////////////////////////////////////////////////////////////
554 void
555 CallPresentationModel::HandleCallConnected(Tizen::Base::Collection::IListT<AppCallInfo>& pCallList)
556 {
557         if (__pTelEventListener != null)
558         {
559                 __pTelEventListener->HandleCallConnected(pCallList);
560         }
561         if(__pSettingsPresentor != null)
562         {
563                 __pSettingsPresentor->SetCallState(CALL_STATE_CALL_VOICE_ACTIVE);
564         }
565 }
566
567 void
568 CallPresentationModel::HandleCallDisconnected(bool isLastCall, Tizen::Base::Collection::IListT<AppCallInfo>& pCallList)
569 {
570         AppLogDebug("Enter");
571         if (isLastCall == true)
572         {
573                 SetSpeakerStatus(false);
574                 SetMuteStatus(false);
575                 if(__pSettingsPresentor != null)
576                 {
577                         __pSettingsPresentor->SetCallState(CALL_STATE_CALL_OFF);
578                 }
579         }
580         else
581         {
582                 if(__pSettingsPresentor != null)
583                 {
584                         __pSettingsPresentor->SetCallState(CALL_STATE_CALL_VOICE_ACTIVE);
585                 }
586         }
587         //1) Defer from sending call disconnected event to form, in case Msg AppControl is running,
588         //to avoid PhoneApp from going to EndCall form, where it shows for 3 sec. and automatically closes.
589         //2) Do not send call disconnected event to any form, in case an incoming call or dialing call is present.
590         if (__pTelEventListener != null && __isMessageAppControlRunning == false
591                         && __pTelephonyMgr->IsIncomingorDialingCallPresent() == false)
592         {
593                 __pTelEventListener->HandleCallDisconnected(isLastCall, pCallList);
594         }
595 }
596
597 void
598 CallPresentationModel::HandleConferenceCall(AppCallInfo& pCallInfo)
599 {
600         if (__pTelEventListener != null)
601         {
602                 __pTelEventListener->HandleConferenceCall(pCallInfo);
603         }
604 }
605
606 void
607 CallPresentationModel::HandleIncomingCall(AppCallInfo& pCallInfo)
608 {
609         AppLogDebug("Error - This will never come here. Since, now we are getting incoming call event through AppControl!!");
610 }
611
612 void
613 CallPresentationModel::HandleCallSwapOccured(Tizen::Base::Collection::IListT<AppCallInfo>& pCallList)
614 {
615         if (__pTelEventListener != null)
616         {
617                 __pTelEventListener->HandleCallSwapOccured(pCallList);
618         }
619 }
620
621 void
622 CallPresentationModel::HandleConferenceChange(void)
623 {
624         //1) Do not send conf. call changed event to any form, in case an incoming call or dialing call is present.
625         if (__pTelEventListener != null && __pTelephonyMgr->IsIncomingorDialingCallPresent() == false)
626         {
627                 __pTelEventListener->HandleConferenceChange();
628         }
629 }
630
631 void
632 CallPresentationModel::HandleTelephonyError(int errorCode)
633 {
634         if (__pTelEventListener != null)
635         {
636                 __pTelEventListener->HandleTelephonyError(errorCode);
637         }
638 }
639
640 result
641 CallPresentationModel::LaunchDialAppControl()
642 {
643         result r = E_SUCCESS;
644         AppControl* pAppControl = null;
645
646         if(__isDialAppControlRunning == true)
647         {
648                 //Do not allow another app control if already running
649                 return r;
650         }
651
652         HashMap extraData;
653         extraData.Construct();
654         extraData.Add(new (std::nothrow) String(PARAM_PHONE_NUMBER), new (std::nothrow) String(L""));
655
656         pAppControl = AppManager::FindAppControlN(PROVIDER_ID_PHONE, OPERATION_ID_DIAL);
657         if (pAppControl != null)
658         {
659                 r = pAppControl->Start(null, null, &extraData, this);
660                 __isDialAppControlRunning = true;
661         }
662
663         extraData.RemoveAll(true);
664
665         return r;
666 }
667
668 bool
669 CallPresentationModel::IsEnableJoinCallButton(void)
670 {
671         //Check if conf. call has maximum participants
672         AppCallInfo* pConfCallInfo = GetConferenceCallInfoN();
673         if(pConfCallInfo != null && pConfCallInfo->GetCallerListCount() >= IDI_MAX_CONF_CALL_PARTICIPANTS)
674         {
675                 return false;
676         }
677
678         //check if either of the caller is same or present in conf call.
679         IListT<AppCallInfo>* pActiveCallList = GetCallListN();
680         if ( pActiveCallList != null && pActiveCallList->GetCount() == IDI_MAX_ACTIVE_CALLS)
681         {
682                 AppCallInfo firstCall;
683                 AppCallInfo secondCall;
684                 pActiveCallList->GetAt(0, firstCall);
685                 pActiveCallList->GetAt(1, secondCall);
686
687                 if (firstCall.IsConferenceCall() == true)
688                 {
689                         IListT<AppCallInfo>* pConfMemberList = firstCall.GetCallerList();
690                         for (int index = 0; index < pConfMemberList->GetCount(); index++)
691                         {
692                                 AppCallInfo singleConfMember;
693                                 pConfMemberList->GetAt(index, singleConfMember);
694                                 if (secondCall.GetContactNumber().IsEmpty() == false && secondCall.GetContactNumber().Equals(singleConfMember.GetContactNumber()) == true)
695                                 {
696                                         return false;
697                                 }
698                         }
699                 }
700                 else if (secondCall.IsConferenceCall() == true)
701                 {
702                         IListT<AppCallInfo>* pConfMemberList = secondCall.GetCallerList();
703                         for (int index = 0; index < pConfMemberList->GetCount(); index++)
704                         {
705                                 AppCallInfo singleConfMember;
706                                 pConfMemberList->GetAt(index, singleConfMember);
707                                 if (firstCall.GetContactNumber().IsEmpty() == false && firstCall.GetContactNumber().Equals(singleConfMember.GetContactNumber()) == true)
708                                 {
709                                         return false;
710                                 }
711                         }
712                 }
713                 else
714                 {
715                         //Now, we definitely know that both are single active calls.
716                         if (firstCall.GetContactNumber().IsEmpty() == false && firstCall.GetContactNumber().Equals(secondCall.GetContactNumber()) == true)
717                         {
718                                 return false;
719                         }
720                 }
721         }
722         delete pConfCallInfo;
723         pConfCallInfo = null;
724         return true;
725 }