tizen 2.3 release
[framework/system/deviced.git] / src / logd / src / liblogd-db / devices.c
1 #define _GNU_SOURCE
2 #include <errno.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5
6 #include "core/log.h"
7 #include "db.h"
8 #include "devices.h"
9 #include "macro.h"
10 #include "socket-helper.h"
11
12 #define STORE_POWER_CONS_SQL "INSERT INTO device_working_time \
13 (time_stamp, device, time) VALUES(?, ?, ?); "
14
15 #define STORE_POWER_MODE_SQL "INSERT INTO power_mode \
16 (time_stamp, old_mode_number, new_mode_number, duration, battery_level_change) \
17 VALUES (?, ?, ?, ?, ?); "
18
19 #define LOAD_POWER_MODE_STAT_SQL "SELECT * FROM power_mode WHERE \
20 old_mode_number=? order by id DESC;"
21
22 #define MIN_BATTERY_LEVEL 0
23 #define MAX_BATTERY_LEVEL 10000
24
25 static int device_state[LOGD_OBJECT_MAX] = { 0, };
26
27 static sqlite3 *db;
28 static sqlite3_stmt *store_power_cons_stmt;
29 static sqlite3_stmt *store_power_mode_stmt;
30 static sqlite3_stmt *load_power_mode_stat_stmt;
31
32 int devices_init(void)
33 {
34         db = logd_get_db();
35
36         PREPARE_STMT(store_power_cons_stmt, STORE_POWER_CONS_SQL);
37         PREPARE_STMT(store_power_mode_stmt, STORE_POWER_MODE_SQL);
38         PREPARE_STMT(load_power_mode_stat_stmt, LOAD_POWER_MODE_STAT_SQL);
39
40         return 0;
41 }
42
43 int devices_finalize(void)
44 {
45         FINALIZE_STMT(store_power_cons_stmt);
46         FINALIZE_STMT(store_power_mode_stmt);
47         FINALIZE_STMT(load_power_mode_stat_stmt);
48
49         return 0;
50 }
51
52 int logd_store_device_wt(uint64_t time_stamp, enum logd_object device, time_t _time)
53 {
54         DB_CHECK(sqlite3_reset(store_power_cons_stmt));
55         DB_CHECK(sqlite3_bind_int64(store_power_cons_stmt, 1, time_stamp));
56         DB_CHECK(sqlite3_bind_int(store_power_cons_stmt, 2, device));
57         DB_CHECK(sqlite3_bind_int(store_power_cons_stmt, 3, _time));
58
59         if (sqlite3_step(store_power_cons_stmt) != SQLITE_DONE) {
60                 _E("Can't store device workingtime: %s", sqlite3_errmsg(db));
61                 return -1;
62         }
63
64         return 0;
65 }
66
67 API int store_devices_workingtime(enum logd_object device, int state)
68 {
69         static time_t last_time = 0;
70         time_t current_time = time(NULL);
71
72         if (last_time) {
73                 for (size_t i = 0; i < ARRAY_SIZE(device_state); ++i) {
74                         if (device_state[i])
75                                 logd_store_device_wt(current_time, i, current_time - last_time);
76                 }
77         }
78
79         device_state[device] = state;
80         last_time = current_time;
81
82         return 0;
83 }
84
85 API int logd_foreach_devices_stat(enum logd_db_query (*cb)
86          (const struct logd_device_stat *, void *), void *user_data)
87 {
88         int sock;
89         int count;
90         int i;
91         int ret = 0;
92         struct logd_device_stat dev_stat;
93         enum logd_socket_req_type req_type = LOGD_DEV_STAT_REQ;
94
95         if ((sock = connect_to_logd_socket()) < 0) {
96                 _E("Failed connect_to_logd_socket");
97                 return sock;
98         }
99
100         if (write(sock, &req_type, sizeof(req_type)) != sizeof(req_type)) {
101                 ret = -errno;
102                 _E("can't write to socket");
103                 goto out;
104         }
105
106         if (read_from_socket(sock, &count, sizeof(count)) != sizeof(count)) {
107                 ret = -errno;
108                 _E("can't read from socket");
109                 goto out;
110         }
111
112         for (i = 0; i < count; ++i) {
113                 if (read_from_socket(sock, &dev_stat, sizeof(dev_stat)) != sizeof(dev_stat)) {
114                         ret = -errno;
115                         _E("can't read from socket");
116                         goto out;
117                 }
118                 if (cb(&dev_stat, user_data) == LOGD_DB_QUERY_STOP)
119                         break;
120         }
121 out:
122         close(sock);
123
124         return ret;
125 }
126
127 API int logd_get_estimate_battery_lifetime(int **estimate_times)
128 {
129         int sock;
130         int ret = 0;
131         enum logd_socket_req_type req_type = LOGD_EST_TIME_REQ;
132         int i;
133
134         (*estimate_times) = (int*)calloc(LOGD_POWER_MODE_MAX, sizeof(int));
135         if (!(*estimate_times)) {
136                 _E("can't alloc memory");
137                 return -ENOMEM;
138         }
139
140         if ((sock = connect_to_logd_socket()) < 0) {
141                 _E("Failed connect_to_logd_socket");
142                 free((*estimate_times));
143                 return sock;
144         }
145
146         if (write(sock, &req_type, sizeof(req_type)) != sizeof(req_type)) {
147                 ret = -errno;
148                 _E("can't write to socket");
149                 free((*estimate_times));
150                 goto out;
151         }
152
153         for (i = 0; i < LOGD_POWER_MODE_MAX; ++i) {
154                 int est_time;
155
156                 if (read_from_socket(sock, &est_time, sizeof(est_time)) != sizeof(est_time)) {
157                         ret = -errno;
158                         _E("can't read from socket");
159                         free((*estimate_times));
160                          goto out;
161                 }
162                 (*estimate_times)[i] = est_time;
163         }
164
165 out:
166         close(sock);
167         return ret;
168
169 }
170
171 API struct logd_battery_info* logd_get_battery_info(void)
172 {
173         int sock;
174         int count;
175         int i;
176         enum logd_socket_req_type req_type = LOGD_BATTERY_LVL_REQ;
177
178         struct logd_battery_info *info = NULL;
179
180         if ((sock = connect_to_logd_socket()) < 0) {
181                 _E("Failed connect_to_logd_socket");
182                 return NULL;
183         }
184
185         if (write(sock, &req_type, sizeof(req_type)) != sizeof(req_type)) {
186                 _E("can't write to socket");
187                 goto err;
188         }
189
190         if (read_from_socket(sock, &count, sizeof(count)) != sizeof(count)) {
191                 _E("can't read from socket");
192                 goto err;
193         }
194
195         if (count <= 0) {
196                 _E("wrong count value");
197                 goto err;
198         }
199
200         info = (struct logd_battery_info*) calloc(1, sizeof(struct logd_battery_info));
201         info->n = count;
202         info->levels = (struct logd_battery_level*)
203                 malloc(sizeof(struct logd_battery_level) * count);
204
205         for (i = 0; i < count; ++i) {
206                 if (read_from_socket(
207                         sock, info->levels + i, sizeof(struct logd_battery_level)) !=
208                                 sizeof(struct logd_battery_level)) {
209                         _E("can't read from socket");
210                         goto err;
211                 }
212         }
213
214         close(sock);
215
216         return info;
217
218 err:
219         close(sock);
220         logd_free_battery_info(info);
221         return NULL;
222 }
223
224 API int logd_seek_battery_level(struct logd_battery_info *info, int level)
225 {
226         int i;
227
228         if (level < MIN_BATTERY_LEVEL || level > MAX_BATTERY_LEVEL
229                 || info == NULL)
230                 return -EINVAL;
231
232         for (i = info->n - 1; i >= 0; --i) {
233                 if (info->levels[i].level == level)
234                         return i;
235         }
236
237         return 0;
238 }
239
240 API void logd_free_battery_info(struct logd_battery_info *info)
241 {
242         if (!info)
243                 return;
244
245         if (info->levels)
246                 free(info->levels);
247         free(info);
248 }
249
250 API float logd_battery_level_at(const struct logd_battery_info *info, time_t date)
251 {
252         int i;
253         struct logd_battery_level *bl = NULL;
254
255         if (!info || !info->levels)
256                 return -EINVAL;
257
258         if (date < info->levels[0].date) {
259                 _E("logd_battery_info not contains info at %ld", date);
260                 return -EINVAL;
261         }
262
263         for (i = 0; i < info->n; ++i) {
264                 bl = &info->levels[i];
265
266                 if (i == info->n - 1)
267                         break;
268                 if (date >= bl->date && date < info->levels[i + 1].date)
269                         break;
270         }
271
272         return bl->level + (date - bl->date) * bl->k;
273 }
274
275 API float logd_battery_charging_speed_at(const struct logd_battery_info *info, time_t date)
276 {
277         int i;
278
279         if (!info || !info->levels)
280                 return -EINVAL;
281
282         if (date < info->levels[0].date) {
283                 _E("logd_battery_info not contains info at %ld", date);
284                 return -EINVAL;
285         }
286
287         for (i = 0; i < info->n - 1; ++i) {
288                 if (date >= info->levels[i].date && date < info->levels[i + 1].date)
289                         break;
290         }
291         if (i != 0 && i == info->n - 1)
292                 --i;
293
294         return info->levels[i].k;
295 }
296
297 API int get_current_battery_level()
298 {
299         int ret = -EIO;
300         const  char *level_file = "/sys/class/power_supply/battery/capacity";
301         int level = 0;
302         FILE *fp = fopen(level_file, "r");
303
304         if (!fp) {
305                 ret = -errno;
306                 _E("can't open %s", level_file);
307                 return ret;
308         }
309         errno = 0;
310         if (fscanf(fp, "%d", &level) != 1) {
311                 if (errno)
312                         ret = -errno;
313                 _E("Can't read battery level");
314                 fclose(fp);
315                 return ret;
316         }
317
318         fclose(fp);
319         return level > MAX_BATTERY_LEVEL ? MAX_BATTERY_LEVEL : level;
320 }
321
322 API float* load_discharging_speed(int long_period)
323 {
324         float *result = NULL;
325         int i;
326
327         if (sqlite3_reset(load_power_mode_stat_stmt) != SQLITE_OK) {
328                 _E("sqlite3_reset failed");
329                 return NULL;
330         }
331
332         result = (float*)calloc(LOGD_POWER_MODE_MAX, sizeof(float));
333         if (!result)
334                 return NULL;
335
336         for (i = 0; i < LOGD_POWER_MODE_MAX; ++i) {
337                 int total_duration = 0;
338                 float total_battery_level_change = 0;
339
340                 if (sqlite3_reset(load_power_mode_stat_stmt) != SQLITE_OK) {
341                         _E("load_power_mode_stat_stmt reset error");
342                         free(result);
343                         return NULL;
344                 }
345
346                 if (sqlite3_bind_int(load_power_mode_stat_stmt, 1, i) != SQLITE_OK) {
347                         _E("load_power_mode_stat_stmt bind error");
348                         free(result);
349                         return NULL;
350                 }
351
352                 while (sqlite3_step(load_power_mode_stat_stmt) == SQLITE_ROW) {
353                         int duration = sqlite3_column_int(load_power_mode_stat_stmt, 3);
354                         int battery_level_change = sqlite3_column_int(load_power_mode_stat_stmt, 4);
355
356                         if (total_duration + duration > long_period) {
357                                 total_battery_level_change +=
358                                         ((float)(long_period - total_duration)) / duration * battery_level_change;
359                                 total_duration = long_period;
360                                 break;
361                         }
362                         total_duration += duration;
363                         total_battery_level_change += battery_level_change;
364                 }
365                 if (total_duration < long_period || total_battery_level_change == 0)
366                         result[i] = -1;
367                 else
368                         result[i] = total_duration / total_battery_level_change;
369         }
370
371         return result;
372 }
373
374
375 API int store_new_power_mode(time_t time_stamp, enum logd_power_mode old_mode,
376         enum logd_power_mode new_mode, time_t duration, int battery_level_change)
377 {
378         DB_CHECK(sqlite3_reset(store_power_mode_stmt));
379         DB_CHECK(sqlite3_bind_int64(store_power_mode_stmt, 1, time_stamp));
380         DB_CHECK(sqlite3_bind_int(store_power_mode_stmt, 2, old_mode));
381         DB_CHECK(sqlite3_bind_int(store_power_mode_stmt, 3, new_mode));
382         DB_CHECK(sqlite3_bind_int(store_power_mode_stmt, 4, duration));
383         DB_CHECK(sqlite3_bind_int(store_power_mode_stmt, 5, battery_level_change));
384
385         if (sqlite3_step(store_power_mode_stmt) != SQLITE_DONE) {
386                 _E("Can't store power mode: %s", sqlite3_errmsg(db));
387                 return -1;
388         }
389
390         return 0;
391 }