d6ef48bbb319e59a3fe3a8e6e1eced5a21cfd71c
[platform/framework/native/appfw.git] / src / server / app / FApp_AulServer.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_AulServer.cpp
19  * @brief       This is the implementation for the _AulServer.cpp class.
20  */
21 #include <cstdio>
22 #include <cstdlib>
23 #include <new>
24 #include <unistd.h>
25 #include <sys/prctl.h>
26 #include <signal.h>
27 #include <unique_ptr.h>
28
29 #include <aul.h>
30 #include <bundle.h>
31 #include <appsvc/appsvc.h>
32
33 #include <FBaseObject.h>
34 #include <FBaseString.h>
35 #include <FBaseUtil.h>
36 #include <FBaseSysLog.h>
37 #include <FBaseColHashMapT.h>
38 #include <FAppPkgPackageInfo.h>
39
40 #include <FBaseRt_Process.h>
41 #include <FBase_StringConverter.h>
42 #include "FAppPkg_PackageManagerImpl.h"
43 #include "FApp_Types.h"
44 #include "FApp_AulServer.h"
45 #include "FApp_TemplateUtil.h"
46
47
48 using namespace Tizen::App::Package;
49 using namespace Tizen::Base;
50 using namespace Tizen::Base::Collection;
51 using namespace Tizen::Base::Runtime;
52 using namespace Tizen::Base::Utility;
53
54 namespace
55 {
56
57 const int _MAX_CATEGORY = 12;
58 const int _MAX_PACKAGE_ID_LENGTH = 10;
59
60 const char _APP_PATH_FORMAT[] = "/opt/usr/apps/0000000000/bin/%ls";
61 const char _APP_PATH_FORMAT2[] = "/opt/apps/0000000000/bin/%ls";
62 const char PATH_ROOT[] = "/opt/usr/apps/";
63 const char PATH_ROOT2[] = "/opt/apps/";
64
65 }
66
67 namespace Tizen { namespace App
68 {
69
70 struct _CategoryList
71 {
72         const char category[_MAX_CATEGORY];
73         _AppType type;
74 };
75
76 static const _CategoryList _CATEGORY_LIST[] =
77 {
78         {"home-screen", _APP_TYPE_HOME_APP},
79         {"lock-screen", _APP_TYPE_LOCK_APP},
80         {"ime", _APP_TYPE_IME_APP},
81 };
82
83 static const int _NUM_CATEGORY = sizeof(_CATEGORY_LIST) / sizeof(_CategoryList);
84
85
86 result
87 _AulServer::SendResult(bundle* b, appsvc_result_val res)
88 {
89         result r = E_SUCCESS;
90
91         int ret = appsvc_send_result(b, res);
92
93         switch (ret)
94         {
95         case AUL_R_EINVAL:
96                 r = E_INVALID_ARG;
97                 SysLogException(NID_APP, r, "Invalid result bundle.");
98                 break;
99
100         case AUL_R_ECOMM:
101                 r = E_SYSTEM;
102                 SysLogException(NID_APP, r, "Internal IPC error.");
103                 break;
104
105         case AUL_R_ERROR:
106                 r = E_SYSTEM;
107                 SysLogException(NID_APP, r, "General error.");
108                 break;
109
110         default:
111                 break;
112         }
113
114         SysLog(NID_APP, "SendResult() ok");
115
116         return r;
117 }
118
119
120 bool
121 _AulServer::IsRunning(const AppId& appId, const String& exeName)
122 {
123         char slpPackageName[MAX_SLP_PACKAGE_ID] = {0, };
124
125         _PackageManagerImpl* pPackageManagerImpl = _PackageManagerImpl::GetInstance();
126         SysTryReturn(NID_APP, pPackageManagerImpl != null, false, E_INVALID_STATE, "[E_INVALID_STATE] Invalid package instance.");
127
128         pPackageManagerImpl->GetPackageName(appId, &exeName, slpPackageName, MAX_SLP_PACKAGE_ID);
129
130         const bool isRunning = (aul_app_is_running(slpPackageName) > 0);
131
132         SysLog(NID_APP, "'%s' %s running now.", slpPackageName, (isRunning) ? "is" : "is NOT");
133
134         return isRunning;
135 }
136
137 bool
138 _AulServer::IsRunning(const String& packageName)
139 {
140         std::unique_ptr<char[]> pPackageId(_StringConverter::CopyToCharArrayN(packageName));
141
142         const bool isRunning = (aul_app_is_running(pPackageId.get()) > 0);
143
144         SysLog(NID_APP, "'%ls' %s running now.", packageName.GetPointer(), (isRunning) ? "is" : "is NOT");
145         return isRunning;
146 }
147
148
149 result
150 _AulServer::Launch(const String& appId)
151 {
152         std::unique_ptr<char[]> pPackageName(_StringConverter::CopyToCharArrayN(appId));
153
154         int ret = aul_launch_app(pPackageName.get(), NULL);
155         if (ret < 0)
156         {
157                 result r = E_SYSTEM;
158                 switch (ret)
159                 {
160                 case AUL_R_EILLACC:
161                         r = E_ILLEGAL_ACCESS;
162                         break;
163                 case AUL_R_EINVAL:
164                         r = E_MAX_EXCEEDED;
165                         break;
166                 default:
167                         break;
168                 }
169
170                 SysLogException(NID_APP, r, "[%s] Error occurred.", GetErrorMessage(r));
171                 return r;
172         }
173
174         return E_SUCCESS;
175 }
176
177
178 void
179 _AulServer::SetOnAppTerminatedCb(int (* pf_app_dead_handler)(int pid, void* pData), void* pData)
180 {
181         aul_listen_app_dead_signal(pf_app_dead_handler, pData);
182         SysLog(NID_APP, "'app_dead_handler is set.");
183 }
184
185
186 result
187 _AulServer::TerminateApplicationByPid(int pid)
188 {
189         int ret_aul = aul_terminate_pid(pid);
190         result r = E_SUCCESS;
191
192         switch (ret_aul)
193         {
194         case AUL_R_EINVAL:
195                 r = E_INVALID_ARG;
196                 SysLogException(NID_APP, r, "invaild pid.\n");
197                 break;
198
199         case AUL_R_ECOMM:
200                 r = E_SYSTEM;
201                 SysLogException(NID_APP, r, "internal AUL IPC error.\n");
202                 break;
203
204         case AUL_R_ERROR:
205                 r = E_SYSTEM;
206                 SysLogException(NID_APP, r, "general error.\n");
207                 break;
208
209         default:
210                 SysLog(NID_APP, "'%d' is terminated.", pid);
211                 break;
212         }
213
214         return r;
215 }
216
217 result
218 _AulServer::SetOomAdj(int pid, int adj)
219 {
220         // set oom_adj to -17 for system service
221         result r = E_SUCCESS;
222         char buf[FILENAME_MAX];
223         FILE *fP = NULL;
224
225         snprintf(buf, FILENAME_MAX, "/proc/%d/oom_adj", pid);
226         fP = fopen(buf, "w");
227         SysTryReturnResult(NID_APP, fP != NULL, E_SYSTEM, "oom_adj change failed with %s.", strerror(errno));
228
229         fprintf(fP, "%d", adj);
230         fclose(fP);
231
232         return r;
233 }
234
235 int
236 _AulServer::GetAppType(const String& category)
237 {
238         int ret = 0;
239
240         HashMapT<String, int> map;
241         map.Construct();
242
243         StringTokenizer strTok(category, L';');
244
245         String token;
246         while (strTok.HasMoreTokens())
247         {
248                 result r = strTok.GetNextToken(token);
249                 if (r == E_SUCCESS)
250                 {
251                         map.Add(token, 0);
252                 }
253         }
254
255         SysLog(NID_APP, "%d category items .", map.GetCount());
256
257         String key;
258
259         for (int i = 0; i < _NUM_CATEGORY; i++)
260         {
261                 bool b = false;
262                 key = _CATEGORY_LIST[i].category;
263                 result r = map.ContainsKey(key, b);
264                 if (r == E_SUCCESS && b)
265                 {
266                         ret |= _CATEGORY_LIST[i].type;
267                 }
268         }
269
270         return ret;
271 }
272
273 bool _AulServer::IsInstalled(const AppId& appId)
274 {
275         String packageId;
276         packageId = _PackageManagerImpl::GetPackageIdByAppId(appId);
277
278         return _PackageManagerImpl::GetInstance()->IsPackageInstalled(packageId);
279 }
280
281 int _AulServer::CreateProcess(const AppId& appId)
282 {
283         SysTryReturn(NID_APP, appId.GetLength() > 10 && appId[10] == L'.', -1, E_INVALID_ARG, "[E_INVALID_ARG] Wrong appId %ls.", appId.GetPointer());
284
285         int pid = fork();
286
287         if (pid == -1)
288         {
289                 return -1;
290         }
291         else if (pid == 0)
292         {
293                 char path[FILENAME_MAX];
294                 memset(path, '\0', FILENAME_MAX);
295
296 #if 0
297                 snprintf(path, FILENAME_MAX, _APP_PATH_FORMAT2, appId.GetPointer() + 11);
298
299                 int ret = wcstombs(path + strlen(PATH_ROOT2), appId.GetPointer(), 10);
300                 if (ret == -1)
301                 {
302                         SysLogException(NID_APP, E_SYSTEM, "Launching service (%ls)(%s) failed with [%s].", appId.GetPointer(), path, strerror(errno));
303                         _Process::Exit(1);
304                 }
305 #else
306                 snprintf(path, FILENAME_MAX, _APP_PATH_FORMAT2, appId.GetPointer() + 11);
307
308                 int ret = wcstombs(path + strlen(PATH_ROOT2), appId.GetPointer(), 10);
309                 if (ret == -1)
310                 {
311                         SysLogException(NID_APP, E_SYSTEM, "Launching service (%ls)(%s) failed with [%s].", appId.GetPointer(), path, strerror(errno));
312                         _Process::Exit(1);
313                 }
314
315                 if (euidaccess(path, R_OK) != 0)
316                 {
317                         snprintf(path, FILENAME_MAX, _APP_PATH_FORMAT, appId.GetPointer() + 11);
318
319                         ret = wcstombs(path + strlen(PATH_ROOT), appId.GetPointer(), 10);
320                         if (ret == -1)
321                         {
322                                 SysLogException(NID_APP, E_SYSTEM, "Launching service (%ls)(%s) failed with [%s].", appId.GetPointer(), path, strerror(errno));
323                                 _Process::Exit(1);
324                         }
325                 }
326 #endif
327
328                 SysLog(NID_APP, "Launching %s.", path);
329
330                 int currentPid = getpid();
331
332                 //SetOomAdj(currentPid, -17); // set oom_adj to -17 for system service
333
334                 prctl(PR_SET_PDEATHSIG, SIGTERM);
335
336                 setpgid(currentPid, currentPid);
337
338                 ret = execl(path, path, static_cast<char*>(NULL));
339                 if (ret < 0)
340                 {
341                         SysLogException(NID_APP, E_SYSTEM, "Launching service (%ls)(%s) failed with [%s].", appId.GetPointer(), path, strerror(errno));
342                         _Process::Exit(1);
343                 }
344         }
345
346         return pid;
347
348 }
349
350 bool
351 _AulServer::IsUserPreferredAppForAppControlResolution(const AppId& appId)
352 {
353         std::unique_ptr<char[]> pAppId(_StringConverter::CopyToCharArrayN(appId));
354
355         int ret = appsvc_is_defapp(pAppId.get());
356         SysTryReturn(NID_APP, ret == 1, false, E_SUCCESS,"%ls is not an UserPreferredAppForAppControlResolution. ret(%d)", appId.GetPointer(), ret);
357         
358         SysLog(NID_APP, "%ls is an UserPreferredAppForAppControlResolution.", appId.GetPointer());      
359         return true;
360 }
361
362 result
363 _AulServer::ClearUserPreferenceForAppControlResolution(const AppId& appId)
364 {
365         std::unique_ptr<char[]> pAppId(_StringConverter::CopyToCharArrayN(appId));
366
367         int ret_aul = appsvc_unset_defapp(pAppId.get());
368         SysTryReturnResult(NID_APP, ret_aul == APPSVC_RET_OK, E_SYSTEM, "Fail to clear UserPreferredAppForAppControlResolution of %ls. ret_aul(%d)", appId.GetPointer(), ret_aul);
369
370         SysLog(NID_APP, "Succeed to clear UserPreferredAppForAppControlResolution of %ls.", appId.GetPointer());
371         return E_SUCCESS;
372 }
373
374 } } // Tizen::App