Add varialbe for checking battery initialization
[platform/core/system/deviced.git] / src / battery / power-supply.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 <stdio.h>
21 #include <stdbool.h>
22 #include <vconf.h>
23 #include <device-node.h>
24 #include <bundle.h>
25 #include <eventsystem.h>
26 #include <hw/battery.h>
27 #include <sys/stat.h>
28
29 #include "core/devices.h"
30 #include "core/device-notifier.h"
31 #include "core/udev.h"
32 #include "core/log.h"
33 #include "core/config-parser.h"
34 #include "display/poll.h"
35 #include "display/setting.h"
36 #include "shared/eventsystem.h"
37 #include "display/core.h"
38 #include "display/display-ops.h"
39 #include "apps/apps.h"
40 #include "power-supply.h"
41 #include "battery.h"
42 #include "battery-ops.h"
43 #include "extcon/extcon.h"
44
45 #ifndef VCONFKEY_SETAPPL_BLOCKMODE_WEARABLE_BOOL
46 #define VCONFKEY_SETAPPL_BLOCKMODE_WEARABLE_BOOL "db/setting/blockmode_wearable"
47 #endif
48
49 #ifndef VCONFKEY_SETAPPL_THEATER_MODE_ENABLE
50 #define VCONFKEY_SETAPPL_THEATER_MODE_ENABLE "db/setting/theater_mode_enable"
51 #endif
52
53 #ifndef VCONFKEY_SETAPPL_GOODNIGHT_MODE_ENABLE
54 #define VCONFKEY_SETAPPL_GOODNIGHT_MODE_ENABLE "db/setting/goodnight_mode_enable"
55 #endif
56
57 #define BATTERY_NAME        "battery"
58 #define CHARGEFULL_NAME     "Full"
59 #define CHARGENOW_NAME      "Charging"
60 #define DISCHARGE_NAME      "Discharging"
61 #define NOTCHARGE_NAME      "Not charging"
62 #define OVERHEAT_NAME       "Overheat"
63 #define TEMPCOLD_NAME       "Cold"
64 #define OVERVOLT_NAME       "Over voltage"
65 #define GOOD_NAME           "Good"
66
67 #define CHARGER_WIRELESS_TYPE_BT    10
68 #define CHARGER_WIRELESS_TYPE_3G    22
69 #define CHARGER_INCOMPATIBLE_TYPE   11
70 #define CHARGER_D2D_TYPE            110
71 #define WIRELESS_CHARGER_CONNECTED  2
72
73 #define SIGNAL_TEMP_GOOD          "TempGood"
74
75 #define METHOD_FULL_NOTI_ON   "BatteryFullNotiOn"
76 #define METHOD_FULL_NOTI_OFF  "BatteryFullNotiOff"
77 #define METHOD_CHARGE_NOTI_ON "BatteryChargeNotiOn"
78
79 #define CHARGER_CHARGE_ON_NODE "/sys/class/power_supply/battery/chg_on"
80
81 #define RETRY_MAX 5
82 #define BATTERY_CHECK_TIMER_INTERVAL 500  /* 0.5 second */
83 #define LCD_DIM_TIME_IN_BATTERY_HEALTH  10000   /* ms */
84
85 static void uevent_power_handler(struct udev_device *dev);
86 static const struct uevent_handler uh = {
87         .subsystem   = POWER_SUBSYSTEM,
88         .uevent_func = uevent_power_handler,
89 };
90
91 struct battery_status battery;
92 struct battery_status old_battery;
93 static int noti_id;
94 static int online_status;
95 static int abnormal_health_popup_timer;
96 static bool launching_health_popup;
97
98 static guint power_timer;
99 static device_notifier_state_e old_state = -1;
100
101 bool battery_initialized;
102
103 bool battery_do_not_disturb(void);
104 int battery_pm_change_internal(int pid, int s_bits);
105 static int booting_done(void *data);
106 static void update_health(enum battery_noti_status status);
107
108 static struct battery_device *battery_dev;
109
110 static int load_uevent(struct parse_result *result, void *user_data);
111 static int event_handler_state_changed(void *data);
112
113 static int lowbat_execute(void *data)
114 {
115         static const struct device_ops *lowbat_ops;
116
117         FIND_DEVICE_INT(lowbat_ops, "lowbat");
118         return device_execute(lowbat_ops, data);
119 }
120
121 static int power_supply_broadcast_str(char *sig, char *status)
122 {
123         static char old_sig[32];
124         static char old_status[32];
125         char *str;
126         int ret;
127
128         if (!sig || !status) {
129                 _E("there is no signal name");
130                 return -EINVAL;
131         }
132
133         if (strncmp(old_sig, sig, strlen(sig)) == 0 && strncmp(old_status, status, strlen(status)) == 0)
134                 return 0;
135
136         snprintf(old_sig, sizeof(old_sig), "%s", sig);
137         snprintf(old_status, sizeof(old_status), "%s", status);
138
139         str = status;
140
141         ret = dbus_handle_emit_dbus_signal(NULL,
142                                                 DEVICED_PATH_BATTERY,
143                                                 DEVICED_INTERFACE_BATTERY,
144                                                 sig,
145                                                 g_variant_new("(s)", str));
146
147         if (ret == 0)
148                 return 1;
149         else
150                 return ret;
151 }
152
153 static void pm_check_and_change(int bInserted)
154 {
155         static int old = -1;
156
157         if (old == bInserted)
158                 return;
159         old = bInserted;
160         battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
161 }
162
163 static void health_status_broadcast(void)
164 {
165         dbus_handle_emit_dbus_signal(NULL,
166                 DEVICED_PATH_BATTERY,
167                 DEVICED_INTERFACE_BATTERY,
168                 SIGNAL_TEMP_GOOD,
169                 NULL);
170 }
171
172 static void full_noti_cb(GVariant *var, void *user_data, GError *err)
173 {
174         int id = 0;
175
176         if (!var)
177                 return;
178
179         if (!dh_get_param_from_var(var, "(i)", &id)) {
180                 _E("Failed to notify full: no message(%s)", g_variant_get_type_string(var));
181                 goto out;
182         }
183
184         noti_id = id;
185         _D("Inserted battery full noti(%d).", noti_id);
186
187 out:
188         g_variant_unref(var);
189 }
190
191 static void noti_off_cb(GVariant *var, void *user_data, GError *err)
192 {
193         int ret = 0;
194
195         if (!dh_get_param_from_var(var, "(i)", &ret)) {
196                 _E("Failed to off notification: no message(%s)", g_variant_get_type_string(var));
197                 goto out;
198         }
199
200         _D("Noti off: %d", ret);
201
202 out:
203         g_variant_unref(var);
204 }
205
206 static int send_full_noti(enum charge_full_type state)
207 {
208         int ret = 0;
209         int noti = 0;
210         int retry;
211
212         if (battery_plgn.check_power_supply_noti)
213                 noti = battery_plgn.check_power_supply_noti();
214
215         if (!noti)
216                 return ret;
217
218         switch (state) {
219         case CHARGING_FULL:
220                 for (retry = RETRY_MAX; retry > 0; retry--) {
221                         ret = dbus_handle_method_async_with_reply(POPUP_BUS_NAME,
222                                         POPUP_PATH_NOTI,
223                                         POPUP_INTERFACE_NOTI,
224                                         METHOD_FULL_NOTI_ON,
225                                         NULL, NULL, full_noti_cb, -1, NULL);
226                         if (ret == 0) {
227                                 _D("Created battery full noti.");
228                                 return ret;
229                         }
230                 }
231                 _E("Failed to call dbus method: %d", ret);
232                 break;
233         case CHARGING_NOT_FULL:
234                 if (noti_id <= 0)
235                         return -EPERM;
236                 for (retry = RETRY_MAX; retry > 0; retry--) {
237                         ret = dbus_handle_method_async_with_reply_var(POPUP_BUS_NAME,
238                                         POPUP_PATH_NOTI,
239                                         POPUP_INTERFACE_NOTI,
240                                         METHOD_FULL_NOTI_OFF,
241                                         g_variant_new("(i)", noti_id),
242                                         noti_off_cb, -1, NULL);
243                         if (ret == 0) {
244                                 _D("Deleted battery full noti.");
245                                 noti_id = 0;
246                                 return ret;
247                         }
248                 }
249                 _E("Failed to call dbus method: %d", ret);
250                 break;
251         }
252         return ret;
253 }
254
255 static void charge_noti_on(GVariant *var, void *user_data, GError *err)
256 {
257         int id = 0;
258
259         if (!var)
260                 return;
261
262         if (!dh_get_param_from_var(var, "(i)", &id)) {
263                 _E("Failed to notify charge: no message(%s)", g_variant_get_type_string(var));
264                 goto out;
265         }
266
267         _D("Inserted battery charge noti: %d", id);
268
269 out:
270         g_variant_unref(var);
271 }
272
273 static int send_charge_noti(void)
274 {
275         int ret = 0;
276         int retry;
277
278         for (retry = RETRY_MAX; retry > 0; retry--) {
279                 ret = dbus_handle_method_async_with_reply(POPUP_BUS_NAME,
280                                 POPUP_PATH_NOTI,
281                                 POPUP_INTERFACE_NOTI,
282                                 METHOD_CHARGE_NOTI_ON,
283                                 NULL, NULL, charge_noti_on, -1, NULL);
284                 if (ret == 0) {
285                         _I("Created battery charge noti.");
286                         return ret;
287                 }
288         }
289         _E("Failed to call dbus method: %d", ret);
290         return ret;
291 }
292
293 static void power_supply_noti(enum battery_noti_type type, enum battery_noti_status status)
294 {
295         static int charger = CHARGER_DISCHARGING;
296         static int full = CHARGING_NOT_FULL;
297         int ret;
298
299         if (type == DEVICE_NOTI_BATT_CHARGE) {
300                 if (status == DEVICE_NOTI_ON && charger == CHARGER_DISCHARGING) {
301                         send_charge_noti();
302                         charger = CHARGER_CHARGING;
303                 } else if (status == DEVICE_NOTI_OFF && charger == CHARGER_CHARGING)
304                         charger = CHARGER_DISCHARGING;
305         } else if (type == DEVICE_NOTI_BATT_FULL) {
306                 if (status == DEVICE_NOTI_ON && full == CHARGING_NOT_FULL) {
307                         ret = send_full_noti(CHARGING_FULL);
308                         if (ret == 0)
309                                 full = CHARGING_FULL;
310                 } else if (status == DEVICE_NOTI_OFF && full == CHARGING_FULL) {
311                         ret = send_full_noti(CHARGING_NOT_FULL);
312                         if (ret == 0)
313                                 full = CHARGING_NOT_FULL;
314                 }
315         }
316 }
317
318 int power_supply_broadcast(char *sig, int status)
319 {
320         static int old;
321         static char sig_old[32];
322         int ret;
323         int chg_on;
324
325         if (!sig) {
326                 _E("There is no signal name.");
327                 return -EINVAL;
328         }
329         if (strncmp(sig_old, sig, strlen(sig)) == 0 && old == status) {
330                 _D("Skip broadcasting same signal(%s) and status(%d).", sig, status);
331                 return 0;
332         }
333
334         old = status;
335
336         if (battery.charger_charging == CHARGER_DISABLED) {
337                 ret = sys_get_int(CHARGER_CHARGE_ON_NODE, &chg_on);
338                 if (ret == 0 && battery.charger_charging != chg_on) {
339                         ret = sys_set_int(CHARGER_CHARGE_ON_NODE, battery.charger_charging);
340                         _I("%s to change status with %d", ((ret == 0) ? "success" : "fail"), battery.charger_charging);
341                 }
342                 if (strncmp(sig, CHARGE_NOW_SIGNAL, strlen(CHARGE_NOW_SIGNAL)) == 0) {
343                         _I("Skip signal while charger disabled.");
344                         return 0;
345                 }
346         }
347
348         snprintf(sig_old, sizeof(sig_old), "%s", sig);
349
350         ret = dbus_handle_emit_dbus_signal(NULL,
351                                                 DEVICED_PATH_BATTERY,
352                                                 DEVICED_INTERFACE_BATTERY,
353                                                 sig,
354                                                 g_variant_new("(i)", status));
355         if (ret == 0)
356                 return 1;
357         else
358                 return ret;
359 }
360
361 static void noti_batt_full(void)
362 {
363         static int bat_full_noti;
364
365         if (!battery.charge_full && bat_full_noti == 1) {
366                 power_supply_noti(DEVICE_NOTI_BATT_FULL, DEVICE_NOTI_OFF);
367                 bat_full_noti = 0;
368                 /* off the full charge state */
369                 device_notify(DEVICE_NOTIFIER_FULLBAT, (void *)&bat_full_noti);
370         }
371         if (battery.charge_full && bat_full_noti == 0) {
372                 power_supply_noti(DEVICE_NOTI_BATT_FULL, DEVICE_NOTI_ON);
373                 bat_full_noti = 1;
374                 /* turn on LCD, if battery is fully charged */
375                 if (battery_plgn.check_power_supply_noti && battery_plgn.check_power_supply_noti()) {
376                         battery_pm_change_internal(INTERNAL_LOCK_BATTERY_FULL, LCD_NORMAL);
377                 } else
378                         _I("Block LCD.");
379
380                 /* on the full charge state */
381                 device_notify(DEVICE_NOTIFIER_FULLBAT, (void *)&bat_full_noti);
382         }
383 }
384
385 static void check_power_supply(int state)
386 {
387         pm_check_and_change(state);
388         if (disp_plgn.update_pm_setting)
389                 disp_plgn.update_pm_setting(SETTING_CHARGING, state);
390 }
391
392 static void charger_state_send_system_event(int state)
393 {
394         const char *str;
395
396         switch (state) {
397         case CHARGE_STATUS_CHARGING:
398                 str = EVT_VAL_BATTERY_CHARGER_CHARGING;
399                 break;
400         case CHARGE_STATUS_FULL:
401                 str = EVT_VAL_BATTERY_CHARGER_DISCHARGING;
402                 CRITICAL_LOG("Battery %s", str);
403                 break;
404         case CHARGE_STATUS_DISCHARGING:
405                 str = EVT_VAL_BATTERY_CHARGER_DISCHARGING;
406                 break;
407         case CHARGE_STATUS_CONNECTED:
408                 str = EVT_VAL_BATTERY_CHARGER_CONNECTED;
409                 CRITICAL_LOG("Battery %s", str);
410                 break;
411         case CHARGE_STATUS_DISCONNECTED:
412                 str = EVT_VAL_BATTERY_CHARGER_DISCONNECTED;
413                 CRITICAL_LOG("Battery %s", str);
414                 break;
415         default:
416                 _E("Invalid parameter: %d", state);
417                 return;
418         }
419
420         _D("System_event: %s", str);
421
422         event_system_send(SYS_EVENT_BATTERY_CHARGER_STATUS, EVT_KEY_BATTERY_CHARGER_STATUS, str);
423 }
424
425 static void update_present(enum battery_noti_status status)
426 {
427
428         CRITICAL_LOG("Charge(%d) present(%d, old: %d)", battery.charge_now, battery.present, old_battery.present);
429
430         old_battery.present = battery.present;
431         if (status == DEVICE_NOTI_ON) {
432                 battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_DIM);
433                 device_notify(DEVICE_NOTIFIER_BATTERY_PRESENT, (void *)&battery.present);
434                 if (disp_plgn.pm_lock_internal)
435                         disp_plgn.pm_lock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, STAY_CUR_STATE, 0);
436         } else {
437                 battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
438                 device_notify(DEVICE_NOTIFIER_BATTERY_PRESENT, (void *)&battery.present);
439                 if (disp_plgn.pm_unlock_internal)
440                         disp_plgn.pm_unlock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, PM_SLEEP_MARGIN);
441         }
442         if (battery_plgn.changed_battery_cf)
443                 battery_plgn.changed_battery_cf(battery.present);
444 }
445
446 static void launch_health_popup(void)
447 {
448         if (launching_health_popup)
449                 return;
450
451         launching_health_popup = true;
452
453         device_notify(DEVICE_NOTIFIER_BATTERY_HEALTH, (void *)&battery.health);
454         battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
455         battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_DIM);
456         if (disp_plgn.pm_unlock_internal)
457                 disp_plgn.pm_unlock_internal(INTERNAL_LOCK_POPUP, LCD_OFF, PM_SLEEP_MARGIN);
458         if (disp_plgn.pm_lock_internal)
459                 disp_plgn.pm_lock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, STAY_CUR_STATE, LCD_DIM_TIME_IN_BATTERY_HEALTH);
460         if (battery.health == HEALTH_LOW)
461                 battery_charge_err_low_act(NULL);
462         else if (battery.health == HEALTH_HIGH)
463                 battery_charge_err_high_act(NULL);
464
465         launching_health_popup = false;
466 }
467
468 /* Warning popup for every 1 minutes until
469  * battery health returns to normal. */
470 static gboolean health_popup_cb(void *data)
471 {
472         launch_health_popup();
473         battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
474         return G_SOURCE_CONTINUE;
475 }
476
477 static void update_health(enum battery_noti_status status)
478 {
479         _I("Charge(%d) health(%d, old: %d)", battery.charge_now, battery.health, old_battery.health);
480
481         old_battery.health = battery.health;
482         if (status == DEVICE_NOTI_ON) {
483                 CRITICAL_LOG("Popup: Battery health status is not good, %s.", battery.health_s);
484                 launch_health_popup();
485                 if (!abnormal_health_popup_timer)
486                         abnormal_health_popup_timer = g_timeout_add_seconds(ABNORMAL_CHECK_TIMER_INTERVAL, health_popup_cb, NULL);
487         } else {
488                 battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
489                 device_notify(DEVICE_NOTIFIER_BATTERY_HEALTH, (void *)&battery.health);
490                 if (disp_plgn.pm_unlock_internal) {
491                         disp_plgn.pm_unlock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, PM_SLEEP_MARGIN);
492                         disp_plgn.pm_unlock_internal(INTERNAL_LOCK_POPUP, LCD_OFF, PM_SLEEP_MARGIN);
493                 }
494                 health_status_broadcast();
495                 if (abnormal_health_popup_timer) {
496                         CRITICAL_LOG("Battery health returned to normal. Stop abnormal popup.");
497                         g_source_remove(abnormal_health_popup_timer);
498                         abnormal_health_popup_timer = 0;
499                 }
500                 if (battery_plgn.remove_health_popup)
501                         battery_plgn.remove_health_popup();
502         }
503 }
504
505 void relaunch_health_popup(void)
506 {
507         if (launching_health_popup)
508                 return;
509
510         launching_health_popup = true;
511
512         if (abnormal_health_popup_timer)
513                 g_source_remove(abnormal_health_popup_timer);
514
515         if (disp_plgn.pm_unlock_internal)
516                 disp_plgn.pm_unlock_internal(INTERNAL_LOCK_POPUP, LCD_OFF, PM_SLEEP_MARGIN);
517         if (disp_plgn.pm_lock_internal)
518                 disp_plgn.pm_lock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, STAY_CUR_STATE, LCD_DIM_TIME_IN_BATTERY_HEALTH);
519         if (battery.health == HEALTH_LOW)
520                 battery_charge_err_low_act(NULL);
521         else if (battery.health == HEALTH_HIGH)
522                 battery_charge_err_high_act(NULL);
523
524         abnormal_health_popup_timer = g_timeout_add_seconds(ABNORMAL_CHECK_TIMER_INTERVAL, health_popup_cb, NULL);
525
526         launching_health_popup = false;
527 }
528
529 static void check_abnormal_status(void)
530 {
531         if (old_battery.health != HEALTH_LOW && old_battery.health != HEALTH_HIGH &&
532             (battery.health == HEALTH_LOW || battery.health == HEALTH_HIGH))
533                 update_health(DEVICE_NOTI_ON);
534         else if ((old_battery.health == HEALTH_LOW || old_battery.health == HEALTH_HIGH) &&
535                 battery.health != HEALTH_LOW && battery.health != HEALTH_HIGH)
536                 update_health(DEVICE_NOTI_OFF);
537
538         if (old_battery.present != PRESENT_ABNORMAL && battery.present == PRESENT_ABNORMAL)
539                 update_present(DEVICE_NOTI_ON);
540         else if (battery.present != PRESENT_ABNORMAL && old_battery.present == PRESENT_ABNORMAL)
541                 update_present(DEVICE_NOTI_OFF);
542
543         if (old_battery.health != HEALTH_OVP && battery.health == HEALTH_OVP) {
544                 if (battery_plgn.update_ovp)
545                         battery_plgn.update_ovp(DEVICE_NOTI_ON);
546         } else if (battery.health != HEALTH_OVP && old_battery.health == HEALTH_OVP) {
547                 if (battery_plgn.update_ovp)
548                         battery_plgn.update_ovp(DEVICE_NOTI_OFF);
549         }
550 }
551
552 static bool update_online(void)
553 {
554         int chg_on;
555         int ret;
556         bool broadcast = false;
557
558         if (battery.online <= POWER_SUPPLY_TYPE_BATTERY &&
559             battery.charger_charging == CHARGER_DISABLED) {
560                 battery.charger_charging = CHARGER_ENABLED;
561                 ret = sys_get_int(CHARGER_CHARGE_ON_NODE, &chg_on);
562                 if (ret == 0 && battery.charger_charging != chg_on) {
563                         ret = sys_set_int(CHARGER_CHARGE_ON_NODE, battery.charger_charging);
564                         _I("%s to change status with %d", ((ret == 0) ? "success" : "fail"), battery.charger_charging);
565                 }
566         }
567
568         if (battery.online > POWER_SUPPLY_TYPE_BATTERY &&
569             online_status == VCONFKEY_SYSMAN_CHARGER_DISCONNECTED) {
570                 online_status = VCONFKEY_SYSMAN_CHARGER_CONNECTED;
571                 extcon_update_count(EXTCON_TA, 1);
572                 check_power_supply(online_status);
573                 charger_state_send_system_event(CHARGE_STATUS_CONNECTED);
574                 if (old_battery.charge_status != battery.charge_status)
575                         charger_state_send_system_event(battery.charge_status);
576                 broadcast = true;
577         } else if (battery.online <= POWER_SUPPLY_TYPE_BATTERY &&
578             online_status == VCONFKEY_SYSMAN_CHARGER_CONNECTED) {
579                 online_status = VCONFKEY_SYSMAN_CHARGER_DISCONNECTED;
580                 check_power_supply(online_status);
581                 if (old_battery.charge_status != battery.charge_status)
582                         charger_state_send_system_event(battery.charge_status);
583                 charger_state_send_system_event(CHARGE_STATUS_DISCONNECTED);
584                 broadcast = true;
585         } else {
586                 if (old_battery.charge_status != battery.charge_status)
587                         charger_state_send_system_event(battery.charge_status);
588         }
589
590         if (battery.online <= POWER_SUPPLY_TYPE_BATTERY)
591                 battery.online_type = CHARGER_TYPE_NONE;
592         else if (battery.online == CHARGER_WIRELESS_TYPE_BT ||
593             battery.online == CHARGER_WIRELESS_TYPE_3G)
594                 battery.online_type = CHARGER_TYPE_WIRELESS;
595         else if (battery.online == CHARGER_INCOMPATIBLE_TYPE)
596                 battery.online_type = CHARGER_TYPE_INCOMPATIBLE;
597         else if (battery.online == CHARGER_D2D_TYPE)
598                 battery.online_type = CHARGER_TYPE_D2D;
599         else
600                 battery.online_type = CHARGER_TYPE_WIRE;
601
602         return broadcast;
603 }
604
605 static void check_charge_status(const char *env_value)
606 {
607         int len;
608
609         if (env_value == NULL)
610                 return;
611
612         len = strlen(env_value);
613         if (strncmp(env_value, CHARGEFULL_NAME, len) == 0)
614                 battery.charge_status = CHARGE_STATUS_FULL;
615         else if (strncmp(env_value, CHARGENOW_NAME, len) == 0)
616                 battery.charge_status = CHARGE_STATUS_CHARGING;
617         else if (strncmp(env_value, DISCHARGE_NAME, len) == 0)
618                 battery.charge_status = CHARGE_STATUS_DISCHARGING;
619         else if (strncmp(env_value, NOTCHARGE_NAME, len) == 0)
620                 battery.charge_status = CHARGE_STATUS_NOT_CHARGING;
621         else
622                 battery.charge_status = CHARGE_STATUS_UNKNOWN;
623
624         if (battery.charge_status == CHARGE_STATUS_FULL) {
625                 battery.charge_full = CHARGING_FULL;
626                 battery.charge_now = CHARGER_DISCHARGING;
627         } else if (battery.charge_status == CHARGE_STATUS_CHARGING) {
628                 battery.charge_full = CHARGING_NOT_FULL;
629                 battery.charge_now = CHARGER_CHARGING;
630         } else if (battery.charge_status == CHARGE_STATUS_DISCHARGING) {
631                 battery.charge_full = CHARGING_NOT_FULL;
632                 battery.charge_now = CHARGER_DISCHARGING;
633         } else if (battery.charge_status == CHARGE_STATUS_NOT_CHARGING) {
634                 battery.charge_full = CHARGING_NOT_FULL;
635                 battery.charge_now = CHARGER_ABNORMAL;
636         } else {
637                 battery.charge_full = CHARGING_NOT_FULL;
638                 battery.charge_now = CHARGER_DISCHARGING;
639         }
640 }
641
642 static void check_health_status(const char *env_value)
643 {
644         int len;
645
646         if (env_value == NULL) {
647                 battery.health = HEALTH_GOOD;
648                 return;
649         }
650
651         snprintf(battery.health_s, sizeof(battery.health_s), "%s", env_value);
652
653         len = strlen(env_value);
654         if (strncmp(env_value, OVERHEAT_NAME, len) == 0)
655                 battery.health = HEALTH_HIGH;
656         else if (strncmp(env_value, TEMPCOLD_NAME, len) == 0)
657                 battery.health = HEALTH_LOW;
658         else if (strncmp(env_value, OVERVOLT_NAME, len) == 0)
659                 battery.health = HEALTH_OVP;
660         else if (strncmp(env_value, GOOD_NAME, len) == 0)
661                 battery.health = HEALTH_GOOD;
662         else
663                 battery.health = HEALTH_NO_OPT;
664 }
665
666 static void check_misc_status(const char *env_value)
667 {
668         if (env_value == NULL) {
669                 battery.misc = MISC_NONE;
670                 return;
671         }
672         battery.misc = atoi(env_value);
673 }
674
675 static void check_online_status(const char *env_value)
676 {
677         if (env_value == NULL)
678                 return;
679         battery.online = atoi(env_value);
680 }
681
682 static void check_present_status(const char *env_value)
683 {
684         if (env_value == NULL) {
685                 battery.present = PRESENT_NORMAL;
686                 return;
687         }
688         battery.present = atoi(env_value);
689 }
690
691 static void check_capacity_status(const char *env_value)
692 {
693         if (env_value == NULL)
694                 return;
695         battery.capacity = atoi(env_value);
696 }
697
698 static void check_temperature_status(const char *env_value)
699 {
700         if (env_value == NULL)
701                 return;
702         battery.temperature = atoi(env_value) / 10;
703 }
704
705 static void update_capacity_full(void)
706 {
707         static int old;
708         int delta;
709
710         if (battery.online <= POWER_SUPPLY_TYPE_BATTERY ||
711             old == 0 ||
712             old >= battery.capacity) {
713                 old = battery.capacity;
714                 return;
715         }
716         delta = battery.capacity - old;
717         old = battery.capacity;
718         extcon_update_count(EXTCON_BATTERY_FULL, delta);
719 }
720
721 static void update_battery_cycle(void)
722 {
723         static int first = 1;
724         static int old;
725         int delta;
726
727         if (first) {
728                 first = 0;
729                 extcon_update_count(EXTCON_BATTERY_CYCLE, 0);
730                 return;
731         }
732
733         if (battery.online > POWER_SUPPLY_TYPE_BATTERY ||
734             old == 0 ||
735             old <= battery.capacity) {
736                 old = battery.capacity;
737                 return;
738         }
739         delta = old - battery.capacity;
740         old = battery.capacity;
741         extcon_update_count(EXTCON_BATTERY_CYCLE, delta);
742 }
743
744 static void process_power_supply(void *data)
745 {
746         bool broadcasted = true;
747         int lock = -1;
748         int ret;
749
750         _D("process_power_supply()");
751         if (disp_plgn.pm_lock_internal) {
752                 lock = disp_plgn.pm_lock_internal(INTERNAL_LOCK_BATTERY, LCD_OFF, STAY_CUR_STATE, 0);
753         if (old_battery.charge_now != battery.charge_now || battery.charge_now == CHARGER_ABNORMAL) {
754                         ret = vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, battery.charge_now);
755                         if (ret < 0)
756                                 _E("Failed to set vconf value for battery charge now: %d", vconf_get_ext_errno());
757
758                         if (power_supply_broadcast(CHARGE_NOW_SIGNAL, battery.charge_now) < 0)
759                                 broadcasted = false;
760                 }
761         }
762
763         if (!strcmp(old_battery.status_s, CHARGEFULL_NAME) &&
764                 !strcmp(battery.status_s, CHARGENOW_NAME)) {
765                 battery_pm_change_internal(INTERNAL_LOCK_BATTERY, LCD_NORMAL);
766         }
767
768         if (old_battery.charge_full != battery.charge_full)
769                 if (power_supply_broadcast(CHARGE_FULL_SIGNAL, battery.charge_full) < 0)
770                         broadcasted = false;
771
772         if (strncmp(old_battery.health_s, battery.health_s, strlen(battery.health_s))) {
773                 snprintf(old_battery.health_s, sizeof(old_battery.health_s), "%s", battery.health_s);
774                 if (power_supply_broadcast_str(CHARGE_HEALTH_SIGNAL, battery.health_s) < 0)
775                         broadcasted = false;
776         }
777
778         if (old_battery.capacity != battery.capacity) {
779                 ret = vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY, battery.capacity);
780                 if (ret < 0)
781                         _E("Failed to set vconf value for battery capacity: %d", vconf_get_ext_errno());
782
783                 if (power_supply_broadcast(CHARGE_CAPACITY_SIGNAL, battery.capacity) < 0)
784                         broadcasted = false;
785         }
786
787         (void)lowbat_execute(data);
788
789         if (update_online()) {
790                 ret = vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, online_status);
791                 if (ret < 0)
792                         _E("Failed to set vconf value for charger status: %d", vconf_get_ext_errno());
793
794                 if (power_supply_broadcast(CHARGER_STATUS_SIGNAL, online_status) < 0)
795                         broadcasted = false;
796         }
797
798         if (old_battery.online_type != battery.online_type) {
799                 ret = vconf_set_int(VCONFKEY_SYSMAN_CHARGER_TYPE, battery.online_type);
800                 if (ret < 0)
801                         _E("Failed to set vconf value for charger type: %d", vconf_get_ext_errno());
802
803                 if (power_supply_broadcast(CHARGER_TYPE_SIGNAL, battery.online_type) < 0)
804                 broadcasted = false;
805         }
806
807         if (old_battery.misc != battery.misc)
808                 if (power_supply_broadcast(CHARGE_MISC_EVENT_SIGNAL, battery.misc) < 0)
809                         broadcasted = false;
810
811         if (old_battery.freq_strength != battery.freq_strength)
812                 if (power_supply_broadcast(CHARGE_FREQ_STRENGTH_SIGNAL, battery.freq_strength) < 0)
813                         broadcasted = false;
814
815         if (old_battery.charge_full != battery.charge_full)
816                 noti_batt_full();
817
818         if (old_battery.charge_now != battery.charge_now ||
819             old_battery.charge_full != battery.charge_full ||
820             old_battery.capacity != battery.capacity ||
821             old_battery.health != battery.health ||
822                 old_battery.misc != battery.misc ||
823                 old_battery.freq_strength != battery.freq_strength ||
824                 old_battery.online_type != battery.online_type)
825                 _I("Signal(%d) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d : %s) %s(%d)",
826                         broadcasted,
827                         CHARGER_STATUS_SIGNAL, online_status,
828                         CHARGER_TYPE_SIGNAL, battery.online_type,
829                         CHARGE_NOW_SIGNAL, battery.charge_now,
830                         CHARGE_FULL_SIGNAL, battery.charge_full,
831                         CHARGE_CAPACITY_SIGNAL, battery.capacity,
832                         CHARGE_LEVEL_SIGNAL, battery.charging_level,
833                         CHARGE_MISC_EVENT_SIGNAL, battery.misc,
834                         CHARGE_HEALTH_SIGNAL, battery.health, battery.health_s,
835                         CHARGE_FREQ_STRENGTH_SIGNAL, battery.freq_strength);
836
837         old_battery.capacity = battery.capacity;
838         old_battery.charging_level = battery.charging_level;
839         old_battery.online = battery.online;
840         old_battery.online_type = battery.online_type;
841         old_battery.charge_status = battery.charge_status;
842         old_battery.charge_full = battery.charge_full;
843
844         old_battery.misc = battery.misc;
845         old_battery.freq_strength = battery.freq_strength;
846         snprintf(old_battery.status_s, sizeof(old_battery.status_s), "%s", battery.status_s);
847
848         check_abnormal_status();
849
850         device_notify(DEVICE_NOTIFIER_POWER_SUPPLY, NULL);
851         if (old_battery.charge_now != battery.charge_now) {
852                 device_notify(DEVICE_NOTIFIER_BATTERY_CHARGING, &battery.charge_now);
853                 old_battery.charge_now = battery.charge_now;
854         }
855         update_capacity_full();
856         update_battery_cycle();
857         if (lock == 0) {
858                 if (disp_plgn.pm_unlock_internal)
859                         disp_plgn.pm_unlock_internal(INTERNAL_LOCK_BATTERY, LCD_OFF, PM_SLEEP_MARGIN);
860         }
861 }
862
863 static void uevent_power_handler(struct udev_device *dev)
864 {
865         struct udev_list_entry *list_entry;
866         const char *env_name;
867         const char *env_value;
868         bool matched = false;
869         int ret;
870
871         udev_list_entry_foreach(list_entry,
872                         udev_device_get_properties_list_entry(dev)) {
873                 env_name = udev_list_entry_get_name(list_entry);
874                 if (!env_name)
875                         continue;
876
877                 if (!strncmp(env_name, CHARGE_NAME, sizeof(CHARGE_NAME))) {
878                         env_value = udev_list_entry_get_value(list_entry);
879                         if (!env_value)
880                                 continue;
881                         if (!strncmp(env_value, BATTERY_NAME,
882                                                 sizeof(BATTERY_NAME))) {
883                                 matched = true;
884                                 break;
885                         }
886                 }
887         }
888
889         if (!matched)
890                 return;
891
892         env_value = udev_device_get_property_value(dev, CHARGE_STATUS);
893         check_charge_status(env_value);
894         env_value = udev_device_get_property_value(dev, CHARGE_ONLINE);
895         check_online_status(env_value);
896         env_value = udev_device_get_property_value(dev, CHARGE_HEALTH);
897         check_health_status(env_value);
898         env_value = udev_device_get_property_value(dev, CHARGE_MISC_EVENT);
899         check_misc_status(env_value);
900         env_value = udev_device_get_property_value(dev, CHARGE_PRESENT);
901         check_present_status(env_value);
902         env_value = udev_device_get_property_value(dev, CAPACITY);
903         check_capacity_status(env_value);
904         env_value = udev_device_get_property_value(dev, TEMPERATURE);
905         check_temperature_status(env_value);
906
907         battery_initialized = true;
908
909         ret = booting_done(NULL);
910         if (ret) {
911                 if (battery.online > POWER_SUPPLY_TYPE_BATTERY)
912                         power_supply_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_ON);
913                 else
914                         power_supply_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_OFF);
915         }
916
917         process_power_supply(&battery.capacity);
918 }
919
920 static int battery_state(struct battery_info *info)
921 {
922         static struct battery_status prev_status;
923
924         if (!info) {
925                 memcpy(&prev_status, &battery, sizeof(battery));
926                 return 0;
927         }
928
929         if (battery.capacity != 0 && prev_status.capacity == battery.capacity &&
930             prev_status.charge_status == battery.charge_status &&
931             prev_status.charge_full == battery.charge_full &&
932             prev_status.charge_now == battery.charge_now &&
933             prev_status.health == battery.health &&
934             prev_status.present == battery.present &&
935             prev_status.online == battery.online &&
936                 prev_status.freq_strength == battery.freq_strength)
937                 return 0;
938
939         prev_status.capacity = battery.capacity;
940         prev_status.charge_status = battery.charge_status;
941         prev_status.charge_full = battery.charge_full;
942         prev_status.charge_now = battery.charge_now;
943         prev_status.health = battery.health;
944         prev_status.present = battery.present;
945         prev_status.online = battery.online;
946         prev_status.freq_strength = battery.freq_strength;
947
948         _I("%s(%s) %s(%d) Capa(%d) Hth(%s,%d) Pres(%d) Curr(%d,%d)",
949                         info->status,
950                         battery.charge_now == CHARGER_CHARGING ? "Charging"
951                                 : (battery.charge_now == CHARGER_DISCHARGING ? "Discharging" : "Abnormal"),
952                         info->power_source,
953                         info->online,
954                         info->capacity,
955                         info->health,
956                         battery.health,
957                         info->present,
958                         info->current_now,
959                         info->current_average);
960         return 1;
961 }
962
963 static void battery_changed(struct battery_info *info, void *data)
964 {
965         int ret;
966
967         if (!info) {
968                 (void)battery_state(NULL);
969                 return;
970         }
971
972         if (info->status) {
973                 snprintf(battery.status_s, sizeof(battery.status_s),
974                                 "%s", info->status);
975                 check_charge_status(info->status);
976         } else
977                 battery.status_s[0] = '\0';
978
979         if (info->health) {
980                 snprintf(battery.health_s, sizeof(battery.health_s),
981                                 "%s", info->health);
982                 check_health_status(info->health);
983         } else
984                 battery.health_s[0] = '\0';
985
986         if (info->power_source)
987                 snprintf(battery.power_source_s, sizeof(battery.power_source_s),
988                                 "%s", info->power_source);
989         else
990                 battery.power_source_s[0] = '\0';
991
992         battery.online = info->online;
993         battery.present = info->present;
994         battery.capacity = info->capacity;
995         battery.current_now = info->current_now;
996         battery.current_average = info->current_average;
997         battery.temperature = info->temperature;
998         battery.voltage_now = info->voltage_now;
999         battery.voltage_average = info->voltage_average;
1000         battery.freq_strength = info->freq_strength;
1001
1002         battery_initialized = true;
1003
1004         ret = battery_state(info);
1005         if (ret != 1)
1006                 return;
1007
1008         ret = booting_done(NULL);
1009         if (ret) {
1010                 /* If the same notification is requested repeatedly, it is ignored by power_supply_noti().
1011                  * A notification will be triggered only when charge_status changes between
1012                  * CHARGE_STATUS_CHARGING/FULL <-> CHARGE_STATUS_DISCHARGING. */
1013                 if (battery.charge_status == CHARGE_STATUS_CHARGING || battery.charge_status == CHARGE_STATUS_FULL)
1014                         power_supply_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_ON);
1015                 else if (battery.charge_status == CHARGE_STATUS_DISCHARGING)
1016                         power_supply_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_OFF);
1017         }
1018
1019         if (ret == 0) {
1020                 battery.health = HEALTH_GOOD;
1021                 battery.present = PRESENT_NORMAL;
1022         }
1023
1024         process_power_supply(&battery.capacity);
1025
1026 }
1027
1028 static void power_supply_status_init(void)
1029 {
1030         int r;
1031
1032         if (battery_dev && battery_dev->get_current_state) {
1033                 r = battery_dev->get_current_state(battery_changed, NULL);
1034                 if (r < 0 || battery.capacity < 0) {
1035                         _E("Failed to get battery capacity (capa: %d, ret: %d)", battery.capacity, r);
1036                         return;
1037                 }
1038         } else {
1039                 r = config_parse(POWER_SUPPLY_UEVENT, load_uevent, &battery);
1040                 if (r < 0) {
1041                         _E("Failed to load %s, %d Use default value.", POWER_SUPPLY_UEVENT, r);
1042                         return;
1043                 }
1044                 battery.health = HEALTH_GOOD;
1045                 battery.present = PRESENT_NORMAL;
1046                 process_power_supply(&battery.capacity);
1047         }
1048 }
1049
1050 static gboolean power_supply_update(void *data)
1051 {
1052         power_supply_status_init();
1053         return G_SOURCE_CONTINUE;
1054 }
1055
1056 static void power_supply_timer_start(void)
1057 {
1058         _D("Battery init timer during booting.");
1059         power_timer = g_timeout_add(BATTERY_CHECK_TIMER_INTERVAL,
1060                                 power_supply_update, NULL);
1061         if (power_timer == 0)
1062                 _E("Failed to add battery init timer during booting.");
1063         else
1064                 _I("Started battery init timer during booting.");
1065 }
1066
1067 static void power_supply_timer_stop(void)
1068 {
1069         if (power_timer == 0)
1070                 return;
1071         _I("Stop battery init timer during booting.");
1072         g_source_remove(power_timer);
1073         power_timer = 0;
1074 }
1075
1076 static GVariant *dbus_get_charger_status(GDBusConnection *conn,
1077         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1078         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1079 {
1080         int ret, status;
1081
1082         ret = vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, &status);
1083         if (ret < 0) {
1084                 _E("Failed to get vconf value for charger status: %d", vconf_get_ext_errno());
1085                 status = -EIO;
1086         }
1087         return g_variant_new("(i)", status);
1088 }
1089
1090 static GVariant *dbus_get_charger_type(GDBusConnection *conn,
1091         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1092         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1093 {
1094         int type = battery.online_type;
1095
1096         return g_variant_new("(i)", type);
1097 }
1098
1099 static GVariant *dbus_charger_charging(GDBusConnection *conn,
1100         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1101         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1102 {
1103         int ret = 0;
1104         int val;
1105         int chg_on;
1106
1107         g_variant_get(param, "(i)", &val);
1108
1109         if (val != CHARGER_ENABLED && val != CHARGER_DISABLED) {
1110                 _E("There is no valid input: %d", battery.charger_charging);
1111                 ret = -EINVAL;
1112                 goto out;
1113         }
1114         if (battery.online <= POWER_SUPPLY_TYPE_BATTERY) {
1115                 _E("There is no charger(%d) input(%d).", battery.online, battery.charger_charging);
1116                 ret = -EACCES;
1117                 goto out;
1118         }
1119         ret = sys_get_int(CHARGER_CHARGE_ON_NODE, &chg_on);
1120         if (ret == 0 && val != chg_on) {
1121                 battery.charger_charging = val;
1122                 ret = sys_set_int(CHARGER_CHARGE_ON_NODE, battery.charger_charging);
1123                 CRITICAL_LOG("chg_on changed to %d %s", battery.charger_charging,
1124                         (ret == 0) ? "success" : "fail");
1125                 _I("%s to change status with %d.", ((ret == 0) ? "success" : "fail"), battery.charger_charging);
1126         } else {
1127                 _I("Skip change status with %d (ret %d prev %d)", val, ret, battery.charger_charging);
1128         }
1129 out:
1130         return g_variant_new("(i)", ret);
1131 }
1132
1133 static GVariant *dbus_get_charge_now(GDBusConnection *conn,
1134         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1135         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1136 {
1137         int ret;
1138
1139         ret = battery.charge_now;
1140
1141         return g_variant_new("(i)", ret);
1142 }
1143
1144 static GVariant *dbus_get_charge_level(GDBusConnection *conn,
1145         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1146         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1147 {
1148         int ret, val;
1149
1150         ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &val);
1151         if (ret < 0) {
1152                 _E("Failed to get vconf value for battery status low: %d", vconf_get_ext_errno());
1153                 val = -EIO;
1154         }
1155
1156         return g_variant_new("(i)", val);
1157 }
1158
1159 static GVariant *dbus_get_percent(GDBusConnection *conn,
1160         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1161         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1162 {
1163         int ret;
1164
1165         ret = battery.capacity;
1166
1167         return g_variant_new("(i)", ret);
1168 }
1169
1170 static GVariant *dbus_get_percent_raw(GDBusConnection *conn,
1171         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1172         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1173 {
1174         int ret;
1175
1176         ret = -ENOTSUP;
1177
1178         return g_variant_new("(i)", ret);
1179 }
1180
1181 static GVariant *dbus_is_full(GDBusConnection *conn,
1182         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1183         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1184 {
1185         int ret;
1186
1187         ret = battery.charge_full;
1188
1189         return g_variant_new("(i)", ret);
1190 }
1191
1192 static GVariant *dbus_get_health(GDBusConnection *conn,
1193         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1194         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1195 {
1196         const char *str;
1197
1198         str = battery.health_s;
1199
1200         return g_variant_new("(s)", str);
1201 }
1202
1203 static GVariant *dbus_get_misc(GDBusConnection *conn,
1204         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1205         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1206 {
1207         int ret;
1208
1209         ret = battery.misc;
1210
1211         return g_variant_new("(i)", ret);
1212 }
1213
1214
1215 static GVariant *dbus_get_freq_strength(GDBusConnection *conn,
1216         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1217         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1218 {
1219         return g_variant_new("(i)", battery.freq_strength);
1220 }
1221
1222 static GVariant *dbus_get_power_supply_handler(GDBusConnection *conn,
1223         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1224         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1225 {
1226         return g_variant_new("(iiiiiiiisiiiii)", 0,
1227                                 battery.capacity,
1228                                 battery.charge_status,
1229                                 battery.health,
1230                                 battery.online,
1231                                 battery.present,
1232                                 battery.misc,
1233                                 battery.freq_strength,
1234                                 battery.power_source_s,
1235                                 battery.voltage_now,
1236                                 battery.voltage_average,
1237                                 battery.current_now,
1238                                 battery.current_average,
1239                                 battery.temperature);
1240 }
1241
1242 static GVariant *dbus_power_supply_handler(GDBusConnection *conn,
1243         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1244         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1245 {
1246         pid_t pid;
1247         int ret = 0, argc = 0;
1248         char *type_str;
1249         char *argv[13];
1250         struct battery_info info = {0, };
1251
1252         g_variant_get(param, "(sisssssssssssss)", &type_str,
1253                                 &argc,
1254                                 &argv[0],
1255                                 &argv[1],
1256                                 &argv[2],
1257                                 &argv[3],
1258                                 &argv[4],
1259                                 &argv[5],
1260                                 &argv[6],
1261                                 &argv[7],
1262                                 &argv[8],
1263                                 &argv[9],
1264                                 &argv[10],
1265                                 &argv[11],
1266                                 &argv[12]);
1267
1268         if (argc < 0) {
1269                 _E("Message is invalid.");
1270                 ret = -EINVAL;
1271                 goto out;
1272         }
1273
1274         pid = dbus_connection_get_sender_pid(conn, sender);
1275         if (pid == -1 || kill(pid, 0) == -1) {
1276                 _E("Process(%d) does not exist, dbus ignored.", pid);
1277                 ret = -ESRCH;
1278                 goto out;
1279         }
1280
1281         info.capacity = atoi(argv[0]);
1282         info.status = strdup(argv[1]);
1283         info.health = strdup(argv[2]);
1284         info.online = atoi(argv[3]);
1285         info.present = atoi(argv[4]);
1286         check_misc_status(argv[5]);
1287         info.freq_strength = atoi(argv[6]);
1288         info.power_source = strdup(argv[7]);
1289         info.voltage_now = atoi(argv[8]);
1290         info.voltage_average = atoi(argv[9]);
1291         info.current_now = atoi(argv[10]);
1292         info.current_average = atoi(argv[11]);
1293         info.temperature = atoi(argv[12]);
1294         _D("C(%d) S(%s) H(%s) O(%d) P(%d) F(%d) SRC(%s) Vol(%d %d) Cur(%d %d) T(%d)",
1295                 info.capacity, info.status, info.health, info.online, info.present, info.freq_strength, info.power_source, info.voltage_now, info.voltage_average, info.current_now, info.current_average, info.temperature);
1296
1297         if (battery_dev)
1298                 battery_changed(&info, NULL);
1299
1300         snprintf(battery.status_s, sizeof(battery.status_s), "%s",
1301                         (battery.charge_now == CHARGER_CHARGING) ? "Charging" :
1302                         (battery.charge_now == CHARGER_ABNORMAL) ? "Not Charging" :
1303                         (battery.charge_full == CHARGING_FULL) ? "Full" :
1304                         "Discharging");
1305         _I("%s(%d) %s(f:%d n:%d) %s(%d) %s(%d) %s(%d) %s(%d)",
1306                 argv[0],
1307                 battery.capacity,
1308                 argv[1],
1309                 battery.charge_full,
1310                 battery.charge_now,
1311                 argv[2],
1312                 battery.health,
1313                 argv[3],
1314                 battery.online,
1315                 argv[4],
1316                 battery.present,
1317                 argv[5],
1318                 battery.misc);
1319         _I("%s(%d) %s(%s) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d)",
1320                 argv[6],
1321                 battery.freq_strength,
1322                 argv[7],
1323                 battery.power_source_s,
1324                 argv[8],
1325                 battery.voltage_now,
1326                 argv[9],
1327                 battery.voltage_average,
1328                 argv[10],
1329                 battery.current_now,
1330                 argv[11],
1331                 battery.current_average,
1332                 argv[12],
1333                 battery.temperature);
1334
1335         if (battery.online > POWER_SUPPLY_TYPE_BATTERY)
1336                 power_supply_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_ON);
1337         else
1338                 power_supply_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_OFF);
1339
1340         process_power_supply(&battery.capacity);
1341 out:
1342         g_free(type_str);
1343         g_free(argv[0]);
1344         g_free(argv[1]);
1345         g_free(argv[2]);
1346         g_free(argv[3]);
1347         g_free(argv[4]);
1348         g_free(argv[5]);
1349         g_free(argv[6]);
1350         g_free(argv[7]);
1351         g_free(argv[8]);
1352         g_free(argv[9]);
1353         g_free(argv[10]);
1354         g_free(argv[11]);
1355         g_free(argv[12]);
1356
1357         free(info.status);
1358         free(info.health);
1359         free(info.power_source);
1360
1361         return g_variant_new("(i)", ret);
1362 }
1363
1364 static void battery_get_info(struct battery_info *info, void *data)
1365 {
1366         struct battery_info *bat = data;
1367
1368         if (!info || !bat)
1369                 return;
1370
1371         bat->status = strdup(info->status);
1372         bat->health = strdup(info->health);
1373         bat->power_source = strdup(info->power_source);
1374         bat->online = info->online;
1375         bat->present = info->present;
1376         bat->capacity = info->capacity;
1377         bat->current_now = info->current_now;
1378         bat->current_average = info->current_average;
1379         bat->temperature = info->temperature;
1380         bat->voltage_now = info->voltage_now;
1381         bat->voltage_average = info->voltage_average;
1382         bat->freq_strength = info->freq_strength;
1383 }
1384
1385 static GVariant *dbus_get_battery_info(GDBusConnection *conn,
1386         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1387         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1388 {
1389         int ret = 0, val;
1390         const char *str;
1391         struct battery_info info = {0, };
1392
1393         if (old_state == DEVICE_NOTIFIER_STATE_STOP)
1394                 goto out;
1395
1396         if (battery_initialized)
1397                 goto out;
1398
1399         if (battery_dev && battery_dev->get_current_state) {
1400                 ret = battery_dev->get_current_state(battery_get_info, &info);
1401                 if (ret < 0)
1402                         _E("Failed to get battery info: %d", ret);
1403
1404                 battery_changed(&info, NULL);
1405                 free(info.status);
1406                 free(info.health);
1407                 free(info.power_source);
1408         } else {
1409                 if (vconf_get_int(VCONFKEY_SYSMAN_USB_STATUS, &val) == 0 &&
1410                         val != VCONFKEY_SYSMAN_USB_DISCONNECTED)
1411                         str = POWER_SOURCE_USB;
1412                 else if (vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, &val) == 0 &&
1413                         val == VCONFKEY_SYSMAN_CHARGER_CONNECTED)
1414                         str = POWER_SOURCE_AC;
1415                 else
1416                         str = POWER_SOURCE_NONE;
1417                 snprintf(battery.power_source_s, sizeof(battery.power_source_s), "%s", str);
1418
1419                 battery.current_now = -1; /* Not supported */
1420                 battery.current_average = -1; /* Not supported */
1421                 ret = 0;
1422         }
1423
1424 out:
1425         return g_variant_new("(isssiiiiiiii)", ret,
1426                                 battery.status_s,
1427                                 battery.health_s,
1428                                 battery.power_source_s,
1429                                 battery.online,
1430                                 battery.present,
1431                                 battery.capacity,
1432                                 battery.current_now,
1433                                 battery.current_average,
1434                                 battery.voltage_now,
1435                                 battery.voltage_average,
1436                                 battery.temperature);
1437 }
1438
1439 static void update_battery_props(void)
1440 {
1441         if (config_parse(POWER_SUPPLY_UEVENT, load_uevent, &battery) < 0)
1442                 _E("Failed to check power supply uevent.");
1443 }
1444
1445 static GVariant *dbus_get_battery_props(GDBusConnection *conn,
1446         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1447         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1448 {
1449         update_battery_props();
1450
1451         return g_variant_new("(iiiiii)",
1452                                         battery.capacity,
1453                                         battery.temperature,
1454                                         battery.voltage_now,
1455                                         battery.voltage_average,
1456                                         battery.current_now,
1457                                         battery.current_average);
1458 }
1459
1460 static const dbus_method_s dbus_methods[] = {
1461         { CHARGER_STATUS_SIGNAL,      NULL, "i", dbus_get_charger_status },
1462         { CHARGE_NOW_SIGNAL,          NULL, "i", dbus_get_charge_now },
1463         { CHARGE_LEVEL_SIGNAL,         NULL, "i", dbus_get_charge_level },
1464         { CHARGE_CAPACITY_SIGNAL,     NULL, "i", dbus_get_percent },
1465         { CHARGE_CAPACITY_LAW_SIGNAL, NULL, "i", dbus_get_percent_raw },
1466         { CHARGE_FULL_SIGNAL,         NULL, "i", dbus_is_full },
1467         { CHARGE_HEALTH_SIGNAL,        NULL, "s", dbus_get_health },
1468         { POWER_SUBSYSTEM,      "sisssssssssssss", "i", dbus_power_supply_handler },
1469         { GET_POWER_SUBSYSTEM,      NULL, "iiiiiiiisiiiii", dbus_get_power_supply_handler },
1470         { "GetBatteryInfo",           NULL, "isssiiiiiiii", dbus_get_battery_info },
1471         { CHARGER_TYPE_SIGNAL,         NULL, "i", dbus_get_charger_type },
1472         { "ChargerCharging",            "i", "i", dbus_charger_charging },
1473         { CHARGE_BATTERY_PROPERTIES,   NULL, "iiiiii", dbus_get_battery_props },
1474         { CHARGE_MISC_EVENT_SIGNAL,    NULL, "i", dbus_get_misc },
1475         { CHARGE_FREQ_STRENGTH_SIGNAL, NULL, "i", dbus_get_freq_strength},
1476 };
1477
1478 static const dbus_interface_u dbus_interface = {
1479         .oh = NULL,
1480         .name = DEVICED_INTERFACE_BATTERY,
1481         .methods = dbus_methods,
1482         .nr_methods = ARRAY_SIZE(dbus_methods),
1483 };
1484
1485 static int booting_done(void *data)
1486 {
1487         static int done;
1488         device_notifier_state_e state = DEVICE_NOTIFIER_STATE_START;
1489
1490         if (data == NULL)
1491                 return done;
1492         done = *(int *)data;
1493         if (done == 0)
1494                 return done;
1495
1496         power_supply_timer_stop();
1497         event_handler_state_changed((void *)&state);
1498
1499         _I("booting done %s(%d) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d : %s)",
1500                         CHARGER_STATUS_SIGNAL, online_status,
1501                         CHARGE_NOW_SIGNAL, battery.charge_now,
1502                         CHARGE_FULL_SIGNAL, battery.charge_full,
1503                         CHARGE_CAPACITY_SIGNAL, battery.capacity,
1504                         CHARGE_LEVEL_SIGNAL, battery.charging_level,
1505                         CHARGE_MISC_EVENT_SIGNAL, battery.misc,
1506                         CHARGE_HEALTH_SIGNAL, battery.health, battery.health_s);
1507
1508         unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
1509
1510         return done;
1511 }
1512
1513 bool battery_do_not_disturb(void)
1514 {
1515         int block = 0, theater = 0, night = 0;
1516         int r;
1517
1518         if (battery_plgn.display_changed) {
1519                 if (battery_plgn.display_changed(NULL) == S_LCDOFF) {
1520                         r = vconf_get_bool(VCONFKEY_SETAPPL_BLOCKMODE_WEARABLE_BOOL, &block);
1521                         if (r < 0)
1522                                 _E("Failed to set vconf value for blockmode wearable: %d", vconf_get_ext_errno());
1523                         r = vconf_get_bool(VCONFKEY_SETAPPL_THEATER_MODE_ENABLE, &theater);
1524                         if (r < 0)
1525                                 _E("Failed to set vconf value for theator mode enable: %d", vconf_get_ext_errno());
1526                         r = vconf_get_bool(VCONFKEY_SETAPPL_GOODNIGHT_MODE_ENABLE, &night);
1527                         if (r < 0)
1528                                 _E("Failed to set vconf value for goodnight mode enable: %d", vconf_get_ext_errno());
1529                 }
1530         }
1531
1532         if (block != 0 || theater != 0 || night != 0) {
1533                 _I("Skip lcd and popup(block %d theater %d night %d).", block, theater, night);
1534                 return true;
1535         }
1536
1537         return false;
1538 }
1539
1540 int battery_pm_change_internal(int pid, int s_bits)
1541 {
1542         if (battery_do_not_disturb())
1543                 return 0;
1544
1545         if (disp_plgn.pm_change_internal)
1546                 disp_plgn.pm_change_internal(pid, s_bits);
1547
1548         return 0;
1549 }
1550
1551 static int load_uevent(struct parse_result *result, void *user_data)
1552 {
1553         struct battery_status *info = user_data;
1554
1555         if (!info)
1556                 return -EINVAL;
1557
1558         if (MATCH(result->name, CHARGE_STATUS)) {
1559                 if (strstr(result->value, "Charging")) {
1560                         info->charge_now = CHARGER_CHARGING;
1561                         info->charge_full = CHARGING_NOT_FULL;
1562                 } else if (strstr(result->value, "Discharging")) {
1563                         info->charge_now = CHARGER_DISCHARGING;
1564                         info->charge_full = CHARGING_NOT_FULL;
1565                 } else if (strstr(result->value, "Full")) {
1566                         info->charge_now = CHARGER_DISCHARGING;
1567                         info->charge_full = CHARGING_FULL;
1568                 } else if (strstr(result->value, "Not charging")) {
1569                         info->charge_now = CHARGER_ABNORMAL;
1570                         info->charge_full = CHARGING_NOT_FULL;
1571                 }
1572                 snprintf(info->status_s, sizeof(info->status_s), "%s", result->value);
1573         } else if (MATCH(result->name, CAPACITY)) {
1574                 info->capacity = atoi(result->value);
1575         } else if (MATCH(result->name, TEMPERATURE)) {
1576                 info->temperature = atoi(result->value) / 10;
1577         } else if (MATCH(result->name, VOLTAGE_NOW)) {
1578                 info->voltage_now = atoi(result->value);
1579         } else if (MATCH(result->name, VOLTAGE_AVG)) {
1580                 info->voltage_average = atoi(result->value);
1581         } else if (MATCH(result->name, CURRENT_NOW)) {
1582                 info->current_now = atoi(result->value);
1583         } else if (MATCH(result->name, CURRENT_AVG)) {
1584                 info->current_average = atoi(result->value);
1585         } else if (MATCH(result->name, CHARGE_HEALTH)) {
1586                 snprintf(info->health_s, sizeof(info->health_s), "%s", result->value);
1587         }
1588
1589         return 0;
1590 }
1591
1592 static int power_supply_probe(void *data)
1593 {
1594         struct hw_info *info;
1595         int ret, r;
1596
1597         if (battery_dev)
1598                 return 0;
1599
1600         ret = hw_get_info(BATTERY_HARDWARE_DEVICE_ID,
1601                         (const struct hw_info **)&info);
1602         if (ret < 0) { /* There is no HAL for battery */
1603                 if (access(POWER_PATH, R_OK) == 0)
1604                         return 0; /* Just power_supply uevent is used */
1605                 goto out;
1606         }
1607
1608         if (!info->open) {
1609                 _E("Failed to open battery device: open(NULL)");
1610                 return -ENODEV;
1611         }
1612
1613         ret = info->open(info, NULL, (struct hw_common**)&battery_dev);
1614         if (ret < 0) {
1615                 _E("Failed to get battery device structure: %d", ret);
1616                 return ret;
1617         }
1618
1619         if (!battery_dev || !battery_dev->get_current_state) {
1620                 _E("get_current_state() is not supported by the Battery HAL.");
1621                 return -ENODEV;
1622         }
1623
1624         _I("Battery device structure load success.");
1625         return 0;
1626
1627 out:
1628         /**
1629          * Set battery vconf as -ENOTSUP
1630          * These vconf key used by runtime-info and capi-system-device.
1631          */
1632         r = vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, -ENOTSUP);
1633         if (r < 0)
1634                 _E("Failed to set vconf value for charger status: %d", vconf_get_ext_errno());
1635         r = vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, -ENOTSUP);
1636         if (r < 0)
1637                 _E("Failed to set vconf value for battery charge now: %d", vconf_get_ext_errno());
1638         r = vconf_set_int(VCONFKEY_SYSMAN_BATTERY_LEVEL_STATUS, -ENOTSUP);
1639         if (r < 0)
1640                 _E("Failed to set vconf value for battery level status: %d", vconf_get_ext_errno());
1641         _I("There is no battery device: %d", ret);
1642         return -ENODEV;
1643 }
1644
1645 static void add_power_supply_handler(void)
1646 {
1647         int ret;
1648
1649         if (battery_dev) {
1650                 if (battery_dev->register_changed_event)
1651                         battery_dev->register_changed_event(battery_changed, NULL);
1652                 if (battery_dev->get_current_state)
1653                         battery_dev->get_current_state(battery_changed, NULL);
1654         } else {
1655                 ret = config_parse(POWER_SUPPLY_UEVENT, load_uevent, &battery);
1656                 if (ret < 0)
1657                         _E("Failed to load %s, %d Use default value!", POWER_SUPPLY_UEVENT, ret);
1658
1659                 /* register power subsystem */
1660                 register_kernel_uevent_control(&uh);
1661         }
1662 }
1663
1664 static void remove_power_supply_handler(void)
1665 {
1666         if (battery_dev)
1667                 battery_dev->unregister_changed_event(battery_changed);
1668         else
1669                 unregister_kernel_uevent_control(&uh);
1670 }
1671
1672 static int event_handler_state_changed(void *data)
1673 {
1674         device_notifier_state_e state = *(device_notifier_state_e *)data;
1675
1676         if (old_state == state)
1677                 return 0;
1678
1679         old_state = state;
1680
1681         if (state == DEVICE_NOTIFIER_STATE_START)
1682                 add_power_supply_handler();
1683         else if (state == DEVICE_NOTIFIER_STATE_STOP)
1684                 remove_power_supply_handler();
1685
1686         return 0;
1687 }
1688
1689 static void power_supply_init(void *data)
1690 {
1691         int ret;
1692
1693         memset(&battery, 0, sizeof(struct battery_status));
1694         memset(&old_battery, 0, sizeof(struct battery_status));
1695         battery.charger_charging = CHARGER_ENABLED;
1696         battery.misc = MISC_NONE;
1697         battery.freq_strength = 0;
1698
1699         /* It will be true on initializing battery structure */
1700         battery_initialized = false;
1701
1702         /* process check battery timer until booting done */
1703         power_supply_timer_start();
1704
1705         register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
1706         register_notifier(DEVICE_NOTIFIER_EVENT_HANDLER, event_handler_state_changed);
1707
1708         ret = dbus_handle_add_dbus_object(NULL, DEVICED_PATH_BATTERY, &dbus_interface);
1709         if (ret < 0)
1710                 _E("Failed to init dbus method: %d", ret);
1711
1712         battery_ops_init((void *)&battery_plgn);
1713 }
1714
1715 static void power_supply_exit(void *data)
1716 {
1717         device_notifier_state_e state = DEVICE_NOTIFIER_STATE_STOP;
1718
1719         unregister_notifier(DEVICE_NOTIFIER_EVENT_HANDLER, event_handler_state_changed);
1720
1721         event_handler_state_changed((void *)&state);
1722
1723         battery_ops_exit(NULL);
1724 }
1725
1726 static const struct device_ops power_supply_ops = {
1727         DECLARE_NAME_LEN("power_supply"),
1728         .probe    = power_supply_probe,
1729         .init     = power_supply_init,
1730         .exit     = power_supply_exit,
1731 };
1732
1733 DEVICE_OPS_REGISTER(&power_supply_ops)