2 * Copyright 2012 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.tizenopensource.org/license
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <Elementary.h>
22 #include <vconf-keys.h>
28 #include <sys/socket.h>
30 #include <sys/types.h>
35 #include <sys/param.h>
38 #include "lockd-debug.h"
39 #include "lock-daemon.h"
40 #include "lockd-process-mgr.h"
41 #include "lockd-window-mgr.h"
42 #include "starter-util.h"
43 #include "menu_daemon.h"
45 static int phone_lock_pid;
49 int phone_lock_app_pid;
50 int lock_type; /* 0:Normal, 1:Security, 2:Other */
51 Eina_Bool request_recovery;
59 pid_t pid; /* PID of sending process. */
60 uid_t uid; /* UID of sending process. */
61 gid_t gid; /* GID of sending process. */
65 #define PHLOCK_SOCK_PREFIX "/tmp/phlock"
66 #define PHLOCK_SOCK_MAXBUFF 65535
67 #define PHLOCK_APP_CMDLINE "/usr/apps/org.tizen.phone-lock/bin/phone-lock"
68 #define MDM_APP_CMDLINE "/usr/bin/mdm-server"
69 #define PHLOCK_UNLOCK_CMD "unlock"
70 #define PHLOCK_LAUNCH_CMD "launch_phone_lock"
71 #define LAUNCH_INTERVAL 100*1000
73 static int lockd_launch_app_lockscreen(struct lockd_data *lockd);
75 static void lockd_unlock_lockscreen(struct lockd_data *lockd);
77 static int _lockd_get_lock_type(void)
82 vconf_get_int(VCONFKEY_SETAPPL_SCREEN_LOCK_TYPE_INT, &lock_type);
84 if (lock_type == SETTING_SCREEN_LOCK_TYPE_PASSWORD ||
85 lock_type == SETTING_SCREEN_LOCK_TYPE_SIMPLE_PASSWORD ||
86 lock_type == SETTING_SCREEN_LOCK_TYPE_FACE_AND_VOICE) {
88 } else if (lock_type == SETTING_SCREEN_LOCK_TYPE_SWIPE ||
89 lock_type == SETTING_SCREEN_LOCK_TYPE_MOTION) {
95 LOCKD_DBG("_lockd_get_lock_type ret(%d), lock_type (%d)", ret, lock_type);
100 static void _lockd_notify_pm_state_cb(keynode_t * node, void *data)
102 LOCKD_DBG("PM state Notification!!");
104 struct lockd_data *lockd = (struct lockd_data *)data;
108 LOCKD_ERR("lockd is NULL");
112 if (vconf_get_int(VCONFKEY_PM_STATE, &val) < 0) {
113 LOCKD_ERR("Cannot get VCONFKEY_PM_STATE");
117 if (val == VCONFKEY_PM_STATE_LCDOFF) {
118 lockd->lock_type = _lockd_get_lock_type();
119 lockd_launch_app_lockscreen(lockd);
124 _lockd_notify_lock_state_cb(keynode_t * node, void *data)
126 LOCKD_DBG("lock state changed!!");
128 struct lockd_data *lockd = (struct lockd_data *)data;
132 LOCKD_ERR("lockd is NULL");
136 if (vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &val) < 0) {
137 LOCKD_ERR("Cannot get VCONFKEY_IDLE_LOCK_STATE");
141 if (val == VCONFKEY_IDLE_UNLOCK) {
142 LOCKD_DBG("unlocked..!!");
143 if (lockd->lock_app_pid != 0) {
144 LOCKD_DBG("terminate lock app..!!");
145 lockd_process_mgr_terminate_lock_app(lockd->lock_app_pid, 1);
151 _lockd_notify_phone_lock_verification_cb(keynode_t * node, void *data)
153 LOCKD_DBG("%s, %d", __func__, __LINE__);
155 struct lockd_data *lockd = (struct lockd_data *)data;
159 LOCKD_ERR("lockd is NULL");
163 if (vconf_get_bool(VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION, &val) < 0) {
164 LOCKD_ERR("Cannot get %s", VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION);
169 /* password verified */
170 /* lockd_unlock_lockscreen(lockd); */
171 lockd_window_mgr_finish_lock(lockd->lockw);
172 vconf_set_int(VCONFKEY_IDLE_LOCK_STATE, VCONFKEY_IDLE_UNLOCK);
176 static int lockd_app_dead_cb(int pid, void *data)
178 LOCKD_DBG("app dead cb call! (pid : %d)", pid);
180 struct lockd_data *lockd = (struct lockd_data *)data;
182 if (pid == lockd->lock_app_pid && lockd->lock_type == 0) {
183 LOCKD_DBG("lock app(pid:%d) is destroyed.", pid);
185 lockd_unlock_lockscreen(lockd);
188 menu_daemon_check_dead_signal(pid);
193 static Eina_Bool lockd_set_lock_state_cb(void *data)
195 LOCKD_DBG("%s, %d", __func__, __LINE__);
196 vconf_set_int(VCONFKEY_IDLE_LOCK_STATE, VCONFKEY_IDLE_LOCK);
197 return ECORE_CALLBACK_CANCEL;
200 static Eina_Bool lockd_app_create_cb(void *data, int type, void *event)
202 struct lockd_data *lockd = (struct lockd_data *)data;
205 return ECORE_CALLBACK_PASS_ON;
207 LOCKD_DBG("%s, %d", __func__, __LINE__);
208 lockd_window_set_window_effect(lockd->lockw, lockd->lock_app_pid,
210 //FIXME sometimes show cb is not called.
211 lockd_window_set_window_property(lockd->lockw, lockd->lock_app_pid,
214 return ECORE_CALLBACK_PASS_ON;
217 static Eina_Bool lockd_app_show_cb(void *data, int type, void *event)
219 struct lockd_data *lockd = (struct lockd_data *)data;
224 LOCKD_DBG("%s, %d", __func__, __LINE__);
225 lockd_window_set_window_property(lockd->lockw, lockd->lock_app_pid,
227 if (lockd->lock_type > 1)
228 ecore_idler_add(lockd_set_lock_state_cb, NULL);
233 static int lockd_launch_app_lockscreen(struct lockd_data *lockd)
235 LOCKD_DBG("launch app lock screen");
237 int call_state = -1, phlock_state = -1, factory_mode = -1, test_mode = -1;
240 WRITE_FILE_LOG("%s", "Launch lockscreen in starter");
241 vconf_get_int(VCONFKEY_TELEPHONY_SIM_FACTORY_MODE, &factory_mode);
242 if (factory_mode == VCONFKEY_TELEPHONY_SIM_FACTORYMODE_ON) {
243 LOCKD_DBG("Factory mode ON, lock screen can't be launched..!!");
246 vconf_get_int(VCONFKEY_TESTMODE_SCREEN_LOCK, &test_mode);
247 if (test_mode == VCONFKEY_TESTMODE_SCREEN_LOCK_DISABLE) {
248 LOCKD_DBG("Test mode ON, lock screen can't be launched..!!");
252 /* Check lock screen application is already exit, no checking phone-lock */
253 if (lockd_process_mgr_check_lock(lockd->lock_app_pid) == TRUE) {
254 LOCKD_DBG("Lock Screen App is already running.");
255 r = lockd_process_mgr_restart_lock(lockd->lock_type);
257 LOCKD_DBG("Restarting Lock Screen App is fail [%d].", r);
258 usleep(LAUNCH_INTERVAL);
260 LOCKD_DBG("Restarting Lock Screen App, pid[%d].", r);
266 vconf_get_int(VCONFKEY_CALL_STATE, &call_state);
267 if (call_state != VCONFKEY_CALL_OFF) {
269 ("Current call state(%d) does not allow to launch lock screen.",
274 if (lockd->lock_type == 0) {
275 lockd->lock_app_pid =
276 lockd_process_mgr_start_normal_lock(lockd, lockd_app_dead_cb);
277 if (lockd->lock_app_pid < 0)
279 /* reset window mgr before start win mgr */
280 lockd_window_mgr_finish_lock(lockd->lockw);
281 lockd_window_mgr_ready_lock(lockd, lockd->lockw, lockd_app_create_cb,
283 } else if (lockd->lock_type == 1) {
284 vconf_set_bool(VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION, FALSE);
285 /* Check phone lock application is already exit */
286 if (lockd_process_mgr_check_lock(lockd->phone_lock_app_pid) == TRUE) {
287 LOCKD_DBG("phone lock App is already running.");
288 if (lockd->request_recovery == FALSE)
292 /* TO DO : Recovery should be checked by EAS interface later */
293 /* After getting EAS interface, we should remove lockd->request_recovery */
294 if (lockd->request_recovery == TRUE) {
295 lockd->phone_lock_app_pid =
296 lockd_process_mgr_start_recovery_lock();
297 lockd->request_recovery = FALSE;
299 lockd->phone_lock_app_pid =
300 lockd_process_mgr_start_phone_lock();
302 phone_lock_pid = lockd->phone_lock_app_pid;
303 LOCKD_DBG("%s, %d, phone_lock_pid = %d", __func__, __LINE__,
305 lockd_window_set_phonelock_pid(lockd->lockw, phone_lock_pid);
308 //ecore_idler_add(lockd_set_lock_state_cb, NULL); //don't set lock state for lcd on.
310 lockd->lock_app_pid =
311 lockd_process_mgr_start_lock(lockd, lockd_app_dead_cb,
313 if (lockd->lock_app_pid < 0)
315 /* reset window mgr before start win mgr */
316 lockd_window_mgr_finish_lock(lockd->lockw);
317 lockd_window_mgr_ready_lock(lockd, lockd->lockw, lockd_app_create_cb,
323 static void lockd_unlock_lockscreen(struct lockd_data *lockd)
325 LOCKD_DBG("unlock lock screen");
326 lockd->lock_app_pid = 0;
328 vconf_set_int(VCONFKEY_IDLE_LOCK_STATE, VCONFKEY_IDLE_UNLOCK);
329 lockd_window_mgr_finish_lock(lockd->lockw);
332 inline static void lockd_set_sock_option(int fd, int cli)
335 struct timeval tv = { 1, 200 * 1000 }; /* 1.2 sec */
337 size = PHLOCK_SOCK_MAXBUFF;
338 setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
339 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
341 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
344 static int lockd_create_sock(void)
346 struct sockaddr_un saddr;
349 fd = socket(AF_UNIX, SOCK_STREAM, 0); /* support above version 2.6.27 */
351 if (errno == EINVAL) {
352 fd = socket(AF_UNIX, SOCK_STREAM, 0);
355 ("second chance - socket create error");
359 LOCKD_DBG("socket error");
364 bzero(&saddr, sizeof(saddr));
365 saddr.sun_family = AF_UNIX;
367 strncpy(saddr.sun_path, PHLOCK_SOCK_PREFIX, strlen(PHLOCK_SOCK_PREFIX));
368 saddr.sun_path[strlen(PHLOCK_SOCK_PREFIX)] = 0;
370 unlink(saddr.sun_path);
372 if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
373 LOCKD_DBG("bind error");
377 if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
378 /* Flawfinder: ignore */
379 LOCKD_DBG("failed to change the socket permission");
383 lockd_set_sock_option(fd, 0);
385 if (listen(fd, 10) == -1) {
386 LOCKD_DBG("listen error");
393 static gboolean lockd_glib_check(GSource * src)
398 fd_list = src->poll_fds;
400 tmp = (GPollFD *) fd_list->data;
401 if ((tmp->revents & (POLLIN | POLLPRI)))
403 fd_list = fd_list->next;
409 static char *lockd_read_cmdline_from_proc(int pid)
413 char *cmdline = NULL, *tempptr = NULL;
416 snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
418 fp = fopen(path, "r");
420 LOCKD_DBG("Cannot open cmdline on pid[%d]", pid);
424 cmdline = malloc(32);
425 if (cmdline == NULL) {
426 LOCKD_DBG("%s", "Out of memory");
431 bzero(cmdline, memsize);
432 if (fgets(cmdline, 32, fp) == NULL) {
433 LOCKD_DBG("%s", "Cannot read cmdline");
439 while (cmdline[memsize - 2] != 0) {
440 cmdline[memsize - 1] = (char)fgetc(fp);
441 tempptr = realloc(cmdline, memsize + 32);
442 if (tempptr == NULL) {
444 LOCKD_DBG("%s", "Out of memory");
448 bzero(cmdline + memsize, 32);
449 fgets(cmdline + memsize, 32, fp);
458 static int lockd_sock_handler(void *data)
464 char cmd[PHLOCK_SOCK_MAXBUFF];
465 char *cmdline = NULL;
468 int recovery_state = -1;
472 struct sockaddr_un lockd_addr;
473 struct lockd_data *lockd = (struct lockd_data *)data;
475 if ((lockd == NULL) || (lockd->gpollfd == NULL)) {
476 LOCKD_DBG("lockd->gpollfd is NULL");
479 gpollfd = (GPollFD *)lockd->gpollfd;
483 sun_size = sizeof(struct sockaddr_un);
486 accept(fd, (struct sockaddr *)&lockd_addr,
487 (socklen_t *) & sun_size)) == -1) {
489 LOCKD_DBG("accept error");
493 if (getsockopt(clifd, SOL_SOCKET, SO_PEERCRED, &cr, (socklen_t *) & cl)
495 LOCKD_DBG("peer information error");
499 LOCKD_DBG("Peer's pid=%d, uid=%d, gid=%d\n", cr.pid, cr.uid, cr.gid);
501 memset(cmd, 0, PHLOCK_SOCK_MAXBUFF);
503 lockd_set_sock_option(clifd, 1);
505 /* receive single packet from socket */
506 len = recv(clifd, cmd, PHLOCK_SOCK_MAXBUFF, 0);
509 LOCKD_DBG("recv error, cmd is NULL");
514 if (len != strlen(cmd)) {
515 LOCKD_DBG("recv error %d %d", len, strlen(cmd));
520 LOCKD_DBG("cmd %s", cmd);
522 /* Read command line of the PID from proc fs */
523 cmdline = lockd_read_cmdline_from_proc(cr.pid);
524 if (cmdline == NULL) {
525 /* It's weired. no file in proc file system, */
526 LOCKD_DBG("Error on opening /proc/%d/cmdline", cr.pid);
531 LOCKD_DBG("/proc/%d/cmdline : %s", cr.pid, cmdline);
532 LOCKD_DBG("phone_lock_pid : %d vs cr.pid : %d", phone_lock_pid, cr.pid);
534 if ((!strncmp(cmdline, PHLOCK_APP_CMDLINE, strlen(cmdline)))
535 && (!strncmp(cmd, PHLOCK_UNLOCK_CMD, strlen(cmd)))) {
536 LOCKD_DBG("cmd is %s\n", PHLOCK_UNLOCK_CMD);
538 if (phone_lock_pid == cr.pid) {
539 LOCKD_DBG("pid [%d] %s is verified, unlock..!!\n", cr.pid,
541 lockd_process_mgr_terminate_phone_lock(phone_lock_pid);
543 vconf_set_bool(VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION, TRUE);
545 } else if (!strncmp(cmd, PHLOCK_LAUNCH_CMD, strlen(cmd))) {
546 LOCKD_DBG("cmd is %s\n", PHLOCK_LAUNCH_CMD);
548 if (!strncmp(cmdline, MDM_APP_CMDLINE, strlen(cmdline))) {
549 LOCKD_DBG("cmdline is %s \n", MDM_APP_CMDLINE);
550 if (vconf_get_int(VCONFKEY_EAS_RECOVERY_MODE, &recovery_state) < 0) {
551 LOCKD_ERR("Cannot get %s vconfkey", VCONFKEY_EAS_RECOVERY_MODE);
552 lockd->request_recovery = FALSE;
553 } else if (recovery_state == 1) {
554 LOCKD_DBG("recovery mode : %d \n", recovery_state);
555 lockd->request_recovery = TRUE;
557 lockd->request_recovery = FALSE;
561 if (_lockd_get_lock_type() == 1) {
562 lockd->lock_type = 1;
563 lockd_launch_app_lockscreen(lockd);
571 static gboolean lockd_glib_handler(gpointer data)
573 if (lockd_sock_handler(data) < 0) {
574 LOCKD_DBG("lockd_sock_handler is failed..!!");
579 static gboolean lockd_glib_dispatch(GSource * src, GSourceFunc callback,
586 static gboolean lockd_glib_prepare(GSource * src, gint * timeout)
591 static GSourceFuncs funcs = {
592 .prepare = lockd_glib_prepare,
593 .check = lockd_glib_check,
594 .dispatch = lockd_glib_dispatch,
598 static int lockd_init_sock(struct lockd_data *lockd)
605 fd = lockd_create_sock();
607 LOCKD_DBG("lock daemon create sock failed..!!");
610 src = g_source_new(&funcs, sizeof(GSource));
612 gpollfd = (GPollFD *) g_malloc(sizeof(GPollFD));
613 gpollfd->events = POLLIN;
616 lockd->gpollfd = gpollfd;
618 g_source_add_poll(src, lockd->gpollfd);
619 g_source_set_callback(src, (GSourceFunc) lockd_glib_handler,
620 (gpointer) lockd, NULL);
621 g_source_set_priority(src, G_PRIORITY_LOW);
623 ret = g_source_attach(src, NULL);
632 static void lockd_init_vconf(struct lockd_data *lockd)
636 if (vconf_notify_key_changed
637 (VCONFKEY_PM_STATE, _lockd_notify_pm_state_cb, lockd) != 0) {
638 LOCKD_ERR("Fail vconf_notify_key_changed : VCONFKEY_PM_STATE");
641 if (vconf_notify_key_changed
642 (VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION,
643 _lockd_notify_phone_lock_verification_cb, lockd) != 0) {
644 if (vconf_get_bool(VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION, &val) < 0) {
646 ("Cannot get %s", VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION);
647 vconf_set_bool(VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION, 0);
648 if (vconf_notify_key_changed
649 (VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION,
650 _lockd_notify_phone_lock_verification_cb,
653 ("Fail vconf_notify_key_changed : %s", VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION);
657 ("Fail vconf_notify_key_changed : %s", VCONFKEY_LOCKSCREEN_PHONE_LOCK_VERIFICATION);
661 if (vconf_notify_key_changed
662 (VCONFKEY_IDLE_LOCK_STATE,
663 _lockd_notify_lock_state_cb,
666 ("[Error] vconf notify : lock state");
670 static void lockd_start_lock_daemon(void *data)
672 struct lockd_data *lockd = NULL;
675 lockd = (struct lockd_data *)data;
681 LOCKD_DBG("%s, %d", __func__, __LINE__);
683 /* register vconf notification */
684 lockd_init_vconf(lockd);
686 /* Initialize socket */
687 r = lockd_init_sock(lockd);
689 LOCKD_DBG("lockd init socket failed: %d", r);
691 /* Create internal 1x1 window */
692 lockd->lockw = lockd_window_init();
694 aul_listen_app_dead_signal(lockd_app_dead_cb, data);
696 LOCKD_DBG("%s, %d", __func__, __LINE__);
699 int start_lock_daemon(int launch_lock)
701 struct lockd_data *lockd = NULL;
703 int recovery_state = -1;
708 LOCKD_DBG("%s, %d", __func__, __LINE__);
710 lockd = (struct lockd_data *)malloc(sizeof(struct lockd_data));
711 memset(lockd, 0x0, sizeof(struct lockd_data));
712 lockd_start_lock_daemon(lockd);
714 if (launch_lock == FALSE) {
715 LOCKD_DBG("Don't launch lockscreen..");
719 if (vconf_get_bool(VCONFKEY_PWLOCK_FIRST_BOOT, &first_boot) < 0) {
720 LOCKD_ERR("Cannot get %s vconfkey", VCONFKEY_PWLOCK_FIRST_BOOT);
721 } else if (first_boot == 1) {
722 LOCKD_DBG("first_boot : %d \n", first_boot);
726 lock_type = _lockd_get_lock_type();
727 if (lock_type == 1) {
728 if (vconf_get_int(VCONFKEY_EAS_RECOVERY_MODE, &recovery_state) < 0) {
729 LOCKD_ERR("Cannot get %s vconfkey", VCONFKEY_EAS_RECOVERY_MODE);
730 lockd->request_recovery = FALSE;
731 } else if (recovery_state == 1) {
732 LOCKD_DBG("recovery mode : %d \n", recovery_state);
733 lockd->request_recovery = TRUE;
735 lockd->request_recovery = FALSE;
737 } else if (lock_type == 2) {
740 lockd->lock_type = lock_type;
741 ret = lockd_launch_app_lockscreen(lockd);