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;
44 CallApp::CallApp(void):__initialSceneId(L""), __pLaunchArgs(null)
46 __listenerList.Construct();
49 CallApp::~CallApp(void)
54 CallApp::CreateInstance(void)
56 // Create the instance through the constructor.
61 CallApp::OnAppInitializing(AppRegistry& appRegistry)
63 AppControlProviderManager* pProviderMgr = AppControlProviderManager::GetInstance();
64 pProviderMgr->SetAppControlProviderEventListener(this);
65 PowerManager::AddScreenEventListener(*this);
70 CallApp::OnAppInitialized(void)
76 CallAppFrame* pCallAppFrame = new CallAppFrame();
77 pCallAppFrame->Construct();
78 pCallAppFrame->SetName(L"CallApp");
79 AddFrame(*pCallAppFrame);
81 //Check if there is no initial scene, then exit application.
82 //This case will normally come when invalid AppControl request has come,
83 //or incoming call is coming from unknown number and "reject unknown number" settings is enabled.
84 if (GetInitialScene().IsEmpty() == true)
93 CallApp::OnAppWillTerminate(void)
101 CallApp::OnAppTerminating(AppRegistry& appRegistry, bool forcedTermination)
104 // Deallocate resources allocated by this App for termination.
105 // The App's permanent data and context can be saved via appRegistry.
106 PowerManager::RemoveScreenEventListener(*this);
111 CallApp::OnForeground(void)
113 IEnumerator* pEnum = __listenerList.GetEnumeratorN();
114 while (pEnum->MoveNext() == E_SUCCESS)
116 IAppStateChangeListener* pInterface = static_cast<IAppStateChangeListener*>(pEnum->GetCurrent());
117 if (pInterface == null)
123 pInterface->OnForeground();
129 CallApp::OnBackground(void)
132 // Stop drawing when the application is moved to the background.
136 CallApp::OnLowMemory(void)
139 // Free unused resources or close the application.
143 CallApp::OnBatteryLevelChanged(BatteryLevel batteryLevel)
146 // Handle any changes in battery level here.
147 // Stop using multimedia features(camera, mp3 etc.) if the battery level is CRITICAL.
151 CallApp::OnScreenOn(void)
154 // Get the released resources or resume the operations that were paused or stopped in OnScreenOff().
158 CallApp::OnScreenOff(void)
160 AppLogDebug("Enter");
161 IEnumerator* pEnum = __listenerList.GetEnumeratorN();
162 while (pEnum->MoveNext() == E_SUCCESS)
164 IAppStateChangeListener* pInterface = static_cast<IAppStateChangeListener*>(pEnum->GetCurrent());
165 if (pInterface == null)
171 pInterface->OnScreenOff();
178 CallApp::GetInitialScene(void)
180 return __initialSceneId;
184 CallApp::GetAppLaunchArguments(void)
186 return __pLaunchArgs;
190 CallApp::AddAppStateChangeListener(const IAppStateChangeListener& listener)
192 __listenerList.Add(listener);
196 CallApp::RemoveAppStateChangeListener(const IAppStateChangeListener& listener)
198 __listenerList.Remove(listener);
202 CallApp::OnAppControlRequestReceived(RequestId reqId, const String& operationId, const String* pUriData,
203 const String* pMimeType, const IMap* pExtraData)
205 AppLogDebug("Enter ");
208 AppLogDebug("%ls ",pUriData->GetPointer());
211 if(pExtraData == null && pUriData != null)
213 //The request is from web app
214 AppLogDebug("%ls",pUriData->GetPointer());
215 ProcessWebAppControlRequest(reqId, operationId, pUriData);
219 //process AppControl parameters
220 ProcessAppControlRequest(reqId, operationId, pExtraData,pUriData);
226 CallApp::ProcessWebAppControlRequest(RequestId reqId, const String& operationId,const String* pUriData)
228 //Construct map from string
229 String delim(DELIMITER);
230 StringTokenizer st(*pUriData,delim);
233 extraData.Construct();
234 while(st.HasMoreTokens())
238 st.GetNextToken(token);
241 if(st.HasMoreTokens())
244 st.GetNextToken(token);
248 extraData.Add(new (std::nothrow) String(key), new (std::nothrow) String(value));
251 //Adding this explicitly as there no other way to invoke call from webapp
252 extraData.Add(new (std::nothrow) String(PARAM_CALL_TYPE), new (std::nothrow) String(PARAM_CALL_VALUE_VOICE));
254 ProcessAppControlRequest(reqId,operationId,&extraData);
256 extraData.RemoveAll(true);
260 CallApp::ProcessAppControlRequest(RequestId reqId, const String& operationId,const IMap* pArgsMap,const String* pUriData)
262 AppLogDebug("Enter %ls",operationId.GetPointer());
263 __pLaunchArgs = null;
264 if(operationId.Equals(OPERATION_ID_CALL,true) == true)
266 AppLogDebug("OPERATION_ID_CALL");
269 bool isIncomingCallRequest = false;
270 String* pKey = new (std::nothrow) String(LAUNCHTYPE);
271 if (pArgsMap->ContainsKey(*pKey) == true)
273 const String* pValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
274 if ((pValue != null) && (pValue->Equals(PARAM_ORIGIN_MT, true) == true))
276 isIncomingCallRequest = true;
279 //Check if incoming call request or outgoing call request
280 if(isIncomingCallRequest == true)
282 HandleIncomingCallAppControlRequest(reqId, pArgsMap);
286 HandleDialCallAppControlRequest(reqId, pArgsMap,pUriData);
291 AppLogDebug("pArgsMap == null");
297 CallApp::HandleIncomingCallAppControlRequest(RequestId reqId,const IMap* pArgsMap)
299 AppLogDebug("Enter");
300 SceneManager* pSceneManager = SceneManager::GetInstance();
302 AppCtrlResult appControlResult = APP_CTRL_RESULT_FAILED;
305 String callHandle(L"");
306 String* pKey = new (std::nothrow) String(CALL_HANDLE);
307 if (pArgsMap->ContainsKey(*pKey) == true)
309 const String* pValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
312 callHandle.Append(*pValue);
317 String contactNumber(L"");
318 pKey = new (std::nothrow) String(CONTACT_NUMBER);
319 if (pArgsMap->ContainsKey(*pKey) == true)
321 const String* pContactValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
322 if (pContactValue != null)
324 contactNumber.Append(*pContactValue);
325 AppLogDebug("%ls",contactNumber.GetPointer());
331 //Fetch incoming call details
332 CallPresentationModel* pCallPresentor = CallPresentationModel::GetInstance();
333 //Check if there is already a dial call present .This can happen in some
334 //race conditions N_SE-39531
335 if(pCallPresentor->IsIncomingorDialingCallPresent())
338 Integer::Parse(callHandle,incomingHandle);
339 pCallPresentor->RejectCall(incomingHandle,false,contactNumber);
340 AppLog("Cancelled already an incoming call present");
341 appControlResult = APP_CTRL_RESULT_CANCELED;
342 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
346 AppCallInfo* pIncomingCall = pCallPresentor->FetchIncomingCallDetailsN(callHandle, contactNumber);
347 if(pIncomingCall != null)
349 bool isCallRejected = pCallPresentor->CheckIncomingCallToBeRejected(pIncomingCall);
350 if(isCallRejected == false)
352 //save app launch argument list
353 __pLaunchArgs = new (std::nothrow) ArrayList(SingleObjectDeleter);
354 __pLaunchArgs->Construct(1);
355 __pLaunchArgs->Add(pIncomingCall);
356 if(__initialSceneId.IsEmpty() == true)
358 __initialSceneId = IDSCN_SCENE_INCOMINGCALL;
362 //App already initialized, goto incoming call form
363 pSceneManager->GoForward(ForwardSceneTransition(IDSCN_SCENE_INCOMINGCALL, SCENE_TRANSITION_ANIMATION_TYPE_NONE,
364 SCENE_HISTORY_OPTION_NO_HISTORY, SCENE_DESTROY_OPTION_DESTROY), __pLaunchArgs);
365 __pLaunchArgs = null;
372 //Show messageBox showing automatic call rejection
373 /*MessageBox callRejectedInoMsgBox;
374 String msg(L"Call From ");
375 msg.Append(contactNumber);
376 msg.Append(L" Rejected.");
377 callRejectedInoMsgBox.Construct(L"Call Rejected", msg, MSGBOX_STYLE_NONE,1000);
379 // Calls ShowAndWait() : Draws and Shows itself and processes events
380 callRejectedInoMsgBox.ShowAndWait(modalResult);*/
382 //go back to previous scene if App was already running, else exit application.
383 if(__initialSceneId.IsEmpty() == true)
385 //KEEP "__initialSceneId" as empty and return false from "OnAppInitialized()"
386 AppLog("Terminate Phone Application");
390 //set success message
391 appControlResult = APP_CTRL_RESULT_SUCCEEDED;
395 appControlResult = APP_CTRL_RESULT_FAILED;
397 AppLogDebug("Exiting %d",appControlResult);
398 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
402 CallApp::HandleDialCallAppControlRequest(RequestId reqId,const IMap* pArgsMap,const String* pUriData)
405 AppCtrlResult appControlResult = APP_CTRL_RESULT_FAILED;
407 if (pArgsMap != null)
409 String callType(L"");
410 String phoneNumber(L"");
412 String* pKey = new (std::nothrow) String(PARAM_PHONE_NUMBER);
413 if(pArgsMap->ContainsKey(*pKey) == true)
415 const String* pPhoneValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
416 if(pPhoneValue != null)
418 AppLogDebug("%ls",pPhoneValue->GetPointer());
419 phoneNumber.Append(*pPhoneValue);
424 AppLogDebug("PARAM_PHONE_NUMBER not present");
425 //Now check if tel uri is present
428 AppLogDebug("pUriData is present %ls",pUriData->GetPointer());
429 phoneNumber.Append(*pUriData);
430 if(phoneNumber.Contains(PARAM_PHONE_NUMBER))
432 phoneNumber.Replace(PARAM_PHONE_NUMBER,L"");
433 if(phoneNumber.Contains(DELIMITER))
435 phoneNumber.Replace(DELIMITER,L"");
436 AppLogDebug("%ls",phoneNumber.GetPointer());
439 AppLogDebug("%ls",phoneNumber.GetPointer());
443 //Check if its a valid number
444 if(CheckNumberIsValid(phoneNumber) == false)
446 //go back to previous scene if App was already running, else exit application.
447 if(__initialSceneId.IsEmpty() == true)
449 //KEEP "__initialSceneId" as empty and return false from "OnAppInitialized()"
450 AppLog("Terminate Phone Application");
451 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
457 //invalid phone number.always return, but App will come to foreground
458 //and show current screen, if any calls is present.
463 pKey = new (std::nothrow) String(PARAM_CALL_TYPE);
464 if(pArgsMap->ContainsKey(*pKey) == true)
466 const String* pCallTypeValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
467 if(pCallTypeValue != null)
469 callType.Append(*pCallTypeValue);
475 //Fetch currently active call count
476 if (callType.IsEmpty() == false
477 && callType.Equals(PARAM_CALL_VALUE_VOICE, false) == true
478 && phoneNumber.IsEmpty() == false)
480 SceneManager* pSceneManager = SceneManager::GetInstance();
481 //check if there is already a call in dialing mode, then dont accept any other dialing request.
482 if (pSceneManager->GetCurrentSceneId() == IDSCN_SCENE_OUTCALL
483 || pSceneManager->GetCurrentSceneId()
484 == IDSCN_SCENE_OUT_EMERGENCYCALL)
487 appControlResult = APP_CTRL_RESULT_CANCELED;
488 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
492 CallPresentationModel* pCallPresentor = CallPresentationModel::GetInstance();
493 //Check if there is already an incoming call
494 //this can happen in some race conditions N_SE-39531
495 if(pCallPresentor->IsIncomingorDialingCallPresent() == true)
497 AppLog("Cancelled already an incoming call present");
498 appControlResult = APP_CTRL_RESULT_CANCELED;
499 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
502 int currentActiveCallCount = pCallPresentor->GetCurrentCallCount();
503 if(currentActiveCallCount <= 1)
505 //Abort any AppControl Request running already to show incoming call screen
506 if (pCallPresentor->IsAppControlRunning() == true)
508 pCallPresentor->AbortAppControlRequest();
510 //make an outgoing call with given number
511 String* contactTxt = new (std::nothrow) String(phoneNumber);
512 __pLaunchArgs = new (std::nothrow) ArrayList(SingleObjectDeleter);
513 __pLaunchArgs->Construct();
514 __pLaunchArgs->Add(contactTxt);
515 bool isEmergencyCall = pCallPresentor->IsEmergencyNumber(*contactTxt, true);
517 SceneId nextScene = IDSCN_SCENE_OUTCALL;
520 nextScene = IDSCN_SCENE_OUT_EMERGENCYCALL;
522 //Check if app was already running
523 if(__initialSceneId.IsEmpty() == true)
525 //phone App is not already launched
526 __initialSceneId = nextScene;
530 AppLog("Outgoing call");
531 pSceneManager->GoForward( ForwardSceneTransition( nextScene, SCENE_TRANSITION_ANIMATION_TYPE_NONE,
532 SCENE_HISTORY_OPTION_NO_HISTORY, SCENE_DESTROY_OPTION_DESTROY), __pLaunchArgs);
534 appControlResult = APP_CTRL_RESULT_SUCCEEDED;
538 //already 2 active calls, 3rd call not allowed
539 appControlResult = APP_CTRL_RESULT_CANCELED;
544 appControlResult = APP_CTRL_RESULT_FAILED;
547 //send response message
548 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
552 CallApp::CheckNumberIsValid(String phoneNumber)
554 //Pattern to compare all characters except 0-9 * # P ; , +
555 String phoneNumberPattern(L"[^0-9*#P,p+;]");
556 RegularExpression checkPhoneNumber;
557 checkPhoneNumber.Construct(phoneNumberPattern);
558 //If there is any character other than these listed above then display invalid number
559 bool resultMatch = checkPhoneNumber.Match(phoneNumber,false);
560 //return false for patterns other than 0-9 * # P ; , +
561 if(resultMatch == true)
563 //return phone number is invalid
572 CallApp::SetTopMostWindow(bool bTopMost)
574 AppLogDebug("bTopMost = %d",bTopMost);
575 result res = E_FAILURE;
576 //ToDO: Need to see if there is better way to handle
581 GetAppFrame()->GetFrame()->SetZOrderGroup(WINDOW_Z_ORDER_GROUP_HIGHEST);
582 AppManager::GetInstance()->AddActiveAppEventListener(*this);
583 /*if(PowerManager::IsScreenOn() == false)
585 AppLogDebug("TurnScreenOn");
586 res = PowerManager::TurnScreenOn();
587 AppLogDebug("TurnScreenOn %d",res);
593 GetAppFrame()->GetFrame()->SetZOrderGroup(WINDOW_Z_ORDER_GROUP_NORMAL);
594 PowerManager::KeepScreenOnState(false);
595 AppManager::GetInstance()->RemoveActiveAppEventListener(*this);
598 if(LockManager::GetInstance()->IsLocked())
600 AppLogDebug("Phone Locked");
601 LockManager::GetInstance()->Unlock();
606 CallApp::OnActiveAppChanged(const String& appId)
608 AppLogDebug("Enter %ls",appId.GetPointer());
609 if(GetAppId().Equals(appId) == true)
611 result res = PowerManager::KeepScreenOnState(true,false);
612 AppLogDebug("KeepScreenOnState %d",res);