ee295bf7848d62a09188f1f4c5c06abc564966f6
[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         IAppControlResponseListener* pListener = dynamic_cast<IAppControlResponseListener*>(pInfo->pListener);
217         if (pListener == null)
218         {
219                 SysLog(NID_APP, "Empty AppControl listener callback for req %d, app %ls.", reqId, appId.GetPointer());
220                 return;
221         }
222
223         result r = E_SUCCESS;
224
225         AppId actualAppId = appId;
226         if (appId == L'c')
227         {
228                 actualAppId.Clear();
229                 r = E_OPERATION_CANCELED;
230         }
231         SysLog(NID_APP, "Invoking callback 0x%x.", pListener);
232
233         _AppControlResponseEvent* pResponseEvent = null;
234         __appControlResponseEventContainer.GetValue(reqId, pResponseEvent);
235         SysLog(NID_APP, "StartResponseReceived Request Id(%d), ResponseEvent 0x%x.", reqId, pResponseEvent);
236         if (pResponseEvent != null)
237         {
238                 String oId(operationId);
239                 _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_START, actualAppId, oId, r, APP_CTRL_RESULT_SUCCEEDED, null, reqId, false);
240
241                 if (pResponseEventArg != null)
242                 {
243                         pResponseEvent->Fire(*pResponseEventArg);
244                         SysLog(NID_APP, "pResponseEvent is Fired");
245                 }
246         }
247         else
248         {
249                 pListener->OnAppControlStartResponseReceived(actualAppId, operationId, r);
250                 SysLog(NID_APP, "OnAppControlStartResponseReceived called directly");
251         }
252
253         if (r == E_OPERATION_CANCELED)
254         {
255                 SysLog(NID_APP, "Removed start listener as operation is canceled.");
256                 __inAppManager.RemoveItem(reqId);
257         }
258 }
259
260
261 void
262 _AppControlManager::InvokeAppControlCompleteListener(IAppControlResponseListener& listener, const AppId& appId, const String& op, AppCtrlResult res, const IMap* pExtraData, bool noRaise)
263 {
264         listener.OnAppControlCompleteResponseReceived(appId, op, res, pExtraData);
265
266         if (!noRaise)
267         {
268                 _AppImpl::GetInstance()->SendUserEvent(_APP_EVENT_RAISE, null, false);
269         }
270
271         SysLog(NID_APP, "AppControl response finished.");
272 }
273
274
275 void
276 _AppControlManager::InvokeLegacyAppControlCompleteListener(IAppControlEventListener& listener, const AppId& appId, const String& op, const IList* pList, bool noRaise)
277 {
278         listener.OnAppControlCompleted(appId, op, pList);
279
280         if (!noRaise)
281         {
282                 _AppImpl::GetInstance()->SendUserEvent(_APP_EVENT_RAISE, null, false);
283         }
284
285         SysLog(NID_APP, "Legacy AppControl response finished.");
286 }
287
288
289 // callback for in-process event handling
290 void
291 _AppControlManager::OnAppControlPluginEventReceivedN(int reqId, int res, const AppId& optAppId, const String& optOperation, const IMap* pArgs, int property)
292 {
293         SysLog(NID_APP, "Received request Id %d, res %d, args 0x%x", reqId, res, pArgs);
294
295         // process proper callback
296         _InProcessInfo* pInfo = __inAppManager.FindItem(reqId);
297         SysTryReturnVoidResult(NID_APP, pInfo != null, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] request Id %d not found with args 0x%x", reqId,
298                                         pArgs);
299
300         if (pInfo->pListener)
301         {
302                 String aId;
303                 String oId;
304
305                 if (optAppId.IsEmpty())
306                 {
307                         aId = pInfo->providerId;
308                         oId = pInfo->operationId;
309                 }
310                 else
311                 {
312                         // implicit launch only
313                         aId = optAppId;
314                         oId = optOperation;
315
316                         SysLog(NID_APP, "Changing appId/operation for implicit launch.");
317                 }
318
319                 SysLog(NID_APP, "Invoking callback 0x%x for (%ls, %ls).", pInfo->pListener, aId.GetPointer(), oId.GetPointer());
320
321                 const bool isSubMode = (property & _APPCONTROL_PROPERTY_SUBMODE);
322                 const bool isServiceCallee = (property & _APPCONTROL_PROPERTY_SERVICE_CALLEE);
323
324                 if (pInfo->isLegacy)
325                 {
326                         IAppControlEventListener* pListener = dynamic_cast<IAppControlEventListener*>(pInfo->pListener);
327                         if (pListener)
328                         {
329                                 ArrayList list(SingleObjectDeleter);
330                                 _AppArg::FillLegacyAppControlResult(list, res, pArgs, aId);
331
332                                 InvokeLegacyAppControlCompleteListener(*pListener, aId, oId, &list, isSubMode | isServiceCallee);
333                         }
334                         else
335                         {
336                                 SysLog(NID_APP, "Wrong AppControl listener type.");
337                         }
338                 }
339                 else
340                 {
341                         IAppControlResponseListener* pListener = dynamic_cast<IAppControlResponseListener*>(pInfo->pListener);
342                         if (pListener)
343                         {
344                                 _AppControlResponseEvent* pResponseEvent = null;
345                                 int responseEventRequestId = RESPONSE_EVENT_REQID_MAGIC + reqId;
346                                 __appControlResponseEventContainer.GetValue(responseEventRequestId, pResponseEvent);
347
348                                 if (pResponseEvent != null)
349                                 {
350                                         _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_COMPLETE, aId, oId, E_SUCCESS, static_cast<AppCtrlResult>(res), const_cast<IMap*> (pArgs), responseEventRequestId, isSubMode);
351                                         if (pResponseEventArg != null)
352                                         {
353                                                 pResponseEvent->Fire(*pResponseEventArg);
354                                                 SysLog(NID_APP, "pResponseEvent is Fired");
355                                         }
356                                 }
357                                 else
358                                 {
359                                         InvokeAppControlCompleteListener(*pListener, aId, oId, ConvertAppControlResultCode(res), pArgs, isSubMode | isServiceCallee);
360                                         SysLog(NID_APP, "Listener called directly");
361                                         delete pArgs;
362                                 }
363                         }
364                         else
365                         {
366                                 SysLog(NID_APP, "Wrong AppControl listener type.");
367                         }
368                 }
369         }
370         else
371         {
372                 SysLog(NID_APP, "Empty AppControl listener.");
373         }
374
375
376         // remove from list and unload dll
377         __inAppManager.RemoveItem(reqId);
378 }
379
380
381 result
382 _AppControlManager::SendAppControlEvent(IEventArg& arg)
383 {
384         return __appControlEvent.FireAsync(arg);
385 }
386
387 Tizen::Base::Collection::IMapT<int,_AppControlResponseEvent*>*
388 _AppControlManager::GetAppControlResponseEventContainer(void)
389 {
390         return &__appControlResponseEventContainer;
391 }
392
393
394 static bool
395 IsMatchingProcListener(const _InProcessInfo& info, IEventListener* pListener)
396 {
397         return (info.pListener == pListener);
398 }
399
400
401 void
402 _AppControlManager::StopAppControlResponseListener(IAppControlResponseListener* pListener)
403 {
404         // __inAppManager, __launchManager
405         _InProcessInfo* pProcInfo = __inAppManager.FindItemWithListener(IsMatchingProcListener, pListener);
406         if (pProcInfo)
407         {
408                 pProcInfo->pListener = null;
409                 SysLog(NID_APP, "Listener 0x%x is removed from in-process stub list.", pListener);
410         }
411 }
412
413
414 // generic launch callback
415 static void
416 LaunchResultCb(bundle* b, int request_code, appsvc_result_val res, void* data)
417 {
418         SysLog(NID_APP, "SLP callee result: %d", res);
419
420         _AppControlManager* pImpl = static_cast<_AppControlManager*>(data);
421         if (pImpl == null)
422         {
423                 return;
424         }
425
426         _AppArg* pAppArg = new (std::nothrow) _AppArg;
427         SysTryReturnVoidResult(NID_APP, pAppArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] AppControl event argument creation failure.");
428
429         _AppControlEventArg* pArg = null;
430         result r = pAppArg->Construct(b);
431         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] AppControl event argument creation failure.", GetErrorMessage(r));
432
433         pArg = new (std::nothrow) _AppControlEventArg(request_code, pAppArg, res);
434         SysTryCatch(NID_APP, pArg != null, r = E_OUT_OF_MEMORY, r, "[E_OUT_OF_MEMORY] AppControl event argument creation failure.");
435
436         //_AppArg::Print(b);
437         pImpl->SendAppControlEvent(*pArg);
438
439         return;
440
441 CATCH:
442         delete pAppArg;
443 }
444
445
446 result
447 _AppControlManager::SendAppControlStartResponse(int req, const char* pValue, const char* pOp)
448 {
449         _AppControlStartEventArg* pArg = new (std::nothrow) _AppControlStartEventArg(req, AppId(pValue), String(pOp));
450         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "AppControl start event creation failure.");
451
452         SendAppControlEvent(*pArg);
453
454         return E_SUCCESS;
455 }
456
457
458 result
459 _AppControlManager::LaunchPkg(_AppMessageImpl& msg, const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
460 {
461         bundle* kb = msg.GetBundle();
462
463         if (pkg_name)
464         {
465                 appsvc_set_pkgname(kb, pkg_name);
466         }
467
468         appsvc_set_operation(kb, (op) ? op : APPSVC_OPERATION_DEFAULT);
469
470         if (mime)
471         {
472                 appsvc_set_mime(kb, mime);
473         }
474
475         if (uri)
476         {
477                 appsvc_set_uri(kb, uri);
478         }
479
480         int pid = LaunchPkg(msg, pCb, data);
481
482         result r = E_SUCCESS;
483         if (pid < 0)
484         {
485                 r = GetLastResult();
486         }
487
488         return r;
489 }
490
491
492 int
493 _AppControlManager::Launch(_AppMessageImpl& msg, const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
494 {
495         bundle* kb = msg.GetBundle();
496         SysTryReturn(NID_APP, kb != NULL, -1, E_OUT_OF_MEMORY, "Bundle allocation failure.");
497
498         if (pkg_name)
499         {
500                 appsvc_set_pkgname(kb, pkg_name);
501         }
502
503         appsvc_set_operation(kb, (op) ? op : APPSVC_OPERATION_DEFAULT);
504
505         if (mime)
506         {
507                 appsvc_set_mime(kb, mime);
508         }
509
510         if (uri)
511         {
512                 appsvc_set_uri(kb, uri);
513         }
514
515         if (_AppImpl::GetInstance() != null)
516         {
517                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
518                 _AppArg::UpdateWindowHandle(kb, handle);
519         }
520
521         SysLog(NID_APP, "MIME(%s), URI(%s).", appsvc_get_mime(kb), appsvc_get_uri(kb));
522         int pid = appsvc_run_service(kb, 0, reinterpret_cast<appsvc_res_fn>(pCb), this);
523
524         result r = E_SUCCESS;
525         if (pid < 0)
526         {
527                 switch (pid)
528                 {
529                 case APPSVC_RET_EILLACC:
530                         r = E_ILLEGAL_ACCESS;
531                         break;
532                 case APPSVC_RET_EINVAL:
533                         r = E_MAX_EXCEEDED;
534                         break;
535                 default:
536                         r = E_SYSTEM;
537                         break;
538                 }
539                 SysLog(NID_APP, "[%s]Launching service %s failure", GetErrorMessage(r), pkg_name);
540         }
541         SetLastResult(r);
542
543         return pid;
544 }
545
546
547 int
548 _AppControlManager::LaunchPkg(_AppMessageImpl& msg, AppSvcResFn pCb, void* data)
549 {
550         bundle* kb = msg.GetBundle();
551         SysTryReturn(NID_APP, kb != NULL, -1, E_OUT_OF_MEMORY, "Bundle allocation failure.");
552
553         if (_AppImpl::GetInstance() != null)
554         {
555                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
556                 _AppArg::UpdateWindowHandle(kb, handle);
557         }
558
559         int pid = appsvc_run_service(kb, 0, reinterpret_cast<appsvc_res_fn>(pCb), this);
560
561         result r = E_SUCCESS;
562         if (pid < 0)
563         {
564                 switch (pid)
565                 {
566                 case APPSVC_RET_EILLACC:
567                         r = E_ILLEGAL_ACCESS;
568                         break;
569                 case APPSVC_RET_EINVAL:
570                         r = E_MAX_EXCEEDED;
571                         break;
572                 default:
573                         r = E_SYSTEM;
574                         break;
575                 }
576                 SysLog(NID_APP, "[%s] Launching service %s failure", GetErrorMessage(r), appsvc_get_appid(kb));
577         }
578         SetLastResult(r);
579
580         return pid;
581 }
582
583
584 result
585 _AppControlManager::LaunchPkg(const char* pkg_name, const char* op, const char* mime, const char* uri, AppSvcResFn pCb, void* data)
586 {
587         _AppMessageImpl msg;
588
589         return LaunchPkg(msg, pkg_name, op, mime, uri, pCb, data);
590 }
591
592 result
593 _AppControlManager::LaunchAppWithCondition(const AppId& appId, const String& condition, IList* pArrayArgs)
594 {
595         result r = E_SUCCESS;
596         _AppArg * pArg = new (std::nothrow) _AppArg();
597         SysTryCatch(NID_APP, pArg != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY]");
598
599         r = pArg->ConstructForAppLaunchCondition(condition, pArrayArgs);
600         SysTryCatch(NID_APP, !IsFailed(r), , r, "[%s] ConstructForAppLaunchCondition(%ls, .. ) fails", GetErrorMessage(r), condition.GetPointer());
601
602         r = _AppControlManager::LaunchApp(appId, pArg);
603 CATCH:
604         delete pArg;
605         return r;
606 }
607
608 result
609 _AppControlManager::LaunchApp(const AppId& appId, _AppArg* pArg, int req)
610 {
611         SysTryReturnResult(NID_APP, pArg != null, E_INVALID_ARG, "Invalid launch argument");
612         SysLog(NID_APP, "App: %ls.", appId.GetPointer());
613
614         String actualAppId = appId;
615         if (appId.GetLength() == 10)
616         {
617                 const String& name = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
618
619                 if (!name.IsEmpty())
620                 {
621                         actualAppId.Append(L'.');
622                         actualAppId.Append(name);
623                 }
624         }
625
626         pArg->UpdateRequestId(req);
627
628         if (_AppImpl::GetInstance() != null)
629         {
630                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
631                 pArg->UpdateWindowHandle(handle);
632         }
633
634         int pid = -1;
635         bundle* kb = NULL;
636
637         std::unique_ptr< PackageAppInfo > pAppInfo(_PackageManagerImpl::GetInstance()->GetPackageAppInfoN(appId));
638         SysTryReturn(NID_APP, pAppInfo != null, E_SYSTEM, GetLastResult(), "[%s] Getting AppInfo failed.", GetErrorMessage(GetLastResult()));
639         _PackageAppInfoImpl* pAppInfoImpl = _PackageAppInfoImpl::GetInstance(pAppInfo.get());
640         SysTryReturnResult(NID_APP, pAppInfoImpl != null , E_SYSTEM, "Severe system error");
641
642         if (pAppInfoImpl->IsServiceApp() == false)
643         {
644                 String tempId;
645                 actualAppId.SubString(0, 10, tempId);
646                 tempId += L'.';
647                 tempId += String(SUBMODE_NAME);
648
649                 // [INFO] Ugly solution for submode support
650                 pArg->UpdateAppId(tempId);
651                 kb = pArg->GetBundle();
652
653                 pid = appsvc_run_service(kb, req, LaunchResultCb, this);
654                 if (pid >= 0)
655                 {
656                         SysLog(NID_APP, "Submode launch successful");
657                         return E_SUCCESS;
658                 }
659                 else if (pid == APPSVC_RET_EINVAL)
660                 {
661                         SysLog(NID_APP, "Argument overflow");
662                         return E_MAX_EXCEEDED;
663                 }
664         }
665
666         pArg->UpdateAppId(actualAppId);
667
668         // retry for possible failure
669         int count = 0;
670         const int TRY_COUNT = 3;
671         const int TRY_SLEEP_TIME = 65;
672         do
673         {
674                 kb = pArg->GetBundle();
675                 pid = appsvc_run_service(kb, req, LaunchResultCb, this);
676                 if (pid >= 0)
677                 {
678                         SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
679                         return E_SUCCESS;
680                 }
681                 else if (pid == APPSVC_RET_EINVAL)
682                 {
683                         SysLog(NID_APP, "Argument overflow");
684                         return E_MAX_EXCEEDED;
685                 }
686
687                 count++;
688                 SysLog(NID_APP, "Waiting %dth time.", count);
689                 Thread::Sleep(TRY_SLEEP_TIME);
690         }
691         while (count < TRY_COUNT);
692
693         result r = E_SUCCESS;
694         switch (pid)
695         {
696         case APPSVC_RET_EILLACC:
697                 r = E_ILLEGAL_ACCESS;
698                 break;
699         default:
700                 r = E_SYSTEM;
701                 break;
702         }
703
704         SysLogException(NID_APP, r, "[%s] Launching service failure for %ls", GetErrorMessage(r), appId.GetPointer());
705
706         return r;
707 }
708
709 static bool
710 _IsDefaultApplication(const AppId& packageId, const String& appId)
711 {
712         const String& execName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(packageId);
713
714         int index = -1;
715         result r = appId.IndexOf(L'.', 0, index);
716         if (r != E_SUCCESS)
717         {
718                 return false;
719         }
720
721         String tmp;
722         appId.SubString(index + 1, tmp);
723         if (tmp == execName)
724         {
725                 SysLog(NID_APP, "Default application %ls", tmp.GetPointer());
726                 return true;
727         }
728
729         return false;
730 }
731
732
733 int
734 _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, int req)
735 {
736         return Launch(appId, pArg, reinterpret_cast<AppSvcResFn>(LaunchResultCb), this, req);
737 }
738
739
740 int
741 _AppControlManager::Launch(const _AppMessageImpl& msg, AppSvcResFn pCb, void* pData, int req)
742 {
743         const bundle* pBundle = msg.GetBundle();
744
745         _AppArg arg;
746         arg.Construct(pBundle);
747
748         return Launch(_AppMessageImpl::GetApplicationId(pBundle), &arg, pCb, pData, req);
749 }
750
751
752 int
753 _AppControlManager::Launch(const AppId& appId, _AppArg* pArg, AppSvcResFn pCb, void* pData, int req)
754 {
755         SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Invalid launch argument");
756         SysLog(NID_APP, "App: %ls.", appId.GetPointer());
757
758         String actualAppId = appId;
759
760         pArg->UpdateRequestId(req);
761
762         if (_AppImpl::GetInstance() != null)
763         {
764                 const long handle = _AppImpl::GetInstance()->GetWindowHandle();
765                 pArg->UpdateWindowHandle(handle);
766         }
767
768         int pid = -1;
769         bundle* kb = NULL;
770         String tempId;
771
772         actualAppId.SubString(0, 10, tempId);
773
774         const int type = _AppInfo::GetAppType();
775         if ((!(type & _APP_TYPE_SERVICE_APP)) && _IsDefaultApplication(tempId, appId))
776         {
777                 tempId += L'.';
778                 tempId += String(SUBMODE_NAME);
779
780                 // [INFO] Ugly solution for submode support
781                 pArg->UpdateAppId(tempId);
782                 kb = pArg->GetBundle();
783
784                 pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
785                 if (pid >= 0)
786                 {
787                         SysLog(NID_APP, "Submode launch successful");
788                         SetLastResult(E_SUCCESS);
789                         return pid;
790                 }
791                 else if (pid == APPSVC_RET_EINVAL)
792                 {
793                         SetLastResult(E_MAX_EXCEEDED);
794                         return pid;
795                 }
796         }
797
798         pArg->UpdateAppId(actualAppId);
799
800         // retry for possible failure
801         int count = 0;
802         const int TRY_COUNT = 3;
803         const int TRY_SLEEP_TIME = 65;
804         do
805         {
806                 kb = pArg->GetBundle();
807                 pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
808                 if (pid >= 0)
809                 {
810                         SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
811                         SetLastResult(E_SUCCESS);
812                         return pid;
813                 }
814                 else if (pid == APPSVC_RET_EINVAL)
815                 {
816                         SetLastResult(E_MAX_EXCEEDED);
817                         return pid;
818                 }
819
820                 count++;
821                 SysLog(NID_APP, "Waiting %dth time with %d.", count, pid);
822                 Thread::Sleep(TRY_SLEEP_TIME);
823         }
824         while (count < TRY_COUNT);
825
826         result r = E_SUCCESS;
827         switch (pid)
828         {
829         case APPSVC_RET_EILLACC:
830                 r = E_ILLEGAL_ACCESS;
831                 break;
832         default:
833                 r = E_SYSTEM;
834                 break;
835         }
836
837         SysLogException(NID_APP, r, "[%s] Launching service failure for %ls", GetErrorMessage(r), appId.GetPointer());
838
839         SetLastResult(r);
840
841         return pid;
842 }
843
844
845 void
846 _AppControlManager::FinishAppControl(int reqId, int res, IMap* pMap)
847 {
848         SysLog(NID_APP, "req %d, res %d.", reqId, res);
849         _NativeAppControlEventArg* pArg = new (std::nothrow) _NativeAppControlEventArg(reqId, res, pMap, _APPCONTROL_PROPERTY_SUBMODE);
850         SysTryReturnVoidResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Return argument allocation failure.");
851
852         SendAppControlEvent(*pArg);
853 }
854
855
856         void
857 _AppControlManager::FinishAppControl(int reqId, int res, const AppId& appId, const String& oId, IMap* pMap, int prop)
858 {
859         SysLog(NID_APP, "req %d, res %d, appId(%ls), oId(%ls).", reqId, res, appId.GetPointer(), oId.GetPointer());
860         _NativeAppControlEventArg* pArg = new (std::nothrow) _NativeAppControlEventArg(reqId, res, appId, oId, pMap, prop);
861         SysTryReturnVoidResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Return argument allocation failure.");
862
863         SendAppControlEvent(*pArg);
864 }
865
866
867 void
868 _AppControlManager::RemoveResultRequest(int reqId)
869 {
870         __resultManager.RemoveItem(reqId);
871 }
872
873 const _AppArg*
874 _AppControlManager::FindResultRequest(int reqId) const
875 {
876         const _ResultInfo* pInfo = __resultManager.FindItem(reqId);
877         return (pInfo) ? &(pInfo->arg) : null;
878 }
879
880 int
881 _AppControlManager::AddLaunchRequest(_AppArg* pArg, LaunchCbType pCb, void* pData, int prop)
882 {
883         SysTryReturn(NID_APP, pArg != null, -1, E_INVALID_ARG, "[E_INVALID_ARG] Empty argument.");
884
885         _DataControlInfo* pItem = new (std::nothrow) _DataControlInfo(pArg, pCb, pData, prop);
886         SysTryReturn(NID_APP, pItem != null, -1, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
887
888         SysLog(NID_APP, "Registering callback 0x%x, 0x%x", pCb, pData);
889
890         return __launchManager.InsertItem(pItem);
891 }
892
893 void
894 _AppControlManager::RemoveLaunchRequest(int req)
895 {
896         __launchManager.RemoveItem(req);
897 }
898
899 result
900 _AppControlManager::RegisterRequest(service_s* service, int& req, _AppHandler& handler)
901 {
902         bundle* b = _AppArg::GetBundleFromSvc(service);
903
904         _AppArg* pArg = new (std::nothrow) _AppArg();
905         SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "ArrayList creation failure.");
906         pArg->Construct(b);
907
908         result r = E_SUCCESS;
909
910         // ownership is transfered to RequestManager
911         _ResultInfo* pItem = new (std::nothrow) _ResultInfo(*pArg);
912         SysTryCatch(NID_APP, pItem != null, , r = E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Empty argument.");
913
914         req = __resultManager.InsertItem(pItem);
915         SysTryCatch(NID_APP, req != -1, , r = E_INVALID_STATE, "[E_INVALID_STATE] Invalid argument handling state.");
916
917         handler = _AppArg::GetHandler(b);
918
919         return E_SUCCESS;
920
921 CATCH:
922         delete pArg;
923
924         return r;
925 }
926
927
928 AppCtrlResult
929 _AppControlManager::ConvertAppControlResultCode(int resCode)
930 {
931         AppCtrlResult ret = APP_CTRL_RESULT_FAILED;
932
933         switch(resCode)
934         {
935                 case SERVICE_RESULT_SUCCEEDED:
936                         ret = APP_CTRL_RESULT_SUCCEEDED;
937                         break;
938                 case SERVICE_RESULT_FAILED:
939                         ret = APP_CTRL_RESULT_CANCELED;
940                         break;
941                 case SERVICE_RESULT_CANCELED:
942                         ret = APP_CTRL_RESULT_ABORTED;
943                         break;
944                 case APPSVC_OSP_RES_FAIL:
945                         ret = APP_CTRL_RESULT_FAILED;
946                         break;
947                 case APPSVC_OSP_RES_TERMINATE:
948                         ret = APP_CTRL_RESULT_TERMINATED;
949                         break;
950                 default:
951                         ret = APP_CTRL_RESULT_FAILED;
952                         break;
953         }
954
955         return ret;
956 }
957
958
959 void
960 _AppControlManager::OnAppControlResponseEventReceivedN(const Tizen::Base::Runtime::IEventArg* arg)
961 {
962         const _AppControlResponseEventArg* pEventArg = dynamic_cast<const _AppControlResponseEventArg*>(arg);
963
964         if (pEventArg != null)
965         {
966                 IAppControlResponseListener* pResponseListener = pEventArg->GetListener();
967
968                 if(pResponseListener != null)
969                 {
970                         if(pEventArg->GetType() == _APPCONTROL_RESPONSETYPE_START)
971                         {
972                                 pResponseListener->OnAppControlStartResponseReceived(pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetResult());
973                                 SysLog(NID_APP, "OnAppControlStartResponseReceived called");
974                         }
975                         else
976                         {
977                                 InvokeAppControlCompleteListener(*pResponseListener, pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetAppControlResult(), pEventArg->GetExtraData(), pEventArg->IsSubMode());
978                                 SysLog(NID_APP, "Listener called");
979
980                                 _AppControlResponseEvent* pResponseEvent = null;
981                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(pEventArg->GetRequestId(), pResponseEvent);
982                                 _AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->Remove(pEventArg->GetRequestId());
983
984                                 delete pResponseEvent;
985                                 SysLog(NID_APP, "pResponseEvent gets deleted, reqId(%d)", pEventArg->GetRequestId());
986                         }
987                 }
988                 else
989                 {
990                         SysLog(NID_APP, "Invalid ResponseListener");
991                 }
992         }
993         else
994         {
995                 SysLog(NID_APP, "Invalid AppControl arguments : arg(0x%x)", &arg);
996         }
997 }
998
999 }} // Tizen::App