678d5ba3820e03670367759d4a212661dab8b365
[apps/osp/Call.git] / src / CallApp.cpp
1 /**
2  * Name        : CallApp
3  * Version     :
4  * Vendor      :
5  * Description :
6  */
7
8 #include <FUi.h>
9 #include <FShell.h>
10 #include "CallApp.h"
11 #include "CallAppFrame.h"
12 #include "CallPresentationModel.h"
13 #include "CallTypes.h"
14 #include "CallAppUtility.h"
15 #include "CallIAppStateChangeListner.h"
16
17 using namespace Tizen::App;
18 using namespace Tizen::Base;
19 using namespace Tizen::System;
20 using namespace Tizen::Ui;
21 using namespace Tizen::Ui::Controls;
22 using namespace Tizen::Ui::Scenes;
23 using namespace Tizen::Base::Utility;
24 using namespace Tizen::Base::Collection;
25 using namespace Tizen::Base::Utility;
26 using namespace Tizen::Shell;
27
28
29 CallApp::CallApp(void):__initialSceneId(L""), __pLaunchArgs(null)
30 {
31         __listenerList.Construct();
32 }
33
34 CallApp::~CallApp(void)
35 {
36 }
37
38 UiApp*
39 CallApp::CreateInstance(void)
40 {
41         // Create the instance through the constructor.
42         return new CallApp();
43 }
44
45 bool
46 CallApp::OnAppInitializing(AppRegistry& appRegistry)
47 {
48         AppControlProviderManager* pProviderMgr = AppControlProviderManager::GetInstance();
49         pProviderMgr->SetAppControlProviderEventListener(this);
50         PowerManager::AddScreenEventListener(*this);
51         return true;
52 }
53
54 bool
55 CallApp::OnAppInitialized(void)
56 {
57         // TODO:
58         // Comment.
59
60         // Create a Frame
61         CallAppFrame* pCallAppFrame = new CallAppFrame();
62         pCallAppFrame->Construct();
63         pCallAppFrame->SetName(L"CallApp");
64         AddFrame(*pCallAppFrame);
65
66         //Check if there is no initial scene, then exit application.
67         //This case will normally come when invalid AppControl request has come,
68         //or incoming call is coming from unknown number and "reject unknown number" settings is enabled.
69         if (GetInitialScene().IsEmpty() == true)
70         {
71                 return false;
72         }
73
74         return true;
75 }
76
77 bool
78 CallApp::OnAppWillTerminate(void)
79 {
80         // TODO:
81         // Comment.
82         return true;
83 }
84
85 bool
86 CallApp::OnAppTerminating(AppRegistry& appRegistry, bool forcedTermination)
87 {
88         // TODO:
89         // Deallocate resources allocated by this App for termination.
90         // The App's permanent data and context can be saved via appRegistry.
91         PowerManager::RemoveScreenEventListener(*this);
92         return true;
93 }
94
95 void
96 CallApp::OnForeground(void)
97 {
98         IEnumerator* pEnum = __listenerList.GetEnumeratorN();
99         while (pEnum->MoveNext() == E_SUCCESS)
100         {
101                 IAppStateChangeListener* pInterface = static_cast<IAppStateChangeListener*>(pEnum->GetCurrent());
102                 if (pInterface == null)
103                 {
104                         delete pEnum;
105
106                         return;
107                 }
108                 pInterface->OnForeground();
109         }
110         delete pEnum;
111 }
112
113 void
114 CallApp::OnBackground(void)
115 {
116         // TODO:
117         // Stop drawing when the application is moved to the background.
118 }
119
120 void
121 CallApp::OnLowMemory(void)
122 {
123         // TODO:
124         // Free unused resources or close the application.
125 }
126
127 void
128 CallApp::OnBatteryLevelChanged(BatteryLevel batteryLevel)
129 {
130         // TODO:
131         // Handle any changes in battery level here.
132         // Stop using multimedia features(camera, mp3 etc.) if the battery level is CRITICAL.
133 }
134
135 void
136 CallApp::OnScreenOn(void)
137 {
138         // TODO:
139         // Get the released resources or resume the operations that were paused or stopped in OnScreenOff().
140 }
141
142 void
143 CallApp::OnScreenOff(void)
144 {
145         AppLogDebug("Enter");
146         IEnumerator* pEnum = __listenerList.GetEnumeratorN();
147         while (pEnum->MoveNext() == E_SUCCESS)
148         {
149                 IAppStateChangeListener* pInterface = static_cast<IAppStateChangeListener*>(pEnum->GetCurrent());
150                 if (pInterface == null)
151                 {
152                         delete pEnum;
153
154                         return;
155                 }
156                 pInterface->OnScreenOff();
157         }
158         delete pEnum;
159
160 }
161
162 SceneId
163 CallApp::GetInitialScene(void)
164 {
165         return __initialSceneId;
166 }
167
168 IList*
169 CallApp::GetAppLaunchArguments(void)
170 {
171         return __pLaunchArgs;
172 }
173
174 void
175 CallApp::AddAppStateChangeListener(const IAppStateChangeListener& listener)
176 {
177         __listenerList.Add(listener);
178
179 }
180 void
181 CallApp::RemoveAppStateChangeListener(const IAppStateChangeListener& listener)
182 {
183         __listenerList.Remove(listener);
184 }
185
186 void
187 CallApp::OnAppControlRequestReceived(RequestId reqId, const String& operationId, const String* pUriData,
188                 const String* pMimeType, const IMap* pExtraData)
189 {
190         AppLogDebug("Enter ");
191         if(pUriData != null)
192         {
193                 AppLogDebug("%ls ",pUriData->GetPointer());
194         }
195
196         if(pExtraData == null && pUriData != null)
197         {
198                 //The request is from web app
199                 AppLogDebug("%ls",pUriData->GetPointer());
200                 ProcessWebAppControlRequest(reqId, operationId, pUriData);
201         }
202         else
203         {
204                 //process AppControl parameters
205                 ProcessAppControlRequest(reqId, operationId, pExtraData,pUriData);
206         }
207         AppLogDebug("EXIT");
208 }
209
210 void
211 CallApp::ProcessWebAppControlRequest(RequestId reqId, const String& operationId,const String* pUriData)
212 {
213         //Construct map from string
214         String delim(DELIMITER);
215         StringTokenizer st(*pUriData,delim);
216         String token;
217         HashMap extraData;
218         extraData.Construct();
219         while(st.HasMoreTokens())
220         {
221                 String key=L"";
222                 String value=L"";
223                 st.GetNextToken(token);
224                 token.Trim();
225                 key.Append(token);
226                 if(st.HasMoreTokens())
227                 {
228                         token.Clear();
229                         st.GetNextToken(token);
230                         token.Trim();
231                         value.Append(token);
232                 }
233                 extraData.Add(new (std::nothrow) String(key), new (std::nothrow) String(value));
234         }
235
236         //Adding this explicitly as there no other way to invoke call from webapp
237         extraData.Add(new (std::nothrow) String(PARAM_CALL_TYPE), new (std::nothrow) String(PARAM_CALL_VALUE_VOICE));
238
239         ProcessAppControlRequest(reqId,operationId,&extraData);
240
241         extraData.RemoveAll(true);
242 }
243
244 void
245 CallApp::ProcessAppControlRequest(RequestId reqId, const String& operationId,const IMap* pArgsMap,const String* pUriData)
246 {
247         AppLogDebug("Enter %ls",operationId.GetPointer());
248         __pLaunchArgs = null;
249         if(operationId.Equals(OPERATION_ID_CALL,true) == true)
250         {
251                 AppLogDebug("OPERATION_ID_CALL");
252                 if(pArgsMap != null)
253                 {
254                         bool isIncomingCallRequest = false;
255                         String* pKey = new (std::nothrow) String(LAUNCHTYPE);
256                         if (pArgsMap->ContainsKey(*pKey) == true)
257                         {
258                                 const String* pValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
259                                 if ((pValue != null) && (pValue->Equals(PARAM_ORIGIN_MT, true) == true))
260                                 {
261                                         isIncomingCallRequest = true;
262                                 }
263                         }
264                         //Check if incoming call request or outgoing call request
265                         if(isIncomingCallRequest == true)
266                         {
267                                 HandleIncomingCallAppControlRequest(reqId, pArgsMap);
268                         }
269                         else
270                         {
271                                 HandleDialCallAppControlRequest(reqId, pArgsMap,pUriData);
272                         }
273                 }
274                 else
275                 {
276                         AppLogDebug("pArgsMap == null");
277                 }
278         }
279 }
280
281 void
282 CallApp::HandleIncomingCallAppControlRequest(RequestId reqId,const IMap* pArgsMap)
283 {
284         AppLogDebug("Enter");
285         SceneManager* pSceneManager = SceneManager::GetInstance();
286         //response message
287         AppCtrlResult appControlResult = APP_CTRL_RESULT_FAILED;
288
289         //call handle
290         String callHandle(L"");
291         String* pKey = new (std::nothrow) String(CALL_HANDLE);
292         if (pArgsMap->ContainsKey(*pKey) == true)
293         {
294                 const String* pValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
295                 if (pValue != null)
296                 {
297                         callHandle.Append(*pValue);
298                 }
299         }
300         delete pKey;
301         //contact number
302         String contactNumber(L"");
303         pKey = new (std::nothrow) String(CONTACT_NUMBER);
304         if (pArgsMap->ContainsKey(*pKey) == true)
305         {
306                 const String* pContactValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
307                 if (pContactValue != null)
308                 {
309                         contactNumber.Append(*pContactValue);
310                         AppLogDebug("%ls",contactNumber.GetPointer());
311                 }
312         }
313         delete pKey;
314         pKey = null;
315
316         //Fetch incoming call details
317         CallPresentationModel* pCallPresentor = CallPresentationModel::GetInstance();
318         AppCallInfo* pIncomingCall = pCallPresentor->FetchIncomingCallDetailsN(callHandle, contactNumber);
319         if(pIncomingCall != null)
320         {
321                 bool isCallRejected = pCallPresentor->CheckIncomingCallToBeRejected(pIncomingCall);
322                 if(isCallRejected == false)
323                 {
324                         //Abort any AppControl Request running already to show incoming call screen
325                         if (pCallPresentor->IsAppControlRunning() == true)
326                         {
327                                 pCallPresentor->AbortAppControlRequest();
328                         }
329                         //save app launch argument list
330                         __pLaunchArgs = new (std::nothrow) ArrayList(SingleObjectDeleter);
331                         __pLaunchArgs->Construct(1);
332                         __pLaunchArgs->Add(pIncomingCall);
333                         if(__initialSceneId.IsEmpty() == true)
334                         {
335                                 __initialSceneId = IDSCN_SCENE_INCOMINGCALL;
336                         }
337                         else
338                         {
339                                 //App already initialized, goto incoming call form
340                                 pSceneManager->GoForward(ForwardSceneTransition(IDSCN_SCENE_INCOMINGCALL), __pLaunchArgs);
341                                 __pLaunchArgs = null;
342                         }
343                 }
344                 else
345                 {
346                         //Show messageBox showing automatic call rejection
347                         /*MessageBox callRejectedInoMsgBox;
348                         String msg(L"Call From ");
349                         msg.Append(contactNumber);
350                         msg.Append(L" Rejected.");
351                         callRejectedInoMsgBox.Construct(L"Call Rejected", msg, MSGBOX_STYLE_NONE,1000);
352                         int modalResult = 0;
353                         // Calls ShowAndWait() : Draws and Shows itself and processes events
354                         callRejectedInoMsgBox.ShowAndWait(modalResult);*/
355
356                         //go back to previous scene if App was already running, else exit application.
357                         if(__initialSceneId.IsEmpty() == true)
358                         {
359                                 //KEEP "__initialSceneId" as empty and return false from "OnAppInitialized()"
360                                 AppLog("Terminate Phone Application");
361                                 Terminate();
362                         }
363                 }
364                 //set success message
365                 appControlResult = APP_CTRL_RESULT_SUCCEEDED;
366         }
367         else
368         {
369                 appControlResult = APP_CTRL_RESULT_FAILED;
370         }
371         AppLogDebug("Exiting %d",appControlResult);
372         AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
373 }
374
375 void
376 CallApp::HandleDialCallAppControlRequest(RequestId reqId,const IMap* pArgsMap,const String* pUriData)
377 {
378         //response message
379         AppCtrlResult appControlResult = APP_CTRL_RESULT_FAILED;
380
381         if (pArgsMap != null)
382         {
383                 String callType(L"");
384                 String phoneNumber(L"");
385                 //phone number
386                 String* pKey = new (std::nothrow) String(PARAM_PHONE_NUMBER);
387                 if(pArgsMap->ContainsKey(*pKey) == true)
388                 {
389                         const String* pPhoneValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
390                         if(pPhoneValue != null)
391                         {
392                                 AppLogDebug("%ls",pPhoneValue->GetPointer());
393                                 phoneNumber.Append(*pPhoneValue);
394                         }
395                 }
396                 else
397                 {
398                         AppLogDebug("PARAM_PHONE_NUMBER not present");
399                         //Now check if tel uri is present
400                         if(pUriData != null)
401                         {
402                                 AppLogDebug("pUriData is present %ls",pUriData->GetPointer());
403                                 phoneNumber.Append(*pUriData);
404                                 if(phoneNumber.Contains(PARAM_PHONE_NUMBER))
405                                 {
406                                         phoneNumber.Replace(PARAM_PHONE_NUMBER,L"");
407                                         if(phoneNumber.Contains(DELIMITER))
408                                         {
409                                                 phoneNumber.Replace(DELIMITER,L"");
410                                                 AppLogDebug("%ls",phoneNumber.GetPointer());
411                                         }
412                                 }
413                                 AppLogDebug("%ls",phoneNumber.GetPointer());
414                         }
415                 }
416                 delete pKey;
417                 //Check if its a valid number
418                 if(CheckNumberIsValid(phoneNumber) == false)
419                 {
420                         //go back to previous scene if App was already running, else exit application.
421                         if(__initialSceneId.IsEmpty() == true)
422                         {
423                                 //KEEP "__initialSceneId" as empty and return false from "OnAppInitialized()"
424                                 AppLog("Terminate Phone Application");
425                                 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
426                                 Terminate();
427                                 return;
428                         }
429                         else
430                         {
431                                 //invalid phone number.always return, but App will come to foreground
432                                 //and show current screen, if any calls is present.
433                                 return;
434                         }
435                 }
436                 //call type
437                 pKey = new (std::nothrow) String(PARAM_CALL_TYPE);
438                 if(pArgsMap->ContainsKey(*pKey) == true)
439                 {
440                         const String* pCallTypeValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
441                         if(pCallTypeValue != null)
442                         {
443                                 callType.Append(*pCallTypeValue);
444                         }
445                 }
446                 delete pKey;
447                 pKey = null;
448
449                 //Fetch currently active call count
450                 if (callType.IsEmpty() == false
451                                 && callType.Equals(PARAM_CALL_VALUE_VOICE, false) == true
452                                 && phoneNumber.IsEmpty() == false)
453                 {
454                         SceneManager* pSceneManager = SceneManager::GetInstance();
455                         //check if there is already a call in dialing mode, then dont accept any other dialing request.
456                         if (pSceneManager->GetCurrentSceneId() == IDSCN_SCENE_OUTCALL
457                                         || pSceneManager->GetCurrentSceneId()
458                                                         == IDSCN_SCENE_OUT_EMERGENCYCALL)
459                         {
460                                 AppLog("Cancelled");
461                                 appControlResult = APP_CTRL_RESULT_CANCELED;
462                                 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
463                                 return;
464                         }
465                         CallPresentationModel* pCallPresentor = CallPresentationModel::GetInstance();
466                         int currentActiveCallCount = pCallPresentor->GetCurrentCallCount();
467                         if(currentActiveCallCount <= 1)
468                         {
469                                 //Abort any AppControl Request running already to show incoming call screen
470                                 if (pCallPresentor->IsAppControlRunning() == true)
471                                 {
472                                         pCallPresentor->AbortAppControlRequest();
473                                 }
474                                 //make an outgoing call with given number
475                                 String* contactTxt = new (std::nothrow) String(phoneNumber);
476                                 __pLaunchArgs =  new (std::nothrow) ArrayList(SingleObjectDeleter);
477                                 __pLaunchArgs->Construct();
478                                 __pLaunchArgs->Add(contactTxt);
479                                 bool isEmergencyCall = pCallPresentor->IsEmergencyNumber(*contactTxt, true);
480
481                                 SceneId nextScene = IDSCN_SCENE_OUTCALL;
482                                 if (isEmergencyCall)
483                                 {
484                                         nextScene = IDSCN_SCENE_OUT_EMERGENCYCALL;
485                                 }
486                                 //Check if app was already running
487                                 if(__initialSceneId.IsEmpty() == true)
488                                 {
489                                         //phone App is not already launched
490                                         __initialSceneId = nextScene;
491                                 }
492                                 else
493                                 {
494                                         AppLog("Outgoing call");
495                                         pSceneManager->GoForward( ForwardSceneTransition( nextScene), __pLaunchArgs);
496                                 }
497                                 appControlResult = APP_CTRL_RESULT_SUCCEEDED;
498                         }
499                         else
500                         {
501                                 //already 2 active calls, 3rd call not allowed
502                                 appControlResult = APP_CTRL_RESULT_CANCELED;
503                         }
504                 }
505                 else
506                 {
507                         appControlResult = APP_CTRL_RESULT_FAILED;
508                 }
509         }
510         //send response message
511         AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
512 }
513
514 bool
515 CallApp::CheckNumberIsValid(String phoneNumber)
516 {
517         //Pattern to compare all characters except 0-9 * # P ; , +
518         String phoneNumberPattern(L"[^0-9*#P,p+;]");
519         RegularExpression checkPhoneNumber;
520         checkPhoneNumber.Construct(phoneNumberPattern);
521         //If there is any character other than these listed above then display invalid number
522         bool resultMatch = checkPhoneNumber.Match(phoneNumber,false);
523         //return false for patterns other than 0-9 * # P ; , +
524         if(resultMatch == true)
525         {
526                 //return phone number is invalid
527                 return false;
528         }
529
530         return true;
531
532 }
533
534 void
535 CallApp::SetTopMostWindow(bool bTopMost)
536 {
537         AppLogDebug("bTopMost = %d",bTopMost);
538         result res = E_FAILURE;
539         //ToDO: Need to see if there is better way to handle
540         //this case
541
542         if(bTopMost == true)
543         {
544                 GetAppFrame()->GetFrame()->SetZOrderGroup(WINDOW_Z_ORDER_GROUP_HIGHEST);
545                 AppManager::GetInstance()->AddActiveAppEventListener(*this);
546                 if(PowerManager::IsScreenOn() == false)
547                 {
548                         AppLogDebug("TurnScreenOn");
549                         res = PowerManager::TurnScreenOn();
550                         AppLogDebug("TurnScreenOn %d",res);
551                 }
552
553         }
554         else
555         {
556                 GetAppFrame()->GetFrame()->SetZOrderGroup(WINDOW_Z_ORDER_GROUP_NORMAL);
557                 PowerManager::KeepScreenOnState(false);
558                 AppManager::GetInstance()->RemoveActiveAppEventListener(*this);
559         }
560
561         if(LockManager::GetInstance()->IsLocked())
562         {
563                 AppLogDebug("Phone Locked");
564                 LockManager::GetInstance()->Unlock();
565         }
566
567 }
568 void
569 CallApp::OnActiveAppChanged(const String& appId)
570 {
571         AppLogDebug("Enter %ls",appId.GetPointer());
572         if(GetAppId().Equals(appId) == true)
573         {
574                 result res = PowerManager::KeepScreenOnState(true,false);
575                 AppLogDebug("KeepScreenOnState %d",res);
576
577         }
578
579 }