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;
52 CallApp::~CallApp(void)
54 if(__pCallRejectedIonPopup != null)
56 delete __pCallRejectedIonPopup;
57 __pCallRejectedIonPopup=null;
62 CallApp::CreateInstance(void)
64 // Create the instance through the constructor.
69 CallApp::OnAppInitializing(AppRegistry& appRegistry)
71 AppControlProviderManager* pProviderMgr = AppControlProviderManager::GetInstance();
72 pProviderMgr->SetAppControlProviderEventListener(this);
73 PowerManager::AddScreenEventListener(*this);
74 __callRejectedIontimer.Construct(*this);
79 CallApp::OnAppInitialized(void)
85 CallAppFrame* pCallAppFrame = new CallAppFrame();
86 pCallAppFrame->Construct();
87 pCallAppFrame->SetName(L"CallApp");
88 AddFrame(*pCallAppFrame);
90 //Check if there is no initial scene, then exit application.
91 //This case will normally come when invalid AppControl request has come,
92 //or incoming call is coming from unknown number and "reject unknown number" settings is enabled.
93 if (GetInitialScene().IsEmpty() == true)
102 CallApp::OnAppWillTerminate(void)
110 CallApp::OnAppTerminating(AppRegistry& appRegistry, bool forcedTermination)
113 // Deallocate resources allocated by this App for termination.
114 // The App's permanent data and context can be saved via appRegistry.
115 PowerManager::RemoveScreenEventListener(*this);
120 CallApp::OnForeground(void)
122 IEnumerator* pEnum = __listenerList.GetEnumeratorN();
123 while (pEnum->MoveNext() == E_SUCCESS)
125 IAppStateChangeListener* pInterface = static_cast<IAppStateChangeListener*>(pEnum->GetCurrent());
126 if (pInterface == null)
132 pInterface->OnForeground();
138 CallApp::OnBackground(void)
141 // Stop drawing when the application is moved to the background.
145 CallApp::OnLowMemory(void)
148 // Free unused resources or close the application.
152 CallApp::OnBatteryLevelChanged(BatteryLevel batteryLevel)
155 // Handle any changes in battery level here.
156 // Stop using multimedia features(camera, mp3 etc.) if the battery level is CRITICAL.
160 CallApp::OnScreenOn(void)
163 // Get the released resources or resume the operations that were paused or stopped in OnScreenOff().
167 CallApp::OnScreenOff(void)
169 AppLogDebug("Enter");
170 IEnumerator* pEnum = __listenerList.GetEnumeratorN();
171 while (pEnum->MoveNext() == E_SUCCESS)
173 IAppStateChangeListener* pInterface = static_cast<IAppStateChangeListener*>(pEnum->GetCurrent());
174 if (pInterface == null)
180 pInterface->OnScreenOff();
187 CallApp::GetInitialScene(void)
189 return __initialSceneId;
193 CallApp::GetAppLaunchArguments(void)
195 return __pLaunchArgs;
199 CallApp::AddAppStateChangeListener(const IAppStateChangeListener& listener)
201 __listenerList.Add(listener);
205 CallApp::RemoveAppStateChangeListener(const IAppStateChangeListener& listener)
207 __listenerList.Remove(listener);
211 CallApp::OnAppControlRequestReceived(RequestId reqId, const String& operationId, const String* pUriData,
212 const String* pMimeType, const IMap* pExtraData)
214 AppLogDebug("Enter ");
217 AppLogDebug("%ls ",pUriData->GetPointer());
220 if(pExtraData == null && pUriData != null)
222 //The request is from web app
223 AppLogDebug("%ls",pUriData->GetPointer());
224 ProcessWebAppControlRequest(reqId, operationId, pUriData);
228 //process AppControl parameters
229 ProcessAppControlRequest(reqId, operationId, pExtraData,pUriData);
235 CallApp::ProcessWebAppControlRequest(RequestId reqId, const String& operationId,const String* pUriData)
237 //Construct map from string
238 String delim(DELIMITER);
239 StringTokenizer st(*pUriData,delim);
242 extraData.Construct();
243 while(st.HasMoreTokens())
247 st.GetNextToken(token);
250 if(st.HasMoreTokens())
253 st.GetNextToken(token);
257 extraData.Add(new (std::nothrow) String(key), new (std::nothrow) String(value));
260 //Adding this explicitly as there no other way to invoke call from webapp
261 extraData.Add(new (std::nothrow) String(PARAM_CALL_TYPE), new (std::nothrow) String(PARAM_CALL_VALUE_VOICE));
263 ProcessAppControlRequest(reqId,operationId,&extraData);
265 extraData.RemoveAll(true);
269 CallApp::ProcessAppControlRequest(RequestId reqId, const String& operationId,const IMap* pArgsMap,const String* pUriData)
271 AppLogDebug("Enter %ls",operationId.GetPointer());
272 __pLaunchArgs = null;
273 if(operationId.Equals(OPERATION_ID_CALL,true) == true)
275 AppLogDebug("OPERATION_ID_CALL");
278 bool isIncomingCallRequest = false;
279 String* pKey = new (std::nothrow) String(LAUNCHTYPE);
280 if (pArgsMap->ContainsKey(*pKey) == true)
282 const String* pValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
283 if ((pValue != null) && (pValue->Equals(PARAM_ORIGIN_MT, true) == true))
285 isIncomingCallRequest = true;
288 //Check if incoming call request or outgoing call request
289 if(isIncomingCallRequest == true)
291 HandleIncomingCallAppControlRequest(reqId, pArgsMap);
295 HandleDialCallAppControlRequest(reqId, pArgsMap,pUriData);
300 AppLogDebug("pArgsMap == null");
306 CallApp::HandleIncomingCallAppControlRequest(RequestId reqId,const IMap* pArgsMap)
308 AppLogDebug("Enter");
309 SceneManager* pSceneManager = SceneManager::GetInstance();
311 AppCtrlResult appControlResult = APP_CTRL_RESULT_FAILED;
314 String callHandle(L"");
315 String* pKey = new (std::nothrow) String(CALL_HANDLE);
316 if (pArgsMap->ContainsKey(*pKey) == true)
318 const String* pValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
321 callHandle.Append(*pValue);
326 String contactNumber(L"");
327 pKey = new (std::nothrow) String(CONTACT_NUMBER);
328 if (pArgsMap->ContainsKey(*pKey) == true)
330 const String* pContactValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
331 if (pContactValue != null)
333 contactNumber.Append(*pContactValue);
334 AppLogDebug("%ls",contactNumber.GetPointer());
340 //Fetch incoming call details
341 CallPresentationModel* pCallPresentor = CallPresentationModel::GetInstance();
342 //Check if there is already a dial call present .This can happen in some
343 //race conditions N_SE-39531
344 if(pCallPresentor->IsIncomingorDialingCallPresent())
347 Integer::Parse(callHandle,incomingHandle);
348 pCallPresentor->RejectCall(incomingHandle,false,contactNumber);
349 AppLog("Cancelled already an incoming call present");
350 appControlResult = APP_CTRL_RESULT_CANCELED;
351 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
355 AppCallInfo* pIncomingCall = pCallPresentor->FetchIncomingCallDetailsN(callHandle, contactNumber);
356 if(pIncomingCall != null)
358 bool isCallRejected = pCallPresentor->CheckIncomingCallToBeRejected(pIncomingCall);
359 if(isCallRejected == false)
361 //save app launch argument list
362 __pLaunchArgs = new (std::nothrow) ArrayList(SingleObjectDeleter);
363 __pLaunchArgs->Construct(1);
364 __pLaunchArgs->Add(pIncomingCall);
365 if(__initialSceneId.IsEmpty() == true)
367 __initialSceneId = IDSCN_SCENE_INCOMINGCALL;
371 //App already initialized, goto incoming call form
372 pSceneManager->GoForward(ForwardSceneTransition(IDSCN_SCENE_INCOMINGCALL, SCENE_TRANSITION_ANIMATION_TYPE_NONE,
373 SCENE_HISTORY_OPTION_NO_HISTORY, SCENE_DESTROY_OPTION_KEEP), __pLaunchArgs);
374 __pLaunchArgs = null;
381 //Show messageBox showing automatic call rejection
382 /*MessageBox callRejectedInoMsgBox;
383 String msg(L"Call From ");
384 msg.Append(contactNumber);
385 msg.Append(L" Rejected.");
386 callRejectedInoMsgBox.Construct(L"Call Rejected", msg, MSGBOX_STYLE_NONE,1000);
388 // Calls ShowAndWait() : Draws and Shows itself and processes events
389 callRejectedInoMsgBox.ShowAndWait(modalResult);*/
390 //go back to previous scene if App was already running, else exit application.
391 if(__initialSceneId.IsEmpty() == true)
393 //KEEP "__initialSceneId" as empty and return false from "OnAppInitialized()"
394 AppLog("Terminate Phone Application");
399 ShowAutoRejectPopup(contactNumber);
402 //set success message
403 appControlResult = APP_CTRL_RESULT_SUCCEEDED;
407 appControlResult = APP_CTRL_RESULT_FAILED;
409 AppLogDebug("Exiting %d",appControlResult);
410 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
414 CallApp::ShowAutoRejectPopup(Tizen::Base::String contactNumber)
416 String msg(AppUtility::GetResourceString(IDS_CALL_REJECT_FROM_STRING));
418 msg.Append(contactNumber);
419 if(__pCallRejectedIonPopup != null)
421 delete __pCallRejectedIonPopup;
422 __pCallRejectedIonPopup = null;
424 __pCallRejectedIonPopup = new (std::nothrow) Popup();
425 Tizen::Graphics::Dimension dim(600,200);
426 __pCallRejectedIonPopup->Construct(true, dim);
427 __pCallRejectedIonPopup->SetTitleText(AppUtility::GetResourceString(IDS_CALL_REJECTED_TITLE_STRING));
428 Label* pLabelText = new (std::nothrow) Label();
429 pLabelText->Construct(Tizen::Graphics::Rectangle(0, 0, dim.width, dim.height-100), msg);
430 pLabelText->SetTextConfig(FONT_SIZE_AUTOREJECT_POPUP_TEXT, LABEL_TEXT_STYLE_NORMAL);
431 pLabelText->SetTextHorizontalAlignment(ALIGNMENT_LEFT);
432 pLabelText->SetTextVerticalAlignment(ALIGNMENT_MIDDLE);
433 __pCallRejectedIonPopup->AddControl(pLabelText);
434 __pCallRejectedIonPopup->Show();
435 __pCallRejectedIonPopup->SetShowState(true);
436 __callRejectedIontimer.Start(3000);
440 CallApp::OnTimerExpired(Tizen::Base::Runtime::Timer &timer)
442 if(__pCallRejectedIonPopup != null)
444 delete __pCallRejectedIonPopup;
445 __pCallRejectedIonPopup = null;
450 CallApp::HandleDialCallAppControlRequest(RequestId reqId,const IMap* pArgsMap,const String* pUriData)
453 AppCtrlResult appControlResult = APP_CTRL_RESULT_FAILED;
455 if (pArgsMap != null)
457 String callType(L"");
458 String phoneNumber(L"");
460 String* pKey = new (std::nothrow) String(PARAM_PHONE_NUMBER);
461 if(pArgsMap->ContainsKey(*pKey) == true)
463 const String* pPhoneValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
464 if(pPhoneValue != null)
466 AppLogDebug("%ls",pPhoneValue->GetPointer());
467 phoneNumber.Append(*pPhoneValue);
472 AppLogDebug("PARAM_PHONE_NUMBER not present");
473 //Now check if tel uri is present
476 AppLogDebug("pUriData is present %ls",pUriData->GetPointer());
477 phoneNumber.Append(*pUriData);
478 if(phoneNumber.Contains(PARAM_PHONE_NUMBER))
480 phoneNumber.Replace(PARAM_PHONE_NUMBER,L"");
481 if(phoneNumber.Contains(DELIMITER))
483 phoneNumber.Replace(DELIMITER,L"");
484 AppLogDebug("%ls",phoneNumber.GetPointer());
487 AppLogDebug("%ls",phoneNumber.GetPointer());
491 //Check if its a valid number
492 /* if(CheckNumberIsValid(phoneNumber) == false)
494 //go back to previous scene if App was already running, else exit application.
495 if(__initialSceneId.IsEmpty() == true)
497 //KEEP "__initialSceneId" as empty and return false from "OnAppInitialized()"
498 AppLog("Terminate Phone Application");
499 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
505 //invalid phone number.always return, but App will come to foreground
506 //and show current screen, if any calls is present.
511 pKey = new (std::nothrow) String(PARAM_CALL_TYPE);
512 if(pArgsMap->ContainsKey(*pKey) == true)
514 const String* pCallTypeValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
515 if(pCallTypeValue != null)
517 callType.Append(*pCallTypeValue);
523 //Fetch currently active call count
524 if (callType.IsEmpty() == false
525 && callType.Equals(PARAM_CALL_VALUE_VOICE, false) == true
526 && phoneNumber.IsEmpty() == false)
528 SceneManager* pSceneManager = SceneManager::GetInstance();
529 //check if there is already a call in dialing mode, then dont accept any other dialing request.
530 if (pSceneManager->GetCurrentSceneId() == IDSCN_SCENE_OUTCALL
531 || pSceneManager->GetCurrentSceneId()
532 == IDSCN_SCENE_OUT_EMERGENCYCALL)
535 appControlResult = APP_CTRL_RESULT_CANCELED;
536 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
540 CallPresentationModel* pCallPresentor = CallPresentationModel::GetInstance();
541 //Check if there is already an incoming call
542 //this can happen in some race conditions N_SE-39531
543 if(pCallPresentor->IsIncomingorDialingCallPresent() == true)
545 AppLog("Cancelled already an incoming call present");
546 appControlResult = APP_CTRL_RESULT_CANCELED;
547 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
550 int currentActiveCallCount = pCallPresentor->GetCurrentCallCount();
551 if(currentActiveCallCount <= 1)
553 //Abort any AppControl Request running already to show incoming call screen
554 if (pCallPresentor->IsAppControlRunning() == true)
556 pCallPresentor->AbortAppControlRequest();
558 //make an outgoing call with given number
559 String* contactTxt = new (std::nothrow) String(phoneNumber);
560 __pLaunchArgs = new (std::nothrow) ArrayList(SingleObjectDeleter);
561 __pLaunchArgs->Construct();
562 __pLaunchArgs->Add(contactTxt);
563 bool isEmergencyCall = pCallPresentor->IsEmergencyNumber(*contactTxt, true);
565 SceneId nextScene = IDSCN_SCENE_OUTCALL;
568 nextScene = IDSCN_SCENE_OUT_EMERGENCYCALL;
570 //Check if app was already running
571 if(__initialSceneId.IsEmpty() == true)
573 //phone App is not already launched
574 __initialSceneId = nextScene;
578 AppLog("Outgoing call");
579 pSceneManager->GoForward( ForwardSceneTransition( nextScene, SCENE_TRANSITION_ANIMATION_TYPE_NONE,
580 SCENE_HISTORY_OPTION_NO_HISTORY, SCENE_DESTROY_OPTION_KEEP), __pLaunchArgs);
582 appControlResult = APP_CTRL_RESULT_SUCCEEDED;
586 //already 2 active calls, 3rd call not allowed
587 appControlResult = APP_CTRL_RESULT_CANCELED;
592 appControlResult = APP_CTRL_RESULT_FAILED;
595 //send response message
596 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
600 CallApp::CheckNumberIsValid(String phoneNumber)
602 //Pattern to compare all characters except 0-9 * # P ; , +
603 String phoneNumberPattern(L"[^0-9*#P,p+;]");
604 RegularExpression checkPhoneNumber;
605 checkPhoneNumber.Construct(phoneNumberPattern);
606 //If there is any character other than these listed above then display invalid number
607 bool resultMatch = checkPhoneNumber.Match(phoneNumber,false);
608 //return false for patterns other than 0-9 * # P ; , +
609 if(resultMatch == true)
611 //return phone number is invalid
620 CallApp::SetTopMostWindow(bool bTopMost)
622 AppLogDebug("bTopMost = %d",bTopMost);
623 result res = E_FAILURE;
624 //ToDO: Need to see if there is better way to handle
629 GetAppFrame()->GetFrame()->SetZOrderGroup(WINDOW_Z_ORDER_GROUP_HIGHEST);
630 AppManager::GetInstance()->AddActiveAppEventListener(*this);
631 /*if(PowerManager::IsScreenOn() == false)
633 AppLogDebug("TurnScreenOn");
634 res = PowerManager::TurnScreenOn();
635 AppLogDebug("TurnScreenOn %d",res);
641 GetAppFrame()->GetFrame()->SetZOrderGroup(WINDOW_Z_ORDER_GROUP_NORMAL);
642 PowerManager::KeepScreenOnState(false);
643 AppManager::GetInstance()->RemoveActiveAppEventListener(*this);
646 if(LockManager::GetInstance()->IsLocked())
648 AppLogDebug("Phone Locked");
649 LockManager::GetInstance()->Unlock();
654 CallApp::OnActiveAppChanged(const String& appId)
656 AppLogDebug("Enter %ls",appId.GetPointer());
657 if(GetAppId().Equals(appId) == true)
659 result res = PowerManager::KeepScreenOnState(true,false);
660 AppLogDebug("KeepScreenOnState %d",res);