Revert "Fix intApp TC failure"
[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::LaunchApp(const AppId& appId, _AppArg* pArg, int req)
590 {
591         SysTryReturnResult(NID_APP, pArg != null, E_INVALID_ARG, "Invalid launch argument");
592         SysLog(NID_APP, "App: %ls.", appId.GetPointer());
593
594         String actualAppId = appId;
595 #if 0
596         // This logic is only for very old legacy code to support "pkgid" launch and should be removed
597         if (appId.GetLength() == 10)
598         {
599                 const String& name = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
600
601                 if (!name.IsEmpty())
602                 {
603                         actualAppId.Append(L'.');
604                         actualAppId.Append(name);
605                 }
606         }
607 #endif
608
609         pArg->UpdateRequestId(req);
610
611         if (_AppImpl::GetInstance() != null)
612         {
613                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
614                 pArg->UpdateWindowHandle(handle);
615         }
616
617         int pid = -1;
618         bundle* kb = NULL;
619
620         std::unique_ptr< PackageAppInfo > pAppInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(appId));
621         SysTryReturn(NID_APP, pAppInfo != null, E_SYSTEM, GetLastResult(), "[%s] Getting AppInfo failed.", GetErrorMessage(GetLastResult()));
622         _PackageAppInfoImpl* pAppInfoImpl = _PackageAppInfoImpl::GetInstance(pAppInfo.get());
623         SysTryReturnResult(NID_APP, pAppInfoImpl != null , E_SYSTEM, "Severe system error");
624
625         if (pAppInfoImpl->IsServiceApp() == false)
626         {
627                 String tempId;
628                 actualAppId.SubString(0, 10, tempId);
629                 tempId += L'.';
630                 tempId += String(SUBMODE_NAME);
631
632                 // [INFO] Ugly solution for submode support
633                 pArg->UpdateAppId(tempId);
634                 kb = pArg->GetBundle();
635
636                 pid = appsvc_run_service(kb, req, LaunchResultCb, this);
637                 if (pid >= 0)
638                 {
639                         SysLog(NID_APP, "Submode launch successful");
640                         return E_SUCCESS;
641                 }
642                 else if (pid == APPSVC_RET_EINVAL)
643                 {
644                         SysLog(NID_APP, "Argument overflow");
645                         return E_MAX_EXCEEDED;
646                 }
647         }
648
649         pArg->UpdateAppId(actualAppId);
650
651         // retry for possible failure
652         int count = 0;
653         const int TRY_COUNT = 3;
654         const int TRY_SLEEP_TIME = 65;
655         do
656         {
657                 kb = pArg->GetBundle();
658                 pid = appsvc_run_service(kb, req, LaunchResultCb, this);
659                 if (pid >= 0)
660                 {
661                         SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
662                         return E_SUCCESS;
663                 }
664                 else if (pid == APPSVC_RET_EINVAL)
665                 {
666                         SysLog(NID_APP, "Argument overflow");
667                         return E_MAX_EXCEEDED;
668                 }
669
670                 count++;
671                 SysLog(NID_APP, "Waiting %dth time.", count);
672                 Thread::Sleep(TRY_SLEEP_TIME);
673         }
674         while (count < TRY_COUNT);
675
676         result r = E_SUCCESS;
677         switch (pid)
678         {
679         case APPSVC_RET_EILLACC:
680                 r = E_ILLEGAL_ACCESS;
681                 break;
682         default:
683                 r = E_SYSTEM;
684                 break;
685         }
686
687         SysLogException(NID_APP, r, "[%s] Launching service failure for %ls", GetErrorMessage(r), appId.GetPointer());
688
689         return r;
690 }
691
692 static bool
693 _IsDefaultApplication(const AppId& packageId, const String& appId)
694 {
695         const String& execName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(packageId);
696
697         int index = -1;
698         result r = appId.IndexOf(L'.', 0, index);
699         if (r != E_SUCCESS)
700         {
701                 return false;
702         }
703
704         String tmp;
705         appId.SubString(index + 1, tmp);
706         if (tmp == execName)
707         {
708                 SysLog(NID_APP, "Default application %ls", tmp.GetPointer());
709                 return true;
710         }
711
712         return false;
713 }
714
715
716 int
717 _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, int req)
718 {
719         return Launch(appId, pArg, reinterpret_cast<AppSvcResFn>(LaunchResultCb), this, req);
720 }
721
722
723 int
724 _AppControlManager::Launch(const _AppMessageImpl& msg, AppSvcResFn pCb, void* pData, int req)
725 {
726         const bundle* pBundle = msg.GetBundle();
727
728         _AppArg arg;
729         arg.Construct(pBundle);
730
731         return Launch(_AppMessageImpl::GetApplicationId(pBundle), &arg, pCb, pData, req);
732 }
733
734
735 int
736 _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, AppSvcResFn pCb, void* pData, int req)
737 {
738         SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Invalid launch argument");
739         SysLog(NID_APP, "App: %ls.", appId.GetPointer());
740
741         String actualAppId = appId;
742
743         pArg->UpdateRequestId(req);
744
745         if (_AppImpl::GetInstance() != null)
746         {
747                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
748                 pArg->UpdateWindowHandle(handle);
749         }
750
751         int pid = -1;
752         bundle* kb = NULL;
753         String tempId;
754
755         actualAppId.SubString(0, 10, tempId);
756
757         const int type = _AppInfo::GetAppType();
758         if ((!(type & _APP_TYPE_SERVICE_APP)) && _IsDefaultApplication(tempId, appId))
759         {
760                 tempId += L'.';
761                 tempId += String(SUBMODE_NAME);
762
763                 // [INFO] Ugly solution for submode support
764                 pArg->UpdateAppId(tempId);
765                 kb = pArg->GetBundle();
766
767                 pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
768                 if (pid >= 0)
769                 {
770                         SysLog(NID_APP, "Submode launch successful");
771                         SetLastResult(E_SUCCESS);
772                         return pid;
773                 }
774                 else if (pid == APPSVC_RET_EINVAL)
775                 {
776                         SetLastResult(E_MAX_EXCEEDED);
777                         return pid;
778                 }
779         }
780
781         pArg->UpdateAppId(actualAppId);
782
783         // retry for possible failure
784         int count = 0;
785         const int TRY_COUNT = 3;
786         const int TRY_SLEEP_TIME = 65;
787         do
788         {
789                 kb = pArg->GetBundle();
790                 pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
791                 if (pid >= 0)
792                 {
793                         SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
794                         SetLastResult(E_SUCCESS);
795                         return pid;
796                 }
797                 else if (pid == APPSVC_RET_EINVAL)
798                 {
799                         SetLastResult(E_MAX_EXCEEDED);
800                         return pid;
801                 }
802
803                 count++;
804                 SysLog(NID_APP, "Waiting %dth time with %d.", count, pid);
805                 Thread::Sleep(TRY_SLEEP_TIME);
806         }
807         while (count < TRY_COUNT);
808
809         result r = E_SUCCESS;
810         switch (pid)
811         {
812         case APPSVC_RET_EILLACC:
813                 r = E_ILLEGAL_ACCESS;
814                 break;
815         default:
816                 r = E_SYSTEM;
817                 break;
818         }
819
820         SysLogException(NID_APP, r, "[%s] Launching service failure for %ls", GetErrorMessage(r), appId.GetPointer());
821
822         SetLastResult(r);
823
824         return pid;
825 }
826
827
828 void
829 _AppControlManager::FinishAppControl(int reqId, int res, IMap* pMap)
830 {
831         SysLog(NID_APP, "req %d, res %d.", reqId, res);
832         _NativeAppControlEventArg* pArg = new (std::nothrow) _NativeAppControlEventArg(reqId, res, pMap, _APPCONTROL_PROPERTY_SUBMODE);
833         SysTryReturnVoidResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Return argument allocation failure.");
834
835         SendAppControlEvent(*pArg);
836 }
837
838
839         void
840 _AppControlManager::FinishAppControl(int reqId, int res, const AppId& appId, const String& oId, IMap* pMap, int prop)
841 {
842         SysLog(NID_APP, "req %d, res %d, appId(%ls), oId(%ls).", reqId, res, appId.GetPointer(), oId.GetPointer());
843         _NativeAppControlEventArg* pArg = new (std::nothrow) _NativeAppControlEventArg(reqId, res, appId, oId, pMap, prop);
844         SysTryReturnVoidResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Return argument allocation failure.");
845
846         SendAppControlEvent(*pArg);
847 }
848
849
850 void
851 _AppControlManager::RemoveResultRequest(int reqId)
852 {
853         __resultManager.RemoveItem(reqId);
854 }
855
856 const _AppArg*
857 _AppControlManager::FindResultRequest(int reqId) const
858 {
859         const _ResultInfo* pInfo = __resultManager.FindItem(reqId);
860         return (pInfo) ? &(pInfo->arg) : null;
861 }
862
863 int
864 _AppControlManager::AddLaunchRequest(_AppArg* pArg, LaunchCbType pCb, void* pData, int prop)
865 {
866         SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Empty argument.");
867
868         _DataControlInfo* pItem = new (std::nothrow) _DataControlInfo(pArg, pCb, pData, prop);
869         SysTryReturn(NID_APP, pItem != null, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
870
871         SysLog(NID_APP, "Registering callback 0x%x, 0x%x", pCb, pData);
872
873         return __launchManager.InsertItem(pItem);
874 }
875
876 void
877 _AppControlManager::RemoveLaunchRequest(int req)
878 {
879         __launchManager.RemoveItem(req);
880 }
881
882 result
883 _AppControlManager::RegisterRequest(service_s* service, int& req, _AppHandler& handler)
884 {
885         bundle* b = _AppArg::GetBundleFromSvc(service);
886
887         _AppArg* pArg = new (std::nothrow) _AppArg();
888         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "ArrayList creation failure.");
889         pArg->Construct(b);
890
891         result r = E_SUCCESS;
892
893         // ownership is transfered to RequestManager
894         _ResultInfo* pItem = new (std::nothrow) _ResultInfo(*pArg);
895         SysTryCatch(NID_APP, pItem != null, , r = E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
896
897         req = __resultManager.InsertItem(pItem);
898         SysTryCatch(NID_APP, req != -1, , r = E_INVALID_STATE, "[E_INVALID_STATE] Invalid argument handling state.");
899
900         handler = _AppArg::GetHandler(b);
901
902         return E_SUCCESS;
903
904 CATCH:
905         delete pArg;
906
907         return r;
908 }
909
910
911 AppCtrlResult
912 _AppControlManager::ConvertAppControlResultCode(int resCode)
913 {
914         AppCtrlResult ret = APP_CTRL_RESULT_FAILED;
915
916         switch(resCode)
917         {
918                 case SERVICE_RESULT_SUCCEEDED:
919                         ret = APP_CTRL_RESULT_SUCCEEDED;
920                         break;
921                 case SERVICE_RESULT_FAILED:
922                         ret = APP_CTRL_RESULT_CANCELED;
923                         break;
924                 case SERVICE_RESULT_CANCELED:
925                         ret = APP_CTRL_RESULT_ABORTED;
926                         break;
927                 case APPSVC_OSP_RES_FAIL:
928                         ret = APP_CTRL_RESULT_FAILED;
929                         break;
930                 case APPSVC_OSP_RES_TERMINATE:
931                         ret = APP_CTRL_RESULT_TERMINATED;
932                         break;
933                 default:
934                         ret = APP_CTRL_RESULT_FAILED;
935                         break;
936         }
937
938         return ret;
939 }
940
941
942 void
943 _AppControlManager::OnAppControlResponseEventReceivedN(const Tizen::Base::Runtime::IEventArg* arg)
944 {
945         const _AppControlResponseEventArg* pEventArg = dynamic_cast<const _AppControlResponseEventArg*>(arg);
946
947         if (pEventArg != null)
948         {
949                 IAppControlResponseListener* pResponseListener = pEventArg->GetListener();
950
951                 if(pResponseListener != null)
952                 {
953                         if(pEventArg->GetType() == _APPCONTROL_RESPONSETYPE_START)
954                         {
955                                 pResponseListener->OnAppControlStartResponseReceived(pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetResult());
956                                 SysLog(NID_APP, "OnAppControlStartResponseReceived called");
957                         }
958                         else
959                         {
960                                 InvokeAppControlCompleteListener(*pResponseListener, pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetAppControlResult(), pEventArg->GetExtraData(), pEventArg->IsSubMode());
961                                 SysLog(NID_APP, "Listener called");
962
963                                 _AppControlResponseEvent* pResponseEvent = null;
964                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(pEventArg->GetRequestId(), pResponseEvent);
965                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->Remove(pEventArg->GetRequestId());
966
967                                 delete pResponseEvent;
968                                 SysLog(NID_APP, "pResponseEvent gets deleted, reqId(%d)", pEventArg->GetRequestId());
969                         }
970                 }
971                 else
972                 {
973                         SysLog(NID_APP, "Invalid ResponseListener");
974                 }
975         }
976         else
977         {
978                 SysLog(NID_APP, "Invalid AppControl arguments : arg(0x%x)", &arg);
979         }
980 }
981
982 }} // Tizen::App