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