Ignore callback for null AppId case and optimize the loop body.
[platform/framework/native/appfw.git] / src / app / FApp_AppManagerImpl.cpp
old mode 100644 (file)
new mode 100755 (executable)
index 5aaf297..f696327
@@ -1,5 +1,4 @@
 //
-// Open Service Platform
 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
 //
 // Licensed under the Apache License, Version 2.0 (the License);
@@ -67,6 +66,7 @@
 #include "FAppPkg_PackageInfoImpl.h"
 #include "FApp_AppControlManager.h"
 #include "FApp_Aul.h"
+#include "FSys_SystemInfoImpl.h"
 
 using namespace Tizen::App::Package;
 using namespace Tizen::Base;
@@ -75,8 +75,6 @@ using namespace Tizen::Base::Runtime;
 using namespace Tizen::Base::Utility;
 using namespace Tizen::Io;
 
-//extern const char* _DATACONTROL_RESULTSET_DIR;
-
 namespace
 {
 
@@ -232,7 +230,6 @@ _AppManagerImpl::_AppManagerImpl(void)
        , __eventListenerCount(0)
        , __pUiLibrary(null)
        , __pX11Library(null)
-       , __pAppEventList(null)
 {
        SysLog(NID_APP, "");
 }
@@ -293,11 +290,31 @@ _AppManagerImpl::GetConditionManagerProxy(void)
 {
        if (__pConditionManager == null)
        {
+               const int MAX_TRY_COUNT = 5;
+               const int TRY_SLEEP_TIME = 250;
+
                __pConditionManager = new (std::nothrow) _ConditionManagerProxy;
                SysAssert(__pConditionManager != null);
 
-               result r = __pConditionManager->Construct();
-               SysAssertf(r == E_SUCCESS, "__pConditionManager->Construct() faliied [%s].", GetErrorMessage(r));
+               int count = 0;
+               while (true)
+               {
+                       result r = __pConditionManager->Construct();
+                       if (r == E_SUCCESS)
+                       {
+                               SysLog(NID_APP, "Succeeded in connecting condition manager.");
+                               break;
+                       }
+
+                       if (count >= MAX_TRY_COUNT)
+                       {
+                               SysLog(NID_APP, "Failed to connecting condition manager.");
+                               break;
+                       }
+
+                       count++;
+                       Thread::Sleep(TRY_SLEEP_TIME);
+               }
        }
 
        return __pConditionManager;
@@ -310,14 +327,7 @@ _AppManagerImpl::FindAppControlN(const AppId& aId, const String& oId)
 
        AppControl* pAc = null;
 
-       pAc = pRegs->GetNativeAppControlN(aId, oId);
-       if (pAc != null)
-       {
-               SetLastResult(E_SUCCESS);
-               return pAc;
-       }
-
-       pAc = pRegs->GetAliasAppControlN(aId, oId);
+       pAc = pRegs->GetTizenAppControlN(aId, oId);
        if (pAc != null)
        {
                SetLastResult(E_SUCCESS);
@@ -367,16 +377,8 @@ _AppManagerImpl::FindAppControlsN(const String* pOperationId, const String* pCat
                                         GetErrorMessage(E_INVALID_FORMAT));
        }
 
-       ArrayList* pRetArg = null;
-       pRetArg = new (std::nothrow) ArrayList();
-       SysTryReturn(NID_APP, pRetArg != null, null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.",
-                                GetErrorMessage(E_OUT_OF_MEMORY));
-
-       pRetArg->Construct();
-
        _AppControlRegistry* pRegs = _AppControlRegistry::GetInstance();
-
-       pRetArg = pRegs->FindAppControlListN(pOperationId, pUriScheme, pMimeType, pCategory);
+       ArrayList* pRetArg = pRegs->FindAppControlListN(pOperationId, pUriScheme, pMimeType, pCategory);
 
        if ((pRetArg == null) || (pRetArg->GetCount() == 0))
        {
@@ -568,7 +570,7 @@ _AppManagerImpl::GetAppRootPath(const AppId& appId, String& appRootPath)
 {
        String pkgId = PackageManager::GetPackageIdByAppId(appId);
        SysTryReturnResult(NID_APP, pkgId.IsEmpty() == false, E_APP_NOT_INSTALLED,
-                       "The application is not installed. (appId: %ls)", appId.GetPointer());
+                       "The application is not installed. (app: %ls)", appId.GetPointer());
 
        _PackageManagerImpl* pPkgMgr = _PackageManagerImpl::GetInstance();
        SysTryReturnResult(NID_APP, pPkgMgr != null, E_SYSTEM,
@@ -576,7 +578,7 @@ _AppManagerImpl::GetAppRootPath(const AppId& appId, String& appRootPath)
 
        std::unique_ptr< PackageInfo >pPkgInfo(pPkgMgr->GetPackageInfoN(pkgId));
        SysTryReturnResult(NID_APP, pPkgInfo != null, E_APP_NOT_INSTALLED,
-                       "The application is not installed. (appId: %ls)", appId.GetPointer());
+                       "The application is not installed. (app: %ls)", appId.GetPointer());
 
        _PackageInfoImpl* pPkgInfoImpl = _PackageInfoImpl::GetInstance(pPkgInfo.get());
        SysTryReturnResult(NID_APP, pPkgInfoImpl != null, E_SYSTEM,
@@ -599,8 +601,8 @@ _AppManagerImpl::LaunchApplication(const String& appId, const IList* pArguments,
 //                                       "The length of appid exceeded the limit(%d).",
 //                                       WIDGET_APP_MAX_APPID_LENGTH);
 
-       AppControl* pAc = _AppControlRegistry::GetInstance()->GetAppControlN(appId, TIZEN_OPERATION_MAIN);
-       SysTryReturnResult(NID_APP, pAc != null, E_OBJ_NOT_FOUND, "The target application (%ls) is not found.", appId.GetPointer());
+       std::unique_ptr<AppControl> pAc(_AppControlRegistry::GetInstance()->GetAppControlN(appId, TIZEN_OPERATION_MAIN));
+       SysTryReturnResult(NID_APP, pAc.get() != null, E_OBJ_NOT_FOUND, "The target application (%ls) is not found.", appId.GetPointer());
 
        if (pArguments)
        {
@@ -735,6 +737,24 @@ _AppManagerImpl::RegisterAppLaunch(const AppId& appId, const String& condition,
        _ConditionManagerProxy* pProxy = GetConditionManagerProxy();
        SysTryReturnResult(NID_APP, null != pProxy, E_INVALID_STATE, "ConditionManager instance must not be null.");
 
+       Tizen::Base::Utility::StringTokenizer strTok(condition, L"=");
+       SysTryReturnResult(NID_APP, strTok.GetTokenCount() > 0, E_INVALID_ARG, "Condition string is invalid.(%ls)", condition.GetPointer());
+
+       String key;
+       result r = strTok.GetNextToken(key);
+       SysTryReturnResult(NID_APP, !IsFailed(r), E_INVALID_ARG, "Condition string is invalid.(%ls)", condition.GetPointer());
+
+       bool ret = true;
+       if (key == L"Serial")
+       {
+               r = Tizen::System::_SystemInfoImpl::GetSysInfo(L"http://tizen.org/feature/usb.accessory", ret);
+       }
+       else if (key == L"NFC")
+       {
+               r = Tizen::System::_SystemInfoImpl::GetSysInfo(L"http://tizen.org/feature/network.nfc", ret);
+       }
+       SysTryReturnResult(NID_APP, ret != false, E_UNSUPPORTED_OPERATION, "Condition(%ls)", condition.GetPointer());
+
        return pProxy->RegisterAppLaunch(appId, condition, pArguments, option);
 }
 
@@ -774,7 +794,7 @@ _AppManagerImpl::SetEventListener(_AppEvent appEvent, Tizen::Base::Runtime::IEve
 result
 _AppManagerImpl::OnServiceEventReceived(int clientId, const _AppManagerEventArg& arg)
 {
-       SysLog(NID_APP, "appId:%ls, appType:0x%x", arg.GetAppId().GetPointer(), arg.GetAppType());
+       SysLog(NID_APP, "app:%ls, appType:0x%x", arg.GetAppId().GetPointer(), arg.GetAppType());
 
        _AppManagerEventArg* pArg = new (std::nothrow)_AppManagerEventArg(arg);
        SysTryReturnResult(NID_APP, pArg != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
@@ -831,102 +851,150 @@ _AppManagerImpl::RemoveEventListener(_IAppManagerEventListener& listener)
 }
 
 
+///////////////////////////////////////////////////////////////////////////////
+// LifecycleManager begins.
+///////////////////////////////////////////////////////////////////////////////
+
 void
-_AppManagerImpl::AppEventCallback(app_context_h app_context, app_context_event_e event, void* pData)
+_AppLifecycleManager::Init(void)
 {
-       _AppManagerImpl* pImpl = static_cast<_AppManagerImpl*>(pData);
-       if (pImpl == null || pImpl->__pAppEventList == null)
-       {
-               SysLogException(NID_APP, E_SYSTEM, "Wrong _AppManagerImpl state.");
-               return;
-       }
+       aul_listen_app_launch_signal(LaunchCallback, this);
+       aul_listen_app_dead_signal(TerminateCallback, this);
+}
 
-       std::unique_ptr< IEnumeratorT<_IAppEventListener*> > pEnum(pImpl->__pAppEventList->GetEnumeratorN());
+void
+_AppLifecycleManager::Fini(void)
+{
+       aul_listen_app_launch_signal(NULL, NULL);
+       aul_listen_app_dead_signal(NULL, NULL);
+}
 
-       if (pEnum.get())
+result
+_AppLifecycleManager::AddListener(_IAppEventListener& listener)
+{
+       if (__pEventList == null)
        {
-               char* pAppId = NULL;
-               app_context_get_app_id(app_context, &pAppId);
-               if (pAppId == NULL)
-               {
-                       SysLogException(NID_APP, E_SYSTEM, "Cannot acquire appId.");
-                       return;
-               }
+               std::unique_ptr< LinkedListT<_IAppEventListener*> > pAppEventList(new LinkedListT<_IAppEventListener*>);
+               SysTryReturnResult(NID_APP, pAppEventList, E_SYSTEM, "Memory allocation failed.");
 
-               const String appId = pAppId;
+               Init();
+
+               __pEventList = pAppEventList.release();
+               SysLog(NID_APP, "Registered app event listener.");
+       }
 
-               free(pAppId);
+       return __pEventList->Add(&listener);
+}
 
-               pid_t pid = -1;
-               app_context_get_pid(app_context, &pid);
-               const int val = event;
+result
+_AppLifecycleManager::RemoveListener(_IAppEventListener& listener)
+{
+       SysTryReturnResult(NID_APP,__pEventList != null, E_OBJ_NOT_FOUND, "_IEventListener list is empty.");
 
-               // loop unfolding
-               switch (val)
-               {
-               case APP_CONTEXT_EVENT_LAUNCHED:
-                       while (pEnum->MoveNext() == E_SUCCESS)
-                       {
-                               _IAppEventListener* pListener = null;
-                               pEnum->GetCurrent(pListener);
+       result r = __pEventList->Remove(&listener);
 
-                               pListener->OnApplicationLaunched(appId, pid);
-                       }
-                       break;
-               case APP_CONTEXT_EVENT_TERMINATED:
-                       while (pEnum->MoveNext() == E_SUCCESS)
-                       {
-                               _IAppEventListener* pListener = null;
-                               pEnum->GetCurrent(pListener);
+       if (__pEventList->GetCount() == 0)
+       {
+               Fini();
 
-                               pListener->OnApplicationTerminated(appId, pid);
-                       }
-                       break;
-               default:
-                       SysLog(NID_APP, "Invalid state.");
-                       break;
-               }
+               delete __pEventList;
+               __pEventList = null;
        }
 
-       SysLog(NID_APP, "Finished invoking application event listener.");
+       return r;
 }
 
-result
-_AppManagerImpl::AddAppEventListener(_IAppEventListener& listener)
+int
+_AppLifecycleManager::LaunchCallback(int pid, void* pData)
 {
-       if (__pAppEventList == null)
+       _AppLifecycleManager* pImpl = static_cast<_AppLifecycleManager*>(pData);
+       if (pImpl == null || pImpl->__pEventList == null)
        {
-               std::unique_ptr< LinkedListT<_IAppEventListener*> > pAppEventList(new LinkedListT<_IAppEventListener*>);
-               SysTryReturnResult(NID_APP, pAppEventList, E_SYSTEM, "Memory allocation failed.");
+               SysLogException(NID_APP, E_SYSTEM, "Wrong _AppLifecycleImpl state.");
+               return -1;
+       }
 
-               const int ret = app_manager_set_app_context_event_cb(_AppManagerImpl::AppEventCallback, this);
-               SysTryReturnResult(NID_APP, ret == APP_MANAGER_ERROR_NONE, E_SYSTEM, "Context registration failed.");
+       char appId[255];
+       int ret = aul_app_get_appid_bypid(pid, appId, sizeof(appId));
+       if (ret != AUL_R_OK)
+       {
+               SysLogException(NID_APP, E_SYSTEM, "Cannot acquire app for %d.", pid);
+               return -1;
+       }
 
-               __pAppEventList = pAppEventList.release();
-               SysLog(NID_APP, "Registered app event listener.");
+       std::unique_ptr< IEnumeratorT<_IAppEventListener*> > pEnum(pImpl->__pEventList->GetEnumeratorN());
+       if (pEnum.get())
+       {
+               const String tmp = appId;
+               pImpl->__map.Add(pid, tmp);
+
+               while (pEnum->MoveNext() == E_SUCCESS)
+               {
+                       _IAppEventListener* pListener = null;
+                       pEnum->GetCurrent(pListener);
+
+                       pListener->OnApplicationLaunched(tmp, pid);
+               }
        }
 
-       return __pAppEventList->Add(&listener);
+       SysLog(NID_APP, "Finished invoking application event listener for %s, %d.", appId, pid);
+
+       return 0;
 }
 
-result
-_AppManagerImpl::RemoveAppEventListener(_IAppEventListener& listener)
+int
+_AppLifecycleManager::TerminateCallback(int pid, void* pData)
 {
-       result r = E_SUCCESS;
+       _AppLifecycleManager* pImpl = static_cast<_AppLifecycleManager*>(pData);
+       if (pImpl == null || pImpl->__pEventList == null)
+       {
+               SysLogException(NID_APP, E_SYSTEM, "Wrong _AppLifecycleImpl state.");
+               return -1;
+       }
 
-       SysTryReturnResult(NID_APP,__pAppEventList != null, E_OBJ_NOT_FOUND, "_IAppEventListener list is empty.");
+       // terminate callback cannot acquire appId from pid
+       String tmp;
+       result r = pImpl->__map.GetValue(pid, tmp);
+       if (r != E_SUCCESS)
+       {
+               SysLog(NID_APP, "Cannot acquire app from pid %d.", pid);
+               return -1;
+       }
 
-       r = __pAppEventList->Remove(&listener);
+       pImpl->__map.Remove(pid);
 
-       if (__pAppEventList->GetCount() == 0)
+       std::unique_ptr< IEnumeratorT<_IAppEventListener*> > pEnum(pImpl->__pEventList->GetEnumeratorN());
+       if (pEnum.get())
        {
-               app_manager_unset_app_context_event_cb();
+               while (pEnum->MoveNext() == E_SUCCESS)
+               {
+                       _IAppEventListener* pListener = null;
+                       pEnum->GetCurrent(pListener);
 
-               delete __pAppEventList;
-               __pAppEventList = null;
+                       pListener->OnApplicationTerminated(tmp, pid);
+               }
        }
 
-       return E_SUCCESS;
+       SysLog(NID_APP, "Finished invoking application event listener for %ls, %d.", tmp.GetPointer(), pid);
+
+       return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// LifecycleManager ends.
+///////////////////////////////////////////////////////////////////////////////
+
+
+result
+_AppManagerImpl::AddAppEventListener(_IAppEventListener& listener)
+{
+       return __lifeManager.AddListener(listener);
+}
+
+result
+_AppManagerImpl::RemoveAppEventListener(_IAppEventListener& listener)
+{
+       return __lifeManager.RemoveListener(listener);
 }
 
 
@@ -994,6 +1062,14 @@ _AppManagerImpl::FireActiveAppEvent(unsigned int xid, int pid, char* pAppName)
        if (oldPid != pid)
        {
                oldPid = pid;
+               char pkgname[255] = {0, };
+               if ((AUL_R_OK != aul_app_get_pkgname_bypid(pid, pkgname, 255)) || pkgname[0] == 0)
+               {
+                       SysSecureLog(NID_APP, "Failed to get the package name from pid=%x pAppName=%s", pid, pAppName ? pAppName : "null");
+                       return;
+               }
+               AppId appId(_Aul::GetRealAppId(String(pkgname)));
+
                std::unique_ptr<IEnumeratorT<Tizen::App::IActiveAppEventListener* > > pEnum(__activeAppEventListenerList.GetEnumeratorN());
                if (pEnum.get())
                {
@@ -1003,10 +1079,7 @@ _AppManagerImpl::FireActiveAppEvent(unsigned int xid, int pid, char* pAppName)
                                pEnum->GetCurrent(pListener);
                                if (pListener)
                                {
-                                       char pkgname[255] = {0, };
-                                       aul_app_get_pkgname_bypid(pid, pkgname, 255);
-                                       // TODO: Translate it to package name --> AppId
-                                       pListener->OnActiveAppChanged(AppId(pkgname));
+                                       pListener->OnActiveAppChanged(appId);
                                }
                        }
                }
@@ -1168,13 +1241,33 @@ _AppManagerImpl::RemoveActiveAppEventListener(IActiveAppEventListener& listener)
 result
 _AppManagerImpl::GetActiveApp(AppId& appId)
 {
-       unsigned int windowId = GetActiveWindow();
-       int processId = GetProcessId(windowId);
+       const unsigned int windowId = GetActiveWindow();
+       const int processId = GetProcessId(windowId);
        char pkgname[255] = {0, };
        aul_app_get_pkgname_bypid(processId, pkgname, 255);
-       // TODO: Translate it to package name --> AppId
-       appId = pkgname;
+       
+       appId = _Aul::GetRealAppId(String(pkgname));
+
+       SysLog(NID_APP, "ActiveApp is %ls.", appId.GetPointer());
        return E_SUCCESS;
 }
 
+bool 
+_AppManagerImpl::IsUserPreferredAppForAppControlResolution(const AppId& appId) const
+{
+       _IAppManager* pMgr = _AppManagerProxy::GetService();
+       SysTryReturn(NID_APP, pMgr, false, E_SYSTEM, "Failed to _AppManagerProxy::GetService().");
+
+       return pMgr->IsUserPreferredAppForAppControlResolution(appId);
+}
+
+result 
+_AppManagerImpl::ClearUserPreferenceForAppControlResolution(const AppId& appId)
+{
+       _IAppManager* pMgr = _AppManagerProxy::GetService();
+       SysTryReturnResult(NID_APP, pMgr, E_SYSTEM, "Failed to _AppManagerProxy::GetService().");
+
+       return pMgr->ClearUserPreferenceForAppControlResolution(appId);
+}
+
 }} // Tizen::App