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