4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
21 #include <sys/types.h>
34 #include <proc_stat.h>
35 #include <security-server.h>
38 #include "amd_config.h"
39 #include "simple_util.h"
41 #include "app_signal.h"
43 #include "amd_request.h"
45 #include "amd_launch.h"
46 #include "amd_appinfo.h"
47 #include "amd_cgutil.h"
48 #include "amd_status.h"
50 #include <pkgmgr-info.h>
52 #define INHOUSE_UID 5000
54 #ifdef _APPFW_FEATURE_MULTI_INSTANCE
55 #define METADATA_MULTI_INSTANCE "http://developer.samsung.com/tizen/metadata/multiinstance"
58 struct appinfomgr *_raf;
60 static DBusConnection *bus = NULL;
61 char *home_appid = NULL;
64 static int __send_result_to_client(int fd, int res);
65 static gboolean __request_handler(gpointer data);
67 static int __send_result_to_client(int fd, int res)
69 _D("__send_result_to_client, res: %d", fd, res);
71 if (send(fd, &res, sizeof(int), MSG_NOSIGNAL) < 0) {
73 _E("send failed due to EPIPE.\n");
76 _E("send fail to client");
82 static void __real_send(int clifd, int ret)
87 if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
89 _E("send failed due to EPIPE.\n");
91 _E("send fail to client");
97 static int __get_caller_pid(bundle *kb)
102 pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID);
106 pid_str = bundle_get_val(kb, AUL_K_CALLER_PID);
118 static int __foward_cmd(int cmd, bundle *kb, int cr_pid)
122 char tmp_pid[MAX_PID_STR_BUFSZ];
127 if ((pid = __get_caller_pid(kb)) < 0)
132 pgid = getpgid(cr_pid);
134 snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", pgid);
135 bundle_del(kb, AUL_K_CALLEE_PID);
136 bundle_add(kb, AUL_K_CALLEE_PID, tmp_pid);
139 _D("__forward_cmd: %d %d", cr_pid, pgid);
141 bundle_encode(kb, &kb_data, &datalen);
142 if ((res = __app_send_raw_with_noreply(pid, cmd, kb_data, datalen)) < 0)
150 static int __app_process_by_pid(int cmd,
151 const char *pkg_name, struct ucred *cr, int clifd)
157 if (pkg_name == NULL)
160 pid = atoi(pkg_name);
166 if (_status_get_app_info_status(pid) == -1) {
168 if (_status_get_pkgname_bypid(pid, buf, 512) == -1) {
169 _E("request for unknown pid. It might not be a pid of app: %d", pid);
174 if (cmd == APP_RESUME_BY_PID)
175 proc_group_change_status(PROC_CGROUP_SET_RESUME_REQUEST, pid, NULL);
177 proc_group_change_status(PROC_CGROUP_SET_TERMINATE_REQUEST, pid, NULL);
179 _D("__app_process_by_pid, cmd: %d, pid: %d, ", cmd, pid);
181 case APP_RESUME_BY_PID:
182 ret = _resume_app(pid, clifd);
184 case APP_TERM_BY_PID:
185 case APP_TERM_BY_PID_WITHOUT_RESTART:
186 ret = _term_app(pid, clifd);
188 case APP_KILL_BY_PID:
189 if ((ret = _send_to_sigkill(pid)) < 0)
190 _E("fail to killing - %d\n", pid);
191 __real_send(clifd, ret);
193 case APP_TERM_REQ_BY_PID:
194 if ((ret = __app_send_raw(pid, cmd, (unsigned char *)&dummy, sizeof(int))) < 0) {
195 _D("terminate req packet send error");
197 __real_send(clifd, ret);
199 case APP_TERM_BY_PID_ASYNC:
200 if ((ret = __app_send_raw_with_noreply(pid, cmd, (unsigned char *)&dummy, sizeof(int))) < 0) {
201 _D("terminate req packet send error");
203 __real_send(clifd, ret);
210 static gboolean __add_history_handler(gpointer user_data)
216 char *app_path = NULL;
218 app_pkt_t *pkt = (app_pkt_t *)user_data;
223 kb = bundle_decode(pkt->data, pkt->len);
224 appid = (char *)bundle_get_val(kb, AUL_K_PKG_NAME);
226 #ifdef _APPFW_FEATURE_CONTACT_PHONE_AS_ONE_APP
227 // When the Phone is executed, the Contacts is shown on task manager.
229 if (strncmp(appid, "org.tizen.phone", strlen("org.tizen.phone")) == 0)
231 appid = strndup("org.tizen.contacts", strlen("org.tizen.contacts"));
235 ai = (struct appinfo *)appinfo_find(_raf, appid);
236 app_path = (char *)appinfo_get_value(ai, AIT_EXEC);
238 memset((void *)&rec, 0, sizeof(rec));
240 rec.pkg_name = appid;
241 rec.app_path = app_path;
244 rec.arg = (char *)pkt->data;
247 SECURE_LOGD("add rua history %s %s", rec.pkg_name, rec.app_path);
249 ret = rua_add_history(&rec);
251 _D("rua add history error");
257 #ifdef _APPFW_FEATURE_CONTACT_PHONE_AS_ONE_APP
265 static int __get_pid_cb(void *user_data, const char *group, pid_t pid)
269 _D("%s: %d : %d", *sz, pid);
270 *sz = 1; /* 1 is enough */
272 return -1; /* stop the iteration */
275 static int __releasable(const char *filename)
280 if (!filename || !*filename) {
281 _E("release service: name is empty");
285 r = cgutil_exist_group(_rcg, CTRL_MGR, filename);
287 SECURE_LOGE("release service: exist: %s", strerror(errno));
291 SECURE_LOGE("release service: '%s' already not exist", filename);
296 r = cgutil_group_foreach_pid(_rcg, CTRL_MGR, filename,
299 SECURE_LOGE("release service: '%s' read pid error", filename);
303 SECURE_LOGE("release service: '%s' group has process", filename);
310 int __release_srv(const char *filename)
313 const struct appinfo *ai;
315 r = __releasable(filename);
319 ai = (struct appinfo *)appinfo_find(_raf, filename);
321 SECURE_LOGE("release service: '%s' not found", filename);
325 r = appinfo_get_boolean(ai, AIT_RESTART);
327 SECURE_LOGD("Auto restart set: '%s'", filename);
328 return _start_srv(ai, NULL);
331 service_release(filename);
333 r = cgutil_remove_group(_rcg, CTRL_MGR, filename);
335 SECURE_LOGE("'%s' group remove error: %s", filename, strerror(errno));
342 static inline int __send_home_launch_signal(int pid)
344 DBusMessage *message;
349 message = dbus_message_new_signal(AUL_DBUS_PATH,
350 AUL_DBUS_SIGNAL_INTERFACE,
351 AUL_DBUS_HOMELAUNCH_SIGNAL);
353 if (dbus_message_append_args(message,
354 DBUS_TYPE_UINT32, &pid,
355 DBUS_TYPE_INVALID) == FALSE) {
356 _E("Failed to load data error");
360 if (dbus_connection_send(bus, message, NULL) == FALSE) {
361 _E("dbus send error");
365 dbus_connection_flush(bus);
366 dbus_message_unref(message);
368 _D("send dead signal done\n");
373 static inline int __send_app_termination_signal(int dead_pid)
375 DBusMessage *message;
380 message = dbus_message_new_signal(AUL_DBUS_PATH,
381 AUL_DBUS_SIGNAL_INTERFACE,
382 AUL_DBUS_APPDEAD_SIGNAL);
384 if (dbus_message_append_args(message,
385 DBUS_TYPE_UINT32, &dead_pid,
386 DBUS_TYPE_INVALID) == FALSE) {
387 _E("Failed to load data error");
391 if (dbus_connection_send(bus, message, NULL) == FALSE) {
392 _E("dbus send error");
396 dbus_connection_flush(bus);
397 dbus_message_unref(message);
399 _D("send dead signal done\n");
404 #ifdef _APPFW_FEATURE_MULTI_INSTANCE
405 static char* __get_metadata_value(const char *appid, const char *metadata_key)
408 pkgmgrinfo_appinfo_h handle;
409 char *metadata_value = NULL;
410 char *multi_appid = NULL;
412 ret = pkgmgrinfo_appinfo_get_appinfo(appid, &handle);
413 if (ret != PMINFO_R_OK)
416 ret = pkgmgrinfo_appinfo_get_metadata_value(handle, metadata_key, &metadata_value);
417 if (ret != PMINFO_R_OK) {
418 pkgmgrinfo_appinfo_destroy_appinfo(handle);
422 multi_appid = strdup(metadata_value);
424 pkgmgrinfo_appinfo_destroy_appinfo(handle);
429 static const char* __check_target_appid(const struct appinfo* ai, const char *appid, const char *multi_appid)
431 const char* target = NULL;
433 // Both apps are running
434 if (_status_app_is_running(appid) != -1 && _status_app_is_running(multi_appid) != -1) {
435 const char* toggle = appinfo_get_value(ai, AIT_TOGGLE_ORDER);
436 int order = atoi(toggle);
438 _D("launch a multi-instance app with toggle mode: %d", order);
441 target = multi_appid;
442 appinfo_set_value(ai, AIT_TOGGLE_ORDER, "1");
447 appinfo_set_value(ai, AIT_TOGGLE_ORDER, "0");
454 // Main app is running
455 if (_status_app_is_running(appid) != -1) {
456 _D("Send a request to the running main appid: %s", appid);
458 // Sub app is running
459 } else if (_status_app_is_running(multi_appid) != -1) {
460 _D("Send a request to the running sub appid: %s", multi_appid);
461 target = multi_appid;
463 _D("Both apps are not running, launch a main app - %s", appid);
472 static gboolean __request_handler(gpointer data)
474 GPollFD *gpollfd = (GPollFD *) data;
475 int fd = gpollfd->fd;
483 char *term_pid = NULL;
486 const struct appinfo *ai;
487 const char *pkg_status;
490 if ((pkt = __app_recv_raw(fd, &clifd, &cr)) == NULL) {
495 _D("__request_handler: %d", pkt->cmd);
501 case APP_START_ASYNC:
502 ret = security_server_check_privilege_by_sockfd(clifd, "aul::launch", "x");
503 if(ret == SECURITY_SERVER_API_ERROR_ACCESS_DENIED) {
504 _E("launch request has been denied by smack");
505 ret = -EILLEGALACCESS;
506 __real_send(clifd, ret);
508 kb = bundle_decode(pkt->data, pkt->len);
509 appid = (char *)bundle_get_val(kb, AUL_K_PKG_NAME);
511 #ifdef _APPFW_FEATURE_MULTI_INSTANCE
512 // Check the multi-instance app
513 ai = appinfo_find(_raf, appid);
516 __real_send(clifd, -1);
519 const char* multi = appinfo_get_value(ai, AIT_MULTI_INSTANCE);
520 if( multi && strncmp(multi, "true", strlen("true")) == 0 ) {
522 char* multi_appid =__get_metadata_value(appid, METADATA_MULTI_INSTANCE);
523 if (multi_appid != NULL)
525 _D("Multi-instance main: %s, sub: %s", appid, multi_appid);
527 const char* target_appid = __check_target_appid(ai, appid, multi_appid);
529 _D("launch a target appid: - %s", target_appid);
530 ret = _start_app(target_appid, kb, pkt->cmd, cr.pid, cr.uid, clifd);
532 _D("No multi-instance app information, launch a main appid: - %s", appid);
533 ret = _start_app(appid, kb, pkt->cmd, cr.pid, cr.uid, clifd);
540 _D("launch a single-instance appid: %s", appid);
541 ret = _start_app(appid, kb, pkt->cmd, cr.pid, cr.uid, clifd);
545 ret = _start_app(appid, kb, pkt->cmd, cr.pid, cr.uid, clifd);
548 if(ret > 0 && bundle_get_type(kb, AUL_K_PRELAUCHING) == BUNDLE_TYPE_NONE) {
549 item = calloc(1, sizeof(item_pkt_t));
551 strncpy(item->appid, appid, 511);
554 if (home_appid && strncmp(appid, home_appid, strlen(appid)) == 0)
555 __send_home_launch_signal(ret);
556 #ifdef _APPFW_FEATURE_BG_PROCESS_LIMIT
557 __add_item_running_list(item);
559 g_timeout_add(1000, __add_history_handler, pkt);
563 bundle_free(kb), kb = NULL;
566 #ifdef _APPFW_FEATURE_MULTI_INSTANCE
567 case APP_START_MULTI_INSTANCE:
568 ret = security_server_check_privilege_by_sockfd(clifd, "aul::launch", "x");
569 if(ret == SECURITY_SERVER_API_ERROR_ACCESS_DENIED) {
570 _E("launch request has been denied by smack");
571 ret = -EILLEGALACCESS;
572 __real_send(clifd, ret);
574 kb = bundle_decode(pkt->data, pkt->len);
575 appid = (char *)bundle_get_val(kb, AUL_K_PKG_NAME);
577 _D("launch a multi-instance appid: %s", appid);
578 ret = _start_app(appid, kb, pkt->cmd, cr.pid, cr.uid, clifd);
582 item = calloc(1, sizeof(item_pkt_t));
584 strncpy(item->appid, appid, 511);
587 if (home_appid && strncmp(appid, home_appid, strlen(appid)) == 0)
588 __send_home_launch_signal(ret);
589 #ifdef _APPFW_FEATURE_BG_PROCESS_LIMIT
590 __add_item_running_list(item);
592 g_timeout_add(1000, __add_history_handler, pkt);
596 bundle_free(kb), kb = NULL;
602 kb = bundle_decode(pkt->data, pkt->len);
603 ret = __foward_cmd(pkt->cmd, kb, cr.pid);
604 //__real_send(clifd, ret);
607 case APP_RESUME_BY_PID:
608 case APP_TERM_REQ_BY_PID:
609 kb = bundle_decode(pkt->data, pkt->len);
610 appid = (char *)bundle_get_val(kb, AUL_K_PKG_NAME);
611 ret = __app_process_by_pid(pkt->cmd, appid, &cr, clifd);
613 case APP_TERM_BY_PID_WITHOUT_RESTART:
614 case APP_TERM_BY_PID_ASYNC:
615 ret = security_server_check_privilege_by_sockfd(clifd, "aul::terminate", "x");
616 if(ret == SECURITY_SERVER_API_ERROR_ACCESS_DENIED) {
617 _E("terminate request has been denied by smack");
618 ret = -EILLEGALACCESS;
619 __real_send(clifd, ret);
621 kb = bundle_decode(pkt->data, pkt->len);
622 term_pid = (char *)bundle_get_val(kb, AUL_K_PKG_NAME);
623 appid = _status_app_get_appid_bypid(atoi(term_pid));
624 ai = appinfo_find(_raf, appid);
626 appinfo_set_value(ai, AIT_STATUS, "norestart");
627 ret = __app_process_by_pid(pkt->cmd, term_pid, &cr, clifd);
630 __real_send(clifd, ret);
634 case APP_TERM_BY_PID:
635 case APP_KILL_BY_PID:
636 ret = security_server_check_privilege_by_sockfd(clifd, "aul::terminate", "x");
637 if(ret == SECURITY_SERVER_API_ERROR_ACCESS_DENIED) {
638 _E("terminate request has been denied by smack");
639 ret = -EILLEGALACCESS;
640 __real_send(clifd, ret);
642 kb = bundle_decode(pkt->data, pkt->len);
643 appid = (char *)bundle_get_val(kb, AUL_K_PKG_NAME);
644 ret = __app_process_by_pid(pkt->cmd, appid, &cr, clifd);
647 case APP_RUNNING_INFO:
648 _status_send_running_appinfo_v2(clifd);
650 case APP_RUNNING_INFO_MEMORY:
651 _status_send_running_appinfo(clifd);
654 appid = malloc(MAX_PACKAGE_STR_SIZE);
658 __send_result_to_client(clifd, ret);
662 strncpy(appid, (const char*)pkt->data, MAX_PACKAGE_STR_SIZE-1);
663 ret = _status_app_is_running_v2(appid);
664 SECURE_LOGD("APP_IS_RUNNING : %s : %d",appid, ret);
665 __send_result_to_client(clifd, ret);
668 case APP_GET_APPID_BYPID:
669 memcpy(&pid, pkt->data, sizeof(int));
670 ret = _status_get_appid_bypid(clifd, pid);
671 _D("APP_GET_APPID_BYPID : %d : %d", pid, ret);
673 case APP_GET_PKGID_BYPID:
674 memcpy(&pid, pkt->data, sizeof(int));
675 ret = _status_get_pkgid_bypid(clifd, pid);
676 _D("APP_GET_PKGID_BYPID : %d : %d", pid, ret);
678 case APP_KEY_RESERVE:
679 ret = _register_key_event(cr.pid);
680 __send_result_to_client(clifd, ret);
682 case APP_KEY_RELEASE:
683 ret = _unregister_key_event(cr.pid);
684 __send_result_to_client(clifd, ret);
686 case APP_STATUS_UPDATE:
687 status = (int *)pkt->data;
688 if(*status == STATUS_NORESTART) {
689 appid = _status_app_get_appid_bypid(cr.pid);
690 ai = appinfo_find(_raf, appid);
692 appinfo_set_value(ai, AIT_STATUS, "norestart");
694 ret = _status_update_app_info_list(cr.pid, *status);
696 //__send_result_to_client(clifd, ret);
700 appid = malloc(MAX_PACKAGE_STR_SIZE);
704 __send_result_to_client(clifd, ret);
708 strncpy(appid, (const char*)&pkt->data[1], MAX_PACKAGE_STR_SIZE-1);
709 ai = appinfo_find(_raf, appid);
710 pkg_status = appinfo_get_value(ai, AIT_STATUS);
711 SECURE_LOGD("appid(%s) pkg_status(%s)", appid, pkg_status);
712 if(ai && pkg_status && strncmp(pkg_status, "blocking", 8) == 0) {
713 appinfo_set_value(ai, AIT_STATUS, "restart");
714 } else if (ai && pkg_status && strncmp(pkg_status, "norestart", 9) == 0) {
715 appinfo_set_value(ai, AIT_STATUS, "installed");
717 ret = __release_srv(appid);
719 __send_result_to_client(clifd, ret);
720 ret = _status_app_is_running(appid);
721 SECURE_LOGI("appid(%s) dead pid(%d)", appid, ret);
723 __send_app_termination_signal(ret);
726 case APP_RUNNING_LIST_UPDATE:
727 /*kb = bundle_decode(pkt->data, pkt->len);
728 appid = (char *)bundle_get_val(kb, AUL_K_APPID);
729 app_path = (char *)bundle_get_val(kb, AUL_K_EXEC);
730 tmp_pid = (char *)bundle_get_val(kb, AUL_K_PID);
732 ret = _status_add_app_info_list(appid, app_path, pid);*/
734 __send_result_to_client(clifd, ret);
737 case APP_GET_CMDLINE:
738 memcpy(&pid, pkt->data, sizeof(int));
739 ret = _status_get_cmdline(clifd, pid);
740 _D("APP_GET_CMDLINE : %d : %d", pid, ret);
744 _E("no support packet");
752 bundle_free(kb), kb = NULL;
757 static gboolean __au_glib_check(GSource *src)
762 fd_list = src->poll_fds;
764 tmp = (GPollFD *) fd_list->data;
765 if ((tmp->revents & (POLLIN | POLLPRI)))
767 fd_list = fd_list->next;
773 static gboolean __au_glib_dispatch(GSource *src, GSourceFunc callback,
780 static gboolean __au_glib_prepare(GSource *src, gint *timeout)
785 static GSourceFuncs funcs = {
786 .prepare = __au_glib_prepare,
787 .check = __au_glib_check,
788 .dispatch = __au_glib_dispatch,
792 static void __home_appid_vconf_cb(keynode_t *key, void *data)
796 tmpstr = vconf_keynode_get_str(key);
797 if (tmpstr == NULL) {
804 home_appid = strdup(tmpstr);
807 int _request_init(struct amdmgr *amd)
815 fd = __create_server_sock(AUL_UTIL_PID);
816 src = g_source_new(&funcs, sizeof(GSource));
818 gpollfd = (GPollFD *) g_malloc(sizeof(GPollFD));
819 if (gpollfd == NULL) {
826 gpollfd->events = POLLIN;
829 g_source_add_poll(src, gpollfd);
830 g_source_set_callback(src, (GSourceFunc) __request_handler,
831 (gpointer) gpollfd, NULL);
832 g_source_set_priority(src, G_PRIORITY_DEFAULT);
834 r = g_source_attach(src, NULL);
837 _E("fail to attach the source : %d", r);
845 r = rua_clear_history();
847 _D("rua_clear_history : %d", r);
849 dbus_error_init(&error);
850 bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
851 home_appid = vconf_get_str(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME);
852 if (vconf_notify_key_changed(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, __home_appid_vconf_cb, NULL) != 0) {
853 _E("Unable to register callback for VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME\n");