summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJinkun Jang <jinkun.jang@samsung.com>2013-03-13 01:38:20 +0900
committerJinkun Jang <jinkun.jang@samsung.com>2013-03-13 01:38:20 +0900
commit62d214f6031c50109217a6162e09be3bcc1656cf (patch)
tree91b23751dc5760dc973fc51eabcfbe5726b41393 /src
parent19a03cb96bd11947328bd98c2b1f2b56f51b5afa (diff)
downloadstarter-62d214f6031c50109217a6162e09be3bcc1656cf.tar.gz
starter-62d214f6031c50109217a6162e09be3bcc1656cf.tar.bz2
starter-62d214f6031c50109217a6162e09be3bcc1656cf.zip
Tizen 2.1 base
Diffstat (limited to 'src')
-rwxr-xr-xsrc/hw_key.c347
-rwxr-xr-xsrc/lock-daemon.c688
-rwxr-xr-xsrc/lockd-debug.c94
-rwxr-xr-xsrc/lockd-process-mgr.c171
-rwxr-xr-xsrc/lockd-window-mgr.c283
-rwxr-xr-xsrc/menu_daemon.c302
-rwxr-xr-xsrc/pkg_event.c305
-rwxr-xr-xsrc/starter.c247
-rw-r--r--src/x11.c111
-rwxr-xr-xsrc/xmonitor.c296
10 files changed, 2844 insertions, 0 deletions
diff --git a/src/hw_key.c b/src/hw_key.c
new file mode 100755
index 0000000..9d9093d
--- /dev/null
+++ b/src/hw_key.c
@@ -0,0 +1,347 @@
+ /*
+ * Copyright 2012 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.0 (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 <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 "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");
+ if (aul_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_home_screen(void *data)
+{
+ char *package;
+ int ret;
+
+ syspopup_destroy_all();
+ key_info.single_timer = NULL;
+
+ package = vconf_get_str(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME);
+ if (package) {
+ ret = aul_open_app(package);
+ if (ret < 0) {
+ _E("cannot launch package %s(err:%d)", package, ret);
+
+ if (-1 == ret) {
+ ret = aul_open_app(HOME_SCREEN_PKG_NAME);
+ if (ret < 0) {
+ _E("Failed to open a default home, %s(err:%d)", HOME_SCREEN_PKG_NAME, ret);
+ }
+ }
+ }
+
+ free(package);
+ } else {
+ ret = aul_open_app(HOME_SCREEN_PKG_NAME);
+ if (ret < 0) _E("Cannot open default home");
+ }
+
+ if (ret > 0) {
+ if (-1 == sysconf_set_mempolicy_bypid(ret, OOM_IGNORE)) {
+ _E("Cannot set the memory policy for Home-screen(%d)", ret);
+ } else {
+ _E("Set the memory policy for Home-screen(%d)", ret);
+ }
+ }
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
+
+
+inline static int _release_home_key(void)
+{
+ 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_home_screen, NULL);
+ return EXIT_SUCCESS;
+ }
+ ecore_timer_del(key_info.single_timer);
+ key_info.single_timer = NULL;
+
+ syspopup_destroy_all();
+
+ return EXIT_SUCCESS;
+}
+
+
+
+inline static void _release_multimedia_key(const char *value)
+{
+ bundle *b;
+ int ret;
+
+ _D("Multimedia key is released with %s", value);
+ ret_if(NULL == value);
+
+ b = bundle_create();
+ if (!b) {
+ _E("Cannot create bundle");
+ return;
+ }
+
+ bundle_add(b, "multimedia_key", value);
+ ret = aul_launch_app(MUSIC_PLAYER_PKG_NAME, b);
+ bundle_free(b);
+
+ if (ret < 0)
+ _E("Failed to launch the running apps, ret : %d", ret);
+}
+
+
+
+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 (aul_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 (aul_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;
+ }
+
+ key_info.long_press = ecore_timer_add(0.6, _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, 0, 0, 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());
+
+ 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();
+}
diff --git a/src/lock-daemon.c b/src/lock-daemon.c
new file mode 100755
index 0000000..3847f8c
--- /dev/null
+++ b/src/lock-daemon.c
@@ -0,0 +1,688 @@
+ /*
+ * Copyright 2012 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.0 (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 <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->lock_type == 0) {
+ 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)) {
+ if (lockd->lock_type > 1) {
+ 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;
+ }
+
+ if (lockd->lock_type == 0) {
+ lockd->lock_app_pid =
+ lockd_process_mgr_start_normal_lock(lockd, lockd_app_dead_cb);
+ 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);
+ } else if (lockd->lock_type == 1) {
+ vconf_set_bool(VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION, FALSE);
+ if (lockd_process_mgr_check_lock(lockd->phone_lock_app_pid) == TRUE) {
+ LOCKD_DBG("phone lock App is already running.");
+ if (lockd->request_recovery == FALSE)
+ return 1;
+ }
+ lockd->phone_lock_app_pid = lockd_process_mgr_start_phone_lock();
+
+ phone_lock_pid = lockd->phone_lock_app_pid;
+ LOCKD_DBG("%s, %d, phone_lock_pid = %d", __func__, __LINE__,
+ phone_lock_pid);
+ lockd_window_set_phonelock_pid(lockd->lockw, phone_lock_pid);
+ } else {
+ 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;
+
+ 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;
+ } else if (lock_type == 2) {
+ lock_type = 0;
+ }
+ lockd->lock_type = lock_type;
+ ret = lockd_launch_app_lockscreen(lockd);
+ return ret;
+}
diff --git a/src/lockd-debug.c b/src/lockd-debug.c
new file mode 100755
index 0000000..dda6bd5
--- /dev/null
+++ b/src/lockd-debug.c
@@ -0,0 +1,94 @@
+ /*
+ * Copyright 2012 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.0 (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(&current_time);
+ gmtime_r(&current_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/src/lockd-process-mgr.c b/src/lockd-process-mgr.c
new file mode 100755
index 0000000..cbda629
--- /dev/null
+++ b/src/lockd-process-mgr.c
@@ -0,0 +1,171 @@
+ /*
+ * Copyright 2012 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.0 (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(VCONF_PRIVATE_LOCKSCREEN_PKGNAME);
+
+ 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;
+
+ 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);
+ 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/src/lockd-window-mgr.c b/src/lockd-window-mgr.c
new file mode 100755
index 0000000..dc05087
--- /dev/null
+++ b/src/lockd-window-mgr.c
@@ -0,0 +1,283 @@
+ /*
+ * Copyright 2012 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.0 (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/src/menu_daemon.c b/src/menu_daemon.c
new file mode 100755
index 0000000..5697eb4
--- /dev/null
+++ b/src/menu_daemon.c
@@ -0,0 +1,302 @@
+ /*
+ * Copyright 2012 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.0 (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 <fcntl.h>
+#include <stdio.h>
+#include <sysman.h>
+#include <syspopup_caller.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <vconf.h>
+#include <errno.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,
+};
+
+
+
+bool menu_daemon_is_homescreen(pid_t pid)
+{
+ if (s_info.home_pid == pid) return true;
+ return false;
+}
+
+
+
+static inline char *_get_selected_pkgname(void)
+{
+ char *pkgname;
+
+ pkgname = vconf_get_str(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME);
+ if (!pkgname) {
+ _E("Cannot get pkgname from vconf.");
+
+ pkgname = strdup(HOME_SCREEN_PKG_NAME);
+ if (!pkgname) {
+ _E("strdup error for pkgname, %s", strerror(errno));
+ return NULL;
+ }
+ }
+
+ return pkgname;
+}
+
+
+
+static inline void _open_homescreen(const char *pkgname)
+{
+ int ret;
+ char *homescreen = (char *) pkgname;
+
+ system("echo -e '[${_G}menu-daemon launches home-screen${C_}]' > /dev/kmsg");
+ ret = aul_open_app(homescreen);
+ _D("can%s launch %s now. (%d)", ret < 0 ? "not" : "", homescreen, ret);
+ if (ret < 0 && strcmp(homescreen, HOME_SCREEN_PKG_NAME)) {
+ _E("cannot launch package %s", homescreen);
+
+ if (-1 == ret) {
+ ret = aul_open_app(HOME_SCREEN_PKG_NAME);
+ if (ret < 0) {
+ _E("Failed to open a default home, %s(err:%d)", HOME_SCREEN_PKG_NAME, 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 {
+ _E("Set the memory policy for Home-screen(%d)", ret);
+ }
+ }
+}
+
+
+
+static void _show_cb(keynode_t* node, void *data)
+{
+ int seq;
+ char *pkgname;
+
+ _D("[MENU_DAEMON] _show_cb is invoked");
+
+ pkgname = _get_selected_pkgname();
+ if (!pkgname)
+ return;
+
+ if (node) {
+ seq = vconf_keynode_get_int(node);
+ } else {
+ if (vconf_get_int(VCONFKEY_STARTER_SEQUENCE, &seq) < 0) {
+ _E("Failed to get sequence info");
+ free(pkgname);
+ 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:
+ _open_homescreen(pkgname);
+ break;
+ default:
+ _E("False sequence [%d]", seq);
+ break;
+ }
+
+ free(pkgname);
+ 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 = _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_terminate_pid(s_info.home_pid) != AUL_R_OK)
+ _D("Failed to terminate pid %d", s_info.home_pid);
+ } else {
+ _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)
+{
+ char *pkgname;
+
+ 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;
+
+ pkgname = _get_selected_pkgname();
+ if (!pkgname)
+ return 0;
+
+ if (pid == s_info.home_pid) {
+ _D("pkg_name : %s", pkgname);
+ _open_homescreen(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);
+ }
+
+ free(pkgname);
+
+ 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 callback for package change event");
+
+ if (vconf_notify_key_changed(VCONFKEY_STARTER_SEQUENCE, _show_cb, NULL) < 0)
+ _E("Failed to add 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)
+{
+ vconf_ignore_key_changed(VCONFKEY_STARTER_SEQUENCE, _show_cb);
+ vconf_ignore_key_changed(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME, _pkg_changed);
+
+ xmonitor_fini();
+ pkg_event_fini();
+ destroy_key_window();
+}
diff --git a/src/pkg_event.c b/src/pkg_event.c
new file mode 100755
index 0000000..f03b9ef
--- /dev/null
+++ b/src/pkg_event.c
@@ -0,0 +1,305 @@
+ /*
+ * Copyright 2012 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.0 (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) {
+ char log[BUFSZE] = {0,};
+ int ret;
+
+ ret = strerror_r(errno, log, sizeof(log));
+ _E("Error: %s", ret == 0? log : "unknown error");
+ }
+ 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/src/starter.c b/src/starter.c
new file mode 100755
index 0000000..c90601c
--- /dev/null
+++ b/src/starter.c
@@ -0,0 +1,247 @@
+ /*
+ * Copyright 2012 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.0 (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 <aul.h>
+#include <vconf.h>
+#include <heynoti.h>
+#include <signal.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"
+
+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 _launch_pwlock(void)
+{
+ int r;
+
+ _DBG("%s", __func__);
+
+ 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;
+ char *file = NULL;
+
+ 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);
+
+ elm_run();
+
+ _fini(&ad);
+
+ elm_shutdown();
+
+ return 0;
+}
diff --git a/src/x11.c b/src/x11.c
new file mode 100644
index 0000000..01119ec
--- /dev/null
+++ b/src/x11.c
@@ -0,0 +1,111 @@
+ /*
+ * Copyright 2012 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.0 (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/src/xmonitor.c b/src/xmonitor.c
new file mode 100755
index 0000000..cc8d481
--- /dev/null
+++ b/src/xmonitor.c
@@ -0,0 +1,296 @@
+ /*
+ * Copyright 2012 Samsung Electronics Co., Ltd
+ *
+ * Licensed under the Flora License, Version 1.0 (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;
+}