sync with master
[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 "CallApp.h"
10 #include "CallAppFrame.h"
11 #include "CallPresentationModel.h"
12 #include "CallTypes.h"
13 #include "CallAppUtility.h"
14 #include "CallIAppStateChangeListner.h"
15
16 using namespace Tizen::App;
17 using namespace Tizen::Base;
18 using namespace Tizen::System;
19 using namespace Tizen::Ui;
20 using namespace Tizen::Ui::Controls;
21 using namespace Tizen::Ui::Scenes;
22 using namespace Tizen::Base::Utility;
23 using namespace Tizen::Base::Collection;
24 using namespace Tizen::Base::Utility;
25
26
27 CallApp::CallApp(void):__initialSceneId(L""), __pLaunchArgs(null)
28 {
29         __listenerList.Construct();
30 }
31
32 CallApp::~CallApp(void)
33 {
34 }
35
36 UiApp*
37 CallApp::CreateInstance(void)
38 {
39         // Create the instance through the constructor.
40         return new CallApp();
41 }
42
43 bool
44 CallApp::OnAppInitializing(AppRegistry& appRegistry)
45 {
46         AppControlProviderManager* pProviderMgr = AppControlProviderManager::GetInstance();
47         pProviderMgr->SetAppControlProviderEventListener(this);
48         return true;
49 }
50
51 bool
52 CallApp::OnAppInitialized(void)
53 {
54         // TODO:
55         // Comment.
56
57         // Create a Frame
58         CallAppFrame* pCallAppFrame = new CallAppFrame();
59         pCallAppFrame->Construct();
60         pCallAppFrame->SetName(L"CallApp");
61         AddFrame(*pCallAppFrame);
62
63         //Check if there is no initial scene, then exit application.
64         //This case will normally come when invalid AppControl request has come,
65         //or incoming call is coming from unknown number and "reject unknown number" settings is enabled.
66         if (GetInitialScene().IsEmpty() == true)
67         {
68                 return false;
69         }
70
71         return true;
72 }
73
74 bool
75 CallApp::OnAppWillTerminate(void)
76 {
77         // TODO:
78         // Comment.
79         return true;
80 }
81
82 bool
83 CallApp::OnAppTerminating(AppRegistry& appRegistry, bool forcedTermination)
84 {
85         // TODO:
86         // Deallocate resources allocated by this App for termination.
87         // The App's permanent data and context can be saved via appRegistry.
88         return true;
89 }
90
91 void
92 CallApp::OnForeground(void)
93 {
94         IEnumerator* pEnum = __listenerList.GetEnumeratorN();
95         while (pEnum->MoveNext() == E_SUCCESS)
96         {
97                 IAppStateChangeListener* pInterface = static_cast<IAppStateChangeListener*>(pEnum->GetCurrent());
98                 if (pInterface == null)
99                 {
100                         delete pEnum;
101
102                         return;
103                 }
104                 pInterface->OnForeground();
105         }
106         delete pEnum;
107 }
108
109 void
110 CallApp::OnBackground(void)
111 {
112         // TODO:
113         // Stop drawing when the application is moved to the background.
114 }
115
116 void
117 CallApp::OnLowMemory(void)
118 {
119         // TODO:
120         // Free unused resources or close the application.
121 }
122
123 void
124 CallApp::OnBatteryLevelChanged(BatteryLevel batteryLevel)
125 {
126         // TODO:
127         // Handle any changes in battery level here.
128         // Stop using multimedia features(camera, mp3 etc.) if the battery level is CRITICAL.
129 }
130
131 void
132 CallApp::OnScreenOn(void)
133 {
134         // TODO:
135         // Get the released resources or resume the operations that were paused or stopped in OnScreenOff().
136 }
137
138 void
139 CallApp::OnScreenOff(void)
140 {
141         // TODO:
142         // Unless there is a strong reason to do otherwise, release resources (such as 3D, media, and sensors) to allow the device
143         // to enter the sleep mode to save the battery.
144         // Invoking a lengthy asynchronous method within this listener method can be risky, because it is not guaranteed to invoke a
145         // callback before the device enters the sleep mode.
146         // Similarly, do not perform lengthy operations in this listener method. Any operation must be a quick one.
147 }
148
149 SceneId
150 CallApp::GetInitialScene(void)
151 {
152         return __initialSceneId;
153 }
154
155 IList*
156 CallApp::GetAppLaunchArguments(void)
157 {
158         return __pLaunchArgs;
159 }
160
161 void
162 CallApp::AddAppStateChangeListener(const IAppStateChangeListener& listener)
163 {
164         __listenerList.Add(listener);
165
166 }
167 void
168 CallApp::RemoveAppStateChangeListener(const IAppStateChangeListener& listener)
169 {
170         __listenerList.Remove(listener);
171 }
172
173 void
174 CallApp::OnAppControlRequestReceived(RequestId reqId, const String& operationId, const String* pUriData,
175                 const String* pMimeType, const IMap* pExtraData)
176 {
177         AppLogDebug("ENTER");
178         //process AppControl parameters
179         ProcessAppControlRequest(reqId, operationId, pExtraData);
180         AppLogDebug("EXIT");
181 }
182
183 void
184 CallApp::ProcessAppControlRequest(RequestId reqId, const String& operationId,const IMap* pArgsMap)
185 {
186         AppLogDebug("Enter %ls",operationId.GetPointer());
187         __pLaunchArgs = null;
188         if(operationId.Equals(OPERATION_ID_CALL,true) == true)
189         {
190                 AppLogDebug("OPERATION_ID_CALL");
191                 if(pArgsMap != null)
192                 {
193                         bool isIncomingCallRequest = false;
194                         String* pKey = new (std::nothrow) String(LAUNCHTYPE);
195                         if (pArgsMap->ContainsKey(*pKey) == true)
196                         {
197                                 const String* pValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
198                                 if ((pValue != null) && (pValue->Equals(PARAM_ORIGIN_MT, true) == true))
199                                 {
200                                         isIncomingCallRequest = true;
201                                 }
202                         }
203                         //Check if incoming call request or outgoing call request
204                         if(isIncomingCallRequest == true)
205                         {
206                                 HandleIncomingCallAppControlRequest(reqId, pArgsMap);
207                         }
208                         else
209                         {
210                                 HandleDialCallAppControlRequest(reqId, pArgsMap);
211                         }
212                 }
213                 else
214                 {
215                         AppLogDebug("pArgsMap == null");
216                 }
217         }
218 }
219
220 void
221 CallApp::HandleIncomingCallAppControlRequest(RequestId reqId,const IMap* pArgsMap)
222 {
223         AppLogDebug("Enter");
224         SceneManager* pSceneManager = SceneManager::GetInstance();
225         //response message
226         AppCtrlResult appControlResult = APP_CTRL_RESULT_FAILED;
227
228         //call handle
229         String callHandle(L"");
230         String* pKey = new (std::nothrow) String(CALL_HANDLE);
231         if (pArgsMap->ContainsKey(*pKey) == true)
232         {
233                 const String* pValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
234                 if (pValue != null)
235                 {
236                         callHandle.Append(*pValue);
237                 }
238         }
239         delete pKey;
240         //contact number
241         String contactNumber(L"");
242         pKey = new (std::nothrow) String(CONTACT_NUMBER);
243         if (pArgsMap->ContainsKey(*pKey) == true)
244         {
245                 const String* pContactValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
246                 if (pContactValue != null)
247                 {
248                         contactNumber.Append(*pContactValue);
249                         AppLogDebug("%ls",contactNumber.GetPointer());
250                 }
251         }
252         delete pKey;
253         pKey = null;
254
255         //Fetch incoming call details
256         CallPresentationModel* pCallPresentor = CallPresentationModel::GetInstance();
257         CallInfo* pIncomingCall = pCallPresentor->FetchIncomingCallDetailsN(callHandle, contactNumber);
258         if(pIncomingCall != null)
259         {
260                 bool isCallRejected = pCallPresentor->CheckIncomingCallToBeRejected(pIncomingCall);
261                 if(isCallRejected == false)
262                 {
263                         //save app launch argument list
264                         __pLaunchArgs = new (std::nothrow) ArrayList(SingleObjectDeleter);
265                         __pLaunchArgs->Construct(1);
266                         __pLaunchArgs->Add(pIncomingCall);
267                         if(__initialSceneId.IsEmpty() == true)
268                         {
269                                 __initialSceneId = IDSCN_SCENE_INCOMINGCALL;
270                         }
271                         else
272                         {
273                                 //App already initialized, goto incoming call form
274                                 pSceneManager->GoForward(ForwardSceneTransition(IDSCN_SCENE_INCOMINGCALL), __pLaunchArgs);
275                                 __pLaunchArgs = null;
276                         }
277                 }
278                 else
279                 {
280                         //Show messageBox showing automatic call rejection
281                         MessageBox callRejectedInoMsgBox;
282                         String msg(L"Call From ");
283                         msg.Append(contactNumber);
284                         msg.Append(L" Rejected.");
285                         callRejectedInoMsgBox.Construct(L"Call Rejected", msg, MSGBOX_STYLE_NONE,1000);
286                         int modalResult = 0;
287                         // Calls ShowAndWait() : Draws and Shows itself and processes events
288                         callRejectedInoMsgBox.ShowAndWait(modalResult);
289
290                         //go back to previous scene if App was already running, else exit application.
291                         if(__initialSceneId.IsEmpty() == true)
292                         {
293                                 //KEEP "__initialSceneId" as empty and return false from "OnAppInitialized()"
294                                 AppLog("Terminate Phone Application");
295                                 Terminate();
296                         }
297
298                 }
299                 //set success message
300                 appControlResult = APP_CTRL_RESULT_SUCCEEDED;
301         }
302         else
303         {
304                 appControlResult = APP_CTRL_RESULT_FAILED;
305         }
306         AppLogDebug("Exiting %d",appControlResult);
307         AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
308 }
309
310 void
311 CallApp::HandleDialCallAppControlRequest(RequestId reqId,const IMap* pArgsMap)
312 {
313         //response message
314         AppCtrlResult appControlResult = APP_CTRL_RESULT_FAILED;
315
316         if (pArgsMap != null)
317         {
318                 String callType(L"");
319                 String phoneNumber(L"");
320                 //phone number
321                 String* pKey = new (std::nothrow) String(PARAM_PHONE_NUMBER);
322                 if(pArgsMap->ContainsKey(*pKey) == true)
323                 {
324                         const String* pPhoneValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
325                         if(pPhoneValue != null)
326                         {
327                                 AppLogDebug("%ls",pPhoneValue->GetPointer());
328                                 phoneNumber.Append(*pPhoneValue);
329                         }
330                 }
331                 else
332                 {
333                         AppLogDebug("PARAM_PHONE_NUMBER not present");
334                 }
335                 delete pKey;
336                 //Check if its a valid number
337                 if(CheckNumberIsValid(phoneNumber) == false)
338                 {
339                         //Show messageBox showing automatic call rejection
340                         MessageBox InvalidNumberMsgBox;
341                         InvalidNumberMsgBox.Construct(AppUtility::GetResourceString(IDS_INVALID_NUMBER), L"",MSGBOX_STYLE_NONE,1000);
342                         int modalResult = 0;
343                         // Calls ShowAndWait() : Draws and Shows itself and processes events
344                         InvalidNumberMsgBox.ShowAndWait(modalResult);
345
346                         //go back to previous scene if App was already running, else exit application.
347                         if(__initialSceneId.IsEmpty() == true)
348                         {
349                                 //KEEP "__initialSceneId" as empty and return false from "OnAppInitialized()"
350                                 AppLog("Terminate Phone Application");
351                                 Terminate();
352                         }
353
354                 }
355                 //call type
356                 pKey = new (std::nothrow) String(PARAM_CALL_TYPE);
357                 if(pArgsMap->ContainsKey(*pKey) == true)
358                 {
359                         const String* pCallTypeValue = static_cast<const String*>(pArgsMap->GetValue(*pKey));
360                         if(pCallTypeValue != null)
361                         {
362                                 callType.Append(*pCallTypeValue);
363                         }
364                 }
365                 delete pKey;
366                 pKey = null;
367
368                 //Fetch currently active call count
369                 if (callType.IsEmpty() == false
370                                 && callType.Equals(PARAM_CALL_VALUE_VOICE, false) == true
371                                 && phoneNumber.IsEmpty() == false)
372                 {
373                         SceneManager* pSceneManager = SceneManager::GetInstance();
374                         //check if there is already a call in dialing mode, then dont accept any other dialing request.
375                         if (pSceneManager->GetCurrentSceneId() == IDSCN_SCENE_OUTCALL
376                                         || pSceneManager->GetCurrentSceneId()
377                                                         == IDSCN_SCENE_OUT_EMERGENCYCALL)
378                         {
379                                 AppLog("Cancelled");
380                                 appControlResult = APP_CTRL_RESULT_CANCELED;
381                                 AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
382                                 return;
383                         }
384                         CallPresentationModel* pCallPresentor = CallPresentationModel::GetInstance();
385                         int currentActiveCallCount = pCallPresentor->GetCurrentCallCount();
386                         if(currentActiveCallCount <= 1)
387                         {
388                                 //make an outgoing call with given number
389                                 String* contactTxt = new (std::nothrow) String(phoneNumber);
390                                 __pLaunchArgs =  new (std::nothrow) ArrayList(SingleObjectDeleter);
391                                 __pLaunchArgs->Construct();
392                                 __pLaunchArgs->Add(contactTxt);
393                                 bool isEmergencyCall = pCallPresentor->IsEmergencyNumber(*contactTxt, true);
394
395                                 SceneId nextScene = IDSCN_SCENE_OUTCALL;
396                                 if (isEmergencyCall)
397                                 {
398                                         nextScene = IDSCN_SCENE_OUT_EMERGENCYCALL;
399                                 }
400                                 //Check if app was already running
401                                 if(__initialSceneId.IsEmpty() == true)
402                                 {
403                                         //phone App is not already launched
404                                         __initialSceneId = nextScene;
405                                 }
406                                 else
407                                 {
408                                         pSceneManager->GoForward( ForwardSceneTransition( nextScene), __pLaunchArgs);
409                                 }
410                                 appControlResult = APP_CTRL_RESULT_SUCCEEDED;
411                         }
412                         else
413                         {
414                                 //already 2 active calls, 3rd call not allowed
415                                 appControlResult = APP_CTRL_RESULT_CANCELED;
416                         }
417                 }
418                 else
419                 {
420                         appControlResult = APP_CTRL_RESULT_FAILED;
421                 }
422         }
423         //send response message
424         AppControlProviderManager::GetInstance()->SendAppControlResult(reqId, appControlResult, null);
425 }
426
427 bool
428 CallApp::CheckNumberIsValid(String phoneNumber)
429 {
430         //Pattern to compare all characters except 0-9 * # P ; , +
431         String phoneNumberPattern(L"[^0-9*#P;,+]");
432         RegularExpression checkPhoneNumber;
433         checkPhoneNumber.Construct(phoneNumberPattern);
434         //If there is any character other than these listed above then display invalid number
435         bool resultMatch = checkPhoneNumber.Match(phoneNumber,false);
436         //return false for patterns other than 0-9 * # P ; , +
437         return !resultMatch;
438
439 }