f6c217bf63a155453853cde6d73b38d2aeb202a0
[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
28 #include "core/devices.h"
29 #include "core/device-notifier.h"
30 #include "core/udev.h"
31 #include "core/log.h"
32 #include "core/config-parser.h"
33 #include "display/poll.h"
34 #include "display/setting.h"
35 #include "apps/apps.h"
36 #include "power-supply.h"
37 #include "battery.h"
38 #include "extcon/extcon_count.h"
39
40 #define BATTERY_NAME        "battery"
41 #define CHARGEFULL_NAME     "Full"
42 #define CHARGENOW_NAME      "Charging"
43 #define DISCHARGE_NAME      "Discharging"
44 #define NOTCHARGE_NAME      "Not charging"
45 #define OVERHEAT_NAME       "Overheat"
46 #define TEMPCOLD_NAME       "Cold"
47 #define OVERVOLT_NAME       "Over voltage"
48
49 #define REMOVE_POPUP "remove_battery_popups"
50
51 #define BUFF_MAX            255
52
53 #define SIGNAL_CHARGEERR_RESPONSE "ChargeErrResponse"
54 #define SIGNAL_TEMP_GOOD          "TempGood"
55
56 #define ABNORMAL_CHECK_TIMER_INTERVAL 60
57
58 #define METHOD_FULL_NOTI_ON   "BatteryFullNotiOn"
59 #define METHOD_FULL_NOTI_OFF  "BatteryFullNotiOff"
60 #define METHOD_CHARGE_NOTI_ON "BatteryChargeNotiOn"
61
62 #define RETRY_MAX 5
63 #define BATTERY_CHECK_TIMER_INTERVAL (0.5)
64
65 enum power_supply_init_type {
66         POWER_SUPPLY_NOT_READY   = 0,
67         POWER_SUPPLY_INITIALIZED = 1,
68 };
69
70 static void uevent_power_handler(struct udev_device *dev);
71 static const struct uevent_handler uh = {
72         .subsystem   = POWER_SUBSYSTEM,
73         .uevent_func = uevent_power_handler,
74 };
75
76 struct battery_status battery;
77 struct battery_status old_battery;
78 static int noti_id;
79 static guint power_timer;
80
81 static int booting_done(void *data);
82
83 static struct battery_device *battery_dev;
84
85 static void lowbat_execute(void *data)
86 {
87         static const struct device_ops *lowbat_ops;
88
89         FIND_DEVICE_VOID(lowbat_ops, "lowbat");
90         device_execute(lowbat_ops, data);
91 }
92
93 static void pm_check_and_change(int bInserted)
94 {
95         static int old = -1;
96
97         if (old == bInserted)
98                 return;
99         old = bInserted;
100         pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
101 }
102
103 static int changed_battery_cf(enum present_type status)
104 {
105         char *value;
106
107         if (status == PRESENT_ABNORMAL)
108                 value = "battdisconnect";
109         else
110                 value = "remove_battery_popups";
111
112         return launch_system_app(APP_DEFAULT,
113                         2, APP_KEY_TYPE, value);
114 }
115
116 static void health_status_broadcast(void)
117 {
118         dbus_handle_broadcast_dbus_signal(DEVICED_PATH_BATTERY, DEVICED_INTERFACE_BATTERY,
119             SIGNAL_TEMP_GOOD, NULL, NULL);
120 }
121
122 #ifdef TIZEN_FEATURE_BATTERY_OVER_TEMPERATURE
123 static guint abnormal_timer;
124
125 static void abnormal_popup_timer_init(void)
126 {
127         if (abnormal_timer == NULL)
128                 return;
129         g_source_remove(abnormal_timer);
130         abnormal_timer = NULL;
131         _I("delete health timer");
132 }
133
134 static void health_timer_reset(void)
135 {
136         abnormal_timer = NULL;
137 }
138
139 static gboolean health_timer_cb(void *data)
140 {
141         int value = HEALTH_BAD;
142
143         health_timer_reset();
144
145         if (battery.health == HEALTH_GOOD)
146                 return G_SOURCE_REMOVE;
147
148         _I("popup - Battery health status is not good");
149         device_notify(DEVICE_NOTIFIER_BATTERY_HEALTH, (void *)&value);
150         pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
151         pm_lock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, STAY_CUR_STATE, 0);
152         if (battery.temp == TEMP_LOW)
153                 battery_charge_err_low_act(NULL);
154         else if (battery.temp == TEMP_HIGH)
155                 battery_charge_err_high_act(NULL);
156         return G_SOURCE_REMOVE;
157 }
158
159 static void abnormal_popup_dbus_signal_handler(GDBusConnection  *conn,
160                 const gchar      *sender,
161                 const gchar      *path,
162                 const gchar      *iface,
163                 const gchar      *name,
164                 GVariant         *param,
165                 gpointer          user_data)
166
167 {
168         if (battery.health == HEALTH_GOOD)
169                 return;
170         _I("restart health timer");
171         abnormal_timer = g_timeout_add_seconds(ABNORMAL_CHECK_TIMER_INTERVAL,
172                                                 health_timer_cb, NULL);
173         if (abnormal_timer == NULL)
174                 _E("Fail to add abnormal check timer");
175 }
176 #endif /* TIZEN_FEATURE_BATTERY_OVER_TEMPERATURE */
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 (!dh_get_param_from_var(var, "(i)", &id)) {
186                 _E("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 int check_power_supply_noti(void)
198 {
199 #ifdef MICRO_DD
200         int r_disturb, s_disturb, r_block, s_block;
201         r_disturb = vconf_get_int("memory/shealth/sleep/do_not_disturb", &s_disturb);
202         r_block = vconf_get_bool("db/setting/blockmode_wearable", &s_block);
203         if ((r_disturb != 0 && r_block != 0) ||
204             (s_disturb == 0 && s_block == 0)) {
205             return 1;
206         }
207         return 0;
208 #else
209         return 1;
210 #endif
211 }
212
213 static int send_full_noti(enum charge_full_type state)
214 {
215         int ret = 0;
216         int noti;
217         int retry;
218
219         noti = check_power_supply_noti();
220
221         if (!noti)
222                 return noti;
223
224         switch (state) {
225         case CHARGING_FULL:
226                 for (retry = RETRY_MAX; retry > 0; retry--) {
227                         ret = dbus_method_async_with_reply(POPUP_BUS_NAME,
228                                         POPUP_PATH_NOTI,
229                                         POPUP_INTERFACE_NOTI,
230                                         METHOD_FULL_NOTI_ON,
231                                         NULL, 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 (err: %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_method_async_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                         if (ret == 0) {
249                                 _D("Deleted battery full noti");
250                                 noti_id = 0;
251                                 return ret;
252                         }
253                 }
254                 _E("Failed to call dbus method (err: %d)", ret);
255         break;
256         }
257         return ret;
258 }
259
260 static int send_charge_noti(void)
261 {
262         int ret = 0;
263         int retry;
264
265         for (retry = RETRY_MAX; retry > 0; retry--) {
266                 ret = dbus_method_async(POPUP_BUS_NAME,
267                                 POPUP_PATH_NOTI,
268                                 POPUP_INTERFACE_NOTI,
269                                 METHOD_CHARGE_NOTI_ON,
270                                 NULL, NULL);
271                 if (ret == 0) {
272                         _D("Created battery charge noti");
273                         return ret;
274                 }
275         }
276         _E("Failed to call dbus method (err: %d)", ret);
277         return ret;
278 }
279
280 static void power_supply_noti(enum battery_noti_type type, enum battery_noti_status status)
281 {
282         static int charger = CHARGER_DISCHARGING;
283         static int full = CHARGING_NOT_FULL;
284         int ret;
285
286         if (type == DEVICE_NOTI_BATT_CHARGE) {
287                 if (status == DEVICE_NOTI_ON && charger == CHARGER_DISCHARGING) {
288                         send_charge_noti();
289                         charger = CHARGER_CHARGING;
290                 } else if (status == DEVICE_NOTI_OFF && charger == CHARGER_CHARGING) {
291                         charger = CHARGER_DISCHARGING;
292                 }
293         } else if (type == DEVICE_NOTI_BATT_FULL) {
294                 if (status == DEVICE_NOTI_ON && full == CHARGING_NOT_FULL) {
295                         ret = send_full_noti(CHARGING_FULL);
296                         if (ret == 0)
297                                 full = CHARGING_FULL;
298                 } else if (status == DEVICE_NOTI_OFF && full == CHARGING_FULL) {
299                         ret = send_full_noti(CHARGING_NOT_FULL);
300                         if (ret == 0)
301                                 full = CHARGING_NOT_FULL;
302                 }
303         }
304 }
305
306 void power_supply_broadcast(char *sig, int status)
307 {
308         static int old;
309         static char sig_old[32];
310
311         if (strcmp(sig_old, sig) == 0 && old == status)
312                 return;
313
314         _D("%s %d", sig, status);
315
316         old = status;
317         snprintf(sig_old, sizeof(sig_old), "%s", sig);
318         /*snprintf(str_status, sizeof(str_status), "%d", status);
319         arr[0] = str_status;*/
320
321         dbus_handle_broadcast_dbus_signal_var(DEVICED_PATH_BATTERY,
322                                                 DEVICED_INTERFACE_BATTERY,
323                                                 sig,
324                                                 g_variant_new("(i)", status));
325
326 }
327
328 static void noti_batt_full(void)
329 {
330         static int bat_full_noti;
331         int noti;
332
333         if (!battery.charge_full && bat_full_noti == 1) {
334                 power_supply_noti(DEVICE_NOTI_BATT_FULL, DEVICE_NOTI_OFF);
335                 bat_full_noti = 0;
336                 /* off the full charge state */
337                 device_notify(DEVICE_NOTIFIER_FULLBAT, (void *)&bat_full_noti);
338         }
339         if (battery.charge_full && bat_full_noti == 0) {
340                 power_supply_noti(DEVICE_NOTI_BATT_FULL, DEVICE_NOTI_ON);
341                 bat_full_noti = 1;
342                 /* turn on LCD, if battery is full charged */
343                 noti = check_power_supply_noti();
344                 if (noti)
345                         pm_change_internal(INTERNAL_LOCK_BATTERY_FULL,
346                                 LCD_NORMAL);
347                 else
348                         _I("block LCD");
349                 /* on the full charge state */
350                 device_notify(DEVICE_NOTIFIER_FULLBAT, (void *)&bat_full_noti);
351         }
352 }
353
354 static void check_power_supply(int state)
355 {
356         pm_check_and_change(state);
357         if (update_pm_setting)
358                 update_pm_setting(SETTING_CHARGING, state);
359 }
360
361 static void charger_state_send_system_event(int state)
362 {
363         bundle *b;
364         const char *str;
365
366         switch (state) {
367         case CHARGE_STATUS_CHARGING:
368                 str = EVT_VAL_BATTERY_CHARGER_CHARGING;
369                 break;
370         case CHARGE_STATUS_FULL:
371         case CHARGE_STATUS_DISCHARGING:
372                 str = EVT_VAL_BATTERY_CHARGER_DISCHARGING;
373                 break;
374         case CHARGE_STATUS_CONNECTED:
375                 str = EVT_VAL_BATTERY_CHARGER_CONNECTED;
376                 break;
377         case CHARGE_STATUS_DISCONNECTED:
378                 str = EVT_VAL_BATTERY_CHARGER_DISCONNECTED;
379                 break;
380         default:
381                 _E("invalid parameter(%d)", state);
382                 return;
383         }
384
385         _D("system_event(%s)", str);
386
387         b = bundle_create();
388         bundle_add_str(b, EVT_KEY_BATTERY_CHARGER_STATUS, str);
389         eventsystem_send_system_event(SYS_EVENT_BATTERY_CHARGER_STATUS, b);
390         bundle_free(b);
391 }
392
393 static void update_present(enum battery_noti_status status)
394 {
395         static int old = DEVICE_NOTI_OFF;
396         enum present_type present;
397
398         if (old == status)
399                 return;
400         _I("charge %d present %d", battery.charge_now, battery.present);
401         old = status;
402         pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
403         if (status == DEVICE_NOTI_ON) {
404                 present = PRESENT_ABNORMAL;
405                 device_notify(DEVICE_NOTIFIER_BATTERY_PRESENT, (void *)&present);
406                 pm_lock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, STAY_CUR_STATE, 0);
407         } else {
408                 present = PRESENT_NORMAL;
409                 device_notify(DEVICE_NOTIFIER_BATTERY_PRESENT, (void *)&present);
410                 pm_unlock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, PM_SLEEP_MARGIN);
411         }
412         changed_battery_cf(present);
413 }
414
415 #ifdef TIZEN_FEATURE_BATTERY_OVER_TEMPERATURE
416 static void update_health(enum battery_noti_status status)
417 {
418         static int old = DEVICE_NOTI_OFF;
419
420         if (old == status)
421                 return;
422         _I("charge %d health %d", battery.charge_now, battery.health);
423         old = status;
424
425         pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
426         if (status == DEVICE_NOTI_ON) {
427                 _I("popup - Battery health status is not good");
428                 pm_lock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, STAY_CUR_STATE, 0);
429                 if (battery.temp == TEMP_LOW)
430                         battery_charge_err_low_act(NULL);
431                 else if (battery.temp == TEMP_HIGH)
432                         battery_charge_err_high_act(NULL);
433         } else {
434                 pm_unlock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, PM_SLEEP_MARGIN);
435                 abnormal_popup_timer_init();
436                 launch_system_app(APP_DEFAULT, 2, APP_KEY_TYPE, REMOVE_POPUP);
437         }
438 }
439 #endif /* TIZEN_FEATURE_BATTERY_OVER_TEMPERATURE */
440
441 static void update_ovp(enum battery_noti_status status)
442 {
443         static int old = DEVICE_NOTI_OFF;
444         int value;
445
446         if (old == status)
447                 return;
448         _I("charge %d ovp %d", battery.charge_now, battery.ovp);
449         old = status;
450         pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
451         if (status == DEVICE_NOTI_ON)
452                 value = OVP_ABNORMAL;
453         else
454                 value = OVP_NORMAL;
455         device_notify(DEVICE_NOTIFIER_BATTERY_OVP, (void *)&value);
456 }
457
458 static void check_battery_status(void)
459 {
460         static int old = DEVICE_CHANGE_NORMAL;
461         int status;
462
463         if (battery.charge_now == CHARGER_ABNORMAL &&
464             (battery.health == HEALTH_BAD || battery.present == PRESENT_ABNORMAL))
465                 status = DEVICE_CHANGE_ABNORMAL;
466         else if (battery.ovp == OVP_ABNORMAL)
467                 status = DEVICE_CHANGE_ABNORMAL;
468         else
469                 status = DEVICE_CHANGE_NORMAL;
470         if (old == status)
471                 return;
472         old = status;
473
474         if (battery.charge_now == CHARGER_ABNORMAL) {
475                 if (battery.health == HEALTH_BAD) {
476                         device_notify(DEVICE_NOTIFIER_BATTERY_HEALTH, (void *)&battery.health);
477 #ifdef TIZEN_FEATURE_BATTERY_OVER_TEMPERATURE
478                         update_health(DEVICE_NOTI_ON);
479 #endif /* TIZEN_FEATURE_BATTERY_OVER_TEMPERATURE */
480                         return;
481                 } else if (battery.present == PRESENT_ABNORMAL) {
482                         update_present(DEVICE_NOTI_ON);
483                         return;
484                 }
485         }
486         if (battery.ovp == OVP_ABNORMAL) {
487                 update_ovp(DEVICE_NOTI_ON);
488                 return;
489         }
490
491         if (battery.charge_now != CHARGER_ABNORMAL &&
492             status == DEVICE_CHANGE_NORMAL) {
493                 device_notify(DEVICE_NOTIFIER_BATTERY_HEALTH, (void *)&battery.health);
494                 health_status_broadcast();
495 #ifdef TIZEN_FEATURE_BATTERY_OVER_TEMPERATURE
496                 update_health(DEVICE_NOTI_OFF);
497 #endif /* TIZEN_FEATURE_BATTERY_OVER_TEMPERATURE */
498                 update_ovp(DEVICE_NOTI_OFF);
499                 update_present(DEVICE_NOTI_OFF);
500         }
501 }
502
503 static void check_online(void)
504 {
505         static int old_online;
506         static int old_charge_status;
507         int charge_status;
508
509         if (battery.charge_status == CHARGE_STATUS_FULL)
510                 charge_status = CHARGE_STATUS_DISCHARGING;
511         else
512                 charge_status = battery.charge_status;
513
514         if (battery.online > POWER_SUPPLY_TYPE_BATTERY &&
515             old_online == VCONFKEY_SYSMAN_CHARGER_DISCONNECTED) {
516                 old_online = VCONFKEY_SYSMAN_CHARGER_CONNECTED;
517                 vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, old_online);
518                 power_supply_broadcast(CHARGER_STATUS_SIGNAL, old_online);
519                 extcon_get_count(EXTCON_TA);
520                 extcon_set_count(EXTCON_TA, 1);
521                 check_power_supply(old_online);
522                 charger_state_send_system_event(CHARGE_STATUS_CONNECTED);
523                 if (charge_status != old_charge_status)
524                         charger_state_send_system_event(charge_status);
525
526         } else if (battery.online <= POWER_SUPPLY_TYPE_BATTERY &&
527             old_online == VCONFKEY_SYSMAN_CHARGER_CONNECTED) {
528                 old_online = VCONFKEY_SYSMAN_CHARGER_DISCONNECTED;
529                 vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, old_online);
530                 power_supply_broadcast(CHARGER_STATUS_SIGNAL, old_online);
531                 check_power_supply(old_online);
532                 if (charge_status != old_charge_status)
533                         charger_state_send_system_event(charge_status);
534                 charger_state_send_system_event(CHARGE_STATUS_DISCONNECTED);
535
536         } else {
537                 if (charge_status != old_charge_status)
538                         charger_state_send_system_event(charge_status);
539         }
540
541         old_charge_status = charge_status;
542 }
543
544 static void check_charge_status(const char *env_value)
545 {
546         if (env_value == NULL)
547                 return;
548
549         _D("Charge Status(%s)", env_value);
550
551         if (strncmp(env_value, CHARGEFULL_NAME,
552                                 sizeof(CHARGEFULL_NAME)) == 0)
553                 battery.charge_status = CHARGE_STATUS_FULL;
554         else if (strncmp(env_value, CHARGENOW_NAME,
555                                 sizeof(CHARGENOW_NAME)) == 0)
556                 battery.charge_status = CHARGE_STATUS_CHARGING;
557         else if (strncmp(env_value, DISCHARGE_NAME,
558                                 sizeof(DISCHARGE_NAME)) == 0)
559                 battery.charge_status = CHARGE_STATUS_DISCHARGING;
560         else if (strncmp(env_value, NOTCHARGE_NAME,
561                                 sizeof(NOTCHARGE_NAME)) == 0)
562                 battery.charge_status = CHARGE_STATUS_NOT_CHARGING;
563         else
564                 battery.charge_status = CHARGE_STATUS_UNKNOWN;
565
566         if (battery.charge_status == CHARGE_STATUS_FULL) {
567                 battery.charge_full = CHARGING_FULL;
568                 battery.charge_now = CHARGER_DISCHARGING;
569         } else if (battery.charge_status == CHARGE_STATUS_CHARGING) {
570                 battery.charge_full = CHARGING_NOT_FULL;
571                 battery.charge_now = CHARGER_CHARGING;
572         } else if (battery.charge_status == CHARGE_STATUS_DISCHARGING) {
573                 battery.charge_full = CHARGING_NOT_FULL;
574                 battery.charge_now = CHARGER_DISCHARGING;
575         } else if (battery.charge_status == CHARGE_STATUS_NOT_CHARGING) {
576                 battery.charge_full = CHARGING_NOT_FULL;
577                 battery.charge_now = CHARGER_ABNORMAL;
578         } else {
579                 battery.charge_full = CHARGING_NOT_FULL;
580                 battery.charge_now = CHARGER_DISCHARGING;
581         }
582 }
583
584 static void check_health_status(const char *env_value)
585 {
586         if (env_value == NULL) {
587                 battery.health = HEALTH_GOOD;
588                 battery.temp = TEMP_LOW;
589                 battery.ovp = OVP_NORMAL;
590                 return;
591         }
592         if (strncmp(env_value, OVERHEAT_NAME,
593                                 sizeof(OVERHEAT_NAME)) == 0) {
594                 battery.health = HEALTH_BAD;
595                 battery.temp = TEMP_HIGH;
596                 battery.ovp = OVP_NORMAL;
597         } else if (strncmp(env_value, TEMPCOLD_NAME,
598                                 sizeof(TEMPCOLD_NAME)) == 0) {
599                 battery.health = HEALTH_BAD;
600                 battery.temp = TEMP_LOW;
601                 battery.ovp = OVP_NORMAL;
602         } else if (strncmp(env_value, OVERVOLT_NAME,
603                                 sizeof(OVERVOLT_NAME)) == 0) {
604                 battery.health = HEALTH_GOOD;
605                 battery.temp = TEMP_LOW;
606                 battery.ovp = OVP_ABNORMAL;
607         } else {
608                 battery.health = HEALTH_GOOD;
609                 battery.temp = TEMP_LOW;
610                 battery.ovp = OVP_NORMAL;
611         }
612 }
613
614 static void check_online_status(const char *env_value)
615 {
616         if (env_value == NULL)
617                 return;
618         battery.online = atoi(env_value);
619 }
620
621 static void check_present_status(const char *env_value)
622 {
623         if (env_value == NULL) {
624                 battery.present = PRESENT_NORMAL;
625                 return;
626         }
627         battery.present = atoi(env_value);
628 }
629
630 static void check_capacity_status(const char *env_value)
631 {
632         if (env_value == NULL)
633                 return;
634         battery.capacity = atoi(env_value);
635 }
636
637 static void update_capacity_full(void)
638 {
639         static int old;
640         int delta;
641
642         if (battery.online <= POWER_SUPPLY_TYPE_BATTERY ||
643             old == 0 ||
644             old >= battery.capacity) {
645                 old = battery.capacity;
646                 return;
647         }
648         delta = battery.capacity - old;
649         old = battery.capacity;
650         extcon_get_count(EXTCON_BATTERY_FULL);
651         extcon_set_count(EXTCON_BATTERY_FULL, delta);
652 }
653
654 static void process_power_supply(void *data)
655 {
656         if (old_battery.charge_now != battery.charge_now || battery.charge_now == CHARGER_ABNORMAL) {
657                 vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, battery.charge_now);
658                 power_supply_broadcast(CHARGE_NOW_SIGNAL, battery.charge_now);
659         }
660
661         lowbat_execute(data);
662         check_online();
663         if (old_battery.charge_full != battery.charge_full)
664                 noti_batt_full();
665
666         old_battery.capacity = battery.capacity;
667         old_battery.online = battery.online;
668         old_battery.charge_status = battery.charge_status;
669         old_battery.charge_now = battery.charge_now;
670         old_battery.charge_full = battery.charge_full;
671
672         check_battery_status();
673         device_notify(DEVICE_NOTIFIER_POWER_SUPPLY, NULL);
674         device_notify(DEVICE_NOTIFIER_BATTERY_CHARGING, &battery.charge_now);
675         update_capacity_full();
676 }
677
678 static void uevent_power_handler(struct udev_device *dev)
679 {
680         struct udev_list_entry *list_entry;
681         const char *env_name;
682         const char *env_value;
683         bool matched = false;
684         int ret;
685
686         udev_list_entry_foreach(list_entry,
687                         udev_device_get_properties_list_entry(dev)) {
688                 env_name = udev_list_entry_get_name(list_entry);
689                 if (!env_name)
690                         continue;
691
692                 if (!strncmp(env_name, CHARGE_NAME, sizeof(CHARGE_NAME))) {
693                         env_value = udev_list_entry_get_value(list_entry);
694                         if (!env_value)
695                                 continue;
696                         if (!strncmp(env_value, BATTERY_NAME,
697                                                 sizeof(BATTERY_NAME))) {
698                                 matched = true;
699                                 break;
700                         }
701                 }
702         }
703
704         if (!matched)
705                 return;
706
707         env_value = udev_device_get_property_value(dev, CHARGE_STATUS);
708         check_charge_status(env_value);
709         env_value = udev_device_get_property_value(dev, CHARGE_ONLINE);
710         check_online_status(env_value);
711         env_value = udev_device_get_property_value(dev, CHARGE_HEALTH);
712         check_health_status(env_value);
713         env_value = udev_device_get_property_value(dev, CHARGE_PRESENT);
714         check_present_status(env_value);
715         env_value = udev_device_get_property_value(dev, CAPACITY);
716         check_capacity_status(env_value);
717
718         ret = booting_done(NULL);
719         if (ret) {
720                 if (battery.online > POWER_SUPPLY_TYPE_BATTERY)
721                         power_supply_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_ON);
722                 else
723                         power_supply_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_OFF);
724         }
725
726         process_power_supply(&battery.capacity);
727 }
728
729 static void battery_state(struct battery_info *info)
730 {
731         if (!info)
732                 return;
733
734         _I("%s(%s) %s(%d) Capa(%d) Hth(%s,%s) Pres(%d) OVP(%s) Curr(%d,%d)",
735                         info->status,
736                         battery.charge_now == CHARGER_CHARGING ? "Charging"
737                                 : (battery.charge_now == CHARGER_DISCHARGING ? "Discharging" : "Abnormal"),
738                         info->power_source,
739                         info->online,
740                         info->capacity,
741                         info->health,
742                         battery.temp == TEMP_LOW ? "Low" : "High",
743                         info->present,
744                         battery.ovp == OVP_NORMAL ? "X" : "O",
745                         info->current_now,
746                         info->current_average);
747 }
748
749 static void battery_changed(struct battery_info *info, void *data)
750 {
751         int ret;
752
753         if (!info)
754                 return;
755
756         if (info->status) {
757                 snprintf(battery.status_s, sizeof(battery.status_s),
758                                 "%s", info->status);
759                 check_charge_status(info->status);
760         } else
761                 battery.status_s[0] = '\0';
762
763         if (info->health) {
764                 snprintf(battery.health_s, sizeof(battery.health_s),
765                                 "%s", info->health);
766                 check_health_status(info->health);
767         } else
768                 battery.health_s[0] = '\0';
769
770         if (info->power_source)
771                 snprintf(battery.power_source_s, sizeof(battery.power_source_s),
772                                 "%s", info->power_source);
773         else
774                 battery.power_source_s[0] = '\0';
775
776         battery.online = info->online;
777         battery.present = info->present;
778         battery.capacity = info->capacity;
779         battery.current_now = info->current_now;
780         battery.current_average = info->current_average;
781
782         battery_state(info);
783
784         ret = booting_done(NULL);
785         if (ret) {
786                 if (battery.online > POWER_SUPPLY_TYPE_BATTERY)
787                         power_supply_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_ON);
788                 else
789                         power_supply_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_OFF);
790         }
791
792         process_power_supply(&battery.capacity);
793
794 }
795
796 static int lowbat_read(int *val)
797 {
798         int r;
799
800         if (!val)
801                 return -EINVAL;
802
803         r = sys_get_int("/sys/class/power_supply/battery/capacity", val);
804         if (r < 0)
805                 return r;
806
807         return 0;
808 }
809
810 static void battery_get_capacity(struct battery_info *info, void *data)
811 {
812         int *capa = data;
813
814         if (info && info->capacity >= 0)
815                 *capa = info->capacity;
816 }
817
818 static void power_supply_status_init(void)
819 {
820         static int charge_now = -1;
821         static int charge_full = -1;
822         static int capacity = -1;
823         int pct;
824         int r;
825
826         if (battery_dev && battery_dev->get_current_state) {
827                 pct = -1;
828                 r = battery_dev->get_current_state(battery_get_capacity, &pct);
829                 if (r < 0 || pct < 0) {
830                         _E("Failed to get battery capacity (capa:%d, ret:%d)", pct, r);
831                         return;
832                 }
833         } else {
834                 r = lowbat_read(&pct);
835                 if (r < 0) {
836                         _E("fail to read capacity data : %d", r);
837                         return;
838                 }
839         }
840
841         battery.capacity = pct;
842         battery.health = HEALTH_GOOD;
843         battery.ovp = OVP_NORMAL;
844         battery.present = PRESENT_NORMAL;
845         battery.temp = TEMP_LOW;
846
847         if (charge_now == battery.charge_now &&
848             charge_full == battery.charge_full &&
849             capacity == battery.capacity)
850                 return;
851
852         _I("charging %d full %d capacity %d", battery.charge_now, battery.charge_full, battery.capacity);
853
854         if (charge_now != battery.charge_now) {
855                 vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, battery.charge_now);
856                 power_supply_broadcast(CHARGE_NOW_SIGNAL, battery.charge_now);
857         }
858         if (capacity != battery.capacity) {
859                 vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY, battery.capacity);
860                 power_supply_broadcast(CHARGE_CAPACITY_SIGNAL, battery.capacity);
861         }
862
863         charge_now = battery.charge_now;
864         charge_full = battery.charge_full;
865         capacity =  battery.capacity;
866 }
867
868 static gboolean power_supply_update(void *data)
869 {
870         power_supply_status_init();
871         return G_SOURCE_CONTINUE;
872 }
873
874 static void power_supply_timer_start(void)
875 {
876         _D("battery init timer during booting");
877         power_timer = g_timeout_add_seconds(BATTERY_CHECK_TIMER_INTERVAL,
878                                 power_supply_update, NULL);
879         if (power_timer == 0)
880                 _E("fail to add battery init timer during booting");
881 }
882
883 static void power_supply_timer_stop(void)
884 {
885         _D("battery init timer during booting");
886         if (!power_timer)
887                 return;
888         g_source_remove(power_timer);
889         power_timer = 0;
890 }
891
892 static GVariant *dbus_get_charger_status(GDBusConnection *conn,
893         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
894         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
895 {
896         int ret;
897
898         if (vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, &ret) < 0) {
899                 _E("vconf_get_int() failed");
900                 ret = -EIO;
901         }
902         return g_variant_new("(i)", ret);
903 }
904
905 static GVariant *dbus_get_charge_now(GDBusConnection *conn,
906         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
907         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
908 {
909         int ret;
910
911         ret = battery.charge_now;
912
913         return g_variant_new("(i)", ret);
914 }
915
916 static GVariant *dbus_get_charge_level(GDBusConnection *conn,
917         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
918         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
919 {
920         int ret;
921
922         if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &ret) < 0) {
923                 _E("vconf_get_int() failed");
924                 ret = -EIO;
925         }
926
927         return g_variant_new("(i)", ret);
928 }
929
930 static GVariant *dbus_get_percent(GDBusConnection *conn,
931         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
932         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
933 {
934         int ret;
935
936         ret = battery.capacity;
937
938         return g_variant_new("(i)", ret);
939 }
940
941 static GVariant *dbus_get_percent_raw(GDBusConnection *conn,
942         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
943         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
944 {
945         int ret;
946
947         ret = -ENOTSUP;
948
949         return g_variant_new("(i)", ret);
950 }
951
952 static GVariant *dbus_is_full(GDBusConnection *conn,
953         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
954         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
955 {
956         int ret;
957
958         ret = battery.charge_full;
959
960         return g_variant_new("(i)", ret);
961 }
962
963 static GVariant *dbus_get_health(GDBusConnection *conn,
964         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
965         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
966 {
967         int ret;
968
969         ret = battery.health;
970
971         return g_variant_new("(i)", ret);
972 }
973
974 static GVariant *dbus_power_supply_handler(GDBusConnection *conn,
975         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
976         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
977 {
978         pid_t pid;
979         int ret = 0;
980         int argc = 0;
981         char *type_str;
982         char *argv[5];
983
984         g_variant_get(param, "(sisssss)", &type_str,
985                                         &argc,
986                                         &argv[0],
987                                         &argv[1],
988                                         &argv[2],
989                                         &argv[3],
990                                         &argv[4]);
991
992         if (argc < 0) {
993                 _E("message is invalid!");
994                 ret = -EINVAL;
995                 goto out;
996         }
997
998         pid = dbus_connection_get_sender_pid(conn, sender);
999         if (kill(pid, 0) == -1) {
1000                 _E("%d process does not exist, dbus ignored!", pid);
1001                 ret = -ESRCH;
1002                 goto out;
1003         }
1004         check_capacity_status(argv[0]);
1005         check_charge_status(argv[1]);
1006         check_health_status(argv[2]);
1007         check_online_status(argv[3]);
1008         check_present_status(argv[4]);
1009         _I("%d %d %d %d %d %d %d %d",
1010                 battery.capacity,
1011                 battery.charge_full,
1012                 battery.charge_now,
1013                 battery.health,
1014                 battery.online,
1015                 battery.ovp,
1016                 battery.present,
1017                 battery.temp);
1018
1019         if (battery.online > POWER_SUPPLY_TYPE_BATTERY)
1020                 power_supply_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_ON);
1021         else
1022                 power_supply_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_OFF);
1023
1024         process_power_supply(&battery.capacity);
1025 out:
1026         g_free(type_str);
1027         g_free(argv[0]);
1028         g_free(argv[1]);
1029         g_free(argv[2]);
1030         g_free(argv[3]);
1031         g_free(argv[4]);
1032
1033         return g_variant_new("(i)", ret);
1034 }
1035
1036 static void battery_get_info(struct battery_info *info, void *data)
1037 {
1038         struct battery_info *bat = data;
1039
1040         if (!info || !bat)
1041                 return;
1042
1043         bat->status = strdup(info->status);
1044         bat->health = strdup(info->health);
1045         bat->power_source = strdup(info->power_source);
1046         bat->online = info->online;
1047         bat->present = info->present;
1048         bat->capacity = info->capacity;
1049         bat->current_now = info->current_now;
1050         bat->current_average = info->current_average;
1051 }
1052
1053 static GVariant *dbus_get_battery_info(GDBusConnection *conn,
1054         const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1055         GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1056 {
1057         int ret, val;
1058         const char *str;
1059         struct battery_info info = { 0, };
1060
1061         if (battery_dev && battery_dev->get_current_state) {
1062                 ret = battery_dev->get_current_state(battery_get_info, &info);
1063                 if (ret < 0)
1064                         _E("Failed to get battery info (%d)", ret);
1065
1066                 battery_changed(&info, NULL);
1067                 free(info.status);
1068                 free(info.health);
1069                 free(info.power_source);
1070         } else {
1071                 if (battery.charge_status == CHARGE_STATUS_FULL)
1072                         str = CHARGEFULL_NAME;
1073                 else if (battery.charge_status == CHARGE_STATUS_CHARGING)
1074                         str = CHARGENOW_NAME;
1075                 else if (battery.charge_status == CHARGE_STATUS_DISCHARGING)
1076                         str = DISCHARGE_NAME;
1077                 else if (battery.charge_status == CHARGE_STATUS_NOT_CHARGING)
1078                         str = NOTCHARGE_NAME;
1079                 else
1080                         str = "Unknown";
1081                 snprintf(battery.status_s, sizeof(battery.status_s), "%s", str);
1082
1083                 if (battery.health == HEALTH_GOOD) {
1084                         if (battery.temp == TEMP_LOW && battery.ovp == OVP_ABNORMAL)
1085                                 str = OVERVOLT_NAME;
1086                         else
1087                                 str = "Good";
1088                 } else { /* HEALTH_BAD */
1089                         if (battery.temp == TEMP_HIGH)
1090                                 str = OVERHEAT_NAME;
1091                         else /* TEMP_LOW */
1092                                 str = TEMPCOLD_NAME;
1093                 }
1094                 snprintf(battery.health_s, sizeof(battery.health_s), "%s", str);
1095
1096                 if (vconf_get_int(VCONFKEY_SYSMAN_USB_STATUS, &val) == 0 &&
1097                         val != VCONFKEY_SYSMAN_USB_DISCONNECTED)
1098                         str = POWER_SOURCE_USB;
1099                 else if (vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, &val) == 0 &&
1100                         val == VCONFKEY_SYSMAN_CHARGER_CONNECTED)
1101                         str = POWER_SOURCE_AC;
1102                 else
1103                         str = POWER_SOURCE_NONE;
1104                 snprintf(battery.power_source_s, sizeof(battery.power_source_s), "%s", str);
1105
1106                 battery.current_now = -1; /* Not supported */
1107                 battery.current_average = -1; /* Not supported */
1108                 ret = 0;
1109         }
1110
1111         return g_variant_new("(isssiiiii)", ret,
1112                                         battery.status_s,
1113                                         battery.health_s,
1114                                         battery.power_source_s,
1115                                         battery.online,
1116                                         battery.present,
1117                                         battery.capacity,
1118                                         battery.current_now,
1119                                         battery.current_average);
1120 }
1121
1122 static const dbus_method_s dbus_methods[] = {
1123         { CHARGER_STATUS_SIGNAL,      NULL, "i", dbus_get_charger_status },
1124         { CHARGE_NOW_SIGNAL,          NULL, "i", dbus_get_charge_now },
1125         { CHARGE_LEVEL_SIGNAL,        NULL, "i", dbus_get_charge_level },
1126         { CHARGE_CAPACITY_SIGNAL,     NULL, "i", dbus_get_percent },
1127         { CHARGE_CAPACITY_LAW_SIGNAL, NULL, "i", dbus_get_percent_raw },
1128         { CHARGE_FULL_SIGNAL,         NULL, "i", dbus_is_full },
1129         { CHARGE_HEALTH_SIGNAL,       NULL, "i", dbus_get_health },
1130         { POWER_SUBSYSTEM,       "sisssss", "i", dbus_power_supply_handler },
1131         { "GetBatteryInfo",           NULL, "isssiiiii", dbus_get_battery_info },
1132         /* Add methods here */
1133 };
1134
1135 static const dbus_interface_u dbus_interface = {
1136         .oh = NULL,
1137         .name = DEVICED_INTERFACE_BATTERY,
1138         .methods = dbus_methods,
1139         .nr_methods = ARRAY_SIZE(dbus_methods),
1140 };
1141
1142 static int booting_done(void *data)
1143 {
1144         static int done;
1145
1146         if (data == NULL)
1147                 return done;
1148         done = *(int *)data;
1149         if (done == 0)
1150                 return done;
1151
1152         _I("booting done");
1153
1154         power_supply_timer_stop();
1155
1156         /* for simple noti change cb */
1157         power_supply_status_init();
1158         process_power_supply(NULL);
1159
1160         return done;
1161 }
1162
1163 static int display_changed(void *data)
1164 {
1165         if (battery.charge_now != CHARGER_ABNORMAL)
1166                 return 0;
1167         if (battery.health != HEALTH_BAD && battery.present != PRESENT_ABNORMAL)
1168                 return 0;
1169         pm_lock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, STAY_CUR_STATE, 0);
1170         return 0;
1171 }
1172
1173 static int load_uevent(struct parse_result *result, void *user_data)
1174 {
1175         struct battery_status *info = user_data;
1176
1177         if (!info)
1178                 return -EINVAL;
1179
1180         if (MATCH(result->name, CHARGE_STATUS)) {
1181                 if (strstr(result->value, "Charging")) {
1182                         info->charge_now = CHARGER_CHARGING;
1183                         info->charge_full = CHARGING_NOT_FULL;
1184                 } else if (strstr(result->value, "Discharging")) {
1185                         info->charge_now = CHARGER_DISCHARGING;
1186                         info->charge_full = CHARGING_NOT_FULL;
1187                 } else if (strstr(result->value, "Full")) {
1188                         info->charge_now = CHARGER_DISCHARGING;
1189                         info->charge_full = CHARGING_FULL;
1190                 } else if (strstr(result->value, "Not charging")) {
1191                         info->charge_now = CHARGER_ABNORMAL;
1192                         info->charge_full = CHARGING_NOT_FULL;
1193                 }
1194                 snprintf(info->status_s, sizeof(info->status_s), "%s", result->value);
1195         } else if (MATCH(result->name, CAPACITY))
1196                 info->capacity = atoi(result->value);
1197         else if (MATCH(result->name, CHARGE_HEALTH))
1198                 snprintf(info->health_s, sizeof(info->health_s), "%s", result->value);
1199         return 0;
1200 }
1201
1202 static int power_supply_probe(void *data)
1203 {
1204         struct hw_info *info;
1205         int ret;
1206
1207         if (battery_dev)
1208                 return 0;
1209
1210         ret = hw_get_info(BATTERY_HARDWARE_DEVICE_ID,
1211                         (const struct hw_info **)&info);
1212
1213         if (ret < 0) { /* There is no HAL for battery */
1214                 if (access(POWER_PATH, R_OK) == 0)
1215                         return 0; /* Just power_supply uevent is used */
1216                 goto out;
1217         }
1218
1219         if (!info->open) {
1220                 _E("Failed to open battery device; open(NULL)");
1221                 return -ENODEV;
1222         }
1223
1224         ret = info->open(info, NULL, (struct hw_common**)&battery_dev);
1225         if (ret < 0) {
1226                 _E("Failed to get battery device structure (%d)", ret);
1227                 return ret;
1228         }
1229
1230         if (!battery_dev || !battery_dev->get_current_state) {
1231                 _E("get_current_state() is not supported by the Battery HAL");
1232                 return -ENODEV;
1233         }
1234
1235         _I("battery device structure load success");
1236         return 0;
1237
1238 out:
1239         /**
1240          * Set battery vconf as -ENOTSUP
1241          * These vconf key used by runtime-info and capi-system-device.
1242          */
1243         vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, -ENOTSUP);
1244         vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, -ENOTSUP);
1245         vconf_set_int(VCONFKEY_SYSMAN_BATTERY_LEVEL_STATUS, -ENOTSUP);
1246         _I("There is no battery device(%d)", ret);
1247         return -ENODEV;
1248 }
1249
1250 static void add_power_supply_handler(void)
1251 {
1252         int ret;
1253
1254         if (battery_dev) {
1255                 if (battery_dev->register_changed_event)
1256                         battery_dev->register_changed_event(battery_changed, NULL);
1257                 if (battery_dev->get_current_state)
1258                         battery_dev->get_current_state(battery_changed, NULL);
1259         } else {
1260                 ret = config_parse(POWER_SUPPLY_UEVENT, load_uevent, &battery);
1261                 if (ret < 0)
1262                         _E("Failed to load %s, %d Use default value!", POWER_SUPPLY_UEVENT, ret);
1263
1264                 /* register power subsystem */
1265                 register_kernel_uevent_control(&uh);
1266         }
1267 }
1268
1269 static void remove_power_supply_handler(void)
1270 {
1271         if (battery_dev)
1272                 battery_dev->unregister_changed_event(battery_changed);
1273         else
1274                 unregister_kernel_uevent_control(&uh);
1275 }
1276
1277 static int event_handler_state_changed(void *data)
1278 {
1279         static device_notifier_state_e old = DEVICE_NOTIFIER_STATE_STOP;
1280         device_notifier_state_e state = *(device_notifier_state_e *)data;
1281
1282         if (old == state)
1283                 return 0;
1284
1285         old = state;
1286
1287         if (state == DEVICE_NOTIFIER_STATE_START)
1288                 add_power_supply_handler();
1289         else if (state == DEVICE_NOTIFIER_STATE_STOP)
1290                 remove_power_supply_handler();
1291
1292         return 0;
1293 }
1294
1295 static void power_supply_init(void *data)
1296 {
1297         int ret;
1298         device_notifier_state_e state = DEVICE_NOTIFIER_STATE_START;
1299
1300         battery.capacity = -1;
1301
1302         event_handler_state_changed((void *)&state);
1303
1304         /* process check battery timer until booting done */
1305         power_supply_timer_start();
1306
1307         register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
1308         register_notifier(DEVICE_NOTIFIER_LCD, display_changed);
1309         register_notifier(DEVICE_NOTIFIER_EVENT_HANDLER, event_handler_state_changed);
1310
1311         ret = dbus_handle_add_dbus_object(NULL, DEVICED_PATH_BATTERY, &dbus_interface);
1312         if (ret < 0)
1313                 _E("fail to init dbus method(%d)", ret);
1314
1315
1316 #ifdef TIZEN_FEATURE_BATTERY_OVER_TEMPERATURE
1317         ret = subscribe_dbus_signal(NULL, DEVICED_PATH_SYSNOTI,
1318                 DEVICED_INTERFACE_SYSNOTI, SIGNAL_CHARGEERR_RESPONSE, abnormal_popup_dbus_signal_handler, NULL, NULL);
1319         if (ret <= 0)
1320                 _E("fail to init dbus signal(%d)", ret);
1321 #endif /* TIZEN_FEATURE_BATTERY_OVER_TEMPERATURE */
1322 }
1323
1324 static void power_supply_exit(void *data)
1325 {
1326         device_notifier_state_e state = DEVICE_NOTIFIER_STATE_STOP;
1327
1328         unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
1329         unregister_notifier(DEVICE_NOTIFIER_LCD, display_changed);
1330         unregister_notifier(DEVICE_NOTIFIER_EVENT_HANDLER, event_handler_state_changed);
1331
1332         event_handler_state_changed((void *)&state);
1333 }
1334
1335 static const struct device_ops power_supply_ops = {
1336         .name     = "power_supply",
1337         .probe    = power_supply_probe,
1338         .init     = power_supply_init,
1339         .exit     = power_supply_exit,
1340 };
1341
1342 DEVICE_OPS_REGISTER(&power_supply_ops)