Removed usage of RemoveControl() in destructor
[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         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         return true;
91 }
92
93 void
94 CallApp::OnForeground(void)
95 {
96         IEnumerator* pEnum = __listenerList.GetEnumeratorN();
97         while (pEnum->MoveNext() == E_SUCCESS)
98         {
99                 IAppStateChangeListener* pInterface = static_cast<IAppStateChangeListener*>(pEnum->GetCurrent());
100                 if (pInterface == null)
101                 {
102                         delete pEnum;
103
104                         return;
105                 }
106                 pInterface->OnForeground();
107         }
108         delete pEnum;
109 }
110
111 void
112 CallApp::OnBackground(void)
113 {
114         // TODO:
115         // Stop drawing when the application is moved to the background.
116 }
117
118 void
119 CallApp::OnLowMemory(void)
120 {
121         // TODO:
122         // Free unused resources or close the application.
123 }
124
125 void
126 CallApp::OnBatteryLevelChanged(BatteryLevel batteryLevel)
127 {
128         // TODO:
129         // Handle any changes in battery level here.
130         // Stop using multimedia features(camera, mp3 etc.) if the battery level is CRITICAL.
131 }
132
133 void
134 CallApp::OnScreenOn(void)
135 {
136         // TODO:
137         // Get the released resources or resume the operations that were paused or stopped in OnScreenOff().
138 }
139
140 void
141 CallApp::OnScreenOff(void)
142 {
143         // TODO:
144         // Unless there is a strong reason to do otherwise, release resources (such as 3D, media, and sensors) to allow the device
145         // to enter the sleep mode to save the battery.
146         // Invoking a lengthy asynchronous method within this listener method can be risky, because it is not guaranteed to invoke a
147         // callback before the device enters the sleep mode.
148         // Similarly, do not perform lengthy operations in this listener method. Any operation must be a quick one.
149 }
150
151 SceneId
152 CallApp::GetInitialScene(void)
153 {
154         return __initialSceneId;
155 }
156
157 IList*
158 CallApp::GetAppLaunchArguments(void)
159 {
160         return __pLaunchArgs;
161 }
162
163 void
164 CallApp::AddAppStateChangeListener(const IAppStateChangeListener& listener)
165 {
166         __listenerList.Add(listener);
167
168 }
169 void
170 CallApp::RemoveAppStateChangeListener(const IAppStateChangeListener& listener)
171 {
172         __listenerList.Remove(listener);
173 }
174
175 void
176 CallApp::OnAppControlRequestReceived(RequestId reqId, const String& operationId, const String* pUriData,
177                 const String* pMimeType, const IMap* pExtraData)
178 {
179         AppLogDebug("Enter ");
180         if(pUriData != null)
181         {
182                 AppLogDebug("%ls ",pUriData->GetPointer());
183         }
184
185         if(pExtraData == null && pUriData != null)
186         {
187                 //The request is from web app
188                 AppLogDebug("%ls",pUriData->GetPointer());
189                 ProcessWebAppControlRequest(reqId, operationId, pUriData);
190         }
191         else
192         {
193                 //process AppControl parameters
194                 ProcessAppControlRequest(reqId, operationId, pExtraData,pUriData);
195         }
196         AppLogDebug("EXIT");
197 }
198
199 void
200 CallApp::ProcessWebAppControlRequest(RequestId reqId, const String& operationId,const String* pUriData)
201 {
202         //Construct map from string
203         String delim(DELIMITER);
204         StringTokenizer st(*pUriData,delim);
205         String token;
206         HashMap extraData;
207         extraData.Construct();
208         while(st.HasMoreTokens())
209         {
210                 String key=L"";
211                 String value=L"";
212                 st.GetNextToken(token);
213                 token.Trim();
214                 key.Append(token);
215                 if(st.HasMoreTokens())
216                 {
217                         token.Clear();
218                         st.GetNextToken(token);
219                         token.Trim();
220                         value.Append(token);
221                 }
222                 extraData.Add(new (std::nothrow) String(key), new (std::nothrow) String(value));
223         }
224
225         //Adding this explicitly as there no other way to invoke call from webapp
226         extraData.Add(new (std::nothrow) String(PARAM_CALL_TYPE), new (std::nothrow) String(PARAM_CALL_VALUE_VOICE));
227
228         ProcessAppControlRequest(reqId,operationId,&extraData);
229
230         extraData.RemoveAll(true);
231 }
232
233 void
234 CallApp::ProcessAppControlRequest(RequestId reqId, const String& operationId,const IMap* pArgsMap,const String* pUriData)
235 {
236         AppLogDebug("Enter %ls",operationId.GetPointer());
237         __pLaunchArgs = null;
238         if(operationId.Equals(OPERATION_ID_CALL,true) == true)
239         {
240                 AppLogDebug("OPERATION_ID_CALL");
241                 if(pArgsMap != null)
242                 {
243                         bool isIncomingCallRequest = false;
244                         String* pKey = new (std::nothrow) String(LAUNCHTYPE);
245                         if (pArgsMap->ContainsKey(*pKey) == true)
246                         {
247                                 const String* pValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
248                                 if ((pValue != null) && (pValue->Equals(PARAM_ORIGIN_MT, true) == true))
249                                 {
250                                         isIncomingCallRequest = true;
251                                 }
252                         }
253                         //Check if incoming call request or outgoing call request
254                         if(isIncomingCallRequest == true)
255                         {
256                                 HandleIncomingCallAppControlRequest(reqId, pArgsMap);
257                         }
258                         else
259                         {
260                                 HandleDialCallAppControlRequest(reqId, pArgsMap,pUriData);
261                         }
262                 }
263                 else
264                 {
265                         AppLogDebug("pArgsMap == null");
266                 }
267         }
268 }
269
270 void
271 CallApp::HandleIncomingCallAppControlRequest(RequestId reqId,const IMap* pArgsMap)
272 {
273         AppLogDebug("Enter");
274         SceneManager* pSceneManager = SceneManager::GetInstance();
275         //response message
276         AppCtrlResult appControlResult = APP_CTRL_RESULT_FAILED;
277
278         //call handle
279         String callHandle(L"");
280         String* pKey = new (std::nothrow) String(CALL_HANDLE);
281         if (pArgsMap->ContainsKey(*pKey) == true)
282         {
283                 const String* pValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
284                 if (pValue != null)
285                 {
286                         callHandle.Append(*pValue);
287                 }
288         }
289         delete pKey;
290         //contact number
291         String contactNumber(L"");
292         pKey = new (std::nothrow) String(CONTACT_NUMBER);
293         if (pArgsMap->ContainsKey(*pKey) == true)
294         {
295                 const String* pContactValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
296                 if (pContactValue != null)
297                 {
298                         contactNumber.Append(*pContactValue);
299                         AppLogDebug("%ls",contactNumber.GetPointer());
300                 }
301         }
302         delete pKey;
303         pKey = null;
304
305         //Fetch incoming call details
306         CallPresentationModel* pCallPresentor = CallPresentationModel::GetInstance();
307         AppCallInfo* pIncomingCall = pCallPresentor->FetchIncomingCallDetailsN(callHandle, contactNumber);
308         if(pIncomingCall != null)
309         {
310                 bool isCallRejected = pCallPresentor->CheckIncomingCallToBeRejected(pIncomingCall);
311                 if(isCallRejected == false)
312                 {
313                         //save app launch argument list
314                         __pLaunchArgs = new (std::nothrow) ArrayList(SingleObjectDeleter);
315                         __pLaunchArgs->Construct(1);
316                         __pLaunchArgs->Add(pIncomingCall);
317                         if(__initialSceneId.IsEmpty() == true)
318                         {
319                                 __initialSceneId = IDSCN_SCENE_INCOMINGCALL;
320                         }
321                         else
322                         {
323                                 //App already initialized, goto incoming call form
324                                 pSceneManager->GoForward(ForwardSceneTransition(IDSCN_SCENE_INCOMINGCALL), __pLaunchArgs);
325                                 __pLaunchArgs = null;
326                         }
327                 }
328                 else
329                 {
330                         //Show messageBox showing automatic call rejection
331                 /*      MessageBox callRejectedInoMsgBox;
332                         String msg(L"Call From ");
333                         msg.Append(contactNumber);
334                         msg.Append(L" Rejected.");
335                         callRejectedInoMsgBox.Construct(L"Call Rejected", msg, MSGBOX_STYLE_NONE,1000);
336                         int modalResult = 0;
337                         // Calls ShowAndWait() : Draws and Shows itself and processes events
338                         callRejectedInoMsgBox.ShowAndWait(modalResult);*/
339
340                         //go back to previous scene if App was already running, else exit application.
341                         if(__initialSceneId.IsEmpty() == true)
342                         {
343                                 //KEEP "__initialSceneId" as empty and return false from "OnAppInitialized()"
344                                 AppLog("Terminate Phone Application");
345                                 Terminate();
346                         }
347
348                 }
349                 //set success message
350                 appControlResult = APP_CTRL_RESULT_SUCCEEDED;
351         }
352         else
353         {
354                 appControlResult = APP_CTRL_RESULT_FAILED;
355         }
356         AppLogDebug("Exiting %d",appControlResult);
357         AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
358 }
359
360 void
361 CallApp::HandleDialCallAppControlRequest(RequestId reqId,const IMap* pArgsMap,const String* pUriData)
362 {
363         //response message
364         AppCtrlResult appControlResult = APP_CTRL_RESULT_FAILED;
365
366         if (pArgsMap != null)
367         {
368                 String callType(L"");
369                 String phoneNumber(L"");
370                 //phone number
371                 String* pKey = new (std::nothrow) String(PARAM_PHONE_NUMBER);
372                 if(pArgsMap->ContainsKey(*pKey) == true)
373                 {
374                         const String* pPhoneValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
375                         if(pPhoneValue != null)
376                         {
377                                 AppLogDebug("%ls",pPhoneValue->GetPointer());
378                                 phoneNumber.Append(*pPhoneValue);
379                         }
380                 }
381                 else
382                 {
383                         AppLogDebug("PARAM_PHONE_NUMBER not present");
384                         //Now check if tel uri is present
385                         if(pUriData != null)
386                         {
387                                 AppLogDebug("pUriData is present %ls",pUriData->GetPointer());
388                                 phoneNumber.Append(*pUriData);
389                                 if(phoneNumber.Contains(PARAM_PHONE_NUMBER))
390                                 {
391                                         phoneNumber.Replace(PARAM_PHONE_NUMBER,L"");
392                                         if(phoneNumber.Contains(DELIMITER))
393                                         {
394                                                 phoneNumber.Replace(DELIMITER,L"");
395                                                 AppLogDebug("%ls",phoneNumber.GetPointer());
396                                         }
397                                 }
398                                 AppLogDebug("%ls",phoneNumber.GetPointer());
399                         }
400                 }
401                 delete pKey;
402                 //Check if its a valid number
403                 if(CheckNumberIsValid(phoneNumber) == false)
404                 {
405                         //Show messageBox showing automatic call rejection
406                         MessageBox InvalidNumberMsgBox;
407                         InvalidNumberMsgBox.Construct(AppUtility::GetResourceString(IDS_INVALID_NUMBER), L"",MSGBOX_STYLE_NONE,1000);
408                         int modalResult = 0;
409                         // Calls ShowAndWait() : Draws and Shows itself and processes events
410                         InvalidNumberMsgBox.ShowAndWait(modalResult);
411
412                         //go back to previous scene if App was already running, else exit application.
413                         if(__initialSceneId.IsEmpty() == true)
414                         {
415                                 //KEEP "__initialSceneId" as empty and return false from "OnAppInitialized()"
416                                 AppLog("Terminate Phone Application");
417                                 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
418                                 Terminate();
419                                 return;
420                         }
421
422                 }
423                 //call type
424                 pKey = new (std::nothrow) String(PARAM_CALL_TYPE);
425                 if(pArgsMap->ContainsKey(*pKey) == true)
426                 {
427                         const String* pCallTypeValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
428                         if(pCallTypeValue != null)
429                         {
430                                 callType.Append(*pCallTypeValue);
431                         }
432                 }
433                 delete pKey;
434                 pKey = null;
435
436                 //Fetch currently active call count
437                 if (callType.IsEmpty() == false
438                                 && callType.Equals(PARAM_CALL_VALUE_VOICE, false) == true
439                                 && phoneNumber.IsEmpty() == false)
440                 {
441                         SceneManager* pSceneManager = SceneManager::GetInstance();
442                         //check if there is already a call in dialing mode, then dont accept any other dialing request.
443                         if (pSceneManager->GetCurrentSceneId() == IDSCN_SCENE_OUTCALL
444                                         || pSceneManager->GetCurrentSceneId()
445                                                         == IDSCN_SCENE_OUT_EMERGENCYCALL)
446                         {
447                                 AppLog("Cancelled");
448                                 appControlResult = APP_CTRL_RESULT_CANCELED;
449                                 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
450                                 return;
451                         }
452                         CallPresentationModel* pCallPresentor = CallPresentationModel::GetInstance();
453                         int currentActiveCallCount = pCallPresentor->GetCurrentCallCount();
454                         if(currentActiveCallCount <= 1)
455                         {
456                                 //make an outgoing call with given number
457                                 String* contactTxt = new (std::nothrow) String(phoneNumber);
458                                 __pLaunchArgs =  new (std::nothrow) ArrayList(SingleObjectDeleter);
459                                 __pLaunchArgs->Construct();
460                                 __pLaunchArgs->Add(contactTxt);
461                                 bool isEmergencyCall = pCallPresentor->IsEmergencyNumber(*contactTxt, true);
462
463                                 SceneId nextScene = IDSCN_SCENE_OUTCALL;
464                                 if (isEmergencyCall)
465                                 {
466                                         nextScene = IDSCN_SCENE_OUT_EMERGENCYCALL;
467                                 }
468                                 //Check if app was already running
469                                 if(__initialSceneId.IsEmpty() == true)
470                                 {
471                                         //phone App is not already launched
472                                         __initialSceneId = nextScene;
473                                 }
474                                 else
475                                 {
476                                         AppLog("Outgoing call");
477                                         pSceneManager->GoForward( ForwardSceneTransition( nextScene), __pLaunchArgs);
478                                 }
479                                 appControlResult = APP_CTRL_RESULT_SUCCEEDED;
480                         }
481                         else
482                         {
483                                 //already 2 active calls, 3rd call not allowed
484                                 appControlResult = APP_CTRL_RESULT_CANCELED;
485                         }
486                 }
487                 else
488                 {
489                         appControlResult = APP_CTRL_RESULT_FAILED;
490                 }
491         }
492         //send response message
493         AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
494 }
495
496 bool
497 CallApp::CheckNumberIsValid(String phoneNumber)
498 {
499         //Pattern to compare all characters except 0-9 * # P ; , +
500         String phoneNumberPattern(L"[^0-9*#P,+;]");
501         RegularExpression checkPhoneNumber;
502         checkPhoneNumber.Construct(phoneNumberPattern);
503         //If there is any character other than these listed above then display invalid number
504         bool resultMatch = checkPhoneNumber.Match(phoneNumber,false);
505         //return false for patterns other than 0-9 * # P ; , +
506         return !resultMatch;
507
508 }
509
510 void
511 CallApp::SetTopMostWindow(bool bTopMost)
512 {
513         AppLogDebug("bTopMost = %d",bTopMost);
514         result res = E_FAILURE;
515         //ToDO: Need to see if there is better way to handle
516         //this case
517
518         if(bTopMost == true)
519         {
520                 GetAppFrame()->GetFrame()->SetZOrderGroup(WINDOW_Z_ORDER_GROUP_HIGHEST);
521                 if(PowerManager::IsScreenOn() == false)
522                 {
523                         res = PowerManager::TurnScreenOn();
524                 }
525                 res = PowerManager::KeepScreenOnState(true,false);
526
527         }
528         else
529         {
530                 GetAppFrame()->GetFrame()->SetZOrderGroup(WINDOW_Z_ORDER_GROUP_NORMAL);
531                 PowerManager::KeepScreenOnState(false);
532         }
533         //Unlock the phone if its locked
534         if(LockManager::GetInstance()->IsLocked())
535         {
536                 LockManager::GetInstance()->Unlock();
537         }
538
539 }