tizen 2.3 release
[framework/system/deviced.git] / src / libdeviced / deviced-noti.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <sys/un.h>
23 #include <stdio.h>
24 #include <unistd.h>
25 #include <stdarg.h>
26 #include <errno.h>
27 #include <vconf.h>
28 #include <vconf-keys.h>
29 #include <limits.h>
30
31 #include "dd-deviced.h"
32 #include "deviced-priv.h"
33 #include "log.h"
34 #include "dbus.h"
35
36 #define PREDEF_PWROFF_POPUP                     "pwroff-popup"
37 #define PREDEF_ENTERSLEEP                       "entersleep"
38 #define PREDEF_LEAVESLEEP                       "leavesleep"
39 #define PREDEF_REBOOT                           "reboot"
40 #define PREDEF_BACKGRD                          "backgrd"
41 #define PREDEF_FOREGRD                          "foregrd"
42 #define PREDEF_ACTIVE                           "active"
43 #define PREDEF_INACTIVE                         "inactive"
44 #define PREDEF_SET_DATETIME                     "set_datetime"
45 #define PREDEF_SET_TIMEZONE                     "set_timezone"
46
47 #define PREDEF_SET_MAX_FREQUENCY                "set_max_frequency"
48 #define PREDEF_SET_MIN_FREQUENCY                "set_min_frequency"
49 #define PREDEF_RELEASE_MAX_FREQUENCY            "release_max_frequency"
50 #define PREDEF_RELEASE_MIN_FREQUENCY            "release_min_frequency"
51
52 #define PREDEF_FACTORY_MODE                     "factorymode"
53
54 #define PREDEF_DUMP_LOG                 "dump_log"
55 #define PREDEF_DELETE_DUMP              "delete_dump"
56 #define FLIGHT_MODE             "flightmode"
57
58 #define ALARM_BUS_NAME          "com.samsung.alarm.manager"
59 #define ALARM_PATH_NAME         "/com/samsung/alarm/manager"
60 #define ALARM_INTERFACE_NAME    ALARM_BUS_NAME
61 #define ALARM_SET_TIME_METHOD   "alarm_set_time"
62
63 enum deviced_noti_cmd {
64         ADD_deviced_ACTION,
65         CALL_deviced_ACTION
66 };
67
68 #define SYSTEM_NOTI_SOCKET_PATH "/tmp/sn"
69 #define RETRY_READ_COUNT        10
70
71 static inline int send_int(int fd, int val)
72 {
73         return write(fd, &val, sizeof(int));
74 }
75
76 static inline int send_str(int fd, char *str)
77 {
78         int len;
79         int ret;
80         if (str == NULL) {
81                 len = 0;
82                 ret = write(fd, &len, sizeof(int));
83         } else {
84                 len = strlen(str);
85                 if (len > SYSTEM_NOTI_MAXSTR)
86                         len = SYSTEM_NOTI_MAXSTR;
87                 write(fd, &len, sizeof(int));
88                 ret = write(fd, str, len);
89         }
90         return ret;
91 }
92
93 static int noti_send(struct sysnoti *msg)
94 {
95         int client_len;
96         int client_sockfd;
97         int result;
98         int r;
99         int retry_count = 0;
100         struct sockaddr_un clientaddr;
101         int i;
102
103         client_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
104         if (client_sockfd == -1) {
105                 _E("socket create failed");
106                 return -1;
107         }
108         bzero(&clientaddr, sizeof(clientaddr));
109         clientaddr.sun_family = AF_UNIX;
110         strncpy(clientaddr.sun_path, SYSTEM_NOTI_SOCKET_PATH, sizeof(clientaddr.sun_path) - 1);
111         client_len = sizeof(clientaddr);
112
113         if (connect(client_sockfd, (struct sockaddr *)&clientaddr, client_len) <
114             0) {
115                 _E("connect failed");
116                 close(client_sockfd);
117                 return -1;
118         }
119
120         send_int(client_sockfd, msg->pid);
121         send_int(client_sockfd, msg->cmd);
122         send_str(client_sockfd, msg->type);
123         send_str(client_sockfd, msg->path);
124         send_int(client_sockfd, msg->argc);
125         for (i = 0; i < msg->argc; i++)
126                 send_str(client_sockfd, msg->argv[i]);
127
128         while (retry_count < RETRY_READ_COUNT) {
129                 r = read(client_sockfd, &result, sizeof(int));
130                 if (r < 0) {
131                         if (errno == EINTR) {
132                                 _E("Re-read for error(EINTR)");
133                                 retry_count++;
134                                 continue;
135                         }
136                         _E("Read fail for str length");
137                         result = -1;
138                         break;
139
140                 }
141                 break;
142         }
143         if (retry_count == RETRY_READ_COUNT) {
144                 _E("Read retry failed");
145         }
146
147         close(client_sockfd);
148         return result;
149 }
150
151 static int dbus_flightmode_handler(char* type, char *buf)
152 {
153         DBusError err;
154         DBusMessage *msg;
155         char *pa[3];
156         int ret, val;
157
158         pa[0] = type;
159         pa[1] = "1";
160         pa[2] = buf;
161
162         msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME,
163                         DEVICED_PATH_POWER, DEVICED_INTERFACE_POWER,
164                         pa[0], "sis", pa);
165         if (!msg)
166                 return -EBADMSG;
167
168         dbus_error_init(&err);
169
170         ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID);
171         if (!ret) {
172                 _E("no message : [%s:%s]", err.name, err.message);
173                 val = -EBADMSG;
174         }
175
176         dbus_message_unref(msg);
177         dbus_error_free(&err);
178
179         _D("%s-%s : %d", DEVICED_INTERFACE_POWER, pa[0], val);
180         return val;
181 }
182
183 API int deviced_change_flightmode(int mode)
184 {
185         char buf[255];
186         snprintf(buf, sizeof(buf), "%d", mode);
187         return dbus_flightmode_handler(FLIGHT_MODE, buf);
188 }
189
190 API int deviced_call_predef_action(const char *type, int num, ...)
191 {
192         struct sysnoti *msg;
193         int ret;
194         va_list argptr;
195         int i;
196         char *args = NULL;
197
198         if (type == NULL || num > SYSTEM_NOTI_MAXARG) {
199                 errno = EINVAL;
200                 return -1;
201         }
202
203         msg = malloc(sizeof(struct sysnoti));
204
205         if (msg == NULL) {
206                 /* Do something for not enought memory error */
207                 return -1;
208         }
209
210         msg->pid = getpid();
211         msg->cmd = CALL_deviced_ACTION;
212         msg->type = (char *)type;
213         msg->path = NULL;
214
215         msg->argc = num;
216         va_start(argptr, num);
217         for (i = 0; i < num; i++) {
218                 args = va_arg(argptr, char *);
219                 msg->argv[i] = args;
220         }
221         va_end(argptr);
222
223         ret = noti_send(msg);
224         free(msg);
225
226         return ret;
227 }
228
229 static int dbus_proc_handler(char* type, char *buf)
230 {
231         DBusError err;
232         DBusMessage *msg;
233         char *pa[3];
234         int ret, val;
235
236         pa[0] = type;
237         pa[1] = "1";
238         pa[2] = buf;
239
240         msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME,
241                         DEVICED_PATH_PROCESS, DEVICED_INTERFACE_PROCESS,
242                         pa[0], "sis", pa);
243         if (!msg)
244                 return -EBADMSG;
245
246         dbus_error_init(&err);
247
248         ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID);
249         if (!ret) {
250                 _E("no message : [%s:%s]", err.name, err.message);
251                 val = -EBADMSG;
252         }
253
254         dbus_message_unref(msg);
255         dbus_error_free(&err);
256
257         _D("%s-%s : %d", DEVICED_INTERFACE_PROCESS, pa[0], val);
258         return val;
259 }
260
261 API int deviced_inform_foregrd(void)
262 {
263         char buf[255];
264         snprintf(buf, sizeof(buf), "%d", getpid());
265         return dbus_proc_handler(PREDEF_FOREGRD, buf);
266 }
267
268 API int deviced_inform_backgrd(void)
269 {
270         char buf[255];
271         snprintf(buf, sizeof(buf), "%d", getpid());
272         return dbus_proc_handler(PREDEF_BACKGRD, buf);
273 }
274
275 API int deviced_inform_active(pid_t pid)
276 {
277         char buf[255];
278         snprintf(buf, sizeof(buf), "%d", pid);
279         return dbus_proc_handler(PREDEF_ACTIVE, buf);
280 }
281
282 API int deviced_inform_inactive(pid_t pid)
283 {
284         char buf[255];
285         snprintf(buf, sizeof(buf), "%d", pid);
286         return dbus_proc_handler(PREDEF_INACTIVE, buf);
287 }
288
289 static int dbus_power_handler(char* type)
290 {
291         DBusError err;
292         DBusMessage *msg;
293         char *pa[2];
294         int ret, val;
295
296         pa[0] = type;
297         pa[1] = "0";
298
299         msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME,
300                         DEVICED_PATH_POWER, DEVICED_INTERFACE_POWER,
301                         pa[0], "si", pa);
302         if (!msg)
303                 return -EBADMSG;
304
305         dbus_error_init(&err);
306
307         ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID);
308         if (!ret) {
309                 _E("no message : [%s:%s]", err.name, err.message);
310                 val = -EBADMSG;
311         }
312
313         dbus_message_unref(msg);
314         dbus_error_free(&err);
315
316         _D("%s-%s : %d", DEVICED_INTERFACE_POWER, pa[0], val);
317         return val;
318 }
319
320 API int deviced_request_poweroff(void)
321 {
322         return dbus_power_handler(PREDEF_PWROFF_POPUP);
323 }
324
325 API int deviced_request_entersleep(void)
326 {
327         return dbus_power_handler(PREDEF_ENTERSLEEP);
328 }
329
330 API int deviced_request_leavesleep(void)
331 {
332         return dbus_power_handler(PREDEF_LEAVESLEEP);
333 }
334
335 API int deviced_request_reboot(void)
336 {
337         return dbus_power_handler(PREDEF_REBOOT);
338 }
339
340 static int dbus_time_handler(char* type, char* buf)
341 {
342         DBusError err;
343         DBusMessage *msg;
344         pid_t pid;
345         char name[PATH_MAX];
346         char *pa[3];
347         int ret, val;
348
349         pa[0] = type;
350         pa[1] = "1";
351         pa[2] = buf;
352
353         pid = getpid();
354         ret = deviced_get_cmdline_name(pid, name, sizeof(name));
355         if (ret != 0)
356                 snprintf(name, sizeof(name), "%d", pid);
357
358         msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME,
359                         DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI,
360                         pa[0], "sis", pa);
361         if (!msg)
362                 return -EBADMSG;
363
364         dbus_error_init(&err);
365
366         ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID);
367         if (!ret) {
368                 _E("no message : [%s:%s]", err.name, err.message);
369                 val = -EBADMSG;
370         }
371
372         dbus_message_unref(msg);
373         dbus_error_free(&err);
374
375         _SI("[%s] %s-%s(%s) : %d", name, DEVICED_INTERFACE_SYSNOTI, pa[0], pa[2], val);
376
377         return val;
378 }
379
380 static DBusMessage *alarm_set_time_sync_with_reply(time_t timet)
381 {
382         DBusConnection *conn;
383         DBusMessage *msg;
384         DBusMessageIter iter;
385         DBusMessage *reply;
386         DBusError err;
387         int r;
388
389         conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
390         if (!conn) {
391                 _E("dbus_bus_get error");
392                 return NULL;
393         }
394
395         msg = dbus_message_new_method_call(ALARM_BUS_NAME, ALARM_PATH_NAME, ALARM_INTERFACE_NAME, ALARM_SET_TIME_METHOD);
396         if (!msg) {
397                 _E("dbus_message_new_method_call(%s:%s-%s)",
398                         ALARM_PATH_NAME, ALARM_INTERFACE_NAME, ALARM_SET_TIME_METHOD);
399                 return NULL;
400         }
401
402         dbus_message_iter_init_append(msg, &iter);
403         dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &timet);
404
405         dbus_error_init(&err);
406
407         reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err);
408         if (!reply) {
409                 _E("dbus_connection_send error(No reply) %s %s:%s-%s",
410                         ALARM_BUS_NAME, ALARM_PATH_NAME, ALARM_INTERFACE_NAME, ALARM_SET_TIME_METHOD);
411         }
412
413         if (dbus_error_is_set(&err)) {
414                 _E("dbus_connection_send error(%s:%s) %s %s:%s-%s",
415                         err.name, err.message, ALARM_BUS_NAME, ALARM_PATH_NAME, ALARM_INTERFACE_NAME, ALARM_SET_TIME_METHOD);
416                 dbus_error_free(&err);
417                 reply = NULL;
418         }
419
420         dbus_message_unref(msg);
421         return reply;
422 }
423
424 static int alarm_set_time(time_t timet)
425 {
426         DBusError err;
427         DBusMessage *msg;
428         pid_t pid;
429         char name[PATH_MAX];
430         int ret, val;
431
432         pid = getpid();
433         ret = deviced_get_cmdline_name(pid, name, sizeof(name));
434         if (ret != 0)
435                 snprintf(name, sizeof(name), "%d", pid);
436         _SI("[%s]start %s %ld", name, ALARM_INTERFACE_NAME, timet);
437
438         msg = alarm_set_time_sync_with_reply(timet);
439         if (!msg)
440                 return -EBADMSG;
441
442         dbus_error_init(&err);
443
444         ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID);
445         if (!ret) {
446                 _E("no message : [%s:%s]", err.name, err.message);
447                 val = -EBADMSG;
448         }
449
450         dbus_message_unref(msg);
451         dbus_error_free(&err);
452
453         _SI("[%s]end %s %ld, %d", name, ALARM_INTERFACE_NAME, timet, val);
454         return val;
455 }
456
457 API int deviced_set_datetime(time_t timet)
458 {
459         if (timet < 0L)
460                 return -1;
461         return alarm_set_time(timet);
462 }
463
464 API int deviced_set_timezone(char *tzpath_str)
465 {
466         if (tzpath_str == NULL)
467                 return -1;
468         char buf[255];
469         snprintf(buf, sizeof(buf), "%s", tzpath_str);
470         return dbus_time_handler(PREDEF_SET_TIMEZONE, buf);
471 }
472
473 static int dbus_cpu_handler(char* type, char* buf_pid, char* buf_freq)
474 {
475         DBusError err;
476         DBusMessage *msg;
477         char *pa[4];
478         int ret, val;
479
480         pa[0] = type;
481         pa[1] = "2";
482         pa[2] = buf_pid;
483         pa[3] = buf_freq;
484
485         msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME,
486                         DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI,
487                         pa[0], "siss", pa);
488         if (!msg)
489                 return -EBADMSG;
490
491         dbus_error_init(&err);
492
493         ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID);
494         if (!ret) {
495                 _E("no message : [%s:%s]", err.name, err.message);
496                 val = -EBADMSG;
497         }
498
499         dbus_message_unref(msg);
500         dbus_error_free(&err);
501
502         _D("%s-%s : %d", DEVICED_INTERFACE_SYSNOTI, pa[0], val);
503         return val;
504 }
505
506 API int deviced_request_set_cpu_max_frequency(int val)
507 {
508         char buf_pid[8];
509         char buf_freq[256];
510
511         // to do - need to check new frequncy is valid
512         snprintf(buf_pid, sizeof(buf_pid), "%d", getpid());
513         snprintf(buf_freq, sizeof(buf_freq), "%d", val * 1000);
514
515         return dbus_cpu_handler(PREDEF_SET_MAX_FREQUENCY, buf_pid, buf_freq);
516 }
517
518 API int deviced_request_set_cpu_min_frequency(int val)
519 {
520         char buf_pid[8];
521         char buf_freq[256];
522
523         // to do - need to check new frequncy is valid
524         snprintf(buf_pid, sizeof(buf_pid), "%d", getpid());
525         snprintf(buf_freq, sizeof(buf_freq), "%d", val * 1000);
526
527         return dbus_cpu_handler(PREDEF_SET_MIN_FREQUENCY, buf_pid, buf_freq);
528 }
529
530 API int deviced_release_cpu_max_frequency()
531 {
532         char buf_pid[8];
533
534         snprintf(buf_pid, sizeof(buf_pid), "%d", getpid());
535
536         return dbus_cpu_handler(PREDEF_RELEASE_MAX_FREQUENCY, buf_pid, "2");
537 }
538
539 API int deviced_release_cpu_min_frequency()
540 {
541         char buf_pid[8];
542
543         snprintf(buf_pid, sizeof(buf_pid), "%d", getpid());
544
545         return dbus_cpu_handler(PREDEF_RELEASE_MIN_FREQUENCY, buf_pid, "2");
546 }
547
548 static int dbus_factory_handler(char* type, char* buf)
549 {
550         DBusError err;
551         DBusMessage *msg;
552         char *pa[3];
553         int ret, val;
554
555         pa[0] = type;
556         pa[1] = "1";
557         pa[2] = buf;
558
559         msg = dbus_method_sync_with_reply(DEVICED_BUS_NAME,
560                         DEVICED_PATH_SYSNOTI, DEVICED_INTERFACE_SYSNOTI,
561                         pa[0], "sis", pa);
562         if (!msg)
563                 return -EBADMSG;
564
565         dbus_error_init(&err);
566
567         ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID);
568         if (!ret) {
569                 _E("no message : [%s:%s]", err.name, err.message);
570                 val = -EBADMSG;
571         }
572
573         dbus_message_unref(msg);
574         dbus_error_free(&err);
575
576         _D("%s-%s : %d", DEVICED_INTERFACE_SYSNOTI, pa[0], val);
577         return val;
578 }
579
580 API int deviced_request_set_factory_mode(int val)
581 {
582         char buf_mode[8];
583         if ( val == 0 || val == 1 ) {
584                 snprintf(buf_mode, sizeof(buf_mode), "%d", val);
585                 return dbus_factory_handler(PREDEF_FACTORY_MODE, buf_mode);
586         } else {
587                 return -1;
588         }
589 }
590
591 static int dbus_crash_handler(char* type, char* buf)
592 {
593         DBusError err;
594         DBusMessage *msg;
595         char *pa[3];
596         int ret, val;
597
598         pa[0] = type;
599         pa[1] = "1";
600         pa[2] = buf;
601         msg = dbus_method_sync_with_reply(CRASHD_BUS_NAME,
602                         CRASHD_PATH_CRASH, CRASHD_INTERFACE_CRASH,
603                         pa[0], "sis", pa);
604         if (!msg)
605                 return -EBADMSG;
606
607         dbus_error_init(&err);
608
609         ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID);
610         if (!ret) {
611                 _E("no message : [%s:%s]", err.name, err.message);
612                 val = -EBADMSG;
613         }
614
615         dbus_message_unref(msg);
616         dbus_error_free(&err);
617
618         _D("%s-%s : %d", CRASHD_INTERFACE_CRASH, pa[0], val);
619         return val;
620 }
621
622 API int deviced_request_dump_log(int type)
623 {
624         char buf_mode[8];
625         if ( type == AP_DUMP || type == CP_DUMP || type == ALL_DUMP) {
626                 snprintf(buf_mode, sizeof(buf_mode), "%d", type);
627                 return dbus_crash_handler(PREDEF_DUMP_LOG, buf_mode);
628         } else {
629                 return -1;
630         }
631 }
632
633 API int deviced_request_delete_dump(char *ticket)
634 {
635         char buf[255];
636         if ( ticket == NULL) {
637                 return -1;
638         }
639         snprintf(buf, sizeof(buf), "%s", ticket);
640         return dbus_crash_handler(PREDEF_DELETE_DUMP, buf);
641 }