2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.1 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://floralicense.org/license/
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an AS IS BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
26 #include "CallAppFrame.h"
27 #include "CallPresentationModel.h"
28 #include "CallTypes.h"
29 #include "CallAppUtility.h"
30 #include "CallIAppStateChangeListner.h"
32 using namespace Tizen::App;
33 using namespace Tizen::Base;
34 using namespace Tizen::System;
35 using namespace Tizen::Ui;
36 using namespace Tizen::Ui::Controls;
37 using namespace Tizen::Ui::Scenes;
38 using namespace Tizen::Base::Utility;
39 using namespace Tizen::Base::Collection;
40 using namespace Tizen::Base::Utility;
41 using namespace Tizen::Shell;
43 static const int FONT_SIZE_AUTOREJECT_POPUP_TEXT = 36;
46 CallApp::CallApp(void):__initialSceneId(L""), __pLaunchArgs(null)
48 __listenerList.Construct();
49 __pCallRejectedIonPopup = null;
50 __pCallAppTimer = null;
54 CallApp::~CallApp(void)
56 if(__pCallRejectedIonPopup != null)
58 delete __pCallRejectedIonPopup;
59 __pCallRejectedIonPopup=null;
64 CallApp::CreateInstance(void)
66 // Create the instance through the constructor.
71 CallApp::OnAppInitializing(AppRegistry& appRegistry)
73 AppControlProviderManager* pProviderMgr = AppControlProviderManager::GetInstance();
74 pProviderMgr->SetAppControlProviderEventListener(this);
75 PowerManager::AddScreenEventListener(*this);
76 __callRejectedIontimer.Construct(*this);
81 CallApp::OnAppInitialized(void)
87 CallAppFrame* pCallAppFrame = new CallAppFrame();
88 pCallAppFrame->Construct();
89 pCallAppFrame->SetName(L"CallApp");
90 AddFrame(*pCallAppFrame);
92 //Check if there is no initial scene, then exit application.
93 //This case will normally come when invalid AppControl request has come,
94 //or incoming call is coming from unknown number and "reject unknown number" settings is enabled.
95 if (GetInitialScene().IsEmpty() == true)
100 if (__pCallAppTimer == null)
102 __pCallAppTimer = new (std::nothrow) Tizen::Base::Runtime::Timer();
103 __pCallAppTimer->Construct(*this);
104 long long currTime = 0;
105 SystemTime::GetTicks(currTime);
106 __callTicks = currTime;
107 __pCallAppTimer->StartAsRepeatable(TimeSpan::NUM_OF_TICKS_IN_SECOND);
115 CallApp::OnAppWillTerminate(void)
123 CallApp::OnAppTerminating(AppRegistry& appRegistry, bool forcedTermination)
126 // Deallocate resources allocated by this App for termination.
127 // The App's permanent data and context can be saved via appRegistry.
128 PowerManager::RemoveScreenEventListener(*this);
129 if (__pCallAppTimer != null)
131 __pCallAppTimer->Cancel();
132 delete __pCallAppTimer;
139 CallApp::OnForeground(void)
141 IEnumerator* pEnum = __listenerList.GetEnumeratorN();
142 while (pEnum->MoveNext() == E_SUCCESS)
144 IAppStateChangeListener* pInterface = static_cast<IAppStateChangeListener*>(pEnum->GetCurrent());
145 if (pInterface == null)
151 pInterface->OnForeground();
157 CallApp::OnBackground(void)
160 // Stop drawing when the application is moved to the background.
164 CallApp::OnLowMemory(void)
167 // Free unused resources or close the application.
171 CallApp::OnBatteryLevelChanged(BatteryLevel batteryLevel)
174 // Handle any changes in battery level here.
175 // Stop using multimedia features(camera, mp3 etc.) if the battery level is CRITICAL.
179 CallApp::OnScreenOn(void)
182 // Get the released resources or resume the operations that were paused or stopped in OnScreenOff().
186 CallApp::OnScreenOff(void)
188 AppLogDebug("Enter");
189 IEnumerator* pEnum = __listenerList.GetEnumeratorN();
190 while (pEnum->MoveNext() == E_SUCCESS)
192 IAppStateChangeListener* pInterface = static_cast<IAppStateChangeListener*>(pEnum->GetCurrent());
193 if (pInterface == null)
199 pInterface->OnScreenOff();
206 CallApp::GetInitialScene(void)
208 return __initialSceneId;
212 CallApp::GetAppLaunchArguments(void)
214 return __pLaunchArgs;
218 CallApp::AddAppStateChangeListener(const IAppStateChangeListener& listener)
220 __listenerList.Add(listener);
224 CallApp::RemoveAppStateChangeListener(const IAppStateChangeListener& listener)
226 __listenerList.Remove(listener);
230 CallApp::OnAppControlRequestReceived(RequestId reqId, const String& operationId, const String* pUriData,
231 const String* pMimeType, const IMap* pExtraData)
233 AppLogDebug("Enter ");
236 AppLogDebug("%ls ",pUriData->GetPointer());
239 if(pExtraData == null && pUriData != null)
241 //The request is from web app
242 AppLogDebug("%ls",pUriData->GetPointer());
243 ProcessWebAppControlRequest(reqId, operationId, pUriData);
247 //process AppControl parameters
248 ProcessAppControlRequest(reqId, operationId, pExtraData,pUriData);
254 CallApp::ProcessWebAppControlRequest(RequestId reqId, const String& operationId,const String* pUriData)
256 //Construct map from string
257 String delim(DELIMITER);
258 StringTokenizer st(*pUriData,delim);
261 extraData.Construct();
262 while(st.HasMoreTokens())
266 st.GetNextToken(token);
269 if(st.HasMoreTokens())
272 st.GetNextToken(token);
276 extraData.Add(new (std::nothrow) String(key), new (std::nothrow) String(value));
279 //Adding this explicitly as there no other way to invoke call from webapp
280 extraData.Add(new (std::nothrow) String(PARAM_CALL_TYPE), new (std::nothrow) String(PARAM_CALL_VALUE_VOICE));
282 ProcessAppControlRequest(reqId,operationId,&extraData);
284 extraData.RemoveAll(true);
288 CallApp::ProcessAppControlRequest(RequestId reqId, const String& operationId,const IMap* pArgsMap,const String* pUriData)
290 AppLogDebug("Enter %ls",operationId.GetPointer());
291 __pLaunchArgs = null;
292 if(operationId.Equals(OPERATION_ID_CALL,true) == true)
294 AppLogDebug("OPERATION_ID_CALL");
297 bool isIncomingCallRequest = false;
298 String* pKey = new (std::nothrow) String(LAUNCHTYPE);
299 if (pArgsMap->ContainsKey(*pKey) == true)
301 const String* pValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
302 if ((pValue != null) && (pValue->Equals(PARAM_ORIGIN_MT, true) == true))
304 isIncomingCallRequest = true;
307 //Check if incoming call request or outgoing call request
308 if(isIncomingCallRequest == true)
310 HandleIncomingCallAppControlRequest(reqId, pArgsMap);
314 HandleDialCallAppControlRequest(reqId, pArgsMap,pUriData);
319 AppLogDebug("pArgsMap == null");
325 CallApp::HandleIncomingCallAppControlRequest(RequestId reqId,const IMap* pArgsMap)
327 AppLogDebug("Enter");
328 SceneManager* pSceneManager = SceneManager::GetInstance();
330 AppCtrlResult appControlResult = APP_CTRL_RESULT_FAILED;
333 String callHandle(L"");
334 String* pKey = new (std::nothrow) String(CALL_HANDLE);
335 if (pArgsMap->ContainsKey(*pKey) == true)
337 const String* pValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
340 callHandle.Append(*pValue);
345 String contactNumber(L"");
346 pKey = new (std::nothrow) String(CONTACT_NUMBER);
347 if (pArgsMap->ContainsKey(*pKey) == true)
349 const String* pContactValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
350 if (pContactValue != null)
352 contactNumber.Append(*pContactValue);
353 AppLogDebug("%ls",contactNumber.GetPointer());
359 //Fetch incoming call details
360 CallPresentationModel* pCallPresentor = CallPresentationModel::GetInstance();
361 //Check if there is already a dial call present .This can happen in some
362 //race conditions N_SE-39531
363 if(pCallPresentor->IsIncomingorDialingCallPresent())
366 Integer::Parse(callHandle,incomingHandle);
367 pCallPresentor->RejectCall(incomingHandle,false,contactNumber);
368 AppLog("Cancelled already an incoming call present");
369 appControlResult = APP_CTRL_RESULT_CANCELED;
370 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
374 AppCallInfo* pIncomingCall = pCallPresentor->FetchIncomingCallDetailsN(callHandle, contactNumber);
375 if(pIncomingCall != null)
377 bool isCallRejected = pCallPresentor->CheckIncomingCallToBeRejected(pIncomingCall);
378 if(isCallRejected == false)
380 //save app launch argument list
381 __pLaunchArgs = new (std::nothrow) ArrayList(SingleObjectDeleter);
382 __pLaunchArgs->Construct(1);
383 __pLaunchArgs->Add(pIncomingCall);
384 if(__initialSceneId.IsEmpty() == true)
386 __initialSceneId = IDSCN_SCENE_INCOMINGCALL;
390 //App already initialized, goto incoming call form
391 pSceneManager->GoForward(ForwardSceneTransition(IDSCN_SCENE_INCOMINGCALL, SCENE_TRANSITION_ANIMATION_TYPE_NONE,
392 SCENE_HISTORY_OPTION_NO_HISTORY, SCENE_DESTROY_OPTION_KEEP), __pLaunchArgs);
393 __pLaunchArgs = null;
400 //Show messageBox showing automatic call rejection
401 /*MessageBox callRejectedInoMsgBox;
402 String msg(L"Call From ");
403 msg.Append(contactNumber);
404 msg.Append(L" Rejected.");
405 callRejectedInoMsgBox.Construct(L"Call Rejected", msg, MSGBOX_STYLE_NONE,1000);
407 // Calls ShowAndWait() : Draws and Shows itself and processes events
408 callRejectedInoMsgBox.ShowAndWait(modalResult);*/
409 //go back to previous scene if App was already running, else exit application.
410 if(__initialSceneId.IsEmpty() == true)
412 //KEEP "__initialSceneId" as empty and return false from "OnAppInitialized()"
413 AppLog("Terminate Phone Application");
418 ShowAutoRejectPopup(contactNumber);
421 //set success message
422 appControlResult = APP_CTRL_RESULT_SUCCEEDED;
426 appControlResult = APP_CTRL_RESULT_FAILED;
428 AppLogDebug("Exiting %d",appControlResult);
429 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
433 CallApp::ShowAutoRejectPopup(Tizen::Base::String contactNumber)
435 String msg(AppUtility::GetResourceString(IDS_CALL_REJECT_FROM_STRING));
437 msg.Append(contactNumber);
438 if(__pCallRejectedIonPopup != null)
440 delete __pCallRejectedIonPopup;
441 __pCallRejectedIonPopup = null;
443 __pCallRejectedIonPopup = new (std::nothrow) Popup();
444 Tizen::Graphics::Dimension dim(600,200);
445 __pCallRejectedIonPopup->Construct(true, dim);
446 __pCallRejectedIonPopup->SetTitleText(AppUtility::GetResourceString(IDS_CALL_REJECTED_TITLE_STRING));
447 Label* pLabelText = new (std::nothrow) Label();
448 pLabelText->Construct(Tizen::Graphics::Rectangle(0, 0, dim.width, dim.height-100), msg);
449 pLabelText->SetTextConfig(FONT_SIZE_AUTOREJECT_POPUP_TEXT, LABEL_TEXT_STYLE_NORMAL);
450 pLabelText->SetTextHorizontalAlignment(ALIGNMENT_LEFT);
451 pLabelText->SetTextVerticalAlignment(ALIGNMENT_MIDDLE);
452 __pCallRejectedIonPopup->AddControl(pLabelText);
453 __pCallRejectedIonPopup->Show();
454 __pCallRejectedIonPopup->SetShowState(true);
455 __callRejectedIontimer.Start(3000);
459 CallApp::OnTimerExpired(Tizen::Base::Runtime::Timer &timer)
461 if (__callRejectedIontimer.Equals(timer))
463 if(__pCallRejectedIonPopup != null)
465 delete __pCallRejectedIonPopup;
466 __pCallRejectedIonPopup = null;
470 if(__pCallAppTimer->Equals(timer))
477 CallApp::HandleDialCallAppControlRequest(RequestId reqId,const IMap* pArgsMap,const String* pUriData)
480 AppCtrlResult appControlResult = APP_CTRL_RESULT_FAILED;
482 if (pArgsMap != null)
484 String callType(L"");
485 String phoneNumber(L"");
487 String* pKey = new (std::nothrow) String(PARAM_PHONE_NUMBER);
488 if(pArgsMap->ContainsKey(*pKey) == true)
490 const String* pPhoneValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
491 if(pPhoneValue != null)
493 AppLogDebug("%ls",pPhoneValue->GetPointer());
494 phoneNumber.Append(*pPhoneValue);
499 AppLogDebug("PARAM_PHONE_NUMBER not present");
500 //Now check if tel uri is present
503 AppLogDebug("pUriData is present %ls",pUriData->GetPointer());
504 phoneNumber.Append(*pUriData);
505 if(phoneNumber.Contains(PARAM_PHONE_NUMBER))
507 phoneNumber.Replace(PARAM_PHONE_NUMBER,L"");
508 if(phoneNumber.Contains(DELIMITER))
510 phoneNumber.Replace(DELIMITER,L"");
511 AppLogDebug("%ls",phoneNumber.GetPointer());
514 AppLogDebug("%ls",phoneNumber.GetPointer());
518 //Check if its a valid number
519 /* if(CheckNumberIsValid(phoneNumber) == false)
521 //go back to previous scene if App was already running, else exit application.
522 if(__initialSceneId.IsEmpty() == true)
524 //KEEP "__initialSceneId" as empty and return false from "OnAppInitialized()"
525 AppLog("Terminate Phone Application");
526 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
532 //invalid phone number.always return, but App will come to foreground
533 //and show current screen, if any calls is present.
538 pKey = new (std::nothrow) String(PARAM_CALL_TYPE);
539 if(pArgsMap->ContainsKey(*pKey) == true)
541 const String* pCallTypeValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
542 if(pCallTypeValue != null)
544 callType.Append(*pCallTypeValue);
550 //Fetch currently active call count
551 if (callType.IsEmpty() == false
552 && callType.Equals(PARAM_CALL_VALUE_VOICE, false) == true
553 && phoneNumber.IsEmpty() == false)
555 SceneManager* pSceneManager = SceneManager::GetInstance();
556 //check if there is already a call in dialing mode, then dont accept any other dialing request.
557 if (pSceneManager->GetCurrentSceneId() == IDSCN_SCENE_OUTCALL
558 || pSceneManager->GetCurrentSceneId()
559 == IDSCN_SCENE_OUT_EMERGENCYCALL)
562 appControlResult = APP_CTRL_RESULT_CANCELED;
563 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
567 CallPresentationModel* pCallPresentor = CallPresentationModel::GetInstance();
568 //Check if there is already an incoming call
569 //this can happen in some race conditions N_SE-39531
570 if(pCallPresentor->IsIncomingorDialingCallPresent() == true)
572 AppLog("Cancelled already an incoming call present");
573 appControlResult = APP_CTRL_RESULT_CANCELED;
574 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
577 int currentActiveCallCount = pCallPresentor->GetCurrentCallCount();
578 if(currentActiveCallCount <= 1)
580 //Abort any AppControl Request running already to show incoming call screen
581 if (pCallPresentor->IsAppControlRunning() == true)
583 pCallPresentor->AbortAppControlRequest();
585 //make an outgoing call with given number
586 String* contactTxt = new (std::nothrow) String(phoneNumber);
587 __pLaunchArgs = new (std::nothrow) ArrayList(SingleObjectDeleter);
588 __pLaunchArgs->Construct();
589 __pLaunchArgs->Add(contactTxt);
590 bool isEmergencyCall = pCallPresentor->IsEmergencyNumber(*contactTxt, true);
592 SceneId nextScene = IDSCN_SCENE_OUTCALL;
595 nextScene = IDSCN_SCENE_OUT_EMERGENCYCALL;
597 //Check if app was already running
598 if(__initialSceneId.IsEmpty() == true)
600 //phone App is not already launched
601 __initialSceneId = nextScene;
605 AppLog("Outgoing call");
606 pSceneManager->GoForward( ForwardSceneTransition( nextScene, SCENE_TRANSITION_ANIMATION_TYPE_NONE,
607 SCENE_HISTORY_OPTION_NO_HISTORY, SCENE_DESTROY_OPTION_KEEP), __pLaunchArgs);
609 appControlResult = APP_CTRL_RESULT_SUCCEEDED;
613 //already 2 active calls, 3rd call not allowed
614 appControlResult = APP_CTRL_RESULT_CANCELED;
619 appControlResult = APP_CTRL_RESULT_FAILED;
622 //send response message
623 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
627 CallApp::CheckNumberIsValid(String phoneNumber)
629 //Pattern to compare all characters except 0-9 * # P ; , +
630 String phoneNumberPattern(L"[^0-9*#P,p+;]");
631 RegularExpression checkPhoneNumber;
632 checkPhoneNumber.Construct(phoneNumberPattern);
633 //If there is any character other than these listed above then display invalid number
634 bool resultMatch = checkPhoneNumber.Match(phoneNumber,false);
635 //return false for patterns other than 0-9 * # P ; , +
636 if(resultMatch == true)
638 //return phone number is invalid
647 CallApp::SetTopMostWindow(bool bTopMost)
649 AppLogDebug("bTopMost = %d",bTopMost);
650 result res = E_FAILURE;
651 //ToDO: Need to see if there is better way to handle
656 GetAppFrame()->GetFrame()->SetZOrderGroup(WINDOW_Z_ORDER_GROUP_HIGHEST);
657 AppManager::GetInstance()->AddActiveAppEventListener(*this);
658 /*if(PowerManager::IsScreenOn() == false)
660 AppLogDebug("TurnScreenOn");
661 res = PowerManager::TurnScreenOn();
662 AppLogDebug("TurnScreenOn %d",res);
668 GetAppFrame()->GetFrame()->SetZOrderGroup(WINDOW_Z_ORDER_GROUP_NORMAL);
669 PowerManager::KeepScreenOnState(false);
670 AppManager::GetInstance()->RemoveActiveAppEventListener(*this);
673 if(LockManager::GetInstance()->IsLocked())
675 AppLogDebug("Phone Locked");
676 LockManager::GetInstance()->Unlock();
681 CallApp::OnActiveAppChanged(const String& appId)
683 AppLogDebug("Enter %ls",appId.GetPointer());
684 if(GetAppId().Equals(appId) == true)
686 result res = PowerManager::KeepScreenOnState(true,false);
687 AppLogDebug("KeepScreenOnState %d",res);
694 CallApp::GetCallAppTicks(void)