#include <aul/aul.h>
#include <bundle.h>
#include <content/mime_type.h>
+#include <appinfo.h>
#include <FBaseInteger.h>
#include <FBaseObject.h>
#include <FBaseSysLog.h>
#include <FBase_StringConverter.h>
-#include <FBaseRt_LibraryImpl.h>
#include <FIo_DataControlResultSetImpl.h>
#include "FApp_AppArg.h"
#include "FApp_AppControlImpl.h"
#include "FApp_AppImpl.h"
#include "FApp_AppInfo.h"
-#include "FApp_AppManagerEventArg.h"
#include "FApp_Aul.h"
#include "FApp_AppControlManager.h"
#include "FApp_AppManagerProxy.h"
#include "FApp_ConditionManagerProxy.h"
-#include "FApp_IAppManagerEventListener.h"
#include "FApp_MapDataControlImpl.h"
#include "FApp_SqlDataControlImpl.h"
#include "FAppPkg_PackageManagerImpl.h"
#include "FApp_AppMessageImpl.h"
#include "FApp_AppManagerImpl.h"
#include "FApp_AppControlResponseEvent.h"
+#include "FApp_IAppControlPluginProvider.h"
+
using namespace Tizen::App::Package;
using namespace Tizen::Base;
using namespace Tizen::Base::Utility;
using namespace Tizen::Io;
-namespace Tizen { namespace App
+namespace
{
-
-const wchar_t TIZEN_OPERATION_PICK[] = L"http://tizen.org/appcontrol/operation/pick";
-const wchar_t SELECTOR_NOTI_KEY[] = L"__APP_SVC_CALLER_NOTI__";
-const int _MAX_PACKAGE_ID_LENGTH = 10;
-
-_InProcessInfo::~_InProcessInfo(void)
-{
- delete pLib;
+const char SELECTOR_NOTI_KEY[] = "__APP_SVC_CALLER_NOTI__";
}
-_LaunchInfo::~_LaunchInfo(void)
+namespace Tizen { namespace App
{
- delete pArg;
-}
+const wchar_t TIZEN_OPERATION_PICK[] = L"http://tizen.org/appcontrol/operation/pick";
_AppControlManager::_AppControlManager(void)
// AppControl event handling is expected to be performed in the main thread.
__appControlEvent.Construct();
__appControlEvent.AddListener(*dynamic_cast<_IAppControlSysEventListener*>(this));
- __listenerList.Construct();
- __pAppControlResponseEventContainer = new (std::nothrow)HashMapT<int, _AppControlResponseEvent*>;
- __pAppControlResponseEventContainer->Construct();
+ __appControlResponseEventContainer.Construct();
__appControlResponseEventList.Construct();
}
{
int reqId;
pEnum->GetCurrent(reqId);
- if (__pAppControlResponseEventContainer != null)
- {
- _AppControlResponseEvent* pResponseEvent = null;
- __pAppControlResponseEventContainer->GetValue(reqId, pResponseEvent);
- delete pResponseEvent;
+ _AppControlResponseEvent* pResponseEvent = null;
+ __appControlResponseEventContainer.GetValue(reqId, pResponseEvent);
+ delete pResponseEvent;
- __pAppControlResponseEventContainer->Remove(reqId);
- SysLog(NID_APP, "pResponseEvent gets deleted. reqId(%d)", reqId);
- }
+ __appControlResponseEventContainer.Remove(reqId);
+ SysLog(NID_APP, "pResponseEvent gets deleted. reqId(%d)", reqId);
}
}
- delete __pAppControlResponseEventContainer;
delete pEnum;
}
SysLog(NID_APP, "Invoking callback 0x%x", pInfo->launchCb);
//pAppArg->Print();
- if (pInfo->pUserData && (!__listenerList.Contains(pInfo->pUserData)))
+ if (pInfo->pUserData)
{
(*pInfo->launchCb)(pInfo->pUserData, pInfo->pArg, pAppArg, static_cast<service_result_e>(res), pInfo->property, reqId);
}
SysLog(NID_APP, "Invoking callback 0x%x.", pListener);
_AppControlResponseEvent* pResponseEvent = null;
- __pAppControlResponseEventContainer->GetValue(reqId, pResponseEvent);
+ __appControlResponseEventContainer.GetValue(reqId, pResponseEvent);
SysLog(NID_APP, "StartResponseReceived Request Id(%d), ResponseEvent 0x%x.", reqId, pResponseEvent);
if (pResponseEvent != null)
{
String oId(operationId);
- _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_START, actualAppId, oId, r, APP_CTRL_RESULT_SUCCEEDED, null, reqId);
+ _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_START, actualAppId, oId, r, APP_CTRL_RESULT_SUCCEEDED, null, reqId, false);
if (pResponseEventArg != null)
{
}
+void
+_AppControlManager::InvokeAppControlCompleteListener(IAppControlResponseListener& listener, const AppId& appId, const String& op, AppCtrlResult res, const IMap* pExtraData, bool noRaise)
+{
+ listener.OnAppControlCompleteResponseReceived(appId, op, res, pExtraData);
+
+ if (!noRaise)
+ {
+ _AppImpl::GetInstance()->SendUserEvent(_APP_EVENT_RAISE, null, false);
+ }
+
+ SysLog(NID_APP, "AppControl response finished.");
+}
+
+
+void
+_AppControlManager::InvokeLegacyAppControlCompleteListener(IAppControlEventListener& listener, const AppId& appId, const String& op, const IList* pList, bool noRaise)
+{
+ listener.OnAppControlCompleted(appId, op, pList);
+
+ if (!noRaise)
+ {
+ _AppImpl::GetInstance()->SendUserEvent(_APP_EVENT_RAISE, null, false);
+ }
+
+ SysLog(NID_APP, "Legacy AppControl response finished.");
+}
+
+
// callback for in-process event handling
void
-_AppControlManager::OnAppControlEventReceivedN(int reqId, int res, const IMap* pArgs)
+_AppControlManager::OnAppControlEventReceivedN(int reqId, int res, const IMap* pArgs, int property)
{
SysLog(NID_APP, "Received request Id %d, res %d, args 0x%x", reqId, res, pArgs);
aId = pEntry->provider;
oId = pEntry->operation;
- SysLog(NID_APP, "Legacy AppControl name (%ls, %ls).", aId.GetPointer(), oId.GetPointer());
+ SysLog(NID_APP, "Legacy AppControl (%ls, %ls).", aId.GetPointer(), oId.GetPointer());
}
}
+ const bool isSubMode = (property & _APPCONTROL_PROPERTY_SUBMODE);
+ const bool isServiceCallee = (property & _APPCONTROL_PROPERTY_SERVICE_CALLEE);
+
if (pInfo->isLegacy)
{
IAppControlEventListener* pListener = dynamic_cast<IAppControlEventListener*>(pInfo->pListener);
ArrayList list(SingleObjectDeleter);
_AppArg::FillLegacyAppControlResult(list, res, pArgs, aId);
- pListener->OnAppControlCompleted(aId, oId, &list);
+ InvokeLegacyAppControlCompleteListener(*pListener, aId, oId, &list, isSubMode | isServiceCallee);
}
else
{
else
{
IAppControlResponseListener* pListener = dynamic_cast<IAppControlResponseListener*>(pInfo->pListener);
- if (pListener && (!__listenerList.Contains(pInfo->pListener)))
+ if (pListener)
{
_AppControlResponseEvent* pResponseEvent = null;
int responseEventRequestId = RESPONSE_EVENT_REQID_MAGIC + reqId;
- __pAppControlResponseEventContainer->GetValue(responseEventRequestId, pResponseEvent);
+ __appControlResponseEventContainer.GetValue(responseEventRequestId, pResponseEvent);
if (pResponseEvent != null)
{
- _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_COMPLETE, aId, oId, E_SUCCESS, static_cast<AppCtrlResult>(res), const_cast<IMap*> (pArgs), responseEventRequestId);
+ _AppControlResponseEventArg* pResponseEventArg = new (std::nothrow) _AppControlResponseEventArg(pListener, _APPCONTROL_RESPONSETYPE_COMPLETE, aId, oId, E_SUCCESS, static_cast<AppCtrlResult>(res), const_cast<IMap*> (pArgs), responseEventRequestId, isSubMode);
if (pResponseEventArg != null)
{
pResponseEvent->Fire(*pResponseEventArg);
}
else
{
- pListener->OnAppControlCompleteResponseReceived(aId, oId, ConvertAppControlResultCode(res), pArgs);
- SysLog(NID_APP, "OnAppControlCompleteResponseReceived called directly");
- IMap* pMap = const_cast<IMap*> (pArgs);
- delete pMap;
+ InvokeAppControlCompleteListener(*pListener, aId, oId, ConvertAppControlResultCode(res), pArgs, isSubMode | isServiceCallee);
+ SysLog(NID_APP, "Listener called directly");
+ delete pArgs;
}
}
else
}
// call TerminateAppControl
- result (* pFunc)(int req) = null;
- pFunc = reinterpret_cast<result (*)(int)>(pInfo->pLib->GetProcAddress(L"TerminateAppControl"));
- if (pFunc)
- {
- (*pFunc)(pInfo->reqId);
- }
- else
+ if (pInfo->pProvider)
{
- SysLogException(NID_APP, E_SYSTEM, "No TerminateAppControl() function.");
+ pInfo->pProvider->StopAppControlPlugin(pInfo->reqId);
+ SysLog(NID_APP, "AppControl stopped for req %d.", pInfo->reqId);
}
// remove from list and unload dll
Tizen::Base::Collection::IMapT<int,_AppControlResponseEvent*>*
_AppControlManager::GetAppControlResponseEventContainer(void)
{
- return __pAppControlResponseEventContainer;
+ return &__appControlResponseEventContainer;
+}
+
+
+static bool
+IsMatchingProcListener(const _InProcessInfo& info, IEventListener* pListener)
+{
+ return (info.pListener == pListener);
+}
+
+static bool
+IsMatchingLaunchListener(const _LaunchInfo& info, IEventListener* pListener)
+{
+ return (info.pUserData == pListener);
+}
+
+void
+_AppControlManager::StopAppControlResponseListener(IAppControlResponseListener* pListener)
+{
+ // __inAppManager, __launchManager
+ _InProcessInfo* pProcInfo = __inAppManager.FindItemWithListener(IsMatchingProcListener, pListener);
+ if (pProcInfo)
+ {
+ __inAppManager.RemoveItem(pProcInfo);
+ SysLog(NID_APP, "Listener 0x%x is removed from in-process stub list.", pListener);
+ }
+
+ _LaunchInfo* pLaunchInfo = __launchManager.FindItemWithListener(IsMatchingLaunchListener, pListener);
+ if (pLaunchInfo)
+ {
+ __launchManager.RemoveItem(pLaunchInfo);
+ SysLog(NID_APP, "Listener 0x%x is removed from launch request list.", pListener);
+ }
+
}
case APPSVC_RET_EILLACC:
r = E_ILLEGAL_ACCESS;
break;
+ case APPSVC_RET_EINVAL:
+ r = E_MAX_EXCEEDED;
+ break;
default:
r = E_SYSTEM;
break;
}
- SysLog(NID_APP, "[%s]Launching service %s failure", GetErrorMessage(r), pkg_name);
+ SysLog(NID_APP, "[%s] Launching service %s failure", GetErrorMessage(r), pkg_name);
}
return r;
case APPSVC_RET_EILLACC:
r = E_ILLEGAL_ACCESS;
break;
+ case APPSVC_RET_EINVAL:
+ r = E_MAX_EXCEEDED;
+ break;
default:
r = E_SYSTEM;
break;
int
+_AppControlManager::LaunchPkg(_AppMessageImpl& msg, AppSvcResFn pCb, void* data)
+{
+ bundle* kb = msg.GetBundle();
+ SysTryReturn(NID_APP, kb != NULL, -1, E_OUT_OF_MEMORY, "Bundle allocation failure.");
+
+ if (_AppImpl::GetInstance() != null)
+ {
+ const long handle = _AppImpl::GetInstance()->GetWindowHandle();
+ _AppArg::UpdateWindowHandle(kb, handle);
+ }
+
+ int pid = appsvc_run_service(kb, 0, reinterpret_cast<appsvc_res_fn>(pCb), this);
+
+ result r = E_SUCCESS;
+ if (pid < 0)
+ {
+ switch (pid)
+ {
+ case APPSVC_RET_EILLACC:
+ r = E_ILLEGAL_ACCESS;
+ break;
+ case APPSVC_RET_EINVAL:
+ r = E_MAX_EXCEEDED;
+ break;
+ default:
+ r = E_SYSTEM;
+ break;
+ }
+ SysLog(NID_APP, "[%s] Launching service %s failure", GetErrorMessage(r), appsvc_get_appid(kb));
+ }
+ SetLastResult(r);
+
+ return pid;
+}
+
+
+int
_AppControlManager::LaunchPkg(_AppMessageImpl& msg, const AppId& appId, const String& opId, const String* pUri, const String* pMime, AppSvcResFn pCb, void* data)
{
std::unique_ptr<char[]> pPackage(_StringConverter::CopyToCharArrayN(appId));
kb = pArg->GetBundle();
pid = appsvc_run_service(kb, req, LaunchResultCb, this);
- if (pid > 0)
+ if (pid >= 0)
{
SysLog(NID_APP, "Submode launch successful");
return E_SUCCESS;
}
+ else if (pid == APPSVC_RET_EINVAL)
+ {
+ SysLog(NID_APP, "Argument overflow");
+ return E_MAX_EXCEEDED;
+ }
pArg->UpdateAppId(actualAppId);
{
kb = pArg->GetBundle();
pid = appsvc_run_service(kb, req, LaunchResultCb, this);
- if (pid > 0)
+ if (pid >= 0)
{
SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
return E_SUCCESS;
}
+ else if (pid == APPSVC_RET_EINVAL)
+ {
+ SysLog(NID_APP, "Argument overflow");
+ return E_MAX_EXCEEDED;
+ }
+
count++;
SysLog(NID_APP, "Waiting %dth time.", count);
Thread::Sleep(TRY_SLEEP_TIME);
int
-_AppControlManager::Launch(const _AppMessageImpl& msg, const AppId& aId, const String& oId, const String* pUriData, const String* pMimeType, AppSvcResFn pCb, void* pData)
+_AppControlManager::Launch(const AppId& appId, _AppArg* pArg, int req)
{
- SysLog(NID_APP, "Enter");
-
- _AppArg arg;
- arg.Construct(msg, oId, pUriData, pMimeType);
-
- int pid = Launch(aId, &arg, pCb, pData, -1);
- SysTryReturn(NID_APP, pid >= 0, -1, GetLastResult(), "Launching(%ls) is failed", aId.GetPointer());
-
- SysLog(NID_APP, "Exit");
-
- return pid;
+ return Launch(appId, pArg, reinterpret_cast<AppSvcResFn>(LaunchResultCb), this, req);
}
int
-_AppControlManager::Launch(const AppId& appId, _AppArg* pArg, int req)
+_AppControlManager::Launch(const _AppMessageImpl& msg, AppSvcResFn pCb, void* pData)
{
- return Launch(appId, pArg, reinterpret_cast<AppSvcResFn>(LaunchResultCb), this, req);
+ const bundle* pBundle = msg.GetBundle();
+
+ _AppArg arg;
+ arg.Construct(pBundle);
+
+ return Launch(_AppMessageImpl::GetApplicationId(pBundle), &arg, pCb, pData, -1);
}
SysLog(NID_APP, "App: %ls.", appId.GetPointer());
String actualAppId = appId;
+#if 0
if (appId.GetLength() == 10)
{
const String& execName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
actualAppId.Append(execName);
}
}
+#endif
pArg->UpdateRequestId(req);
actualAppId.SubString(0, 10, tempId);
- if (_IsDefaultApplication(tempId, appId))
+ const int type = _AppInfo::GetAppType();
+ if ((!(type & _APP_TYPE_SERVICE_APP)) && _IsDefaultApplication(tempId, appId))
{
tempId += L'.';
tempId += L"_AppControl";
kb = pArg->GetBundle();
pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
- if (pid > 0)
+ if (pid >= 0)
{
SysLog(NID_APP, "Submode launch successful");
+ SetLastResult(E_SUCCESS);
+ return pid;
+ }
+ else if (pid == APPSVC_RET_EINVAL)
+ {
+ SetLastResult(E_MAX_EXCEEDED);
return pid;
}
}
{
kb = pArg->GetBundle();
pid = appsvc_run_service(kb, req, reinterpret_cast<appsvc_res_fn>(pCb), pData);
- if (pid > 0)
+ if (pid >= 0)
{
SysLog(NID_APP, "Application(%d) launched with reqId(%d) and arg(0x%x).", pid, req, pArg);
+ SetLastResult(E_SUCCESS);
+ return pid;
+ }
+ else if (pid == APPSVC_RET_EINVAL)
+ {
+ SetLastResult(E_MAX_EXCEEDED);
return pid;
}
+
count++;
- SysLog(NID_APP, "Waiting %dth time.", count);
+ SysLog(NID_APP, "Waiting %dth time with %d.", count, pid);
Thread::Sleep(TRY_SLEEP_TIME);
}
while (count < TRY_COUNT);
if (req >= 0)
{
pArg->UpdateRequestId(req);
- _AppMessageImpl::AddData(kb, SELECTOR_NOTI_KEY, _AppInfo::GetApplicationId());
+ appsvc_add_data(kb, SELECTOR_NOTI_KEY, appinfo_get_appid());
}
if (_AppImpl::GetInstance() != null)
}
int pid = appsvc_run_service(kb, req, LaunchResultCb, this);
- if (pid > 0)
+ if (pid >= 0)
{
+ if (pid == 0)
+ {
+ SysLog(NID_APP, "Sending local process again.");
+ pid = getpid();
+ }
+
char pkgname[255] = {0, };
- aul_app_get_pkgname_bypid(pid, pkgname, 255);
+ if (aul_app_get_pkgname_bypid(pid, pkgname, 255) != AUL_R_OK)
+ {
+ SysLog(NID_APP, "Fail to get package name by pid : (%d).", pid);
+ return E_SYSTEM;
+ }
if (strncmp(pkgname, APP_SELECTOR, strlen(APP_SELECTOR)) != 0)
{
_AppControlManager::FinishAppControl(int reqId, int res, IMap* pMap)
{
SysLog(NID_APP, "req %d, res %d.", reqId, res);
- _NativeAppControlEventArg* pArg = new (std::nothrow) _NativeAppControlEventArg(reqId, res, pMap);
+ _NativeAppControlEventArg* pArg = new (std::nothrow) _NativeAppControlEventArg(reqId, res, pMap, _APPCONTROL_PROPERTY_SUBMODE);
SysTryReturnVoidResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Return argument allocation failure.");
SendAppControlEvent(*pArg);
SysLog(NID_APP, "Exit.");
}
+void
+_AppControlManager::RemoveResultRequest(int reqId)
+{
+ __resultManager.RemoveItem(reqId);
+}
+
const _AppArg*
_AppControlManager::FindResultRequest(int reqId) const
{
}
-bool
-_AppControlManager::IsAllowedAppControl(const char aTable[][2][96], int count, const String& aId, const String& oId)
-{
- for (int i = 0; i < count; i++)
- {
- if (aId == aTable[i][0] && oId == aTable[i][1])
- {
- SysLog(NID_APP, "Found entry (%s, %s)", aTable[i][0], aTable[i][1]);
- return true;
- }
- }
-
- return false;
-}
-
-
AppCtrlResult
_AppControlManager::ConvertAppControlResultCode(int resCode)
{
}
else
{
- pResponseListener->OnAppControlCompleteResponseReceived(pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetAppControlResult(), pEventArg->GetExtraData());
- SysLog(NID_APP, "OnAppControlCompleteResponseReceived called");
+ InvokeAppControlCompleteListener(*pResponseListener, pEventArg->GetAppId(), pEventArg->GetOperationId(), pEventArg->GetAppControlResult(), pEventArg->GetExtraData(), pEventArg->IsSubMode());
+ SysLog(NID_APP, "Listener called");
_AppControlResponseEvent* pResponseEvent = null;
_AppControlManager::GetInstance()->GetAppControlResponseEventContainer()->GetValue(pEventArg->GetRequestId(), pResponseEvent);
}
}
-AppId
-_AppControlManager::GetAliasAppId(const AppId& appId)
-{
- return _AppControlRegistry::GetInstance()->GetAliasAppId(appId);
-}
-
}} // Tizen::App