Merge "Fix duplicated alarms." into tizen_2.2
[platform/framework/native/appfw.git] / src / app / FApp_AppControlManager.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Apache License, Version 2.0 (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://www.apache.org/licenses/LICENSE-2.0
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 /**
18  * @file        FApp_AppControlManager.cpp
19  * @brief       This is the implementation for the _AppControlManager class.
20  */
21
22 #include <stdint.h>
23 #include <cstdio>
24 #include <unique_ptr.h>
25
26 #include <appsvc/appsvc.h>
27 #include <aul/aul.h>
28 #include <bundle.h>
29 #include <content/mime_type.h>
30 #include <appinfo.h>
31
32 #include <FBaseInteger.h>
33 #include <FBaseObject.h>
34 #include <FBaseString.h>
35 #include <FBaseColIListT.h>
36 #include <FBaseColArrayList.h>
37 #include <FBaseErrors.h>
38 #include <FAppAppControl.h>
39 #include <FAppAppManager.h>
40 #include <FAppIAppControlListener.h>
41 #include <FAppIAppControlResponseListener.h>
42 #include <FAppIAppFrame.h>
43 #include <FAppSqlDataControl.h>
44 #include <FAppMapDataControl.h>
45 #include <FAppPkgPackageInfo.h>
46 #include <FAppPkgPackageAppInfo.h>
47 #include <FBaseSysLog.h>
48
49 #include <FBase_StringConverter.h>
50 #include <FIo_DataControlResultSetImpl.h>
51
52 #include "FApp_AppArg.h"
53 #include "FApp_AppControlEventArg.h"
54 #include "FApp_AppControlRegistry.h"
55 #include "FApp_AppControlImpl.h"
56 #include "FApp_AppImpl.h"
57 #include "FApp_AppInfo.h"
58 #include "FApp_Aul.h"
59 #include "FApp_AppControlManager.h"
60 #include "FApp_AppManagerProxy.h"
61 #include "FApp_ConditionManagerProxy.h"
62 #include "FApp_MapDataControlImpl.h"
63 #include "FApp_SqlDataControlImpl.h"
64 #include "FAppPkg_PackageManagerImpl.h"
65 #include "FAppPkg_PackageInfoImpl.h"
66 #include "FApp_AppMessageImpl.h"
67 #include "FApp_AppManagerImpl.h"
68 #include "FApp_AppControlResponseEvent.h"
69 #include "FApp_IAppControlPluginProvider.h"
70
71
72 using namespace Tizen::App::Package;
73 using namespace Tizen::Base;
74 using namespace Tizen::Base::Collection;
75 using namespace Tizen::Base::Runtime;
76 using namespace Tizen::Base::Utility;
77 using namespace Tizen::Io;
78
79
80 namespace Tizen { namespace App
81 {
82
83 const wchar_t TIZEN_OPERATION_PICK[] = L"http://tizen.org/appcontrol/operation/pick";
84 const wchar_t TIZEN_OPERATION_MAIN[] = L"http://tizen.org/appcontrol/operation/main";
85 const wchar_t LEGACY_OPERATION_MAIN[] = L"osp.operation.MAIN";
86 const char TIZEN_NOTIFICATION_DATA[] = "http://tizen.org/appcontrol/data/notification";
87
88 _AppControlManager::_AppControlManager(void)
89 {
90         SysLog(NID_APP, "");
91
92         // AppControl event handling is expected to be performed in the main thread.
93         __appControlEvent.Construct();
94         __appControlEvent.AddListener(*dynamic_cast<_IAppControlSysEventListener*>(this));
95         __appControlResponseEventContainer.Construct();
96         __appControlResponseEventList.Construct();
97 }
98
99 _AppControlManager::~_AppControlManager(void)
100 {
101         SysLog(NID_APP, "");
102         __appControlEvent.RemoveListener(*dynamic_cast<_IAppControlSysEventListener*>(this));
103         IEnumeratorT<int>* pEnum = __appControlResponseEventList.GetEnumeratorN();
104
105         if (pEnum != null)
106         {
107                 while(pEnum->MoveNext() == E_SUCCESS)
108                 {
109                         int reqId;
110                         pEnum->GetCurrent(reqId);
111                         _AppControlResponseEvent* pResponseEvent = null;
112                         __appControlResponseEventContainer.GetValue(reqId, pResponseEvent);
113                         delete pResponseEvent;
114
115                         __appControlResponseEventContainer.Remove(reqId);
116                         SysLog(NID_APP, "pResponseEvent gets deleted. reqId(%d)", reqId);
117                 }
118         }
119         delete pEnum;
120 }
121
122 _AppControlManager*
123 _AppControlManager::GetInstance(void)
124 {
125         static _AppControlManager inst;
126
127         return &inst;
128 }
129
130 result
131 _AppControlManager::GetMimeFromExt(const String& ext, String& out)
132 {
133         std::unique_ptr<char[]> pExtension(_StringConverter::CopyToCharArrayN(ext));
134         SysTryReturnResult(NID_APP, pExtension != null, E_OUT_OF_MEMORY, "String allocation failure.");
135
136         char* mime = NULL;
137         mime_type_get_mime_type(pExtension.get(), &mime);
138
139         SysTryReturnResult(NID_APP, mime != NULL, E_UNSUPPORTED_FORMAT, "MIME type conversion failure for %ls.", ext.GetPointer());
140
141         out = mime;
142         free(mime);
143
144         return E_SUCCESS;
145 }
146
147
148 String
149 _AppControlManager::GetMimeTypeFromDataType(const String& data)
150 {
151         // Data type is either MIME type or .[extension]
152
153         if (data.IsEmpty() || data[0] != L'.')
154         {
155                 return data;
156         }
157
158         // .[extension]
159         String ext;
160         data.SubString(1, ext);
161
162         String res;
163         result r = _AppControlManager::GetMimeFromExt(ext, res);
164         SysTryReturn(NID_APP, !IsFailed(r), L"", r, "[%s] MIME type conversion failed for %ls.", GetErrorMessage(r), ext.GetPointer());
165
166         SysLog(NID_APP, "Conversion from %ls into %ls.", data.GetPointer(), res.GetPointer());
167         return res;
168 }
169
170
171 void
172 _AppControlManager::OnAppControlEventReceivedN(int reqId, _AppArg* pAppArg, int res)
173 {
174         SysLog(NID_APP, "Received request Id %d, arg 0x%x", reqId, pAppArg);
175
176         //_AppArg::Print(b);
177         // get launch info from request Id
178         _DataControlInfo* pInfo = __launchManager.FindItem(reqId);
179         SysTryReturnVoidResult(NID_APP, pInfo != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] request Id %d not found with response %d", reqId,
180                                         res);
181
182         // invoke callback
183         if (pInfo->launchCb)
184         {
185                 if (pInfo->magic == LAUNCH_INFO_MAGIC)
186                 {
187                         SysLog(NID_APP, "Invoking callback 0x%x", pInfo->launchCb);
188                         //pAppArg->Print();
189
190                         if (pInfo->pUserData)
191                         {
192                                 (*pInfo->launchCb)(pInfo->pUserData, pInfo->pArg, pAppArg, static_cast<service_result_e>(res), pInfo->property, reqId);
193                         }
194                 }
195                 else
196                 {
197                         SysLogException(NID_APP, E_SYSTEM, "Corrupted data structure.");
198                 }
199         }
200
201         // clean up argument
202         __launchManager.RemoveItem(reqId);
203 }
204
205
206 // callback for AppControl start event
207 void
208 _AppControlManager::OnAppControlEventReceivedN(int reqId, const AppId& appId, const String& operationId)
209 {
210         SysLog(NID_APP, "Received request Id %d, app %ls, operationId %ls", reqId, appId.GetPointer(), operationId.GetPointer());
211
212         // get launch info from request Id
213         _InProcessInfo* pInfo = __inAppManager.FindItem(reqId);
214         SysTryReturnVoidResult(NID_APP, pInfo != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] request Id %d not found.", reqId);
215
216         // at least listener
217         IAppControlResponseListener* pListener = dynamic_cast<IAppControlResponseListener*>(pInfo->pListener);
218         SysTryReturnVoidResult(NID_APP, pListener != null, E_SYSTEM, "[E_SYSTEM] Invalid result callback for req %d, app %ls.", reqId, appId.GetPointer());
219
220         result r = E_SUCCESS;
221
222         if (pListener)
223         {
224                 AppId actualAppId = appId;
225                 if (appId == L'c')
226                 {
227                         actualAppId.Clear();
228                         r = E_OPERATION_CANCELED;
229                 }
230                 SysLog(NID_APP, "Invoking callback 0x%x.", pListener);
231
232                 _AppControlResponseEvent* pResponseEvent = null;
233                 __appControlResponseEventContainer.GetValue(reqId, pResponseEvent);
234                 SysLog(NID_APP, "StartResponseReceived Request Id(%d), ResponseEvent 0x%x.", reqId, pResponseEvent);
235                 if (pResponseEvent != null)
236                 {
237                         String oId(operationId);
238                         _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_START, actualAppId, oId, r, APP_CTRL_RESULT_SUCCEEDED, null, reqId, false);
239
240                         if (pResponseEventArg != null)
241                         {
242                                 pResponseEvent->Fire(*pResponseEventArg);
243                                 SysLog(NID_APP, "pResponseEvent is Fired");
244                         }
245                 }
246                 else
247                 {
248                         pListener->OnAppControlStartResponseReceived(actualAppId, operationId, r);
249                         SysLog(NID_APP, "OnAppControlStartResponseReceived called directly");
250                 }
251         }
252         else
253         {
254                 SysLog(NID_APP, "No listener registered.");
255         }
256
257         if (r == E_OPERATION_CANCELED)
258         {
259                 SysLog(NID_APP, "Removed start listener as operation is canceled.");
260                 __inAppManager.RemoveItem(reqId);
261         }
262 }
263
264
265 void
266 _AppControlManager::InvokeAppControlCompleteListener(IAppControlResponseListener& listener, const AppId& appId, const String& op, AppCtrlResult res, const IMap* pExtraData, bool noRaise)
267 {
268         listener.OnAppControlCompleteResponseReceived(appId, op, res, pExtraData);
269
270         if (!noRaise)
271         {
272                 _AppImpl::GetInstance()->SendUserEvent(_APP_EVENT_RAISE, null, false);
273         }
274
275         SysLog(NID_APP, "AppControl response finished.");
276 }
277
278
279 void
280 _AppControlManager::InvokeLegacyAppControlCompleteListener(IAppControlEventListener& listener, const AppId& appId, const String& op, const IList* pList, bool noRaise)
281 {
282         listener.OnAppControlCompleted(appId, op, pList);
283
284         if (!noRaise)
285         {
286                 _AppImpl::GetInstance()->SendUserEvent(_APP_EVENT_RAISE, null, false);
287         }
288
289         SysLog(NID_APP, "Legacy AppControl response finished.");
290 }
291
292
293 // callback for in-process event handling
294 void
295 _AppControlManager::OnAppControlPluginEventReceivedN(int reqId, int res, const AppId& optAppId, const String& optOperation, const IMap* pArgs, int property)
296 {
297         SysLog(NID_APP, "Received request Id %d, res %d, args 0x%x", reqId, res, pArgs);
298
299         // process proper callback
300         _InProcessInfo* pInfo = __inAppManager.FindItem(reqId);
301         SysTryReturnVoidResult(NID_APP, pInfo != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] request Id %d not found with args 0x%x", reqId,
302                                         pArgs);
303
304         if (pInfo->pListener)
305         {
306                 String aId;
307                 String oId;
308
309                 if (optAppId.IsEmpty())
310                 {
311                         aId = pInfo->providerId;
312                         oId = pInfo->operationId;
313                 }
314                 else
315                 {
316                         // implicit launch only
317                         aId = optAppId;
318                         oId = optOperation;
319
320                         SysLog(NID_APP, "Changing appId/operation for implicit launch.");
321                 }
322
323                 SysLog(NID_APP, "Invoking callback 0x%x for (%ls, %ls).", pInfo->pListener, aId.GetPointer(), oId.GetPointer());
324
325                 const bool isSubMode = (property & _APPCONTROL_PROPERTY_SUBMODE);
326                 const bool isServiceCallee = (property & _APPCONTROL_PROPERTY_SERVICE_CALLEE);
327
328                 if (pInfo->isLegacy)
329                 {
330                         IAppControlEventListener* pListener = dynamic_cast<IAppControlEventListener*>(pInfo->pListener);
331                         if (pListener)
332                         {
333                                 ArrayList list(SingleObjectDeleter);
334                                 _AppArg::FillLegacyAppControlResult(list, res, pArgs, aId);
335
336                                 InvokeLegacyAppControlCompleteListener(*pListener, aId, oId, &list, isSubMode | isServiceCallee);
337                         }
338                         else
339                         {
340                                 SysLog(NID_APP, "Wrong AppControl listener type.");
341                         }
342                 }
343                 else
344                 {
345                         IAppControlResponseListener* pListener = dynamic_cast<IAppControlResponseListener*>(pInfo->pListener);
346                         if (pListener)
347                         {
348                                 _AppControlResponseEvent* pResponseEvent = null;
349                                 int responseEventRequestId = RESPONSE_EVENT_REQID_MAGIC + reqId;
350                                 __appControlResponseEventContainer.GetValue(responseEventRequestId, pResponseEvent);
351
352                                 if (pResponseEvent != null)
353                                 {
354                                         _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_COMPLETE, aId, oId, E_SUCCESS, static_cast<AppCtrlResult>(res), const_cast<IMap*> (pArgs), responseEventRequestId, isSubMode);
355                                         if (pResponseEventArg != null)
356                                         {
357                                                 pResponseEvent->Fire(*pResponseEventArg);
358                                                 SysLog(NID_APP, "pResponseEvent is Fired");
359                                         }
360                                 }
361                                 else
362                                 {
363                                         InvokeAppControlCompleteListener(*pListener, aId, oId, ConvertAppControlResultCode(res), pArgs, isSubMode | isServiceCallee);
364                                         SysLog(NID_APP, "Listener called directly");
365                                         delete pArgs;
366                                 }
367                         }
368                         else
369                         {
370                                 SysLog(NID_APP, "Wrong AppControl listener type.");
371                         }
372                 }
373         }
374         else
375         {
376                 SysLogException(NID_APP, E_SYSTEM, "Invalid AppControl listener.");
377         }
378
379
380         // remove from list and unload dll
381         __inAppManager.RemoveItem(reqId);
382 }
383
384
385 result
386 _AppControlManager::SendAppControlEvent(IEventArg& arg)
387 {
388         return __appControlEvent.FireAsync(arg);
389 }
390
391 Tizen::Base::Collection::IMapT<int,_AppControlResponseEvent*>*
392 _AppControlManager::GetAppControlResponseEventContainer(void)
393 {
394         return &__appControlResponseEventContainer;
395 }
396
397
398 static bool
399 IsMatchingProcListener(const _InProcessInfo& info, IEventListener* pListener)
400 {
401         return (info.pListener == pListener);
402 }
403
404
405 void
406 _AppControlManager::StopAppControlResponseListener(IAppControlResponseListener* pListener)
407 {
408         // __inAppManager, __launchManager
409         _InProcessInfo* pProcInfo = __inAppManager.FindItemWithListener(IsMatchingProcListener, pListener);
410         if (pProcInfo)
411         {
412                 __inAppManager.RemoveItem(pProcInfo);
413                 SysLog(NID_APP, "Listener 0x%x is removed from in-process stub list.", pListener);
414         }
415 }
416
417
418 // generic launch callback
419 static void
420 LaunchResultCb(bundle* b, int request_code, appsvc_result_val res, void* data)
421 {
422         SysLog(NID_APP, "SLP callee result: %d", res);
423
424         _AppControlManager* pImpl = static_cast<_AppControlManager*>(data);
425         if (pImpl == null)
426         {
427                 return;
428         }
429
430         _AppArg* pAppArg = new (std::nothrow) _AppArg;
431         SysTryReturnVoidResult(NID_APP, pAppArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] AppControl event argument creation failure.");
432
433         _AppControlEventArg* pArg = null;
434         result r = pAppArg->Construct(b);
435         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] AppControl event argument creation failure.", GetErrorMessage(r));
436
437         pArg = new (std::nothrow) _AppControlEventArg(request_code, pAppArg, res);
438         SysTryCatch(NID_APP, pArg != null, r = E_OUT_OF_MEMORY, r, "[E_OUT_OF_MEMORY] AppControl event argument creation failure.");
439
440         //_AppArg::Print(b);
441         pImpl->SendAppControlEvent(*pArg);
442
443         return;
444
445 CATCH:
446         delete pAppArg;
447 }
448
449
450 result
451 _AppControlManager::SendAppControlStartResponse(int req, const char* pValue, const char* pOp)
452 {
453         _AppControlStartEventArg* pArg = new (std::nothrow) _AppControlStartEventArg(req, AppId(pValue), String(pOp));
454         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "AppControl start event creation failure.");
455
456         SendAppControlEvent(*pArg);
457
458         return E_SUCCESS;
459 }
460
461
462 result
463 _AppControlManager::LaunchPkg(_AppMessageImpl& msg, const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
464 {
465         bundle* kb = msg.GetBundle();
466
467         if (pkg_name)
468         {
469                 appsvc_set_pkgname(kb, pkg_name);
470         }
471
472         appsvc_set_operation(kb, (op) ? op : APPSVC_OPERATION_DEFAULT);
473
474         if (mime)
475         {
476                 appsvc_set_mime(kb, mime);
477         }
478
479         if (uri)
480         {
481                 appsvc_set_uri(kb, uri);
482         }
483
484         int pid = LaunchPkg(msg, pCb, data);
485
486         result r = E_SUCCESS;
487         if (pid < 0)
488         {
489                 r = GetLastResult();
490         }
491
492         return r;
493 }
494
495
496 int
497 _AppControlManager::Launch(_AppMessageImpl& msg, const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
498 {
499         bundle* kb = msg.GetBundle();
500         SysTryReturn(NID_APP, kb != NULL, -1, E_OUT_OF_MEMORY, "Bundle allocation failure.");
501
502         if (pkg_name)
503         {
504                 appsvc_set_pkgname(kb, pkg_name);
505         }
506
507         appsvc_set_operation(kb, (op) ? op : APPSVC_OPERATION_DEFAULT);
508
509         if (mime)
510         {
511                 appsvc_set_mime(kb, mime);
512         }
513
514         if (uri)
515         {
516                 appsvc_set_uri(kb, uri);
517         }
518
519         if (_AppImpl::GetInstance() != null)
520         {
521                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
522                 _AppArg::UpdateWindowHandle(kb, handle);
523         }
524
525         SysLog(NID_APP, "MIME(%s), URI(%s).", appsvc_get_mime(kb), appsvc_get_uri(kb));
526         int pid = appsvc_run_service(kb, 0, reinterpret_cast<appsvc_res_fn>(pCb), this);
527
528         result r = E_SUCCESS;
529         if (pid < 0)
530         {
531                 switch (pid)
532                 {
533                 case APPSVC_RET_EILLACC:
534                         r = E_ILLEGAL_ACCESS;
535                         break;
536                 case APPSVC_RET_EINVAL:
537                         r = E_MAX_EXCEEDED;
538                         break;
539                 default:
540                         r = E_SYSTEM;
541                         break;
542                 }
543                 SysLog(NID_APP, "[%s]Launching service %s failure", GetErrorMessage(r), pkg_name);
544         }
545         SetLastResult(r);
546
547         return pid;
548 }
549
550
551 int
552 _AppControlManager::LaunchPkg(_AppMessageImpl& msg, AppSvcResFn pCb, void* data)
553 {
554         bundle* kb = msg.GetBundle();
555         SysTryReturn(NID_APP, kb != NULL, -1, E_OUT_OF_MEMORY, "Bundle allocation failure.");
556
557         if (_AppImpl::GetInstance() != null)
558         {
559                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
560                 _AppArg::UpdateWindowHandle(kb, handle);
561         }
562
563         int pid = appsvc_run_service(kb, 0, reinterpret_cast<appsvc_res_fn>(pCb), this);
564
565         result r = E_SUCCESS;
566         if (pid < 0)
567         {
568                 switch (pid)
569                 {
570                 case APPSVC_RET_EILLACC:
571                         r = E_ILLEGAL_ACCESS;
572                         break;
573                 case APPSVC_RET_EINVAL:
574                         r = E_MAX_EXCEEDED;
575                         break;
576                 default:
577                         r = E_SYSTEM;
578                         break;
579                 }
580                 SysLog(NID_APP, "[%s] Launching service %s failure", GetErrorMessage(r), appsvc_get_appid(kb));
581         }
582         SetLastResult(r);
583
584         return pid;
585 }
586
587
588 result
589 _AppControlManager::LaunchPkg(const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
590 {
591         _AppMessageImpl msg;
592
593         return LaunchPkg(msg, pkg_name, op, mime, uri, pCb, data);
594 }
595
596 result
597 _AppControlManager::LaunchAppWithCondition(const AppId& appId, const String& condition, IList* pArrayArgs)
598 {
599         result r = E_SUCCESS;
600         _AppArg * pArg = new (std::nothrow) _AppArg();
601         SysTryCatch(NID_APP, pArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY]");
602
603         r = pArg->ConstructForAppLaunchCondition(condition, pArrayArgs);
604         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] ConstructForAppLaunchCondition(%ls, .. ) fails", GetErrorMessage(r), condition.GetPointer());
605
606         r = _AppControlManager::LaunchApp(appId, pArg);
607 CATCH:
608         delete pArg;
609         return r;
610 }
611
612 result
613 _AppControlManager::LaunchApp(const AppId& appId, _AppArg* pArg, int req)
614 {
615         SysTryReturnResult(NID_APP, pArg != null, E_INVALID_ARG, "Invalid launch argument");
616         SysLog(NID_APP, "App: %ls.", appId.GetPointer());
617
618         String actualAppId = appId;
619         if (appId.GetLength() == 10)
620         {
621                 const String& name = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
622
623                 if (!name.IsEmpty())
624                 {
625                         actualAppId.Append(L'.');
626                         actualAppId.Append(name);
627                 }
628         }
629
630         pArg->UpdateRequestId(req);
631
632         if (_AppImpl::GetInstance() != null)
633         {
634                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
635                 pArg->UpdateWindowHandle(handle);
636         }
637
638         int pid = -1;
639         bundle* kb = NULL;
640
641         std::unique_ptr< PackageAppInfo > pAppInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(appId));
642         SysTryReturn(NID_APP, pAppInfo != null, E_SYSTEM, GetLastResult(), "[%s] Getting AppInfo failed.", GetErrorMessage(GetLastResult()));
643         _PackageAppInfoImpl* pAppInfoImpl = _PackageAppInfoImpl::GetInstance(pAppInfo.get());
644         SysTryReturnResult(NID_APP, pAppInfoImpl != null , E_SYSTEM, "Severe system error");
645
646         if (pAppInfoImpl->IsServiceApp() == false)
647         {
648                 String tempId;
649                 actualAppId.SubString(0, 10, tempId);
650                 tempId += L'.';
651                 tempId += String(SUBMODE_NAME);
652
653                 // [INFO] Ugly solution for submode support
654                 pArg->UpdateAppId(tempId);
655                 kb = pArg->GetBundle();
656
657                 pid = appsvc_run_service(kb, req, LaunchResultCb, this);
658                 if (pid >= 0)
659                 {
660                         SysLog(NID_APP, "Submode launch successful");
661                         return E_SUCCESS;
662                 }
663                 else if (pid == APPSVC_RET_EINVAL)
664                 {
665                         SysLog(NID_APP, "Argument overflow");
666                         return E_MAX_EXCEEDED;
667                 }
668         }
669
670         pArg->UpdateAppId(actualAppId);
671
672         // retry for possible failure
673         int count = 0;
674         const int TRY_COUNT = 3;
675         const int TRY_SLEEP_TIME = 65;
676         do
677         {
678                 kb = pArg->GetBundle();
679                 pid = appsvc_run_service(kb, req, LaunchResultCb, this);
680                 if (pid >= 0)
681                 {
682                         SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
683                         return E_SUCCESS;
684                 }
685                 else if (pid == APPSVC_RET_EINVAL)
686                 {
687                         SysLog(NID_APP, "Argument overflow");
688                         return E_MAX_EXCEEDED;
689                 }
690
691                 count++;
692                 SysLog(NID_APP, "Waiting %dth time.", count);
693                 Thread::Sleep(TRY_SLEEP_TIME);
694         }
695         while (count < TRY_COUNT);
696
697         result r = E_SUCCESS;
698         switch (pid)
699         {
700         case APPSVC_RET_EILLACC:
701                 r = E_ILLEGAL_ACCESS;
702                 break;
703         default:
704                 r = E_SYSTEM;
705                 break;
706         }
707
708         SysLogException(NID_APP, r, "[%s] Launching service failure for %ls", GetErrorMessage(r), appId.GetPointer());
709
710         return r;
711 }
712
713 static bool
714 _IsDefaultApplication(const AppId& packageId, const String& appId)
715 {
716         const String& execName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(packageId);
717
718         int index = -1;
719         result r = appId.IndexOf(L'.', 0, index);
720         if (r != E_SUCCESS)
721         {
722                 return false;
723         }
724
725         String tmp;
726         appId.SubString(index + 1, tmp);
727         if (tmp == execName)
728         {
729                 SysLog(NID_APP, "Default application %ls", tmp.GetPointer());
730                 return true;
731         }
732
733         return false;
734 }
735
736
737 int
738 _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, int req)
739 {
740         return Launch(appId, pArg, reinterpret_cast<AppSvcResFn>(LaunchResultCb), this, req);
741 }
742
743
744 int
745 _AppControlManager::Launch(const _AppMessageImpl& msg, AppSvcResFn pCb, void* pData, int req)
746 {
747         const bundle* pBundle = msg.GetBundle();
748
749         _AppArg arg;
750         arg.Construct(pBundle);
751
752         return Launch(_AppMessageImpl::GetApplicationId(pBundle), &arg, pCb, pData, req);
753 }
754
755
756 int
757 _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, AppSvcResFn pCb, void* pData, int req)
758 {
759         SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Invalid launch argument");
760         SysLog(NID_APP, "App: %ls.", appId.GetPointer());
761
762         String actualAppId = appId;
763
764         pArg->UpdateRequestId(req);
765
766         if (_AppImpl::GetInstance() != null)
767         {
768                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
769                 pArg->UpdateWindowHandle(handle);
770         }
771
772         int pid = -1;
773         bundle* kb = NULL;
774         String tempId;
775
776         actualAppId.SubString(0, 10, tempId);
777
778         const int type = _AppInfo::GetAppType();
779         if ((!(type & _APP_TYPE_SERVICE_APP)) && _IsDefaultApplication(tempId, appId))
780         {
781                 tempId += L'.';
782                 tempId += String(SUBMODE_NAME);
783
784                 // [INFO] Ugly solution for submode support
785                 pArg->UpdateAppId(tempId);
786                 kb = pArg->GetBundle();
787
788                 pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
789                 if (pid >= 0)
790                 {
791                         SysLog(NID_APP, "Submode launch successful");
792                         SetLastResult(E_SUCCESS);
793                         return pid;
794                 }
795                 else if (pid == APPSVC_RET_EINVAL)
796                 {
797                         SetLastResult(E_MAX_EXCEEDED);
798                         return pid;
799                 }
800         }
801
802         pArg->UpdateAppId(actualAppId);
803
804         // retry for possible failure
805         int count = 0;
806         const int TRY_COUNT = 3;
807         const int TRY_SLEEP_TIME = 65;
808         do
809         {
810                 kb = pArg->GetBundle();
811                 pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
812                 if (pid >= 0)
813                 {
814                         SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
815                         SetLastResult(E_SUCCESS);
816                         return pid;
817                 }
818                 else if (pid == APPSVC_RET_EINVAL)
819                 {
820                         SetLastResult(E_MAX_EXCEEDED);
821                         return pid;
822                 }
823
824                 count++;
825                 SysLog(NID_APP, "Waiting %dth time with %d.", count, pid);
826                 Thread::Sleep(TRY_SLEEP_TIME);
827         }
828         while (count < TRY_COUNT);
829
830         result r = E_SUCCESS;
831         switch (pid)
832         {
833         case APPSVC_RET_EILLACC:
834                 r = E_ILLEGAL_ACCESS;
835                 break;
836         default:
837                 r = E_SYSTEM;
838                 break;
839         }
840
841         SysLogException(NID_APP, r, "[%s] Launching service failure for %ls", GetErrorMessage(r), appId.GetPointer());
842
843         SetLastResult(r);
844
845         return pid;
846 }
847
848
849 void
850 _AppControlManager::FinishAppControl(int reqId, int res, IMap* pMap)
851 {
852         SysLog(NID_APP, "req %d, res %d.", reqId, res);
853         _NativeAppControlEventArg* pArg = new (std::nothrow) _NativeAppControlEventArg(reqId, res, pMap, _APPCONTROL_PROPERTY_SUBMODE);
854         SysTryReturnVoidResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Return argument allocation failure.");
855
856         SendAppControlEvent(*pArg);
857 }
858
859
860         void
861 _AppControlManager::FinishAppControl(int reqId, int res, const AppId& appId, const String& oId, IMap* pMap, int prop)
862 {
863         SysLog(NID_APP, "req %d, res %d, appId(%ls), oId(%ls).", reqId, res, appId.GetPointer(), oId.GetPointer());
864         _NativeAppControlEventArg* pArg = new (std::nothrow) _NativeAppControlEventArg(reqId, res, appId, oId, pMap, prop);
865         SysTryReturnVoidResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Return argument allocation failure.");
866
867         SendAppControlEvent(*pArg);
868 }
869
870
871 void
872 _AppControlManager::RemoveResultRequest(int reqId)
873 {
874         __resultManager.RemoveItem(reqId);
875 }
876
877 const _AppArg*
878 _AppControlManager::FindResultRequest(int reqId) const
879 {
880         const _ResultInfo* pInfo = __resultManager.FindItem(reqId);
881         return (pInfo) ? &(pInfo->arg) : null;
882 }
883
884 int
885 _AppControlManager::AddLaunchRequest(_AppArg* pArg, LaunchCbType pCb, void* pData, int prop)
886 {
887         SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Empty argument.");
888
889         _DataControlInfo* pItem = new (std::nothrow) _DataControlInfo(pArg, pCb, pData, prop);
890         SysTryReturn(NID_APP, pItem != null, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
891
892         SysLog(NID_APP, "Registering callback 0x%x, 0x%x", pCb, pData);
893
894         return __launchManager.InsertItem(pItem);
895 }
896
897 void
898 _AppControlManager::RemoveLaunchRequest(int req)
899 {
900         __launchManager.RemoveItem(req);
901 }
902
903 result
904 _AppControlManager::RegisterRequest(service_s* service, int& req, _AppHandler& handler)
905 {
906         bundle* b = _AppArg::GetBundleFromSvc(service);
907
908         _AppArg* pArg = new (std::nothrow) _AppArg();
909         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "ArrayList creation failure.");
910         pArg->Construct(b);
911
912         result r = E_SUCCESS;
913
914         // ownership is transfered to RequestManager
915         _ResultInfo* pItem = new (std::nothrow) _ResultInfo(*pArg);
916         SysTryCatch(NID_APP, pItem != null, , r = E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
917
918         req = __resultManager.InsertItem(pItem);
919         SysTryCatch(NID_APP, req != -1, , r = E_INVALID_STATE, "[E_INVALID_STATE] Invalid argument handling state.");
920
921         handler = _AppArg::GetHandler(b);
922
923         return E_SUCCESS;
924
925 CATCH:
926         delete pArg;
927
928         return r;
929 }
930
931
932 AppCtrlResult
933 _AppControlManager::ConvertAppControlResultCode(int resCode)
934 {
935         AppCtrlResult ret = APP_CTRL_RESULT_FAILED;
936
937         switch(resCode)
938         {
939                 case SERVICE_RESULT_SUCCEEDED:
940                         ret = APP_CTRL_RESULT_SUCCEEDED;
941                         break;
942                 case SERVICE_RESULT_FAILED:
943                         ret = APP_CTRL_RESULT_CANCELED;
944                         break;
945                 case SERVICE_RESULT_CANCELED:
946                         ret = APP_CTRL_RESULT_ABORTED;
947                         break;
948                 case APPSVC_OSP_RES_FAIL:
949                         ret = APP_CTRL_RESULT_FAILED;
950                         break;
951                 case APPSVC_OSP_RES_TERMINATE:
952                         ret = APP_CTRL_RESULT_TERMINATED;
953                         break;
954                 default:
955                         ret = APP_CTRL_RESULT_FAILED;
956                         break;
957         }
958
959         return ret;
960 }
961
962
963 void
964 _AppControlManager::OnAppControlResponseEventReceivedN(const Tizen::Base::Runtime::IEventArg* arg)
965 {
966         const _AppControlResponseEventArg* pEventArg = dynamic_cast<const _AppControlResponseEventArg*>(arg);
967
968         if (pEventArg != null)
969         {
970                 IAppControlResponseListener* pResponseListener = pEventArg->GetListener();
971
972                 if(pResponseListener != null)
973                 {
974                         if(pEventArg->GetType() == _APPCONTROL_RESPONSETYPE_START)
975                         {
976                                 pResponseListener->OnAppControlStartResponseReceived(pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetResult());
977                                 SysLog(NID_APP, "OnAppControlStartResponseReceived called");
978                         }
979                         else
980                         {
981                                 InvokeAppControlCompleteListener(*pResponseListener, pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetAppControlResult(), pEventArg->GetExtraData(), pEventArg->IsSubMode());
982                                 SysLog(NID_APP, "Listener called");
983
984                                 _AppControlResponseEvent* pResponseEvent = null;
985                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(pEventArg->GetRequestId(), pResponseEvent);
986                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->Remove(pEventArg->GetRequestId());
987
988                                 delete pResponseEvent;
989                                 SysLog(NID_APP, "pResponseEvent gets deleted, reqId(%d)", pEventArg->GetRequestId());
990                         }
991                 }
992                 else
993                 {
994                         SysLog(NID_APP, "Invalid ResponseListener");
995                 }
996         }
997         else
998         {
999                 SysLog(NID_APP, "Invalid AppControl arguments : arg(0x%x)", &arg);
1000         }
1001 }
1002
1003 }} // Tizen::App