4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Seungtaek Chung <seungtaek.chung@samsung.com>, Mi-Ju Lee <miju52.lee@samsung.com>, Xi Zhichan <zhichan.xi@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 #include <Elementary.h>
25 #include <vconf-keys.h>
30 #include <sys/socket.h>
31 #include <sys/types.h>
37 #include <sys/param.h>
40 #include "lockd-debug.h"
41 #include "lock-daemon.h"
42 #include "lockd-process-mgr.h"
44 static int phone_lock_pid;
47 int phone_lock_app_pid;
57 #define VCONFKEY_PHONE_LOCK_VERIFICATION "memory/lockscreen/phone_lock_verification"
58 #define PHLOCK_SOCK_PREFIX "/tmp/phlock"
59 #define PHLOCK_SOCK_MAXBUFF 65535
60 #define PHLOCK_APP_CMDLINE "/opt/apps/org.tizen.phone-lock/bin/phone-lock"
62 static void lockd_launch_app_lockscreen(struct lockd_data *lockd);
64 static void _lockd_notify_pm_state_cb(keynode_t * node, void *data)
66 LOCKD_DBG("PM state Notification!!");
68 struct lockd_data *lockd = (struct lockd_data *)data;
72 LOCKD_ERR("lockd is NULL");
76 if (vconf_get_int(VCONFKEY_PM_STATE, &val) < 0) {
77 LOCKD_ERR("Cannot get VCONFKEY_PM_STATE");
81 if (val == VCONFKEY_PM_STATE_LCDOFF) {
82 lockd_launch_app_lockscreen(lockd);
87 _lockd_notify_lock_state_cb(keynode_t * node, void *data)
89 LOCKD_DBG("lock state changed!!");
91 struct lockd_data *lockd = (struct lockd_data *)data;
95 LOCKD_ERR("lockd is NULL");
99 if (vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &val) < 0) {
100 LOCKD_ERR("Cannot get VCONFKEY_IDLE_LOCK_STATE");
104 if (val == VCONFKEY_IDLE_UNLOCK) {
105 LOCKD_DBG("unlocked..!!");
110 _lockd_notify_phone_lock_verification_cb(keynode_t * node, void *data)
112 LOCKD_DBG("%s, %d", __func__, __LINE__);
114 struct lockd_data *lockd = (struct lockd_data *)data;
118 LOCKD_ERR("lockd is NULL");
122 if (vconf_get_bool(VCONFKEY_PHONE_LOCK_VERIFICATION, &val) < 0) {
123 LOCKD_ERR("Cannot get VCONFKEY_PHONE_LOCK_VERIFICATION");
128 vconf_set_int(VCONFKEY_IDLE_LOCK_STATE, VCONFKEY_IDLE_UNLOCK);
132 static void lockd_launch_app_lockscreen(struct lockd_data *lockd)
134 LOCKD_DBG("launch app lock screen");
136 int call_state = -1, bootlock_state = -1;
138 vconf_get_bool(VCONFKEY_SETAPPL_STATE_POWER_ON_LOCK_BOOL,
141 if (bootlock_state) {
142 lockd->phone_lock_state = 1;
144 lockd->phone_lock_state = 0;
147 vconf_get_int(VCONFKEY_CALL_STATE, &call_state);
148 if (call_state != VCONFKEY_CALL_OFF) {
150 ("Current call state(%d) does not allow to launch lock screen.",
155 if (lockd->phone_lock_state == 1) {
156 vconf_set_bool(VCONFKEY_PHONE_LOCK_VERIFICATION, FALSE);
157 /* Check phone lock application is already exit */
158 if (lockd_process_mgr_check_lock(lockd->phone_lock_app_pid) == TRUE) {
159 LOCKD_DBG("phone lock App is already running.");
162 vconf_set_int(VCONFKEY_IDLE_LOCK_STATE, VCONFKEY_IDLE_LOCK);
163 lockd->phone_lock_app_pid =
164 lockd_process_mgr_start_phone_lock();
165 phone_lock_pid = lockd->phone_lock_app_pid;
166 LOCKD_DBG("%s, %d, phone_lock_pid = %d", __func__, __LINE__,
171 inline static void lockd_set_sock_option(int fd, int cli)
174 struct timeval tv = { 1, 200 * 1000 };
176 size = PHLOCK_SOCK_MAXBUFF;
177 setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
178 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
180 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
183 static int lockd_create_sock(void)
185 struct sockaddr_un saddr;
188 fd = socket(AF_UNIX, SOCK_STREAM, 0);
190 if (errno == EINVAL) {
191 fd = socket(AF_UNIX, SOCK_STREAM, 0);
194 ("second chance - socket create error");
198 LOCKD_DBG("socket error");
203 bzero(&saddr, sizeof(saddr));
204 saddr.sun_family = AF_UNIX;
206 strncpy(saddr.sun_path, PHLOCK_SOCK_PREFIX, strlen(PHLOCK_SOCK_PREFIX));
207 saddr.sun_path[strlen(PHLOCK_SOCK_PREFIX)] = 0;
209 unlink(saddr.sun_path);
211 if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
212 LOCKD_DBG("bind error");
216 if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
217 LOCKD_DBG("failed to change the socket permission");
221 lockd_set_sock_option(fd, 0);
223 if (listen(fd, 10) == -1) {
224 LOCKD_DBG("listen error");
231 static gboolean lockd_glib_check(GSource * src)
236 fd_list = src->poll_fds;
238 tmp = (GPollFD *) fd_list->data;
239 if ((tmp->revents & (POLLIN | POLLPRI)))
241 fd_list = fd_list->next;
247 static char *lockd_read_cmdline_from_proc(int pid)
251 char *cmdline = NULL, *tempptr = NULL;
254 snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
256 fp = fopen(path, "r");
258 LOCKD_DBG("Cannot open cmdline on pid[%d]", pid);
262 cmdline = malloc(32);
263 if (cmdline == NULL) {
264 LOCKD_DBG("%s", "Out of memory");
269 bzero(cmdline, memsize);
270 if (fgets(cmdline, 32, fp) == NULL) {
271 LOCKD_DBG("%s", "Cannot read cmdline");
277 while (cmdline[memsize - 2] != 0) {
278 cmdline[memsize - 1] = (char)fgetc(fp);
279 tempptr = realloc(cmdline, memsize + 32);
280 if (tempptr == NULL) {
282 LOCKD_DBG("%s", "Out of memory");
286 bzero(cmdline + memsize, 32);
287 fgets(cmdline + memsize, 32, fp);
296 static int lockd_sock_handler(int fd)
302 char cmd[PHLOCK_SOCK_MAXBUFF];
303 char *cmdline = NULL;
306 struct sockaddr_un lockd_addr;
309 sun_size = sizeof(struct sockaddr_un);
312 accept(fd, (struct sockaddr *)&lockd_addr,
313 (socklen_t *) & sun_size)) == -1) {
315 LOCKD_DBG("accept error");
319 if (getsockopt(clifd, SOL_SOCKET, SO_PEERCRED, &cr, (socklen_t *) & cl)
321 LOCKD_DBG("peer information error");
325 LOCKD_DBG("Peer's pid=%d, uid=%d, gid=%d\n", cr.pid, cr.uid, cr.gid);
327 memset(cmd, 0, PHLOCK_SOCK_MAXBUFF);
329 lockd_set_sock_option(clifd, 1);
331 len = recv(clifd, cmd, PHLOCK_SOCK_MAXBUFF, 0);
334 LOCKD_DBG("recv error, cmd is NULL");
339 if (len != strlen(cmd)) {
340 LOCKD_DBG("recv error %d %d", len, strlen(cmd));
345 LOCKD_DBG("cmd %s", cmd);
347 cmdline = lockd_read_cmdline_from_proc(cr.pid);
348 if (cmdline == NULL) {
349 LOCKD_DBG("Error on opening /proc/%d/cmdline", cr.pid);
353 LOCKD_DBG("/proc/%d/cmdline : %s", cr.pid, cmdline);
355 if ((!strncmp(cmdline, PHLOCK_APP_CMDLINE, strlen(cmdline)))
356 && (phone_lock_pid == cr.pid)) {
357 LOCKD_DBG("pid [%d] %s is verified, unlock..!!\n", cr.pid,
359 lockd_process_mgr_terminate_phone_lock(phone_lock_pid);
361 vconf_set_bool(VCONFKEY_PHONE_LOCK_VERIFICATION, TRUE);
367 static gboolean lockd_glib_handler(gpointer data)
369 GPollFD *gpollfd = (GPollFD *) data;
370 if (lockd_sock_handler(gpollfd->fd) < 0) {
371 LOCKD_DBG("lockd_sock_handler is failed..!!");
376 static gboolean lockd_glib_dispatch(GSource * src, GSourceFunc callback,
383 static gboolean lockd_glib_prepare(GSource * src, gint * timeout)
388 static GSourceFuncs funcs = {
389 .prepare = lockd_glib_prepare,
390 .check = lockd_glib_check,
391 .dispatch = lockd_glib_dispatch,
395 static int lockd_init_sock(void)
402 fd = lockd_create_sock();
404 LOCKD_DBG("lock daemon create sock failed..!!");
407 src = g_source_new(&funcs, sizeof(GSource));
409 gpollfd = (GPollFD *) g_malloc(sizeof(GPollFD));
410 gpollfd->events = POLLIN;
413 g_source_add_poll(src, gpollfd);
414 g_source_set_callback(src, (GSourceFunc) lockd_glib_handler,
415 (gpointer) gpollfd, NULL);
416 g_source_set_priority(src, G_PRIORITY_LOW);
418 ret = g_source_attach(src, NULL);
427 static void lockd_init_vconf(struct lockd_data *lockd)
431 if (vconf_notify_key_changed
432 (VCONFKEY_PM_STATE, _lockd_notify_pm_state_cb, lockd) != 0) {
433 LOCKD_ERR("Fail vconf_notify_key_changed : VCONFKEY_PM_STATE");
436 if (vconf_notify_key_changed
437 (VCONFKEY_PHONE_LOCK_VERIFICATION,
438 _lockd_notify_phone_lock_verification_cb, lockd) != 0) {
439 if (vconf_get_bool(VCONFKEY_PHONE_LOCK_VERIFICATION, &val) < 0) {
441 ("Cannot get VCONFKEY_PHONE_LOCK_VERIFICATION");
442 vconf_set_bool(VCONFKEY_PHONE_LOCK_VERIFICATION, 0);
443 if (vconf_notify_key_changed
444 (VCONFKEY_PHONE_LOCK_VERIFICATION,
445 _lockd_notify_phone_lock_verification_cb,
448 ("Fail vconf_notify_key_changed : VCONFKEY_PHONE_LOCK_VERIFICATION");
452 ("Fail vconf_notify_key_changed : VCONFKEY_PHONE_LOCK_VERIFICATION");
456 if (vconf_notify_key_changed
457 (VCONFKEY_IDLE_LOCK_STATE,
458 _lockd_notify_lock_state_cb,
461 ("[Error] vconf notify : lock state");
466 static void lockd_start_lock_daemon(void *data)
468 struct lockd_data *lockd = NULL;
471 lockd = (struct lockd_data *)data;
477 LOCKD_DBG("%s, %d", __func__, __LINE__);
479 lockd_init_vconf(lockd);
481 r = lockd_init_sock();
483 LOCKD_DBG("lockd init socket failed: %d", r);
486 LOCKD_DBG("%s, %d", __func__, __LINE__);
489 int start_lock_daemon()
491 struct lockd_data *lockd = NULL;
494 LOCKD_DBG("%s, %d", __func__, __LINE__);
496 lockd = (struct lockd_data *)malloc(sizeof(struct lockd_data));
497 memset(lockd, 0x0, sizeof(struct lockd_data));
498 lockd_start_lock_daemon(lockd);
500 vconf_get_bool(VCONFKEY_SETAPPL_STATE_POWER_ON_LOCK_BOOL, &val);
501 LOCKD_DBG("%s, %d, val = %d", __func__, __LINE__, val);
504 lockd_launch_app_lockscreen(lockd);