Change usb sequence to broadcast usb state after setting vconf value
[platform/core/system/deviced.git] / src / display / lock-detector.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 /**
21  * @file        lock-detector.c
22  * @brief
23  *
24  */
25
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <stdbool.h>
29 #include <errno.h>
30 #include <sys/time.h>
31 #include <unistd.h>
32 #include <sys/types.h>
33
34 #include "util.h"
35 #include "core.h"
36 #include "core/list.h"
37
38 struct lock_info {
39         unsigned long hash;
40         char *name;
41         int state;
42         int count;
43         long locktime;
44         long unlocktime;
45         long time;
46 };
47
48 #define LIMIT_COUNT     128
49
50 static dd_list *lock_info_list;
51
52 static long get_time(void)
53 {
54         struct timeval now;
55         gettimeofday(&now, NULL);
56         return (long)(now.tv_sec * 1000 + now.tv_usec / 1000);
57 }
58
59 static void shrink_lock_info_list(void)
60 {
61         dd_list *l, *l_prev;
62         struct lock_info *info;
63         unsigned int count;
64
65         count = DD_LIST_LENGTH(lock_info_list);
66         if (count <= LIMIT_COUNT)
67                 return;
68         _D("list is shrink : count %d", count);
69
70         DD_LIST_REVERSE_FOREACH_SAFE(lock_info_list, l, l_prev, info) {
71                 if (info->locktime == 0) {
72                         DD_LIST_REMOVE_LIST(lock_info_list, l);
73                         if (info->name)
74                                 free(info->name);
75                         free(info);
76                         count--;
77                 }
78                 if (count <= (LIMIT_COUNT / 2))
79                         break;
80         }
81 }
82
83 int set_lock_time(const char *pname, int state)
84 {
85         struct lock_info *info;
86         dd_list *l;
87         unsigned long val;
88
89         if (!pname)
90                 return -EINVAL;
91
92         if (state < S_NORMAL || state > S_SLEEP)
93                 return -EINVAL;
94
95         val = g_str_hash(pname);
96
97         DD_LIST_FOREACH(lock_info_list, l, info)
98                 if (info->hash == val &&
99                     !strncmp(info->name, pname, strlen(pname)+1) &&
100                     info->state == state) {
101                         info->count += 1;
102                         if (info->locktime == 0)
103                                 info->locktime = get_time();
104                         info->unlocktime = 0;
105                         DD_LIST_REMOVE(lock_info_list, info);
106                         DD_LIST_PREPEND(lock_info_list, info);
107                         return 0;
108                 }
109
110         info = malloc(sizeof(struct lock_info));
111         if (!info) {
112                 _E("Malloc is failed for lock_info!");
113                 return -ENOMEM;
114         }
115
116         info->hash = val;
117         info->name = strndup(pname, strlen(pname));
118         info->state = state;
119         info->count = 1;
120         info->locktime = get_time();
121         info->unlocktime = 0;
122         info->time = 0;
123
124         DD_LIST_APPEND(lock_info_list, info);
125
126         return 0;
127 }
128
129 int set_unlock_time(const char *pname, int state)
130 {
131         bool find = false;
132         long diff;
133         struct lock_info *info;
134         dd_list *l;
135         unsigned long val;
136
137         if (!pname)
138                 return -EINVAL;
139
140         if (state < S_NORMAL || state > S_SLEEP)
141                 return -EINVAL;
142
143         val = g_str_hash(pname);
144
145         DD_LIST_FOREACH(lock_info_list, l, info)
146                 if (info->hash == val &&
147                     !strncmp(info->name, pname, strlen(pname)+1) &&
148                     info->state == state) {
149                         DD_LIST_REMOVE(lock_info_list, info);
150                         DD_LIST_PREPEND(lock_info_list, info);
151                         find = true;
152                         break;
153                 }
154
155         if (!find)
156                 return -EINVAL;
157
158         if (info->locktime == 0)
159                 return -EINVAL;
160
161         /* update time */
162         info->unlocktime = get_time();
163         diff = info->unlocktime - info->locktime;
164         if (diff > 0)
165                 info->time += diff;
166         info->locktime = 0;
167
168         if (DD_LIST_LENGTH(lock_info_list) > LIMIT_COUNT)
169                 shrink_lock_info_list();
170
171         return 0;
172 }
173
174 void free_lock_info_list(void)
175 {
176         dd_list *l, *l_next;
177         struct lock_info *info;
178
179         if (!lock_info_list)
180                 return;
181
182         DD_LIST_FOREACH_SAFE(lock_info_list, l, l_next, info) {
183                 DD_LIST_REMOVE(lock_info_list, info);
184                 if (info->name)
185                         free(info->name);
186                 free(info);
187         }
188         lock_info_list = NULL;
189 }
190
191 void print_lock_info_list(int fd)
192 {
193         struct lock_info *info;
194         dd_list *l;
195         char buf[255];
196         int ret;
197
198         if (!lock_info_list)
199                 return;
200
201         snprintf(buf, sizeof(buf),
202             "current time : %ld ms\n", get_time());
203         ret = write(fd, buf, strlen(buf));
204         if (ret < 0)
205                 _E("write() failed (%d)", errno);
206
207         snprintf(buf, sizeof(buf),
208             "[%10s %6s] %6s %10s %10s %10s %s\n", "hash", "state",
209             "count", "locktime", "unlocktime", "time", "process name");
210         ret = write(fd, buf, strlen(buf));
211         if (ret < 0)
212                 _E("write() failed (%d)", errno);
213
214         DD_LIST_FOREACH(lock_info_list, l, info) {
215                 long time = 0;
216                 if (info->locktime != 0 && info->unlocktime == 0)
217                         time = get_time() - info->locktime;
218                 snprintf(buf, sizeof(buf),
219                     "[%10lu %6d] %6d %10ld %10ld %10ld %s\n",
220                     info->hash,
221                     info->state,
222                     info->count,
223                     info->locktime,
224                     info->unlocktime,
225                     info->time + time,
226                     info->name);
227                 ret = write(fd, buf, strlen(buf));
228                 if (ret < 0)
229                         _E("write() failed (%d)", errno);
230         }
231 }
232