diff options
author | Sehong Na <sehong.na@samsung.com> | 2014-05-31 13:00:43 +0900 |
---|---|---|
committer | Sehong Na <sehong.na@samsung.com> | 2014-05-31 13:00:43 +0900 |
commit | 49b40a5d9545c0847889292acf5a8da545e970eb (patch) | |
tree | f524af009437a07e766f9bdba1c48a5aa2a58ec0 /mobile/src | |
download | starter-49b40a5d9545c0847889292acf5a8da545e970eb.tar.gz starter-49b40a5d9545c0847889292acf5a8da545e970eb.tar.bz2 starter-49b40a5d9545c0847889292acf5a8da545e970eb.zip |
Initialize Tizen 2.3submit/tizen_2.3/20140531.1119222.3a_release
Diffstat (limited to 'mobile/src')
-rw-r--r-- | mobile/src/hw_key.c | 323 | ||||
-rw-r--r-- | mobile/src/lock-daemon.c | 674 | ||||
-rw-r--r-- | mobile/src/lockd-debug.c | 94 | ||||
-rw-r--r-- | mobile/src/lockd-process-mgr.c | 176 | ||||
-rw-r--r-- | mobile/src/lockd-window-mgr.c | 283 | ||||
-rw-r--r-- | mobile/src/menu_daemon.c | 373 | ||||
-rw-r--r-- | mobile/src/pkg_event.c | 301 | ||||
-rw-r--r-- | mobile/src/starter.c | 273 | ||||
-rw-r--r-- | mobile/src/x11.c | 111 | ||||
-rw-r--r-- | mobile/src/xmonitor.c | 296 |
10 files changed, 2904 insertions, 0 deletions
diff --git a/mobile/src/hw_key.c b/mobile/src/hw_key.c new file mode 100644 index 0000000..14361bf --- /dev/null +++ b/mobile/src/hw_key.c @@ -0,0 +1,323 @@ + /* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +#include <ail.h> +#include <bundle.h> +#include <Elementary.h> +#include <Ecore_X.h> +#include <Ecore_Input.h> +#include <sysman.h> +#include <syspopup_caller.h> +#include <utilX.h> +#include <vconf.h> +#include <system/media_key.h> + +#include "hw_key.h" +#include "menu_daemon.h" +#include "util.h" + +#define TASKMGR_PKG_NAME "org.tizen.taskmgr" +#define CAMERA_PKG_NAME "org.tizen.camera-app" +#define CALLLOG_PKG_NAME "org.tizen.calllog" +#define MUSIC_PLAYER_PKG_NAME "org.tizen.music-player" + + + +static struct { + Ecore_X_Window win; + Ecore_Event_Handler *key_up; + Ecore_Event_Handler *key_down; + Ecore_Timer *long_press; + Ecore_Timer *single_timer; + Ecore_Timer *volume_up_long_press; + Ecore_Timer *volume_down_long_press; + Eina_Bool cancel; +} key_info = { + .win = 0x0, + .key_up = NULL, + .key_down = NULL, + .long_press = NULL, + .single_timer = NULL, + .volume_up_long_press = NULL, + .volume_down_long_press = NULL, + .cancel = EINA_FALSE, +}; + + + +static Eina_Bool _launch_taskmgr_cb(void* data) +{ + int val1 = -1; + int val2 = -1; + _D("Launch TASKMGR"); + + key_info.long_press = NULL; + + if (vconf_get_int(VCONFKEY_PM_STATE, &val1) < 0) { + _E("Cannot get VCONFKEY_PM_STATE"); + return ECORE_CALLBACK_CANCEL; + } + if (vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &val2) < 0) { + _E("Cannot get VCONFKEY_IDLE_LOCK_STATE"); + return ECORE_CALLBACK_CANCEL; + } + + if ((val1 == VCONFKEY_PM_STATE_NORMAL) && (val2 == VCONFKEY_IDLE_UNLOCK)) { + _D("LCD ON, UNLOCK state => launch taskmgr"); + syspopup_destroy_all(); + if (menu_daemon_open_app(TASKMGR_PKG_NAME) < 0) + _E("Failed to launch the taskmgr"); + } else { + _D("Can't launch TASKMGR pm state : %d lock state : %d", val1, val2); + } + + return ECORE_CALLBACK_CANCEL; +} + + + +static Eina_Bool _launch_by_home_key(void *data) +{ + key_info.single_timer = NULL; + syspopup_destroy_all(); + menu_daemon_open_homescreen(NULL); + return ECORE_CALLBACK_CANCEL; +} + + + +inline static int _release_home_key(void) +{ + syspopup_destroy_all(); + retv_if(NULL == key_info.long_press, EXIT_SUCCESS); + ecore_timer_del(key_info.long_press); + key_info.long_press = NULL; + + if (NULL == key_info.single_timer) { + key_info.single_timer = ecore_timer_add(0.3, _launch_by_home_key, NULL); + return EXIT_SUCCESS; + } + ecore_timer_del(key_info.single_timer); + key_info.single_timer = NULL; + + return EXIT_SUCCESS; +} + + + +inline static void _release_multimedia_key(const char *value) +{ + ret_if(NULL == value); + + _D("Multimedia key is released with %s", value); + + bundle *b; + b = bundle_create(); + if (!b) { + _E("Cannot create bundle"); + return; + } + bundle_add(b, "multimedia_key", value); + + int ret; + ret = menu_daemon_launch_app(MUSIC_PLAYER_PKG_NAME, b); + if (ret < 0) + _E("Failed to launch the running apps, ret : %d", ret); + + bundle_free(b); +} + + + +static Eina_Bool _key_release_cb(void *data, int type, void *event) +{ + Evas_Event_Key_Up *ev = event; + int val = -1; + + _D("Released"); + + if (!ev) { + _D("Invalid event object"); + return ECORE_CALLBACK_RENEW; + } + + if (!strcmp(ev->keyname, KEY_END)) { + } else if (!strcmp(ev->keyname, KEY_CONFIG)) { + } else if (!strcmp(ev->keyname, KEY_SEND)) { + } else if (!strcmp(ev->keyname, KEY_HOME)) { + + if (vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &val) < 0) { + _D("Cannot get VCONFKEY_IDLE_LOCK_STATE"); + } + if (val == VCONFKEY_IDLE_LOCK) { + _D("lock state, ignore home key..!!"); + return ECORE_CALLBACK_RENEW; + } + + if (EINA_TRUE == key_info.cancel) { + _D("Cancel key is activated"); + if (key_info.long_press) { + ecore_timer_del(key_info.long_press); + key_info.long_press = NULL; + } + + if (key_info.single_timer) { + ecore_timer_del(key_info.single_timer); + key_info.single_timer = NULL; + } + + return ECORE_CALLBACK_RENEW; + } + + _release_home_key(); + } else if (!strcmp(ev->keyname, KEY_PAUSE)) { + } else if (!strcmp(ev->keyname, KEY_CANCEL)) { + _D("CANCEL Key is released"); + key_info.cancel = EINA_FALSE; + } else if (!strcmp(ev->keyname, KEY_MEDIA)) { + _release_multimedia_key("KEY_PLAYCD"); + } + + return ECORE_CALLBACK_RENEW; +} + + + +static Eina_Bool _key_press_cb(void *data, int type, void *event) +{ + Evas_Event_Key_Down *ev = event; + int val = -1; + + _D("Pressed"); + + if (!ev) { + _D("Invalid event object"); + return ECORE_CALLBACK_RENEW; + } + + if (!strcmp(ev->keyname, KEY_SEND)) { + _D("Launch calllog"); + if (menu_daemon_open_app(CALLLOG_PKG_NAME) < 0) + _E("Failed to launch %s", CALLLOG_PKG_NAME); + } else if(!strcmp(ev->keyname, KEY_CONFIG)) { + _D("Launch camera"); + if (menu_daemon_open_app(CAMERA_PKG_NAME) < 0) + _E("Failed to launch %s", CAMERA_PKG_NAME); + } else if (!strcmp(ev->keyname, KEY_HOME)) { + if (vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &val) < 0) { + _D("Cannot get VCONFKEY_IDLE_LOCK_STATE"); + } + if (val == VCONFKEY_IDLE_LOCK) { + _D("lock state, ignore home key..!!"); + return ECORE_CALLBACK_RENEW; + } + if (key_info.long_press) { + ecore_timer_del(key_info.long_press); + key_info.long_press = NULL; + } + + syspopup_destroy_all(); + + key_info.long_press = ecore_timer_add(0.5, _launch_taskmgr_cb, NULL); + if (!key_info.long_press) + _E("Failed to add timer for long press detection"); + } else if (!strcmp(ev->keyname, KEY_CANCEL)) { + _D("Cancel button is pressed"); + key_info.cancel = EINA_TRUE; + } else if (!strcmp(ev->keyname, KEY_MEDIA)) { + _D("Media key is pressed"); + } + + return ECORE_CALLBACK_RENEW; +} + + + +void _media_key_event_cb(media_key_e key, media_key_event_e status, void *user_data) +{ + _D("MEDIA KEY EVENT"); + if (MEDIA_KEY_STATUS_PRESSED == status) return; + + if (MEDIA_KEY_PAUSE == key) { + _release_multimedia_key("KEY_PAUSECD"); + } else if (MEDIA_KEY_PLAY == key) { + _release_multimedia_key("KEY_PLAYCD"); + } +} + + + +void create_key_window(void) +{ + key_info.win = ecore_x_window_input_new(0, -10000, -10000, 1, 1); + if (!key_info.win) { + _D("Failed to create hidden window"); + return; + } + //ecore_x_event_mask_unset(key_info.win, ECORE_X_EVENT_MASK_NONE); + ecore_x_icccm_title_set(key_info.win, "menudaemon,key,receiver"); + ecore_x_netwm_name_set(key_info.win, "menudaemon,key,receiver"); + ecore_x_netwm_pid_set(key_info.win, getpid()); + ecore_x_flush(); + + utilx_grab_key(ecore_x_display_get(), key_info.win, KEY_HOME, SHARED_GRAB); + utilx_grab_key(ecore_x_display_get(), key_info.win, KEY_VOLUMEDOWN, SHARED_GRAB); + utilx_grab_key(ecore_x_display_get(), key_info.win, KEY_VOLUMEUP, SHARED_GRAB); + utilx_grab_key(ecore_x_display_get(), key_info.win, KEY_CONFIG, SHARED_GRAB); + utilx_grab_key(ecore_x_display_get(), key_info.win, KEY_MEDIA, SHARED_GRAB); + + key_info.key_up = ecore_event_handler_add(ECORE_EVENT_KEY_UP, _key_release_cb, NULL); + if (!key_info.key_up) + _D("Failed to register a key up event handler"); + + key_info.key_down = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _key_press_cb, NULL); + if (!key_info.key_down) + _D("Failed to register a key down event handler"); + + media_key_reserve(_media_key_event_cb, NULL); +} + + + +void destroy_key_window(void) +{ + utilx_ungrab_key(ecore_x_display_get(), key_info.win, KEY_HOME); + utilx_ungrab_key(ecore_x_display_get(), key_info.win, KEY_VOLUMEDOWN); + utilx_ungrab_key(ecore_x_display_get(), key_info.win, KEY_VOLUMEUP); + utilx_ungrab_key(ecore_x_display_get(), key_info.win, KEY_CONFIG); + utilx_ungrab_key(ecore_x_display_get(), key_info.win, KEY_MEDIA); + + if (key_info.key_up) { + ecore_event_handler_del(key_info.key_up); + key_info.key_up = NULL; + } + + if (key_info.key_down) { + ecore_event_handler_del(key_info.key_down); + key_info.key_down = NULL; + } + + ecore_x_window_delete_request_send(key_info.win); + key_info.win = 0x0; + + media_key_release(); +} + + + +// End of a file diff --git a/mobile/src/lock-daemon.c b/mobile/src/lock-daemon.c new file mode 100644 index 0000000..d3908a5 --- /dev/null +++ b/mobile/src/lock-daemon.c @@ -0,0 +1,674 @@ + /* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +#include <Elementary.h> + +#include <vconf.h> +#include <vconf-keys.h> +#include <systemd/sd-daemon.h> +#include <glib.h> +#include <poll.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <sys/param.h> +#include <errno.h> + +#include "lockd-debug.h" +#include "lock-daemon.h" +#include "lockd-process-mgr.h" +#include "lockd-window-mgr.h" +#include "starter-util.h" +#include "menu_daemon.h" + +static int phone_lock_pid; + +struct lockd_data { + int lock_app_pid; + int phone_lock_app_pid; + int lock_type; + Eina_Bool request_recovery; + lockw_data *lockw; + GPollFD *gpollfd; +}; + +#define PHLOCK_SOCK_PREFIX "/tmp/phlock" +#define PHLOCK_SOCK_MAXBUFF 65535 +#define PHLOCK_APP_CMDLINE "/usr/apps/org.tizen.lockscreen/bin/lockscreen" +#define PHLOCK_UNLOCK_CMD "unlock" +#define PHLOCK_LAUNCH_CMD "launch_phone_lock" +#define LAUNCH_INTERVAL 100*1000 + +static int lockd_launch_app_lockscreen(struct lockd_data *lockd); + +static void lockd_unlock_lockscreen(struct lockd_data *lockd); + +static int _lockd_get_lock_type(void) +{ + int lock_type = 0; + int ret = 0; + + vconf_get_int(VCONFKEY_SETAPPL_SCREEN_LOCK_TYPE_INT, &lock_type); + + if (lock_type == SETTING_SCREEN_LOCK_TYPE_PASSWORD || + lock_type == SETTING_SCREEN_LOCK_TYPE_SIMPLE_PASSWORD) { + ret = 1; + } else if (lock_type == SETTING_SCREEN_LOCK_TYPE_SWIPE || + lock_type == SETTING_SCREEN_LOCK_TYPE_MOTION) { + ret = 0; + } else { + ret = 2; + } + + LOCKD_DBG("_lockd_get_lock_type ret(%d), lock_type (%d)", ret, lock_type); + + return ret; +} + +static void _lockd_notify_pm_state_cb(keynode_t * node, void *data) +{ + LOCKD_DBG("PM state Notification!!"); + + struct lockd_data *lockd = (struct lockd_data *)data; + int val = -1; + + if (lockd == NULL) { + LOCKD_ERR("lockd is NULL"); + return; + } + + if (vconf_get_int(VCONFKEY_PM_STATE, &val) < 0) { + LOCKD_ERR("Cannot get VCONFKEY_PM_STATE"); + return; + } + + if (val == VCONFKEY_PM_STATE_LCDOFF) { + lockd->lock_type = _lockd_get_lock_type(); + lockd_launch_app_lockscreen(lockd); + } +} + +static void +_lockd_notify_lock_state_cb(keynode_t * node, void *data) +{ + LOCKD_DBG("lock state changed!!"); + + struct lockd_data *lockd = (struct lockd_data *)data; + int val = -1; + + if (lockd == NULL) { + LOCKD_ERR("lockd is NULL"); + return; + } + + if (vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &val) < 0) { + LOCKD_ERR("Cannot get VCONFKEY_IDLE_LOCK_STATE"); + return; + } + + if (val == VCONFKEY_IDLE_UNLOCK) { + LOCKD_DBG("unlocked..!!"); + if (lockd->lock_app_pid != 0) { + LOCKD_DBG("terminate lock app..!!"); + lockd_process_mgr_terminate_lock_app(lockd->lock_app_pid, 1); + } + } +} + +static Eina_Bool lockd_set_lock_state_cb(void *data) +{ + LOCKD_DBG("%s, %d", __func__, __LINE__); + vconf_set_int(VCONFKEY_IDLE_LOCK_STATE, VCONFKEY_IDLE_LOCK); + return ECORE_CALLBACK_CANCEL; +} + +static void +_lockd_notify_phone_lock_verification_cb(keynode_t * node, void *data) +{ + LOCKD_DBG("%s, %d", __func__, __LINE__); + + struct lockd_data *lockd = (struct lockd_data *)data; + int val = -1; + + if (lockd == NULL) { + LOCKD_ERR("lockd is NULL"); + return; + } + + if (vconf_get_bool(VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION, &val) < 0) { + LOCKD_ERR("Cannot get %s", VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION); + return; + } + + if (val == TRUE) { + lockd_window_mgr_finish_lock(lockd->lockw); + vconf_set_int(VCONFKEY_IDLE_LOCK_STATE, VCONFKEY_IDLE_UNLOCK); + } +} + +static int lockd_app_dead_cb(int pid, void *data) +{ + LOCKD_DBG("app dead cb call! (pid : %d)", pid); + + struct lockd_data *lockd = (struct lockd_data *)data; + + if (pid == lockd->lock_app_pid) { + LOCKD_DBG("lock app(pid:%d) is destroyed.", pid); + + lockd_unlock_lockscreen(lockd); + } + + menu_daemon_check_dead_signal(pid); + + return 0; + +} + +static Eina_Bool lockd_app_create_cb(void *data, int type, void *event) +{ + struct lockd_data *lockd = (struct lockd_data *)data; + + if (lockd == NULL) { + return ECORE_CALLBACK_PASS_ON; + } + LOCKD_DBG("%s, %d", __func__, __LINE__); + if (lockd_window_set_window_effect(lockd->lockw, lockd->lock_app_pid, + event) == EINA_TRUE) { + if(lockd_window_set_window_property(lockd->lockw, lockd->lock_app_pid, + event) == EINA_FALSE) { + LOCKD_ERR("window is not matched..!!"); + } + } + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool lockd_app_show_cb(void *data, int type, void *event) +{ + struct lockd_data *lockd = (struct lockd_data *)data; + + if (lockd == NULL) { + return EINA_TRUE; + } + LOCKD_DBG("%s, %d", __func__, __LINE__); + if (lockd_window_set_window_property(lockd->lockw, lockd->lock_app_pid, + event)) { + ecore_idler_add(lockd_set_lock_state_cb, NULL); + } + return EINA_FALSE; +} + +static int lockd_launch_app_lockscreen(struct lockd_data *lockd) +{ + LOCKD_DBG("launch app lock screen"); + + int call_state = -1, phlock_state = -1, factory_mode = -1, test_mode = -1; + int r = 0; + + WRITE_FILE_LOG("%s", "Launch lockscreen in starter"); + + if (lockd_process_mgr_check_lock(lockd->lock_app_pid) == TRUE) { + LOCKD_DBG("Lock Screen App is already running."); + r = lockd_process_mgr_restart_lock(lockd->lock_type); + if (r < 0) { + LOCKD_DBG("Restarting Lock Screen App is fail [%d].", r); + usleep(LAUNCH_INTERVAL); + } else { + LOCKD_DBG("Restarting Lock Screen App, pid[%d].", r); + return 1; + } + } + + vconf_get_int(VCONFKEY_CALL_STATE, &call_state); + if (call_state != VCONFKEY_CALL_OFF) { + LOCKD_DBG + ("Current call state(%d) does not allow to launch lock screen.", + call_state); + return 0; + } + + lockd->lock_app_pid = + lockd_process_mgr_start_lock(lockd, lockd_app_dead_cb, + lockd->lock_type); + if (lockd->lock_app_pid < 0) + return 0; + lockd_window_mgr_finish_lock(lockd->lockw); + lockd_window_mgr_ready_lock(lockd, lockd->lockw, lockd_app_create_cb, + lockd_app_show_cb); + + return 1; +} + +static void lockd_unlock_lockscreen(struct lockd_data *lockd) +{ + LOCKD_DBG("unlock lock screen"); + lockd->lock_app_pid = 0; + + vconf_set_int(VCONFKEY_IDLE_LOCK_STATE, VCONFKEY_IDLE_UNLOCK); + lockd_window_mgr_finish_lock(lockd->lockw); +} + +inline static void lockd_set_sock_option(int fd, int cli) +{ + int size; + int ret; + struct timeval tv = { 1, 200 * 1000 }; + + size = PHLOCK_SOCK_MAXBUFF; + ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); + if(ret != 0) + return; + ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); + if(ret != 0) + return; + if (cli) { + ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + if(ret != 0) + return; + } +} + +static int lockd_create_sock(void) +{ + struct sockaddr_un saddr; + int fd; + + int n = sd_listen_fds(1); + if (n > 1) { + LOCKD_DBG("too many file descriptors received"); + return -1; + } else if (n == 1) { + int r; + if ((r = sd_is_socket_unix(SD_LISTEN_FDS_START, SOCK_STREAM, 1, PHLOCK_SOCK_PREFIX, 0)) <= 0) { + LOCKD_DBG("passed systemd file descriptor is of wrong type"); + return -1; + } + fd = SD_LISTEN_FDS_START + 0; + } else { + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + if (errno == EINVAL) { + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + LOCKD_DBG("second chance - socket create error"); + return -1; + } + } else { + LOCKD_DBG("socket error"); + return -1; + } + } + + bzero(&saddr, sizeof(saddr)); + saddr.sun_family = AF_UNIX; + + strncpy(saddr.sun_path, PHLOCK_SOCK_PREFIX, strlen(PHLOCK_SOCK_PREFIX)); + saddr.sun_path[strlen(PHLOCK_SOCK_PREFIX)] = 0; + + unlink(saddr.sun_path); + + if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { + LOCKD_DBG("bind error"); + close(fd); + return -1; + } + + if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + LOCKD_DBG("failed to change the socket permission"); + close(fd); + return -1; + } + + lockd_set_sock_option(fd, 0); + + if (listen(fd, 10) == -1) { + LOCKD_DBG("listen error"); + close(fd); + return -1; + } + } + return fd; +} + +static gboolean lockd_glib_check(GSource * src) +{ + GSList *fd_list; + GPollFD *tmp; + + fd_list = src->poll_fds; + do { + tmp = (GPollFD *) fd_list->data; + if ((tmp->revents & (POLLIN | POLLPRI))) + return TRUE; + fd_list = fd_list->next; + } while (fd_list); + + return FALSE; +} + +static char *lockd_read_cmdline_from_proc(int pid) +{ + int memsize = 32; + char path[32]; + char *cmdline = NULL, *tempptr = NULL; + FILE *fp = NULL; + + snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); + + fp = fopen(path, "r"); + if (fp == NULL) { + LOCKD_DBG("Cannot open cmdline on pid[%d]", pid); + return NULL; + } + + cmdline = malloc(32); + if (cmdline == NULL) { + LOCKD_DBG("%s", "Out of memory"); + fclose(fp); + return NULL; + } + + bzero(cmdline, memsize); + if (fgets(cmdline, 32, fp) == NULL) { + LOCKD_DBG("%s", "Cannot read cmdline"); + free(cmdline); + fclose(fp); + return NULL; + } + + while (cmdline[memsize - 2] != 0) { + cmdline[memsize - 1] = (char)fgetc(fp); + tempptr = realloc(cmdline, memsize + 32); + if (tempptr == NULL) { + fclose(fp); + LOCKD_DBG("%s", "Out of memory"); + return NULL; + } + cmdline = tempptr; + bzero(cmdline + memsize, 32); + fgets(cmdline + memsize, 32, fp); + memsize += 32; + } + + if (fp != NULL) + fclose(fp); + return cmdline; +} + +static int lockd_sock_handler(void *data) +{ + int cl; + int len; + int sun_size; + int clifd = -1; + char cmd[PHLOCK_SOCK_MAXBUFF]; + char *cmdline = NULL; + int val = -1; + int fd = -1; + int recovery_state = -1; + GPollFD *gpollfd; + + struct ucred cr; + struct sockaddr_un lockd_addr; + struct lockd_data *lockd = (struct lockd_data *)data; + + if ((lockd == NULL) || (lockd->gpollfd == NULL)) { + LOCKD_DBG("lockd->gpollfd is NULL"); + return -1; + } + gpollfd = (GPollFD *)lockd->gpollfd; + fd = gpollfd->fd; + + cl = sizeof(cr); + sun_size = sizeof(struct sockaddr_un); + + if ((clifd = + accept(fd, (struct sockaddr *)&lockd_addr, + (socklen_t *) & sun_size)) == -1) { + if (errno != EINTR) + LOCKD_DBG("accept error"); + return -1; + } + + if (getsockopt(clifd, SOL_SOCKET, SO_PEERCRED, &cr, (socklen_t *) & cl) + < 0) { + LOCKD_DBG("peer information error"); + close(clifd); + return -1; + } + LOCKD_DBG("Peer's pid=%d, uid=%d, gid=%d\n", cr.pid, cr.uid, cr.gid); + + memset(cmd, 0, PHLOCK_SOCK_MAXBUFF); + + lockd_set_sock_option(clifd, 1); + + len = recv(clifd, cmd, PHLOCK_SOCK_MAXBUFF, 0); + cmd[PHLOCK_SOCK_MAXBUFF - 1] = '\0'; + + if (len != strlen(cmd)) { + LOCKD_DBG("recv error %d %d", len, strlen(cmd)); + close(clifd); + return -1; + } + + LOCKD_DBG("cmd %s", cmd); + + cmdline = lockd_read_cmdline_from_proc(cr.pid); + if (cmdline == NULL) { + LOCKD_DBG("Error on opening /proc/%d/cmdline", cr.pid); + close(clifd); + return -1; + } + + LOCKD_DBG("/proc/%d/cmdline : %s", cr.pid, cmdline); + LOCKD_DBG("phone_lock_pid : %d vs cr.pid : %d", phone_lock_pid, cr.pid); + + if ((!strncmp(cmdline, PHLOCK_APP_CMDLINE, strlen(cmdline))) + && (!strncmp(cmd, PHLOCK_UNLOCK_CMD, strlen(cmd)))) { + LOCKD_DBG("cmd is %s\n", PHLOCK_UNLOCK_CMD); + + if (phone_lock_pid == cr.pid) { + LOCKD_DBG("pid [%d] %s is verified, unlock..!!\n", cr.pid, + cmdline); + lockd_process_mgr_terminate_phone_lock(phone_lock_pid); + phone_lock_pid = 0; + vconf_set_bool(VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION, TRUE); + } + } else if (!strncmp(cmd, PHLOCK_LAUNCH_CMD, strlen(cmd))) { + LOCKD_DBG("cmd is %s\n", PHLOCK_LAUNCH_CMD); + if (_lockd_get_lock_type() == 1) { + lockd->lock_type = 1; + lockd_launch_app_lockscreen(lockd); + } + } + + if(cmdline != NULL) { + free(cmdline); + cmdline = NULL; + } + + close(clifd); + return 0; +} + +static gboolean lockd_glib_handler(gpointer data) +{ + if (lockd_sock_handler(data) < 0) { + LOCKD_DBG("lockd_sock_handler is failed..!!"); + } + return TRUE; +} + +static gboolean lockd_glib_dispatch(GSource * src, GSourceFunc callback, + gpointer data) +{ + callback(data); + return TRUE; +} + +static gboolean lockd_glib_prepare(GSource * src, gint * timeout) +{ + return FALSE; +} + +static GSourceFuncs funcs = { + .prepare = lockd_glib_prepare, + .check = lockd_glib_check, + .dispatch = lockd_glib_dispatch, + .finalize = NULL +}; + +static int lockd_init_sock(struct lockd_data *lockd) +{ + int fd; + GPollFD *gpollfd; + GSource *src; + int ret; + + fd = lockd_create_sock(); + if (fd < 0) { + LOCKD_DBG("lock daemon create sock failed..!!"); + } + + src = g_source_new(&funcs, sizeof(GSource)); + + gpollfd = (GPollFD *) g_malloc(sizeof(GPollFD)); + gpollfd->events = POLLIN; + gpollfd->fd = fd; + + lockd->gpollfd = gpollfd; + + g_source_add_poll(src, lockd->gpollfd); + g_source_set_callback(src, (GSourceFunc) lockd_glib_handler, + (gpointer) lockd, NULL); + g_source_set_priority(src, G_PRIORITY_LOW); + + ret = g_source_attach(src, NULL); + if (ret == 0) + return -1; + + g_source_unref(src); + + return 0; +} + +static void lockd_init_vconf(struct lockd_data *lockd) +{ + int val = -1; + + if (vconf_notify_key_changed + (VCONFKEY_PM_STATE, _lockd_notify_pm_state_cb, lockd) != 0) { + LOCKD_ERR("Fail vconf_notify_key_changed : VCONFKEY_PM_STATE"); + } + + if (vconf_notify_key_changed + (VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION, + _lockd_notify_phone_lock_verification_cb, lockd) != 0) { + if (vconf_get_bool(VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION, &val) < 0) { + LOCKD_ERR + ("Cannot get %s", VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION); + vconf_set_bool(VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION, 0); + if (vconf_notify_key_changed + (VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION, + _lockd_notify_phone_lock_verification_cb, + lockd) != 0) { + LOCKD_ERR + ("Fail vconf_notify_key_changed : %s", VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION); + } + } else { + LOCKD_ERR + ("Fail vconf_notify_key_changed : %s", VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION); + } + } + + if (vconf_notify_key_changed + (VCONFKEY_IDLE_LOCK_STATE, + _lockd_notify_lock_state_cb, + lockd) != 0) { + LOCKD_ERR + ("[Error] vconf notify : lock state"); + } +} + +static void lockd_start_lock_daemon(void *data) +{ + struct lockd_data *lockd = NULL; + int r = 0; + + lockd = (struct lockd_data *)data; + + if (!lockd) { + return; + } + + LOCKD_DBG("%s, %d", __func__, __LINE__); + + lockd_init_vconf(lockd); + + r = lockd_init_sock(lockd); + if (r < 0) { + LOCKD_DBG("lockd init socket failed: %d", r); + } + + lockd->lockw = lockd_window_init(); + + aul_listen_app_dead_signal(lockd_app_dead_cb, data); + + LOCKD_DBG("%s, %d", __func__, __LINE__); +} + +int start_lock_daemon(int launch_lock) +{ + struct lockd_data *lockd = NULL; + int val = -1; + int recovery_state = -1; + int first_boot = 0; + int lock_type = 0; + int ret = 0; + + LOCKD_DBG("%s, %d", __func__, __LINE__); + + lockd = (struct lockd_data *)malloc(sizeof(struct lockd_data)); + memset(lockd, 0x0, sizeof(struct lockd_data)); + lockd_start_lock_daemon(lockd); + + if (launch_lock == FALSE) { + LOCKD_DBG("Don't launch lockscreen.."); + return 0; + } + + if (vconf_get_bool(VCONFKEY_PWLOCK_FIRST_BOOT, &first_boot) < 0) { + LOCKD_ERR("Cannot get %s vconfkey", VCONFKEY_PWLOCK_FIRST_BOOT); + } else if (first_boot == 1) { + LOCKD_DBG("first_boot : %d \n", first_boot); + return 0; + } + + lock_type = _lockd_get_lock_type(); + if (lock_type == 1) { + lockd->request_recovery = FALSE; + } + lockd->lock_type = lock_type; + ret = lockd_launch_app_lockscreen(lockd); + return ret; +} diff --git a/mobile/src/lockd-debug.c b/mobile/src/lockd-debug.c new file mode 100644 index 0000000..72c7227 --- /dev/null +++ b/mobile/src/lockd-debug.c @@ -0,0 +1,94 @@ + /* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +#include <stdio.h> +#include <stdarg.h> +#include <fcntl.h> +#include <time.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <glib.h> + +#include "lockd-debug.h" + +#define LINEMAX 256 +#define MAXFILELEN 1048576 +#define LOGFILE "/tmp/starter.log" + +void lockd_log_t(char *fmt, ...) +{ + va_list ap; + FILE *fd = 0; + char buf[LINEMAX] = { 0, }; + char debugString[LINEMAX] = { 0, }; + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + int fileLen = 0; + struct tm local_t; + time_t current_time = 0; + bzero((char *)&debugString, LINEMAX); + time(¤t_time); + gmtime_r(¤t_time, &local_t); + int len = snprintf(debugString, sizeof(debugString), + "[%d-%02d-%02d, %02d:%02d:%02d]: ", + local_t.tm_year + 1900, local_t.tm_mon + 1, + local_t.tm_mday, local_t.tm_hour, local_t.tm_min, + local_t.tm_sec); + if (len == -1) { + return; + } else { + debugString[len] = '\0'; + } + len = g_strlcat(debugString, buf, LINEMAX); + if (len >= LINEMAX) { + return; + } else { + debugString[len] = '\n'; + } + if ((fd = fopen(LOGFILE, "at+")) == NULL) { + LOCKD_DBG("File fopen fail for writing Pwlock information"); + } else { + int pid = -1; + if (fwrite(debugString, strlen(debugString), 1, fd) < 1) { + LOCKD_DBG + ("File fwrite fail for writing Pwlock information"); + fclose(fd); + if ((pid = fork()) < 0) { + } else if (pid == 0) { + execl("/bin/rm", "rm", "-f", LOGFILE, + (char *)0); + } + } else { + fseek(fd, 0l, SEEK_END); + fileLen = ftell(fd); + if (fileLen > MAXFILELEN) { + fclose(fd); + if ((pid = fork()) < 0) { + return; + } else if (pid == 0) { + execl("/bin/rm", "rm", "-f", LOGFILE, + (char *)0); + } + } else + fclose(fd); + } + } +} diff --git a/mobile/src/lockd-process-mgr.c b/mobile/src/lockd-process-mgr.c new file mode 100644 index 0000000..f9bc863 --- /dev/null +++ b/mobile/src/lockd-process-mgr.c @@ -0,0 +1,176 @@ + /* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +#include <vconf.h> +#include <vconf-keys.h> + +#include <aul.h> + +#include "lockd-debug.h" +#include "lockd-process-mgr.h" +#include "starter-vconf.h" + +#define LOCKD_DEFAULT_PKG_NAME "org.tizen.lockscreen" +#define LOCKD_DEFAULT_LOCKSCREEN "org.tizen.lockscreen" +#define LOCKD_PHONE_LOCK_PKG_NAME "org.tizen.lockscreen" +#define RETRY_MAXCOUNT 30 +#define RELAUNCH_INTERVAL 100*1000 + +static char *_lockd_process_mgr_get_pkgname(void) +{ + char *pkgname = NULL; + + pkgname = vconf_get_str(VCONFKEY_SETAPPL_3RD_LOCK_PKG_NAME_STR); + + LOCKD_DBG("pkg name is %s", pkgname); + + if (pkgname == NULL) { + return LOCKD_DEFAULT_PKG_NAME; + } + + return pkgname; +} + +int lockd_process_mgr_restart_lock(int phone_lock_state) +{ + char *lock_app_path = NULL; + int pid; + + lock_app_path = _lockd_process_mgr_get_pkgname(); + pid = aul_launch_app(lock_app_path, NULL); + + LOCKD_DBG("Reset : aul_launch_app(%s, NULL), pid = %d", lock_app_path, + pid); + + return pid; +} + +int lockd_process_mgr_start_lock(void *data, int (*dead_cb) (int, void *), + int phone_lock_state) +{ + char *lock_app_path = NULL; + int pid; + int ret; + + lock_app_path = _lockd_process_mgr_get_pkgname(); + + int i; + for (i=0; i<RETRY_MAXCOUNT; i++) + { + pid = aul_launch_app(lock_app_path, NULL); + + LOCKD_DBG("aul_launch_app(%s), pid = %d", lock_app_path, pid); + + if (pid == AUL_R_ECOMM) { + LOCKD_DBG("Relaunch lock application [%d]times", i); + usleep(RELAUNCH_INTERVAL); + } else if (pid == AUL_R_ERROR) { + LOCKD_DBG("launch[%s] is failed, launch default lock screen", lock_app_path); + ret = vconf_set_str(VCONFKEY_SETAPPL_3RD_LOCK_PKG_NAME_STR, LOCKD_DEFAULT_LOCKSCREEN); + if (ret != 0) { + LOCKD_ERR("set failed"); + } + pid = aul_launch_app(LOCKD_DEFAULT_LOCKSCREEN, NULL); + if (pid >0) { + return pid; + } + } else { + return pid; + } + } + LOCKD_DBG("Relaunch lock application failed..!!"); + return pid; +} + +int lockd_process_mgr_start_normal_lock(void *data, int (*dead_cb) (int, void *)) +{ + int pid = 0; + + int i; + for (i=0; i<RETRY_MAXCOUNT; i++) + { + pid = aul_launch_app(LOCKD_DEFAULT_PKG_NAME, NULL); + + LOCKD_DBG("aul_launch_app(%s), pid = %d", LOCKD_DEFAULT_PKG_NAME, pid); + + if (pid == AUL_R_ECOMM) { + LOCKD_DBG("Relaunch lock application [%d]times", i); + usleep(RELAUNCH_INTERVAL); + } else if (pid == AUL_R_ERROR) { + LOCKD_DBG("launch[%s] is failed, launch default lock screen", LOCKD_DEFAULT_PKG_NAME); + pid = aul_launch_app(LOCKD_DEFAULT_LOCKSCREEN, NULL); + if (pid >0) { + return pid; + } + } else { + return pid; + } + } + LOCKD_DBG("Relaunch lock application failed..!!"); + return pid; +} + +int lockd_process_mgr_start_phone_lock(void) +{ + int pid = 0; + + pid = aul_launch_app(LOCKD_PHONE_LOCK_PKG_NAME, NULL); + LOCKD_DBG("aul_launch_app(%s, b), pid = %d", LOCKD_PHONE_LOCK_PKG_NAME, + pid); + return pid; +} + +void lockd_process_mgr_terminate_lock_app(int lock_app_pid, int state) +{ + LOCKD_DBG + ("lockd_process_mgr_terminate_lock_app, state:%d\n", + state); + + if (state == 1) { + if (lock_app_pid != 0) { + LOCKD_DBG("Terminate Lock app(pid : %d)", lock_app_pid); + aul_terminate_pid(lock_app_pid); + } + } +} + +void lockd_process_mgr_terminate_phone_lock(int phone_lock_pid) +{ + LOCKD_DBG("Terminate Phone Lock(pid : %d)", phone_lock_pid); + aul_terminate_pid(phone_lock_pid); +} + +int lockd_process_mgr_check_lock(int pid) +{ + char buf[128]; + LOCKD_DBG("%s, %d", __func__, __LINE__); + + if (aul_app_get_pkgname_bypid(pid, buf, sizeof(buf)) < 0) { + LOCKD_DBG("no such pkg by pid %d\n", pid); + } else { + LOCKD_DBG("app pkgname = %s, pid = %d\n", buf, pid); + if (aul_app_is_running(buf) == TRUE) { + LOCKD_DBG("%s [pid = %d] is running\n", buf, pid); + return TRUE; + } else { + LOCKD_DBG("[pid = %d] is exist but %s is not running\n", + pid, buf); + } + } + return FALSE; +} diff --git a/mobile/src/lockd-window-mgr.c b/mobile/src/lockd-window-mgr.c new file mode 100644 index 0000000..4d826e5 --- /dev/null +++ b/mobile/src/lockd-window-mgr.c @@ -0,0 +1,283 @@ + /* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +#include <Elementary.h> +#include <Ecore_X.h> +#include <utilX.h> +#include <ui-gadget.h> +#include <vconf.h> +#include <bundle.h> +#include <appcore-efl.h> +#include <app.h> + +#include "lockd-debug.h" +#include "lockd-window-mgr.h" + +#define PACKAGE "starter" +#define SOS_KEY_COUNT 3 +#define SOS_KEY_INTERVAL 0.5 + +struct _lockw_data { + Evas_Object *main_win; + Evas_Object *main_layout; + + Ecore_X_Window lock_x_window; + + Ecore_Event_Handler *h_keydown; + Ecore_Event_Handler *h_wincreate; + Ecore_Event_Handler *h_winshow; + + Ecore_Timer *pTimerId; + int volume_key_cnt; + + int phone_lock_state; + int phone_lock_app_pid; +}; + +static Eina_Bool _lockd_window_key_down_cb(void *data, int type, void *event) +{ + Ecore_Event_Key *ev = event; + + LOCKD_DBG("Key Down CB : %s", ev->keyname); + + return ECORE_CALLBACK_PASS_ON; +} + +static int +_lockd_window_check_validate_rect(Ecore_X_Display * dpy, Ecore_X_Window window) +{ + Ecore_X_Window root; + Ecore_X_Window child; + + int rel_x = 0; + int rel_y = 0; + int abs_x = 0; + int abs_y = 0; + + unsigned int width = 0; + unsigned int height = 0; + unsigned int border = 0; + unsigned int depth = 0; + + Eina_Bool ret = FALSE; + + root = ecore_x_window_root_first_get(); + + if (XGetGeometry + (dpy, window, &root, &rel_x, &rel_y, &width, &height, &border, + &depth)) { + if (XTranslateCoordinates + (dpy, window, root, 0, 0, &abs_x, &abs_y, &child)) { + if ((abs_x - border) >= 480 || (abs_y - border) >= 800 + || (width + abs_x) <= 0 || (height + abs_y) <= 0) { + ret = FALSE; + } else { + ret = TRUE; + } + } + } + + return ret; +} + +static Window get_user_created_window(Window win) +{ + Atom type_ret = 0; + int ret, size_ret = 0; + unsigned long num_ret = 0, bytes = 0; + unsigned char *prop_ret = NULL; + unsigned int xid; + Atom prop_user_created_win; + + prop_user_created_win = + XInternAtom(ecore_x_display_get(), "_E_USER_CREATED_WINDOW", False); + + ret = + XGetWindowProperty(ecore_x_display_get(), win, + prop_user_created_win, 0L, 1L, False, 0, + &type_ret, &size_ret, &num_ret, &bytes, + &prop_ret); + + if (ret != Success) { + if (prop_ret) + XFree((void *)prop_ret); + return win; + } else if (!prop_ret) { + return win; + } + + memcpy(&xid, prop_ret, sizeof(unsigned int)); + XFree((void *)prop_ret); + + return xid; + +} + +Eina_Bool +lockd_window_set_window_property(lockw_data * data, int lock_app_pid, + void *event) +{ + Ecore_X_Event_Window_Create *e = event; + Ecore_X_Window user_window = 0; + lockw_data *lockw = (lockw_data *) data; + int pid = 0; + + if (!lockw) { + return EINA_FALSE; + } + LOCKD_DBG("%s, %d", __func__, __LINE__); + + user_window = get_user_created_window((Window) (e->win)); + + int ret = ecore_x_netwm_pid_get(user_window, &pid); + if(ret != 1) { + return EINA_FALSE; + } + + LOCKD_DBG("Check PID(%d) window. (lock_app_pid : %d)\n", pid, + lock_app_pid); + + if (lock_app_pid == pid) { + if (_lockd_window_check_validate_rect + (ecore_x_display_get(), user_window) == TRUE) { + lockw->lock_x_window = user_window; + LOCKD_DBG + ("This is lock application. Set window property. win id : %x", + user_window); + + ecore_x_icccm_name_class_set(user_window, "LOCK_SCREEN", + "LOCK_SCREEN"); + ecore_x_netwm_window_type_set(user_window, + ECORE_X_WINDOW_TYPE_NOTIFICATION); + utilx_set_system_notification_level(ecore_x_display_get + (), user_window, + UTILX_NOTIFICATION_LEVEL_NORMAL); + utilx_set_window_opaque_state(ecore_x_display_get(), + user_window, + UTILX_OPAQUE_STATE_ON); + return EINA_TRUE; + } + } + return EINA_FALSE; +} + +Eina_Bool +lockd_window_set_window_effect(lockw_data * data, int lock_app_pid, void *event) +{ + Ecore_X_Event_Window_Create *e = event; + Ecore_X_Window user_window = 0; + int pid = 0; + + user_window = get_user_created_window((Window) (e->win)); + int ret = ecore_x_netwm_pid_get(user_window, &pid); + if(ret != 1) { + return EINA_FALSE; + } + + LOCKD_DBG("%s, %d", __func__, __LINE__); + + LOCKD_DBG("PID(%d) window created. (lock_app_pid : %d)\n", pid, + lock_app_pid); + + if (lock_app_pid == pid) { + if (_lockd_window_check_validate_rect + (ecore_x_display_get(), user_window) == TRUE) { + LOCKD_DBG + ("This is lock application. Disable window effect. win id : %x\n", + user_window); + + utilx_set_window_effect_state(ecore_x_display_get(), + user_window, 0); + return EINA_TRUE; + } + } + return EINA_FALSE; +} + +void lockd_window_set_phonelock_pid(lockw_data * data, int phone_lock_pid) +{ + lockw_data *lockw = (lockw_data *) data; + + if (!lockw) { + return; + } + LOCKD_DBG("%s, %d", __func__, __LINE__); + lockw->phone_lock_app_pid = phone_lock_pid; + LOCKD_DBG("%s, %d, lockw->phone_lock_app_pid = %d", __func__, __LINE__, + lockw->phone_lock_app_pid); +} + +void +lockd_window_mgr_ready_lock(void *data, lockw_data * lockw, + Eina_Bool(*create_cb) (void *, int, void *), + Eina_Bool(*show_cb) (void *, int, void *)) +{ + if (lockw == NULL) { + LOCKD_ERR("lockw is NULL."); + return; + } + lockw->h_wincreate = + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CREATE, create_cb, + data); + lockw->h_winshow = + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW, show_cb, data); + + lockw->volume_key_cnt = 0; + + lockw->h_keydown = + ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, + _lockd_window_key_down_cb, lockw); +} + +void lockd_window_mgr_finish_lock(lockw_data * lockw) +{ + Ecore_X_Window xwin; + + if (lockw == NULL) { + LOCKD_ERR("lockw is NULL."); + return; + } + if (lockw->h_wincreate != NULL) { + ecore_event_handler_del(lockw->h_wincreate); + lockw->h_wincreate = NULL; + } + if (lockw->h_winshow != NULL) { + ecore_event_handler_del(lockw->h_winshow); + lockw->h_winshow = NULL; + } + + ecore_x_pointer_ungrab(); + + if (lockw->h_keydown != NULL) { + ecore_event_handler_del(lockw->h_keydown); + lockw->h_keydown = NULL; + } +} + +lockw_data *lockd_window_init(void) +{ + lockw_data *lockw = NULL; + long pid; + + lockw = (lockw_data *) malloc(sizeof(lockw_data)); + memset(lockw, 0x0, sizeof(lockw_data)); + + pid = getpid(); + + return lockw; +} diff --git a/mobile/src/menu_daemon.c b/mobile/src/menu_daemon.c new file mode 100644 index 0000000..ebb5237 --- /dev/null +++ b/mobile/src/menu_daemon.c @@ -0,0 +1,373 @@ + /* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +#include <ail.h> +#include <aul.h> +#include <db-util.h> +#include <Elementary.h> +#include <errno.h> +#include <fcntl.h> +#include <pkgmgr-info.h> +#include <stdio.h> +#include <sysman.h> +#include <syspopup_caller.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include <vconf.h> + +#include "hw_key.h" +#include "pkg_event.h" +#include "util.h" +#include "xmonitor.h" + + +int errno; + + +#define QUERY_UPDATE_NAME "UPDATE app_info SET name='%s' where package='%s';" +#define SAT_DESKTOP_FILE "/opt/share/applications/org.tizen.sat-ui.desktop" +#define RELAUNCH_INTERVAL 100*1000 +#define RETRY_MAXCOUNT 30 + +static struct info { + pid_t home_pid; + pid_t volume_pid; + int power_off; +} s_info = { + .home_pid = -1, + .volume_pid = -1, + .power_off = 0, +}; + + + +#define RETRY_COUNT 5 +int menu_daemon_open_app(const char *pkgname) +{ + register int i; + int r = AUL_R_ETIMEOUT; + for (i = 0; AUL_R_ETIMEOUT == r && i < RETRY_COUNT; i ++) { + r = aul_open_app(pkgname); + if (0 <= r) return r; + else { + _D("aul_open_app error(%d)", r); + _F("cannot open an app(%s) by %d", pkgname, r); + } + usleep(500000); + } + + return r; +} + + + +int menu_daemon_launch_app(const char *pkgname, bundle *b) +{ + register int i; + int r = AUL_R_ETIMEOUT; + for (i = 0; AUL_R_ETIMEOUT == r && i < RETRY_COUNT; i ++) { + r = aul_launch_app(pkgname, b); + if (0 <= r) return r; + else { + _D("aul_launch_app error(%d)", r); + _F("cannot launch an app(%s) by %d", pkgname, r); + } + usleep(500000); + } + + return r; +} + + + +bool menu_daemon_is_homescreen(pid_t pid) +{ + if (s_info.home_pid == pid) return true; + return false; +} + + + +inline char *menu_daemon_get_selected_pkgname(void) +{ + char *pkgname = NULL; + + pkgname = vconf_get_str(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME); + retv_if(NULL == pkgname, NULL); + + return pkgname; +} + + + +static bool _exist_package(char *pkgid) +{ + int ret = 0; + pkgmgrinfo_pkginfo_h handle = NULL; + + ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &handle); + if (PMINFO_R_OK != ret || NULL == handle) { + _D("%s doesn't exist in this binary", pkgid); + return false; + } + + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + + return true; +} + + + +inline void menu_daemon_open_homescreen(const char *pkgname) +{ + char *homescreen = NULL; + char *tmp = NULL; + + system("echo -e '[${_G}menu-daemon launches home-screen${C_}]' > /dev/kmsg"); + + if (NULL == pkgname) { + tmp = menu_daemon_get_selected_pkgname(); + ret_if(NULL == tmp); + homescreen = tmp; + } else { + homescreen = (char *) pkgname; + } + + syspopup_destroy_all(); + + int ret; + ret = menu_daemon_open_app(homescreen); + _D("can%s launch %s now. (%d)", ret < 0 ? "not" : "", homescreen, ret); + if (ret < 0 && strcmp(homescreen, HOME_SCREEN_PKG_NAME) && _exist_package(HOME_SCREEN_PKG_NAME)) { + _E("cannot launch package %s", homescreen); + + if (0 != vconf_set_str(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, HOME_SCREEN_PKG_NAME)) { + _E("Cannot set value(%s) into key(%s)", VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, HOME_SCREEN_PKG_NAME); + } + + while (AUL_R_ETIMEOUT == ret) { + _E("Failed to open a default home, %s", HOME_SCREEN_PKG_NAME); + ret = menu_daemon_open_app(HOME_SCREEN_PKG_NAME); + } + } + + if (ret < 0) { + _E("Critical! Starter cannot launch anymore[%d]", ret); + _F("Critical! Starter cannot launch anymore[%d]", ret); + } + + s_info.home_pid = ret; + if (ret > 0) { + if (-1 == sysconf_set_mempolicy_bypid(ret, OOM_IGNORE)) { + _E("Cannot set the memory policy for Home-screen(%d)", ret); + } else { + _D("Set the memory policy for Home-screen(%d)", ret); + } + } + + if (tmp) free(tmp); +} + + + +static void _show_cb(keynode_t* node, void *data) +{ + int seq; + + _D("[MENU_DAEMON] _show_cb is invoked"); + + if (node) { + seq = vconf_keynode_get_int(node); + } else { + if (vconf_get_int(VCONFKEY_STARTER_SEQUENCE, &seq) < 0) { + _E("Failed to get sequence info"); + return; + } + } + + switch (seq) { + case 0: + if (s_info.home_pid > 0) { + int pid; + _D("pid[%d] is terminated.", s_info.home_pid); + pid = s_info.home_pid; + s_info.home_pid = -1; + + if (aul_terminate_pid(pid) != AUL_R_OK) + _E("Failed to terminate %d", s_info.home_pid); + } + break; + case 1: + menu_daemon_open_homescreen(NULL); + break; + default: + _E("False sequence [%d]", seq); + break; + } + + return; +} + + + +static void _pkg_changed(keynode_t* node, void *data) +{ + char *pkgname; + int seq; + + if (vconf_get_int(VCONFKEY_STARTER_SEQUENCE, &seq) < 0) { + _E("Do nothing, there is no sequence info yet"); + return; + } + + if (seq < 1) { + _E("Sequence is not ready yet, do nothing"); + return; + } + + _D("_pkg_changed is invoked"); + + pkgname = menu_daemon_get_selected_pkgname(); + if (!pkgname) + return; + + _D("pkg_name : %s", pkgname); + + if (s_info.home_pid > 0) { + char old_pkgname[256]; + + if (aul_app_get_pkgname_bypid(s_info.home_pid, old_pkgname, sizeof(old_pkgname)) == AUL_R_OK) { + if (!strcmp(pkgname, old_pkgname)) { + _D("Package is changed but same package is selected"); + free(pkgname); + return; + } + } + + if (AUL_R_OK != aul_terminate_pid(s_info.home_pid)) + _D("Failed to terminate pid %d", s_info.home_pid); + } else { + /* If there is no running home */ + menu_daemon_open_homescreen(pkgname); + } + + free(pkgname); + return; +} + + + +static void _launch_volume(void) +{ + int pid; + int i; + _D("_launch_volume"); + + for (i=0; i<RETRY_MAXCOUNT; i++) + { + pid = syspopup_launch("volume", NULL); + + _D("syspopup_launch(volume), pid = %d", pid); + + if (pid <0) { + _D("syspopup_launch(volume)is failed [%d]times", i); + usleep(RELAUNCH_INTERVAL); + } else { + s_info.volume_pid = pid; + return; + } + } +} + +int menu_daemon_check_dead_signal(int pid) +{ + if (s_info.power_off) { + _D("Power off. ignore dead cb\n"); + return 0; + } + + _D("Process %d is termianted", pid); + + if (pid < 0) + return 0; + + if (pid == s_info.home_pid) { + char *pkgname = NULL; + pkgname = menu_daemon_get_selected_pkgname(); + retv_if(NULL == pkgname, 0); + + _D("pkg_name : %s", pkgname); + menu_daemon_open_homescreen(pkgname); + free(pkgname); + } else if (pid == s_info.volume_pid) { + _launch_volume(); + } else { + _D("Unknown process, ignore it (pid %d, home pid %d)", + pid, s_info.home_pid); + } + + + return 0; +} + + + +void menu_daemon_init(void *data) +{ + _D( "[MENU_DAEMON]menu_daemon_init is invoked"); + + aul_launch_init(NULL,NULL); + + create_key_window(); + if (xmonitor_init() < 0) _E("cannot init xmonitor"); + + pkg_event_init(); + _launch_volume(); + + if (unlink(SAT_DESKTOP_FILE) != 0) + _E("cannot remove sat-ui desktop."); + + if (vconf_notify_key_changed(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, _pkg_changed, NULL) < 0) + _E("Failed to add the callback for package change event"); + + if (vconf_notify_key_changed(VCONFKEY_STARTER_SEQUENCE, _show_cb, NULL) < 0) + _E("Failed to add the callback for show event"); + + _pkg_changed(NULL, NULL); + vconf_set_int(VCONFKEY_IDLE_SCREEN_LAUNCHED, VCONFKEY_IDLE_SCREEN_LAUNCHED_TRUE); +} + + + +void menu_daemon_fini(void) +{ + if (vconf_ignore_key_changed(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, _pkg_changed) < 0) + _E("Failed to ignore the callback for package change event"); + + if (vconf_ignore_key_changed(VCONFKEY_STARTER_SEQUENCE, _show_cb) < 0) + _E("Failed to ignore the callback for show event"); + + xmonitor_fini(); + pkg_event_fini(); + destroy_key_window(); +} + + + +// End of a file diff --git a/mobile/src/pkg_event.c b/mobile/src/pkg_event.c new file mode 100644 index 0000000..46feba9 --- /dev/null +++ b/mobile/src/pkg_event.c @@ -0,0 +1,301 @@ + /* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +#include <ail.h> +#include <errno.h> +#include <Elementary.h> +#include <Ecore.h> +#include <Ecore_File.h> +#include <stdio.h> +#include <sys/inotify.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <stdbool.h> +#include <unistd.h> +#include <vconf.h> + +#include "pkg_event.h" +#include "util.h" + + +#define CONF_FILE "/usr/share/install-info/desktop.conf" +#define BUFSZE 1024 + + +extern int errno; +struct inotify_path +{ + int wd; + char *path; +}; + +struct desktop_notifier s_desktop_notifier = { + .number = 0, + .ifd = 0, + .handler = NULL, +}; + + + +struct inotify_path paths[CONF_PATH_NUMBER]; + + +static Eina_Bool +directory_notify(void* data, Ecore_Fd_Handler* fd_handler) +{ + char *buf; + ssize_t read_size, len, i = 0; + int fd; + + fd = ecore_main_fd_handler_fd_get(fd_handler); + _D("There are some modification, ifd [%d]", fd); + if(fd < 0) { + _E("Failed to get fd"); + return ECORE_CALLBACK_CANCEL; + } + + if (ioctl(fd, FIONREAD, &read_size) < 0) { + _E("Failed to get q size"); + return ECORE_CALLBACK_CANCEL; + } + + if (read_size <= 0) { + _E("Buffer is not ready!!!"); + return ECORE_CALLBACK_RENEW; + } + + buf = malloc(read_size); + if (!buf) { + _E("Failed to allocate heap for event handling"); + return ECORE_CALLBACK_RENEW; + } + + len = read(fd, buf, read_size); + if (len < 0) { + free(buf); + return ECORE_CALLBACK_CANCEL; + } + buf[read_size - 1] = '\0'; + + while (i < len) { + struct inotify_event* event = (struct inotify_event*) &buf[i]; + char *str_potksed = "potksed."; + char *package = NULL; + ssize_t idx; + int nev_name; + + nev_name = strlen(event->name) - 1; + for (idx = 0; nev_name >= 0 && str_potksed[idx]; idx++) { + if (event->name[nev_name] != str_potksed[idx]) { + break; + } + nev_name --; + } + + if (str_potksed[idx] != '\0' || nev_name < 0) { + _D("This is not a desktop file : %s", event->name); + i += sizeof(struct inotify_event) + event->len; + continue; + } + + package = strdup(event->name); + break_if(NULL == package); + + package[nev_name + 1] = '\0'; + _D("Package : %s", package); + + if (event->mask & IN_CLOSE_WRITE || event->mask & IN_MOVED_TO) { + ail_appinfo_h ai = NULL; + ail_error_e ret; + + ret = ail_get_appinfo(package, &ai); + if (AIL_ERROR_OK == ret || AIL_ERROR_NO_DATA == ret) { + if (ai) ail_destroy_appinfo(ai); + + if (AIL_ERROR_NO_DATA == ret) { + if (ail_desktop_add(package) < 0) { + _D("Failed to add a new package (%s)", event->name); + } + } else if (AIL_ERROR_OK == ret) { + if (ail_desktop_update(package) < 0) { + _D("Failed to add a new package (%s)", event->name); + } + } + } else { + _E("Failed to get appinfo"); + } + } else if (event->mask & IN_DELETE) { + if (ail_desktop_remove(package) < 0) + _D("Failed to remove a package (%s)", event->name); + } else { + _D("this event is not dealt with inotify"); + } + + free(package); + + i += sizeof(struct inotify_event) + event->len; + } + + free(buf); + return ECORE_CALLBACK_RENEW; +} + + + +static inline char *_ltrim(char *str) +{ + retv_if(NULL == str, NULL); + while (*str && (*str == ' ' || *str == '\t' || *str == '\n')) str ++; + return str; +} + + + +static inline int _rtrim(char *str) +{ + int len; + + retv_if(NULL == str, 0); + + len = strlen(str); + while (--len >= 0 && (str[len] == ' ' || str[len] == '\n' || str[len] == '\t')) { + str[len] = '\0'; + } + + return len; +} + + + +static int _retrieve_conf_path(struct inotify_path* paths) +{ + char *line = NULL; + FILE *fp; + size_t size = 0; + ssize_t read; + int i = 0; + + fp = fopen(CONF_FILE, "r"); + if (NULL == fp) { + _E(CONF_FILE); + return -1; + } + + while ((read = getline(&line, &size, fp)) != -1 && i < CONF_PATH_NUMBER - 1) { + char *begin; + + if (size <= 0) break; + + begin = _ltrim(line); + _rtrim(line); + + if (*begin == '#' || *begin == '\0') continue; + + paths[i].path = strdup(begin); + i++; + } + + if (line) free(line); + paths[i].path = NULL; + fclose(fp); + + return i; +} + + + +static void _unretrieve_conf_path(struct inotify_path* paths, int number) +{ + register int i; + + for (i = 0; i < number; i ++) { + if (paths[i].path) { + free(paths[i].path); + paths[i].path = NULL; + } + } +} + + + +void pkg_event_init() +{ + int wd = 0; + int i; + + s_desktop_notifier.ifd = inotify_init(); + if (s_desktop_notifier.ifd == -1) { + _E("inotify_init error: %s", strerror(errno)); + return; + } + + s_desktop_notifier.number = _retrieve_conf_path(paths); + + for (i = 0; i < CONF_PATH_NUMBER && paths[i].path; i++) + { + _D("Configuration file for desktop file monitoring [%s] is added", paths[i].path); + if (access(paths[i].path, R_OK) != 0) + { + ecore_file_mkpath(paths[i].path); + if (chmod(paths[i].path, 0777) == -1) { + _E("cannot chmod %s", paths[i].path); + } + } + + wd = inotify_add_watch(s_desktop_notifier.ifd, paths[i].path, IN_CLOSE_WRITE | IN_MOVED_TO | IN_DELETE); + if (wd == -1) { + _E("inotify_add_watch error: %s", strerror(errno)); + close(s_desktop_notifier.ifd); + return; + } + + paths[i].wd = wd; + } + + s_desktop_notifier.handler = ecore_main_fd_handler_add(s_desktop_notifier.ifd, ECORE_FD_READ, directory_notify, NULL, NULL, NULL); + if (!s_desktop_notifier.handler) { + _E("cannot add handler for inotify"); + } +} + + + +void pkg_event_fini(void) +{ + register int i; + + if (s_desktop_notifier.handler) { + ecore_main_fd_handler_del(s_desktop_notifier.handler); + } + + for (i = 0; i < CONF_PATH_NUMBER; i ++) { + if (paths[i].wd) { + if (inotify_rm_watch(s_desktop_notifier.ifd, paths[i].wd) < 0) { + _E("Error: %s", strerror(errno)); + } + paths[i].wd = 0; + } + } + + _unretrieve_conf_path(paths, s_desktop_notifier.number); + + if (s_desktop_notifier.ifd) { + close(s_desktop_notifier.ifd); + s_desktop_notifier.ifd = 0; + } +} diff --git a/mobile/src/starter.c b/mobile/src/starter.c new file mode 100644 index 0000000..d96c444 --- /dev/null +++ b/mobile/src/starter.c @@ -0,0 +1,273 @@ + /* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +#include <Elementary.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <poll.h> +#include <systemd/sd-daemon.h> + +#include <aul.h> +#include <vconf.h> +#include <heynoti.h> +#include <signal.h> +#include <system_info.h> + +#include "starter.h" +#include "starter-util.h" +#include "x11.h" +#include "lock-daemon.h" +#include "lockd-debug.h" +#include "menu_daemon.h" + +#ifndef PACKAGE_NAME +#define PACKAGE_NAME "org.tizen.starter" +#endif + +#define DEFAULT_THEME "tizen" +#define PWLOCK_PATH "/usr/apps/org.tizen.pwlock/bin/pwlock" +#define PWLOCK_PKG_NAME "org.tizen.pwlock" +#define QP_EMUL_STR "Emulator" + +static void lock_menu_screen(void) +{ + vconf_set_int(VCONFKEY_STARTER_SEQUENCE, 0); +} + +static void unlock_menu_screen(void) +{ + int r; + int show_menu; + + show_menu = 0; + r = vconf_get_int(VCONFKEY_STARTER_SEQUENCE, &show_menu); + if (r || !show_menu) { + vconf_set_int(VCONFKEY_STARTER_SEQUENCE, 1); + } +} + +static void _set_elm_theme(void) +{ + char *vstr; + char *theme; + Elm_Theme *th = NULL; + vstr = vconf_get_str(VCONFKEY_SETAPPL_WIDGET_THEME_STR); + if (vstr == NULL) + theme = DEFAULT_THEME; + else + theme = vstr; + + th = elm_theme_new(); + _DBG("theme vconf[%s]\n set[%s]\n", vstr, theme); + elm_theme_set(th, theme); + + if (vstr) + free(vstr); +} + +static int _check_emul() +{ + int is_emul = 0; + char *info = NULL; + + if (system_info_get_value_string(SYSTEM_INFO_KEY_MODEL, &info) == 0) { + if (info == NULL) return 0; + if (!strncmp(QP_EMUL_STR, info, strlen(info))) { + is_emul = 1; + } + } + + if (info != NULL) free(info); + + return is_emul; +} + +static int _launch_pwlock(void) +{ + int r; + + _DBG("%s", __func__); + + if(_check_emul()) { + _DBG("Emulator => skip pwlock"); + vconf_set_int(VCONFKEY_STARTER_SEQUENCE, 1); + return 0; + } + + r = aul_launch_app(PWLOCK_PKG_NAME, NULL); + if (r < 0) { + _ERR("PWLock launch error: error(%d)", r); + if (r == AUL_R_ETIMEOUT) { + _DBG("Launch pwlock is failed for AUL_R_ETIMEOUT, again launch pwlock"); + r = aul_launch_app(PWLOCK_PKG_NAME, NULL); + if (r < 0) { + _ERR("2'nd PWLock launch error: error(%d)", r); + return -1; + } else { + _DBG("Launch pwlock"); + return 0; + } + } else { + return -1; + } + } else { + _DBG("Launch pwlock"); + return 0; + } +} + +static void _signal_handler(int signum, siginfo_t *info, void *unused) +{ + _DBG("_signal_handler : Terminated..."); + elm_exit(); +} + +static void _heynoti_event_power_off(void *data) +{ + _DBG("_heynoti_event_power_off : Terminated..."); + elm_exit(); +} + +static Eina_Bool _init_idle(void *data) +{ + _DBG("%s %d\n", __func__, __LINE__); + if (_launch_pwlock() < 0) { + _ERR("launch pwlock error"); + } + menu_daemon_init(NULL); + + return ECORE_CALLBACK_CANCEL; +} + +static void _lock_state_cb(keynode_t * node, void *data) +{ + _DBG("%s %d\n", __func__, __LINE__); + WRITE_FILE_LOG("%s", "Lock state is changed!"); + + if (_launch_pwlock() < 0) { + _ERR("launch pwlock error"); + } + menu_daemon_init(NULL); + if (vconf_ignore_key_changed(VCONFKEY_IDLE_LOCK_STATE, + _lock_state_cb) != 0) { + LOCKD_DBG("Fail to unregister"); + } +} + +static void _init(struct appdata *ad) +{ + int r; + struct sigaction act; + + memset(&act,0x00,sizeof(struct sigaction)); + act.sa_sigaction = _signal_handler; + act.sa_flags = SA_SIGINFO; + + int ret = sigemptyset(&act.sa_mask); + if (ret < 0) { + _ERR("Failed to sigemptyset[%s]", strerror(errno)); + } + ret = sigaddset(&act.sa_mask, SIGTERM); + if (ret < 0) { + _ERR("Failed to sigaddset[%s]", strerror(errno)); + } + ret = sigaction(SIGTERM, &act, NULL); + if (ret < 0) { + _ERR("Failed to sigaction[%s]", strerror(errno)); + } + + memset(ad, 0, sizeof(struct appdata)); + + gettimeofday(&ad->tv_start, NULL); + + lock_menu_screen(); + _set_elm_theme(); + + _DBG("%s %d\n", __func__, __LINE__); + + r = start_lock_daemon(TRUE); + if (r == 1) { + if (vconf_notify_key_changed(VCONFKEY_IDLE_LOCK_STATE, + _lock_state_cb, NULL) != 0) { + _ERR("[Error] vconf notify : lock state"); + ecore_timer_add(1.5, _init_idle, NULL); + } + } else { + if (_launch_pwlock() < 0) { + _ERR("launch pwlock error"); + } + menu_daemon_init(NULL); + } +} + +static void _fini(struct appdata *ad) +{ + struct timeval tv, res; + + if (ad == NULL) { + fprintf(stderr, "Invalid argument: appdata is NULL\n"); + return; + } + + unlock_menu_screen(); + menu_daemon_fini(); + + gettimeofday(&tv, NULL); + timersub(&tv, &ad->tv_start, &res); + _DBG("Total time: %d.%06d sec\n", (int)res.tv_sec, (int)res.tv_usec); +} + +int main(int argc, char *argv[]) +{ + struct appdata ad; + + WRITE_FILE_LOG("%s", "Main function is started in starter"); + + int heyfd = heynoti_init(); + if (heyfd < 0) { + _ERR("Failed to heynoti_init[%d]", heyfd); + return -1; + } + + int ret = heynoti_subscribe(heyfd, "power_off_start", _heynoti_event_power_off, NULL); + if (ret < 0) { + _ERR("Failed to heynoti_subscribe[%d]", ret); + } + ret = heynoti_attach_handler(heyfd); + if (ret < 0) { + _ERR("Failed to heynoti_attach_handler[%d]", ret); + } + + elm_init(argc, argv); + + _init(&ad); + + sd_notify(0, "READY=1"); + elm_run(); + + _fini(&ad); + + elm_shutdown(); + + return 0; +} diff --git a/mobile/src/x11.c b/mobile/src/x11.c new file mode 100644 index 0000000..df41f28 --- /dev/null +++ b/mobile/src/x11.c @@ -0,0 +1,111 @@ + /* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +#include <X11/Xlib.h> +#include <X11/Xatom.h> +#include <X11/Xutil.h> + +#define DEFAULT_WINDOW_H 1280 + +void prop_string_set(const char *name, const char *value) +{ + Display *d; + Atom a_name; + Atom a_UTF8; + XTextProperty xtp; + + if (name == NULL || value == NULL || value[0] == '\0') + return; + + d = XOpenDisplay(NULL); + if (d == NULL) + return; + + a_name = XInternAtom(d, name, False); + if (a_name == None) + goto exit; + + a_UTF8 = XInternAtom(d, "UTF8_STRING", False); + if (a_UTF8 == None) + goto exit; + + xtp.value = (unsigned char *)value; + xtp.format = 8; + xtp.encoding = a_UTF8; + xtp.nitems = strlen(value); + + XSetTextProperty(d, DefaultRootWindow(d), &xtp, a_name); + + exit: + XCloseDisplay(d); +} + +void prop_int_set(const char *name, unsigned int val) +{ + Display *d; + Atom a_name; + + if (name == NULL) + return; + + d = XOpenDisplay(NULL); + if (d == NULL) + return; + + a_name = XInternAtom(d, name, False); + if (a_name == None) + goto exit; + + XChangeProperty(d, DefaultRootWindow(d), a_name, XA_CARDINAL, 32, + PropModeReplace, (unsigned char *)&val, 1); + + exit: + XCloseDisplay(d); +} + +void set_window_scale(void) +{ + double root_width = 0.0, root_height = 0.0; + char buf[128] = { 0, }; + Display *disp; + int screen_num; + + disp = XOpenDisplay(NULL); + if (disp == NULL) + return; + + screen_num = DefaultScreen(disp); + + root_width = DisplayWidth(disp, screen_num); + root_height = DisplayHeight(disp, screen_num); + + XCloseDisplay(disp); + + snprintf(buf, sizeof(buf), "%lf", root_height / DEFAULT_WINDOW_H); + + if (root_width == 800 && root_height == 1280) { + snprintf(buf, sizeof(buf), "0.71"); + } + + setenv("ELM_SCALE", buf, 1); + setenv("SCALE_FACTOR", buf, 1); +} diff --git a/mobile/src/xmonitor.c b/mobile/src/xmonitor.c new file mode 100644 index 0000000..4c87285 --- /dev/null +++ b/mobile/src/xmonitor.c @@ -0,0 +1,296 @@ + /* + * Copyright 2012 Samsung Electronics Co., Ltd + * + * Licensed under the Flora License, Version 1.1 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +#include <ail.h> +#include <aul.h> +#include <dlog.h> +#include <Ecore.h> +#include <Ecore_X.h> +#include <Evas.h> +#include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include <sys/shm.h> +#include <vconf.h> + +#include "menu_daemon.h" +#include "util.h" +#include "starter-util.h" +#include "xmonitor.h" + + + +static struct info { + Ecore_Event_Handler *create_handler; + Ecore_Event_Handler *destroy_handler; + Ecore_Event_Handler *focus_in_handler; + Ecore_Event_Handler *focus_out_handler; + int is_top; +} xmonitor_info = { + .create_handler = NULL, + .destroy_handler = NULL, + .focus_in_handler = NULL, + .focus_out_handler = NULL, + .is_top = VCONFKEY_IDLE_SCREEN_TOP_FALSE, +}; + + + +int errno; + + + +static inline int _get_pid(Ecore_X_Window win) +{ + int pid; + Ecore_X_Atom atom; + unsigned char *in_pid = NULL; + int num; + + atom = ecore_x_atom_get("X_CLIENT_PID"); + if (ecore_x_window_prop_property_get(win, atom, ECORE_X_ATOM_CARDINAL, + sizeof(int), &in_pid, &num) == EINA_FALSE) { + if(in_pid != NULL) { + free(in_pid); + in_pid = NULL; + } + if (ecore_x_netwm_pid_get(win, &pid) == EINA_FALSE) { + _E("Failed to get PID from a window 0x%X", win); + return -EINVAL; + } + } else { + pid = *(int *)in_pid; + free(in_pid); + } + + return pid; +} + + + +bool _set_idlescreen_top(void) +{ + Ecore_X_Window win; + + int is_top; + int ret; + int focused_pid; + + win = ecore_x_window_focus_get(); + focused_pid = _get_pid(win); + retv_if(focused_pid <= 0, false); + + is_top = menu_daemon_is_homescreen(focused_pid)? + VCONFKEY_IDLE_SCREEN_TOP_TRUE : VCONFKEY_IDLE_SCREEN_TOP_FALSE; + + if (is_top != xmonitor_info.is_top) { + ret = vconf_set_int(VCONFKEY_IDLE_SCREEN_TOP, is_top); + retv_if(0 != ret, false); + xmonitor_info.is_top = is_top; + _D("set the key of idlescreen_is_top as %d", is_top); + } + + return true; +} + + + +static Eina_Bool _create_cb(void *data, int type, void *event) +{ + Ecore_X_Event_Window_Create *info = event; + + _D("Create a window[%x]", info->win); + + ecore_x_window_client_sniff(info->win); + + return ECORE_CALLBACK_PASS_ON; +} + + + +static Eina_Bool _destroy_cb(void *data, int type, void *event) +{ + return ECORE_CALLBACK_PASS_ON; +} + + + +static Eina_Bool _focus_in_cb(void *data, int type, void *event) +{ + Ecore_X_Event_Window_Focus_In *info = event; + + _D("Focus in a window[%x]", info->win); + + retv_if(false == _set_idlescreen_top(), ECORE_CALLBACK_PASS_ON); + + return ECORE_CALLBACK_PASS_ON; +} + + + +static Eina_Bool _focus_out_cb(void *data, int type, void *event) +{ + Ecore_X_Event_Window_Focus_Out *info = event; + + _D("Focus out a window[%x]", info->win); + + return ECORE_CALLBACK_PASS_ON; +} + + + +static inline void _sniff_all_windows(void) +{ + Ecore_X_Window root; + Ecore_X_Window ret; + struct stack_item *new_item; + struct stack_item *item; + Eina_List *win_stack = NULL; + struct stack_item { + Ecore_X_Window *wins; + int nr_of_wins; + int i; + }; + + root = ecore_x_window_root_first_get(); + ecore_x_window_sniff(root); + + new_item = malloc(sizeof(*new_item)); + if (!new_item) { + _E("Error(%s)\n", strerror(errno)); + return; + } + + new_item->nr_of_wins = 0; + new_item->wins = + ecore_x_window_children_get(root, &new_item->nr_of_wins); + new_item->i = 0; + + if (new_item->wins) + win_stack = eina_list_append(win_stack, new_item); + else + free(new_item); + + while ((item = eina_list_nth(win_stack, 0))) { + win_stack = eina_list_remove(win_stack, item); + + if (!item->wins) { + free(item); + continue; + } + + while (item->i < item->nr_of_wins) { + ret = item->wins[item->i]; + + ecore_x_window_client_sniff(ret); + + new_item = malloc(sizeof(*new_item)); + if (!new_item) { + _E("Error %s\n", strerror(errno)); + item->i++; + continue; + } + + new_item->i = 0; + new_item->nr_of_wins = 0; + new_item->wins = + ecore_x_window_children_get(ret, + &new_item->nr_of_wins); + if (new_item->wins) { + win_stack = + eina_list_append(win_stack, new_item); + } else { + free(new_item); + } + + item->i++; + } + + free(item->wins); + free(item); + } + + return; +} + + + +int xmonitor_init(void) +{ + if (ecore_x_composite_query() == EINA_FALSE) + _D("====> COMPOSITOR IS NOT ENABLED"); + + xmonitor_info.create_handler = + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CREATE, _create_cb, NULL); + goto_if(NULL == xmonitor_info.create_handler, Error); + + xmonitor_info.destroy_handler = + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY, _destroy_cb, NULL); + goto_if(NULL == xmonitor_info.destroy_handler, Error); + + xmonitor_info.focus_in_handler = + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_IN, _focus_in_cb, NULL); + goto_if(NULL == xmonitor_info.focus_in_handler, Error); + + xmonitor_info.focus_out_handler = + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, _focus_out_cb, NULL); + goto_if(NULL == xmonitor_info.focus_out_handler, Error); + + _sniff_all_windows(); + if (false == _set_idlescreen_top()) _E("cannot set idlescreen_is_top"); + + return 0; + +Error: + if (xmonitor_info.create_handler) { + ecore_event_handler_del(xmonitor_info.create_handler); + xmonitor_info.create_handler = NULL; + } else return -EFAULT; + + if (xmonitor_info.destroy_handler) { + ecore_event_handler_del(xmonitor_info.destroy_handler); + xmonitor_info.destroy_handler = NULL; + } else return -EFAULT; + + if (xmonitor_info.focus_in_handler) { + ecore_event_handler_del(xmonitor_info.focus_in_handler); + xmonitor_info.focus_in_handler = NULL; + } else return -EFAULT; + + if (xmonitor_info.focus_out_handler) { + ecore_event_handler_del(xmonitor_info.focus_out_handler); + xmonitor_info.focus_out_handler = NULL; + } else return -EFAULT; + + return -EFAULT; +} + +void xmonitor_fini(void) +{ + ecore_event_handler_del(xmonitor_info.create_handler); + xmonitor_info.create_handler = NULL; + + ecore_event_handler_del(xmonitor_info.destroy_handler); + xmonitor_info.destroy_handler = NULL; + + ecore_event_handler_del(xmonitor_info.focus_in_handler); + xmonitor_info.focus_in_handler = NULL; + + ecore_event_handler_del(xmonitor_info.focus_out_handler); + xmonitor_info.focus_out_handler = NULL; +} |