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