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