battery: redefine battery level threshold
[platform/core/system/deviced.git] / src / battery / power-supply.c
index f6c217b..197fabe 100644 (file)
 #include <stdio.h>
 #include <stdbool.h>
 #include <vconf.h>
-#include <device-node.h>
 #include <bundle.h>
 #include <eventsystem.h>
-#include <hw/battery.h>
+#include <hal/device/hal-battery.h>
+#include <sys/stat.h>
+#include <libsyscommon/ini-parser.h>
 
-#include "core/devices.h"
-#include "core/device-notifier.h"
+#include "shared/devices.h"
+#include "shared/device-notifier.h"
 #include "core/udev.h"
 #include "core/log.h"
-#include "core/config-parser.h"
 #include "display/poll.h"
 #include "display/setting.h"
-#include "apps/apps.h"
+#include "shared/eventsystem.h"
+#include "shared/plugin.h"
+#include "shared/apps.h"
+#include "display/core.h"
+#include "display/display-ops.h"
 #include "power-supply.h"
 #include "battery.h"
-#include "extcon/extcon_count.h"
+#include "battery-ops.h"
+#include "extcon/extcon.h"
+#include "lowbat-handler.h"
+
+#ifndef VCONFKEY_SETAPPL_BLOCKMODE_WEARABLE_BOOL
+#define VCONFKEY_SETAPPL_BLOCKMODE_WEARABLE_BOOL "db/setting/blockmode_wearable"
+#endif
+
+#ifndef VCONFKEY_SETAPPL_THEATER_MODE_ENABLE
+#define VCONFKEY_SETAPPL_THEATER_MODE_ENABLE "db/setting/theater_mode_enable"
+#endif
+
+#ifndef VCONFKEY_SETAPPL_GOODNIGHT_MODE_ENABLE
+#define VCONFKEY_SETAPPL_GOODNIGHT_MODE_ENABLE "db/setting/goodnight_mode_enable"
+#endif
 
 #define BATTERY_NAME        "battery"
 #define CHARGEFULL_NAME     "Full"
 #define OVERHEAT_NAME       "Overheat"
 #define TEMPCOLD_NAME       "Cold"
 #define OVERVOLT_NAME       "Over voltage"
+#define GOOD_NAME           "Good"
 
-#define REMOVE_POPUP "remove_battery_popups"
+#define CHARGER_WIRELESS_TYPE_BT    10
+#define CHARGER_WIRELESS_TYPE_3G    22
+#define CHARGER_INCOMPATIBLE_TYPE   11
+#define CHARGER_D2D_TYPE            110
+#define WIRELESS_CHARGER_CONNECTED  2
 
-#define BUFF_MAX            255
-
-#define SIGNAL_CHARGEERR_RESPONSE "ChargeErrResponse"
 #define SIGNAL_TEMP_GOOD          "TempGood"
 
-#define ABNORMAL_CHECK_TIMER_INTERVAL 60
-
 #define METHOD_FULL_NOTI_ON   "BatteryFullNotiOn"
 #define METHOD_FULL_NOTI_OFF  "BatteryFullNotiOff"
 #define METHOD_CHARGE_NOTI_ON "BatteryChargeNotiOn"
 
-#define RETRY_MAX 5
-#define BATTERY_CHECK_TIMER_INTERVAL (0.5)
+#define CHARGER_CHARGE_ON_NODE "/sys/class/power_supply/battery/chg_on"
 
-enum power_supply_init_type {
-       POWER_SUPPLY_NOT_READY   = 0,
-       POWER_SUPPLY_INITIALIZED = 1,
-};
+#define RETRY_MAX 5
+#define BATTERY_CHECK_TIMER_INTERVAL 500  /* 0.5 second */
+#define LCD_DIM_TIME_IN_BATTERY_HEALTH 10000   /* ms */
 
-static void uevent_power_handler(struct udev_device *dev);
-static const struct uevent_handler uh = {
-       .subsystem   = POWER_SUBSYSTEM,
-       .uevent_func = uevent_power_handler,
-};
+static struct display_plugin *disp_plgn;
+static struct battery_plugin *battery_plgn;
 
-struct battery_status battery;
+static struct battery_status battery;
 struct battery_status old_battery;
 static int noti_id;
+static int abnormal_health_popup_timer;
+static bool launching_health_popup;
+
 static guint power_timer;
+static device_notifier_state_e old_state = -1;
 
-static int booting_done(void *data);
+bool battery_initialized;
 
-static struct battery_device *battery_dev;
+bool battery_do_not_disturb(void);
+int battery_pm_change_internal(int pid, int s_bits);
+static int delayed_init_done(void *data);
+static void update_health(enum battery_noti_status status);
+static int load_uevent(struct parse_result *result, void *user_data);
+static int event_handler_state_changed(void *data);
+static void power_supply_exit(void *data);
 
-static void lowbat_execute(void *data)
+inline struct battery_status *get_var_battery_status(void)
 {
-       static const struct device_ops *lowbat_ops;
-
-       FIND_DEVICE_VOID(lowbat_ops, "lowbat");
-       device_execute(lowbat_ops, data);
+       return &battery;
 }
 
-static void pm_check_and_change(int bInserted)
+static int lowbat_execute(void *data)
 {
-       static int old = -1;
+       static const struct device_ops *lowbat_ops;
 
-       if (old == bInserted)
-               return;
-       old = bInserted;
-       pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
+       FIND_DEVICE_INT(lowbat_ops, "lowbat");
+       return device_execute(lowbat_ops, data);
 }
 
-static int changed_battery_cf(enum present_type status)
+static int power_supply_broadcast_str(char *sig, char *status)
 {
-       char *value;
+       static char old_sig[32];
+       static char old_status[32];
+       char *str;
+       int ret;
 
-       if (status == PRESENT_ABNORMAL)
-               value = "battdisconnect";
-       else
-               value = "remove_battery_popups";
+       if (!sig || !status) {
+               _E("there is no signal name");
+               return -EINVAL;
+       }
 
-       return launch_system_app(APP_DEFAULT,
-                       2, APP_KEY_TYPE, value);
-}
+       if (strncmp(old_sig, sig, strlen(sig)) == 0 && strncmp(old_status, status, strlen(status)) == 0)
+               return 0;
 
-static void health_status_broadcast(void)
-{
-       dbus_handle_broadcast_dbus_signal(DEVICED_PATH_BATTERY, DEVICED_INTERFACE_BATTERY,
-           SIGNAL_TEMP_GOOD, NULL, NULL);
-}
+       snprintf(old_sig, sizeof(old_sig), "%s", sig);
+       snprintf(old_status, sizeof(old_status), "%s", status);
 
-#ifdef TIZEN_FEATURE_BATTERY_OVER_TEMPERATURE
-static guint abnormal_timer;
+       str = status;
 
-static void abnormal_popup_timer_init(void)
-{
-       if (abnormal_timer == NULL)
-               return;
-       g_source_remove(abnormal_timer);
-       abnormal_timer = NULL;
-       _I("delete health timer");
-}
+       ret = gdbus_signal_emit(NULL,
+                                               DEVICED_PATH_BATTERY,
+                                               DEVICED_INTERFACE_BATTERY,
+                                               sig,
+                                               g_variant_new("(s)", str));
 
-static void health_timer_reset(void)
-{
-       abnormal_timer = NULL;
+       if (ret == 0)
+               return 1;
+       else
+               return ret;
 }
 
-static gboolean health_timer_cb(void *data)
+static void pm_check_and_change(int bInserted)
 {
-       int value = HEALTH_BAD;
-
-       health_timer_reset();
-
-       if (battery.health == HEALTH_GOOD)
-               return G_SOURCE_REMOVE;
+       static int old = -1;
 
-       _I("popup - Battery health status is not good");
-       device_notify(DEVICE_NOTIFIER_BATTERY_HEALTH, (void *)&value);
-       pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
-       pm_lock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, STAY_CUR_STATE, 0);
-       if (battery.temp == TEMP_LOW)
-               battery_charge_err_low_act(NULL);
-       else if (battery.temp == TEMP_HIGH)
-               battery_charge_err_high_act(NULL);
-       return G_SOURCE_REMOVE;
+       if (old == bInserted)
+               return;
+       old = bInserted;
+       battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
 }
 
-static void abnormal_popup_dbus_signal_handler(GDBusConnection  *conn,
-               const gchar      *sender,
-               const gchar      *path,
-               const gchar      *iface,
-               const gchar      *name,
-               GVariant         *param,
-               gpointer          user_data)
-
+static void health_status_broadcast(void)
 {
-       if (battery.health == HEALTH_GOOD)
-               return;
-       _I("restart health timer");
-       abnormal_timer = g_timeout_add_seconds(ABNORMAL_CHECK_TIMER_INTERVAL,
-                                               health_timer_cb, NULL);
-       if (abnormal_timer == NULL)
-               _E("Fail to add abnormal check timer");
+       gdbus_signal_emit(NULL,
+               DEVICED_PATH_BATTERY,
+               DEVICED_INTERFACE_BATTERY,
+               SIGNAL_TEMP_GOOD,
+               NULL);
 }
-#endif /* TIZEN_FEATURE_BATTERY_OVER_TEMPERATURE */
 
 static void full_noti_cb(GVariant *var, void *user_data, GError *err)
 {
@@ -182,98 +176,117 @@ static void full_noti_cb(GVariant *var, void *user_data, GError *err)
        if (!var)
                return;
 
-       if (!dh_get_param_from_var(var, "(i)", &id)) {
-               _E("no message [%s]", g_variant_get_type_string(var));
+       if (!g_variant_get_safe(var, "(i)", &id)) {
+               _E("Failed to notify full: no message(%s)", g_variant_get_type_string(var));
                goto out;
        }
 
        noti_id = id;
-       _D("Inserted battery full noti : %d", noti_id);
+       _D("Inserted battery full noti(%d).", noti_id);
 
 out:
        g_variant_unref(var);
 }
 
-static int check_power_supply_noti(void)
+static void noti_off_cb(GVariant *var, void *user_data, GError *err)
 {
-#ifdef MICRO_DD
-       int r_disturb, s_disturb, r_block, s_block;
-       r_disturb = vconf_get_int("memory/shealth/sleep/do_not_disturb", &s_disturb);
-       r_block = vconf_get_bool("db/setting/blockmode_wearable", &s_block);
-       if ((r_disturb != 0 && r_block != 0) ||
-           (s_disturb == 0 && s_block == 0)) {
-           return 1;
+       int val = 0;
+
+       if (!g_variant_get_safe(var, "(i)", &val)) {
+               _E("Failed to off notification: no message(%s)", g_variant_get_type_string(var));
+               goto out;
        }
-       return 0;
-#else
-       return 1;
-#endif
+
+       _D("Noti off: %d", val);
+
+out:
+       g_variant_unref(var);
 }
 
 static int send_full_noti(enum charge_full_type state)
 {
        int ret = 0;
-       int noti;
+       int noti = 0;
        int retry;
 
-       noti = check_power_supply_noti();
+       if (battery_plgn->check_power_supply_noti)
+               noti = battery_plgn->check_power_supply_noti();
 
        if (!noti)
-               return noti;
+               return ret;
 
        switch (state) {
        case CHARGING_FULL:
                for (retry = RETRY_MAX; retry > 0; retry--) {
-                       ret = dbus_method_async_with_reply(POPUP_BUS_NAME,
+                       ret = gdbus_call_async_with_reply(POPUP_BUS_NAME,
                                        POPUP_PATH_NOTI,
                                        POPUP_INTERFACE_NOTI,
                                        METHOD_FULL_NOTI_ON,
-                                       NULL, NULL, full_noti_cb, -1, NULL);
+                                       NULL, full_noti_cb, -1, NULL);
                        if (ret == 0) {
-                               _D("Created battery full noti");
+                               _D("Created battery full noti.");
                                return ret;
                        }
                }
-               _E("Failed to call dbus method (err: %d)", ret);
-       break;
+               _E("Failed to call dbus method: %d", ret);
+               break;
        case CHARGING_NOT_FULL:
                if (noti_id <= 0)
                        return -EPERM;
                for (retry = RETRY_MAX; retry > 0; retry--) {
-                       ret = dbus_method_async_var(POPUP_BUS_NAME,
+                       ret = gdbus_call_async_with_reply(POPUP_BUS_NAME,
                                        POPUP_PATH_NOTI,
                                        POPUP_INTERFACE_NOTI,
                                        METHOD_FULL_NOTI_OFF,
-                                       g_variant_new("(i)", noti_id));
+                                       g_variant_new("(i)", noti_id),
+                                       noti_off_cb, -1, NULL);
                        if (ret == 0) {
-                               _D("Deleted battery full noti");
+                               _D("Deleted battery full noti.");
                                noti_id = 0;
                                return ret;
                        }
                }
-               _E("Failed to call dbus method (err: %d)", ret);
-       break;
+               _E("Failed to call dbus method: %d", ret);
+               break;
        }
        return ret;
 }
 
+static void charge_noti_on(GVariant *var, void *user_data, GError *err)
+{
+       int id = 0;
+
+       if (!var)
+               return;
+
+       if (!g_variant_get_safe(var, "(i)", &id)) {
+               _E("Failed to notify charge: no message(%s)", g_variant_get_type_string(var));
+               goto out;
+       }
+
+       _D("Inserted battery charge noti: %d", id);
+
+out:
+       g_variant_unref(var);
+}
+
 static int send_charge_noti(void)
 {
        int ret = 0;
        int retry;
 
        for (retry = RETRY_MAX; retry > 0; retry--) {
-               ret = dbus_method_async(POPUP_BUS_NAME,
+               ret = gdbus_call_async_with_reply(POPUP_BUS_NAME,
                                POPUP_PATH_NOTI,
                                POPUP_INTERFACE_NOTI,
                                METHOD_CHARGE_NOTI_ON,
-                               NULL, NULL);
+                               NULL, charge_noti_on, -1, NULL);
                if (ret == 0) {
-                       _D("Created battery charge noti");
+                       _I("Created battery charge noti.");
                        return ret;
                }
        }
-       _E("Failed to call dbus method (err: %d)", ret);
+       _E("Failed to call dbus method: %d", ret);
        return ret;
 }
 
@@ -281,54 +294,60 @@ static void power_supply_noti(enum battery_noti_type type, enum battery_noti_sta
 {
        static int charger = CHARGER_DISCHARGING;
        static int full = CHARGING_NOT_FULL;
-       int ret;
+       int ret_val;
 
        if (type == DEVICE_NOTI_BATT_CHARGE) {
                if (status == DEVICE_NOTI_ON && charger == CHARGER_DISCHARGING) {
                        send_charge_noti();
                        charger = CHARGER_CHARGING;
-               } else if (status == DEVICE_NOTI_OFF && charger == CHARGER_CHARGING) {
+               } else if (status == DEVICE_NOTI_OFF && charger == CHARGER_CHARGING)
                        charger = CHARGER_DISCHARGING;
-               }
        } else if (type == DEVICE_NOTI_BATT_FULL) {
                if (status == DEVICE_NOTI_ON && full == CHARGING_NOT_FULL) {
-                       ret = send_full_noti(CHARGING_FULL);
-                       if (ret == 0)
+                       ret_val = send_full_noti(CHARGING_FULL);
+                       if (ret_val == 0)
                                full = CHARGING_FULL;
                } else if (status == DEVICE_NOTI_OFF && full == CHARGING_FULL) {
-                       ret = send_full_noti(CHARGING_NOT_FULL);
-                       if (ret == 0)
+                       ret_val = send_full_noti(CHARGING_NOT_FULL);
+                       if (ret_val == 0)
                                full = CHARGING_NOT_FULL;
                }
        }
 }
 
-void power_supply_broadcast(char *sig, int status)
+int power_supply_broadcast(char *sig, int status)
 {
        static int old;
        static char sig_old[32];
+       int ret;
 
-       if (strcmp(sig_old, sig) == 0 && old == status)
-               return;
-
-       _D("%s %d", sig, status);
+       if (!sig) {
+               _E("There is no signal name.");
+               return -EINVAL;
+       }
+       if (strncmp(sig_old, sig, strlen(sig)) == 0 && old == status) {
+               _D("Skip broadcasting same signal(%s) and status(%d).", sig, status);
+               return 0;
+       }
 
        old = status;
+
        snprintf(sig_old, sizeof(sig_old), "%s", sig);
-       /*snprintf(str_status, sizeof(str_status), "%d", status);
-       arr[0] = str_status;*/
 
-       dbus_handle_broadcast_dbus_signal_var(DEVICED_PATH_BATTERY,
+       ret = gdbus_signal_emit(NULL,
+                                               DEVICED_PATH_BATTERY,
                                                DEVICED_INTERFACE_BATTERY,
                                                sig,
                                                g_variant_new("(i)", status));
-
+       if (ret == 0)
+               return 1;
+       else
+               return ret;
 }
 
 static void noti_batt_full(void)
 {
        static int bat_full_noti;
-       int noti;
 
        if (!battery.charge_full && bat_full_noti == 1) {
                power_supply_noti(DEVICE_NOTI_BATT_FULL, DEVICE_NOTI_OFF);
@@ -339,13 +358,12 @@ static void noti_batt_full(void)
        if (battery.charge_full && bat_full_noti == 0) {
                power_supply_noti(DEVICE_NOTI_BATT_FULL, DEVICE_NOTI_ON);
                bat_full_noti = 1;
-               /* turn on LCD, if battery is full charged */
-               noti = check_power_supply_noti();
-               if (noti)
-                       pm_change_internal(INTERNAL_LOCK_BATTERY_FULL,
-                               LCD_NORMAL);
-               else
-                       _I("block LCD");
+               /* turn on LCD, if battery is fully charged */
+               if (battery_plgn->check_power_supply_noti && battery_plgn->check_power_supply_noti()) {
+                       battery_pm_change_internal(INTERNAL_LOCK_BATTERY_FULL, LCD_NORMAL);
+               } else
+                       _I("Block LCD.");
+
                /* on the full charge state */
                device_notify(DEVICE_NOTIFIER_FULLBAT, (void *)&bat_full_noti);
        }
@@ -354,225 +372,190 @@ static void noti_batt_full(void)
 static void check_power_supply(int state)
 {
        pm_check_and_change(state);
-       if (update_pm_setting)
-               update_pm_setting(SETTING_CHARGING, state);
+       if (disp_plgn->update_pm_setting)
+               disp_plgn->update_pm_setting(SETTING_CHARGING, state);
 }
 
 static void charger_state_send_system_event(int state)
 {
-       bundle *b;
        const char *str;
 
        switch (state) {
-       case CHARGE_STATUS_CHARGING:
+       case CHARGING_STATUS_CHARGING:
                str = EVT_VAL_BATTERY_CHARGER_CHARGING;
                break;
-       case CHARGE_STATUS_FULL:
-       case CHARGE_STATUS_DISCHARGING:
+       case CHARGING_STATUS_FULL:
                str = EVT_VAL_BATTERY_CHARGER_DISCHARGING;
+               CRITICAL_LOG("Battery charger: %s", str);
                break;
-       case CHARGE_STATUS_CONNECTED:
-               str = EVT_VAL_BATTERY_CHARGER_CONNECTED;
-               break;
-       case CHARGE_STATUS_DISCONNECTED:
-               str = EVT_VAL_BATTERY_CHARGER_DISCONNECTED;
+       case CHARGING_STATUS_DISCHARGING:
+               str = EVT_VAL_BATTERY_CHARGER_DISCHARGING;
+               CRITICAL_LOG("Battery charger: %s", str);
                break;
        default:
-               _E("invalid parameter(%d)", state);
+               _E("Invalid parameter: %d", state);
                return;
        }
 
-       _D("system_event(%s)", str);
-
-       b = bundle_create();
-       bundle_add_str(b, EVT_KEY_BATTERY_CHARGER_STATUS, str);
-       eventsystem_send_system_event(SYS_EVENT_BATTERY_CHARGER_STATUS, b);
-       bundle_free(b);
+       event_system_send(SYS_EVENT_BATTERY_CHARGER_STATUS, EVT_KEY_BATTERY_CHARGER_STATUS, str);
 }
 
 static void update_present(enum battery_noti_status status)
 {
-       static int old = DEVICE_NOTI_OFF;
-       enum present_type present;
 
-       if (old == status)
-               return;
-       _I("charge %d present %d", battery.charge_now, battery.present);
-       old = status;
-       pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
+       CRITICAL_LOG("Charge(%d) present(%d, old: %d)", battery.charge_now, battery.present, old_battery.present);
+
+       old_battery.present = battery.present;
        if (status == DEVICE_NOTI_ON) {
-               present = PRESENT_ABNORMAL;
-               device_notify(DEVICE_NOTIFIER_BATTERY_PRESENT, (void *)&present);
-               pm_lock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, STAY_CUR_STATE, 0);
+               battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_DIM);
+               device_notify(DEVICE_NOTIFIER_BATTERY_PRESENT, (void *)&battery.present);
+               if (disp_plgn->pm_lock_internal)
+                       disp_plgn->pm_lock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, STAY_CUR_STATE, 0);
        } else {
-               present = PRESENT_NORMAL;
-               device_notify(DEVICE_NOTIFIER_BATTERY_PRESENT, (void *)&present);
-               pm_unlock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, PM_SLEEP_MARGIN);
+               battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
+               device_notify(DEVICE_NOTIFIER_BATTERY_PRESENT, (void *)&battery.present);
+               if (disp_plgn->pm_unlock_internal)
+                       disp_plgn->pm_unlock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, PM_SLEEP_MARGIN);
        }
-       changed_battery_cf(present);
+       if (battery_plgn->changed_battery_cf)
+               battery_plgn->changed_battery_cf(battery.present);
 }
 
-#ifdef TIZEN_FEATURE_BATTERY_OVER_TEMPERATURE
-static void update_health(enum battery_noti_status status)
+static void launch_health_popup(void)
 {
-       static int old = DEVICE_NOTI_OFF;
-
-       if (old == status)
+       if (launching_health_popup)
                return;
-       _I("charge %d health %d", battery.charge_now, battery.health);
-       old = status;
 
-       pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
-       if (status == DEVICE_NOTI_ON) {
-               _I("popup - Battery health status is not good");
-               pm_lock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, STAY_CUR_STATE, 0);
-               if (battery.temp == TEMP_LOW)
-                       battery_charge_err_low_act(NULL);
-               else if (battery.temp == TEMP_HIGH)
-                       battery_charge_err_high_act(NULL);
-       } else {
-               pm_unlock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, PM_SLEEP_MARGIN);
-               abnormal_popup_timer_init();
-               launch_system_app(APP_DEFAULT, 2, APP_KEY_TYPE, REMOVE_POPUP);
-       }
+       launching_health_popup = true;
+
+       device_notify(DEVICE_NOTIFIER_BATTERY_HEALTH, (void *)&battery.health);
+       battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
+       battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_DIM);
+       if (disp_plgn->pm_unlock_internal)
+               disp_plgn->pm_unlock_internal(INTERNAL_LOCK_POPUP, LCD_OFF, PM_SLEEP_MARGIN);
+       if (disp_plgn->pm_lock_internal)
+               disp_plgn->pm_lock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, STAY_CUR_STATE, LCD_DIM_TIME_IN_BATTERY_HEALTH);
+       if (battery.health == HEALTH_LOW)
+               battery_charge_err_low_act(NULL);
+       else if (battery.health == HEALTH_HIGH)
+               battery_charge_err_high_act(NULL);
+
+       launching_health_popup = false;
 }
-#endif /* TIZEN_FEATURE_BATTERY_OVER_TEMPERATURE */
 
-static void update_ovp(enum battery_noti_status status)
+/* Warning popup for every 1 minutes until
+ * battery health returns to normal. */
+static gboolean health_popup_cb(void *data)
 {
-       static int old = DEVICE_NOTI_OFF;
-       int value;
-
-       if (old == status)
-               return;
-       _I("charge %d ovp %d", battery.charge_now, battery.ovp);
-       old = status;
-       pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
-       if (status == DEVICE_NOTI_ON)
-               value = OVP_ABNORMAL;
-       else
-               value = OVP_NORMAL;
-       device_notify(DEVICE_NOTIFIER_BATTERY_OVP, (void *)&value);
+       launch_health_popup();
+       battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
+       return G_SOURCE_CONTINUE;
 }
 
-static void check_battery_status(void)
+static void update_health(enum battery_noti_status status)
 {
-       static int old = DEVICE_CHANGE_NORMAL;
-       int status;
-
-       if (battery.charge_now == CHARGER_ABNORMAL &&
-           (battery.health == HEALTH_BAD || battery.present == PRESENT_ABNORMAL))
-               status = DEVICE_CHANGE_ABNORMAL;
-       else if (battery.ovp == OVP_ABNORMAL)
-               status = DEVICE_CHANGE_ABNORMAL;
-       else
-               status = DEVICE_CHANGE_NORMAL;
-       if (old == status)
-               return;
-       old = status;
+       _I("Charge(%d) health(%d, old: %d)", battery.charge_now, battery.health, old_battery.health);
 
-       if (battery.charge_now == CHARGER_ABNORMAL) {
-               if (battery.health == HEALTH_BAD) {
-                       device_notify(DEVICE_NOTIFIER_BATTERY_HEALTH, (void *)&battery.health);
-#ifdef TIZEN_FEATURE_BATTERY_OVER_TEMPERATURE
-                       update_health(DEVICE_NOTI_ON);
-#endif /* TIZEN_FEATURE_BATTERY_OVER_TEMPERATURE */
-                       return;
-               } else if (battery.present == PRESENT_ABNORMAL) {
-                       update_present(DEVICE_NOTI_ON);
-                       return;
+       old_battery.health = battery.health;
+       if (status == DEVICE_NOTI_ON) {
+               CRITICAL_LOG("Popup: Battery health status is not good, %s.", battery.health_s);
+               launch_health_popup();
+               if (!abnormal_health_popup_timer)
+                       abnormal_health_popup_timer = g_timeout_add_seconds(ABNORMAL_CHECK_TIMER_INTERVAL, health_popup_cb, NULL);
+       } else {
+               battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
+               device_notify(DEVICE_NOTIFIER_BATTERY_HEALTH, (void *)&battery.health);
+               if (disp_plgn->pm_unlock_internal) {
+                       disp_plgn->pm_unlock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, PM_SLEEP_MARGIN);
+                       disp_plgn->pm_unlock_internal(INTERNAL_LOCK_POPUP, LCD_OFF, PM_SLEEP_MARGIN);
+               }
+               health_status_broadcast();
+               if (abnormal_health_popup_timer) {
+                       CRITICAL_LOG("Battery health returned to normal. Stop abnormal popup.");
+                       g_source_remove(abnormal_health_popup_timer);
+                       abnormal_health_popup_timer = 0;
                }
+               if (battery_plgn->remove_health_popup)
+                       battery_plgn->remove_health_popup();
        }
-       if (battery.ovp == OVP_ABNORMAL) {
-               update_ovp(DEVICE_NOTI_ON);
+}
+
+void relaunch_health_popup(void)
+{
+       if (launching_health_popup)
                return;
-       }
 
-       if (battery.charge_now != CHARGER_ABNORMAL &&
-           status == DEVICE_CHANGE_NORMAL) {
-               device_notify(DEVICE_NOTIFIER_BATTERY_HEALTH, (void *)&battery.health);
-               health_status_broadcast();
-#ifdef TIZEN_FEATURE_BATTERY_OVER_TEMPERATURE
-               update_health(DEVICE_NOTI_OFF);
-#endif /* TIZEN_FEATURE_BATTERY_OVER_TEMPERATURE */
-               update_ovp(DEVICE_NOTI_OFF);
-               update_present(DEVICE_NOTI_OFF);
-       }
+       launching_health_popup = true;
+
+       if (abnormal_health_popup_timer)
+               g_source_remove(abnormal_health_popup_timer);
+
+       if (disp_plgn->pm_unlock_internal)
+               disp_plgn->pm_unlock_internal(INTERNAL_LOCK_POPUP, LCD_OFF, PM_SLEEP_MARGIN);
+       if (disp_plgn->pm_lock_internal)
+               disp_plgn->pm_lock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, STAY_CUR_STATE, LCD_DIM_TIME_IN_BATTERY_HEALTH);
+       if (battery.health == HEALTH_LOW)
+               battery_charge_err_low_act(NULL);
+       else if (battery.health == HEALTH_HIGH)
+               battery_charge_err_high_act(NULL);
+
+       abnormal_health_popup_timer = g_timeout_add_seconds(ABNORMAL_CHECK_TIMER_INTERVAL, health_popup_cb, NULL);
+
+       launching_health_popup = false;
 }
 
-static void check_online(void)
+static void check_abnormal_status(void)
 {
-       static int old_online;
-       static int old_charge_status;
-       int charge_status;
+       if (old_battery.health != HEALTH_LOW && old_battery.health != HEALTH_HIGH &&
+           (battery.health == HEALTH_LOW || battery.health == HEALTH_HIGH))
+               update_health(DEVICE_NOTI_ON);
+       else if ((old_battery.health == HEALTH_LOW || old_battery.health == HEALTH_HIGH) &&
+               battery.health != HEALTH_LOW && battery.health != HEALTH_HIGH)
+               update_health(DEVICE_NOTI_OFF);
 
-       if (battery.charge_status == CHARGE_STATUS_FULL)
-               charge_status = CHARGE_STATUS_DISCHARGING;
-       else
-               charge_status = battery.charge_status;
-
-       if (battery.online > POWER_SUPPLY_TYPE_BATTERY &&
-           old_online == VCONFKEY_SYSMAN_CHARGER_DISCONNECTED) {
-               old_online = VCONFKEY_SYSMAN_CHARGER_CONNECTED;
-               vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, old_online);
-               power_supply_broadcast(CHARGER_STATUS_SIGNAL, old_online);
-               extcon_get_count(EXTCON_TA);
-               extcon_set_count(EXTCON_TA, 1);
-               check_power_supply(old_online);
-               charger_state_send_system_event(CHARGE_STATUS_CONNECTED);
-               if (charge_status != old_charge_status)
-                       charger_state_send_system_event(charge_status);
-
-       } else if (battery.online <= POWER_SUPPLY_TYPE_BATTERY &&
-           old_online == VCONFKEY_SYSMAN_CHARGER_CONNECTED) {
-               old_online = VCONFKEY_SYSMAN_CHARGER_DISCONNECTED;
-               vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, old_online);
-               power_supply_broadcast(CHARGER_STATUS_SIGNAL, old_online);
-               check_power_supply(old_online);
-               if (charge_status != old_charge_status)
-                       charger_state_send_system_event(charge_status);
-               charger_state_send_system_event(CHARGE_STATUS_DISCONNECTED);
+       if (old_battery.present != PRESENT_ABNORMAL && battery.present == PRESENT_ABNORMAL)
+               update_present(DEVICE_NOTI_ON);
+       else if (battery.present != PRESENT_ABNORMAL && old_battery.present == PRESENT_ABNORMAL)
+               update_present(DEVICE_NOTI_OFF);
 
-       } else {
-               if (charge_status != old_charge_status)
-                       charger_state_send_system_event(charge_status);
+       if (old_battery.health != HEALTH_OVP && battery.health == HEALTH_OVP) {
+               if (battery_plgn->update_ovp)
+                       battery_plgn->update_ovp(DEVICE_NOTI_ON);
+       } else if (battery.health != HEALTH_OVP && old_battery.health == HEALTH_OVP) {
+               if (battery_plgn->update_ovp)
+                       battery_plgn->update_ovp(DEVICE_NOTI_OFF);
        }
-
-       old_charge_status = charge_status;
 }
 
-static void check_charge_status(const char *env_value)
+static void check_charging_status(const char *env_value)
 {
+       int len;
+
        if (env_value == NULL)
                return;
 
-       _D("Charge Status(%s)", env_value);
-
-       if (strncmp(env_value, CHARGEFULL_NAME,
-                               sizeof(CHARGEFULL_NAME)) == 0)
-               battery.charge_status = CHARGE_STATUS_FULL;
-       else if (strncmp(env_value, CHARGENOW_NAME,
-                               sizeof(CHARGENOW_NAME)) == 0)
-               battery.charge_status = CHARGE_STATUS_CHARGING;
-       else if (strncmp(env_value, DISCHARGE_NAME,
-                               sizeof(DISCHARGE_NAME)) == 0)
-               battery.charge_status = CHARGE_STATUS_DISCHARGING;
-       else if (strncmp(env_value, NOTCHARGE_NAME,
-                               sizeof(NOTCHARGE_NAME)) == 0)
-               battery.charge_status = CHARGE_STATUS_NOT_CHARGING;
+       len = strlen(env_value);
+       if (strncmp(env_value, CHARGEFULL_NAME, len) == 0)
+               battery.charging_status = CHARGING_STATUS_FULL;
+       else if (strncmp(env_value, CHARGENOW_NAME, len) == 0)
+               battery.charging_status = CHARGING_STATUS_CHARGING;
+       else if (strncmp(env_value, DISCHARGE_NAME, len) == 0)
+               battery.charging_status = CHARGING_STATUS_DISCHARGING;
+       else if (strncmp(env_value, NOTCHARGE_NAME, len) == 0)
+               battery.charging_status = CHARGING_STATUS_NOT_CHARGING;
        else
-               battery.charge_status = CHARGE_STATUS_UNKNOWN;
+               battery.charging_status = CHARGING_STATUS_UNKNOWN;
 
-       if (battery.charge_status == CHARGE_STATUS_FULL) {
+       if (battery.charging_status == CHARGING_STATUS_FULL) {
                battery.charge_full = CHARGING_FULL;
                battery.charge_now = CHARGER_DISCHARGING;
-       } else if (battery.charge_status == CHARGE_STATUS_CHARGING) {
+       } else if (battery.charging_status == CHARGING_STATUS_CHARGING) {
                battery.charge_full = CHARGING_NOT_FULL;
                battery.charge_now = CHARGER_CHARGING;
-       } else if (battery.charge_status == CHARGE_STATUS_DISCHARGING) {
+       } else if (battery.charging_status == CHARGING_STATUS_DISCHARGING) {
                battery.charge_full = CHARGING_NOT_FULL;
                battery.charge_now = CHARGER_DISCHARGING;
-       } else if (battery.charge_status == CHARGE_STATUS_NOT_CHARGING) {
+       } else if (battery.charging_status == CHARGING_STATUS_NOT_CHARGING) {
                battery.charge_full = CHARGING_NOT_FULL;
                battery.charge_now = CHARGER_ABNORMAL;
        } else {
@@ -583,155 +566,211 @@ static void check_charge_status(const char *env_value)
 
 static void check_health_status(const char *env_value)
 {
+       int len;
+
        if (env_value == NULL) {
                battery.health = HEALTH_GOOD;
-               battery.temp = TEMP_LOW;
-               battery.ovp = OVP_NORMAL;
                return;
        }
-       if (strncmp(env_value, OVERHEAT_NAME,
-                               sizeof(OVERHEAT_NAME)) == 0) {
-               battery.health = HEALTH_BAD;
-               battery.temp = TEMP_HIGH;
-               battery.ovp = OVP_NORMAL;
-       } else if (strncmp(env_value, TEMPCOLD_NAME,
-                               sizeof(TEMPCOLD_NAME)) == 0) {
-               battery.health = HEALTH_BAD;
-               battery.temp = TEMP_LOW;
-               battery.ovp = OVP_NORMAL;
-       } else if (strncmp(env_value, OVERVOLT_NAME,
-                               sizeof(OVERVOLT_NAME)) == 0) {
-               battery.health = HEALTH_GOOD;
-               battery.temp = TEMP_LOW;
-               battery.ovp = OVP_ABNORMAL;
-       } else {
+
+       snprintf(battery.health_s, sizeof(battery.health_s), "%s", env_value);
+
+       len = strlen(env_value);
+       if (strncmp(env_value, OVERHEAT_NAME, len) == 0)
+               battery.health = HEALTH_HIGH;
+       else if (strncmp(env_value, TEMPCOLD_NAME, len) == 0)
+               battery.health = HEALTH_LOW;
+       else if (strncmp(env_value, OVERVOLT_NAME, len) == 0)
+               battery.health = HEALTH_OVP;
+       else if (strncmp(env_value, GOOD_NAME, len) == 0)
                battery.health = HEALTH_GOOD;
-               battery.temp = TEMP_LOW;
-               battery.ovp = OVP_NORMAL;
-       }
+       else
+               battery.health = HEALTH_NO_OPT;
 }
 
-static void check_online_status(const char *env_value)
+static void check_power_source(const char *env_value)
 {
-       if (env_value == NULL)
+       int maxlen = sizeof(battery.power_source_s);
+
+       if (!env_value)
                return;
-       battery.online = atoi(env_value);
+
+       snprintf(battery.power_source_s, maxlen, "%s", env_value);
+       battery.power_source_s[maxlen - 1] = '\0';
+
+       if (strncmp(battery.power_source_s, "ac", sizeof("ac")) == 0) {
+               battery.online_type = CHARGER_TYPE_AC;
+       } else if (strncmp(battery.power_source_s, "usb", sizeof("usb")) == 0) {
+               battery.online_type = CHARGER_TYPE_USB;
+       } else if (strncmp(battery.power_source_s, "wireless", sizeof("wireless")) == 0) {
+               battery.online_type = CHARGER_TYPE_WIRELESS;
+       } else {
+               battery.online_type = CHARGER_TYPE_NONE;
+       }
 }
 
-static void check_present_status(const char *env_value)
+static void check_misc_status(const char *env_value)
 {
        if (env_value == NULL) {
-               battery.present = PRESENT_NORMAL;
+               battery.misc = MISC_NONE;
                return;
        }
-       battery.present = atoi(env_value);
+       battery.misc = atoi(env_value);
 }
 
-static void check_capacity_status(const char *env_value)
+static void process_power_supply(void *data)
 {
-       if (env_value == NULL)
-               return;
-       battery.capacity = atoi(env_value);
-}
+       bool broadcasted = true;
+       int ret_lock = -1;
+       int ret_val;
 
-static void update_capacity_full(void)
-{
-       static int old;
-       int delta;
+       if (disp_plgn->pm_lock_internal)
+               ret_lock = disp_plgn->pm_lock_internal(INTERNAL_LOCK_BATTERY, LCD_OFF, STAY_CUR_STATE, 0);
 
-       if (battery.online <= POWER_SUPPLY_TYPE_BATTERY ||
-           old == 0 ||
-           old >= battery.capacity) {
-               old = battery.capacity;
-               return;
+       if (old_battery.charge_now != battery.charge_now || battery.charge_now == CHARGER_ABNORMAL) {
+               ret_val = vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, battery.charge_now);
+               if (ret_val < 0)
+                       _E("Failed to set vconf value for battery charge now: %d", vconf_get_ext_errno());
+
+               if (power_supply_broadcast(CHARGE_NOW_SIGNAL, battery.charge_now) < 0)
+                       broadcasted = false;
        }
-       delta = battery.capacity - old;
-       old = battery.capacity;
-       extcon_get_count(EXTCON_BATTERY_FULL);
-       extcon_set_count(EXTCON_BATTERY_FULL, delta);
-}
 
-static void process_power_supply(void *data)
-{
-       if (old_battery.charge_now != battery.charge_now || battery.charge_now == CHARGER_ABNORMAL) {
-               vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, battery.charge_now);
-               power_supply_broadcast(CHARGE_NOW_SIGNAL, battery.charge_now);
+       if (!strcmp(old_battery.status_s, CHARGEFULL_NAME) &&
+               !strcmp(battery.status_s, CHARGENOW_NAME)) {
+               battery_pm_change_internal(INTERNAL_LOCK_BATTERY, LCD_NORMAL);
+       }
+
+       if (old_battery.charge_full != battery.charge_full)
+               if (power_supply_broadcast(CHARGE_FULL_SIGNAL, battery.charge_full) < 0)
+                       broadcasted = false;
+
+       if (strncmp(old_battery.health_s, battery.health_s, strlen(battery.health_s))) {
+               snprintf(old_battery.health_s, sizeof(old_battery.health_s), "%s", battery.health_s);
+               if (power_supply_broadcast_str(CHARGE_HEALTH_SIGNAL, battery.health_s) < 0)
+                       broadcasted = false;
+       }
+
+       if (old_battery.capacity != battery.capacity) {
+               ret_val = vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY, battery.capacity);
+               if (ret_val < 0)
+                       _E("Failed to set vconf value for battery capacity: %d", vconf_get_ext_errno());
+
+               if (power_supply_broadcast(CHARGE_CAPACITY_SIGNAL, battery.capacity) < 0)
+                       broadcasted = false;
+       }
+
+       (void)lowbat_execute(data);
+
+       if (old_battery.charger_connected != battery.charger_connected) {
+               check_power_supply(battery.charger_connected);
+               ret_val = vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, battery.charger_connected);
+               if (ret_val < 0)
+                       _E("Failed to set vconf value for charger status: %d", vconf_get_ext_errno());
+               if (battery.charger_connected == 0) {
+                       CRITICAL_LOG("Battery charger disconnected");
+                       event_system_send(SYS_EVENT_BATTERY_CHARGER_STATUS, EVT_KEY_BATTERY_CHARGER_STATUS, EVT_VAL_BATTERY_CHARGER_CONNECTED);
+                       device_notify(DEVICE_NOTIFIER_BATTERY_CHARGER_DISCONNECTED, NULL);
+               } else if (battery.charger_connected == 1) {
+                       CRITICAL_LOG("Battery charger connected");
+                       event_system_send(SYS_EVENT_BATTERY_CHARGER_STATUS, EVT_KEY_BATTERY_CHARGER_STATUS, EVT_VAL_BATTERY_CHARGER_DISCONNECTED);
+                       device_notify(DEVICE_NOTIFIER_BATTERY_CHARGER_CONNECTED, NULL);
+               } else {
+                       _E("Invalid charger connected");
+               }
        }
 
-       lowbat_execute(data);
-       check_online();
+       if (old_battery.charging_status != battery.charging_status)
+               charger_state_send_system_event(battery.charging_status);
+
+       if (old_battery.online_type != battery.online_type) {
+               ret_val = vconf_set_int(VCONFKEY_SYSMAN_CHARGER_TYPE, battery.online_type);
+               if (ret_val < 0)
+                       _E("Failed to set vconf value for charger type: %d", vconf_get_ext_errno());
+
+               if (power_supply_broadcast(CHARGER_TYPE_SIGNAL, battery.online_type) < 0)
+               broadcasted = false;
+       }
+
+       if (old_battery.misc != battery.misc)
+               if (power_supply_broadcast(CHARGE_MISC_EVENT_SIGNAL, battery.misc) < 0)
+                       broadcasted = false;
+
        if (old_battery.charge_full != battery.charge_full)
                noti_batt_full();
 
+       if (old_battery.charge_now != battery.charge_now ||
+           old_battery.charge_full != battery.charge_full ||
+           old_battery.capacity != battery.capacity ||
+           old_battery.health != battery.health ||
+               old_battery.misc != battery.misc ||
+               old_battery.online_type != battery.online_type)
+               _I("Signal(%d) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d : %s)",
+                       broadcasted,
+                       CHARGER_STATUS_SIGNAL, battery.charger_connected,
+                       CHARGER_TYPE_SIGNAL, battery.online_type,
+                       CHARGE_NOW_SIGNAL, battery.charge_now,
+                       CHARGE_FULL_SIGNAL, battery.charge_full,
+                       CHARGE_CAPACITY_SIGNAL, battery.capacity,
+                       CHARGE_LEVEL_SIGNAL, battery.capacity_level,
+                       CHARGE_MISC_EVENT_SIGNAL, battery.misc,
+                       CHARGE_HEALTH_SIGNAL, battery.health, battery.health_s);
+
        old_battery.capacity = battery.capacity;
-       old_battery.online = battery.online;
-       old_battery.charge_status = battery.charge_status;
-       old_battery.charge_now = battery.charge_now;
+       old_battery.capacity_level = battery.capacity_level;
+       old_battery.charger_connected = battery.charger_connected;
+       old_battery.online_type = battery.online_type;
+       old_battery.charging_status = battery.charging_status;
        old_battery.charge_full = battery.charge_full;
 
-       check_battery_status();
-       device_notify(DEVICE_NOTIFIER_POWER_SUPPLY, NULL);
-       device_notify(DEVICE_NOTIFIER_BATTERY_CHARGING, &battery.charge_now);
-       update_capacity_full();
-}
+       old_battery.misc = battery.misc;
+       snprintf(old_battery.status_s, sizeof(old_battery.status_s), "%s", battery.status_s);
 
-static void uevent_power_handler(struct udev_device *dev)
-{
-       struct udev_list_entry *list_entry;
-       const char *env_name;
-       const char *env_value;
-       bool matched = false;
-       int ret;
+       check_abnormal_status();
 
-       udev_list_entry_foreach(list_entry,
-                       udev_device_get_properties_list_entry(dev)) {
-               env_name = udev_list_entry_get_name(list_entry);
-               if (!env_name)
-                       continue;
-
-               if (!strncmp(env_name, CHARGE_NAME, sizeof(CHARGE_NAME))) {
-                       env_value = udev_list_entry_get_value(list_entry);
-                       if (!env_value)
-                               continue;
-                       if (!strncmp(env_value, BATTERY_NAME,
-                                               sizeof(BATTERY_NAME))) {
-                               matched = true;
-                               break;
-                       }
+       device_notify(DEVICE_NOTIFIER_POWER_SUPPLY, NULL);
+       if (old_battery.charge_now != battery.charge_now) {
+               device_notify(DEVICE_NOTIFIER_BATTERY_CHARGING, &battery.charge_now);
+               old_battery.charge_now = battery.charge_now;
+       }
+
+       if (disp_plgn->pm_unlock_internal) {
+               if (ret_lock == 0) {
+                       disp_plgn->pm_unlock_internal(INTERNAL_LOCK_BATTERY, LCD_OFF, PM_SLEEP_MARGIN);
                }
        }
+}
 
-       if (!matched)
-               return;
+static int battery_state(struct battery_info *info)
+{
+       static struct battery_status prev_status;
 
-       env_value = udev_device_get_property_value(dev, CHARGE_STATUS);
-       check_charge_status(env_value);
-       env_value = udev_device_get_property_value(dev, CHARGE_ONLINE);
-       check_online_status(env_value);
-       env_value = udev_device_get_property_value(dev, CHARGE_HEALTH);
-       check_health_status(env_value);
-       env_value = udev_device_get_property_value(dev, CHARGE_PRESENT);
-       check_present_status(env_value);
-       env_value = udev_device_get_property_value(dev, CAPACITY);
-       check_capacity_status(env_value);
-
-       ret = booting_done(NULL);
-       if (ret) {
-               if (battery.online > POWER_SUPPLY_TYPE_BATTERY)
-                       power_supply_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_ON);
-               else
-                       power_supply_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_OFF);
+       if (!info) {
+               memcpy(&prev_status, &battery, sizeof(battery));
+               return 0;
        }
 
-       process_power_supply(&battery.capacity);
-}
+       if (battery.capacity != 0 && prev_status.capacity == battery.capacity &&
+               prev_status.charging_status == battery.charging_status &&
+               prev_status.online_type == battery.online_type &&
+               prev_status.charge_full == battery.charge_full &&
+               prev_status.charge_now == battery.charge_now &&
+               prev_status.health == battery.health &&
+               prev_status.present == battery.present &&
+               prev_status.current_now == battery.current_now &&
+               prev_status.current_average == battery.current_average &&
+               prev_status.charger_connected == battery.charger_connected)
+               return 0;
 
-static void battery_state(struct battery_info *info)
-{
-       if (!info)
-               return;
+       prev_status.capacity = battery.capacity;
+       prev_status.charging_status = battery.charging_status;
+       prev_status.charge_full = battery.charge_full;
+       prev_status.charge_now = battery.charge_now;
+       prev_status.health = battery.health;
+       prev_status.present = battery.present;
+       prev_status.charger_connected = battery.charger_connected;
 
-       _I("%s(%s) %s(%d) Capa(%d) Hth(%s,%s) Pres(%d) OVP(%s) Curr(%d,%d)",
+       _I("%s(%s) %s(%d) Capa(%d) Hth(%s,%d) Pres(%d) Curr(%d,%d)",
                        info->status,
                        battery.charge_now == CHARGER_CHARGING ? "Charging"
                                : (battery.charge_now == CHARGER_DISCHARGING ? "Discharging" : "Abnormal"),
@@ -739,24 +778,56 @@ static void battery_state(struct battery_info *info)
                        info->online,
                        info->capacity,
                        info->health,
-                       battery.temp == TEMP_LOW ? "Low" : "High",
+                       battery.health,
                        info->present,
-                       battery.ovp == OVP_NORMAL ? "X" : "O",
                        info->current_now,
                        info->current_average);
+       return 1;
+}
+
+static void battery_disable_module(int value)
+{
+       int retval;
+       static const struct invalidate_list {
+               const char *vconfkey;
+               int *member;
+       } list[] = {
+               { VCONFKEY_SYSMAN_BATTERY_CAPACITY, &old_battery.capacity },
+               { VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &old_battery.capacity_level },
+               { VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, &old_battery.charge_now },
+               { VCONFKEY_SYSMAN_BATTERY_LEVEL_STATUS, NULL },
+       };
+
+       _D("Invalidate battery value to %d", value);
+
+       for (int i = 0; i < ARRAY_SIZE(list); ++i) {
+               if (list[i].vconfkey) {
+                       retval = vconf_set_int(list[i].vconfkey, value);
+                       if (retval == 0)
+                               _D("Set vconf %s to %d", list[i].vconfkey, value);
+                       else
+                               _E("Failed to set %s to %d, %d", list[i].vconfkey, value, retval);
+               }
+               if (list[i].member)
+                       *(list[i].member) = value;
+       }
+
+       power_supply_exit(NULL);
 }
 
 static void battery_changed(struct battery_info *info, void *data)
 {
-       int ret;
+       int ret_val;
 
-       if (!info)
+       if (!info) {
+               (void)battery_state(NULL);
                return;
+       }
 
        if (info->status) {
                snprintf(battery.status_s, sizeof(battery.status_s),
                                "%s", info->status);
-               check_charge_status(info->status);
+               check_charging_status(info->status);
        } else
                battery.status_s[0] = '\0';
 
@@ -768,138 +839,95 @@ static void battery_changed(struct battery_info *info, void *data)
                battery.health_s[0] = '\0';
 
        if (info->power_source)
-               snprintf(battery.power_source_s, sizeof(battery.power_source_s),
-                               "%s", info->power_source);
+               check_power_source(info->power_source);
        else
                battery.power_source_s[0] = '\0';
 
-       battery.online = info->online;
+       battery.charger_connected = info->online;
        battery.present = info->present;
        battery.capacity = info->capacity;
        battery.current_now = info->current_now;
        battery.current_average = info->current_average;
+       battery.temperature = info->temperature;
+       battery.voltage_now = info->voltage_now;
+       battery.voltage_average = info->voltage_average;
 
-       battery_state(info);
+       battery_initialized = true;
 
-       ret = booting_done(NULL);
-       if (ret) {
-               if (battery.online > POWER_SUPPLY_TYPE_BATTERY)
+       ret_val = battery_state(info);
+       if (ret_val != 1)
+               return;
+
+       ret_val = delayed_init_done(NULL);
+       if (ret_val) {
+               /* If the same notification is requested repeatedly, it is ignored by power_supply_noti().
+                * A notification will be triggered only when charging_status changes between
+                * CHARGING_STATUS_CHARGING/FULL <-> CHARGING_STATUS_DISCHARGING. */
+               if (battery.charging_status == CHARGING_STATUS_CHARGING || battery.charging_status == CHARGING_STATUS_FULL)
                        power_supply_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_ON);
-               else
+               else if (battery.charging_status == CHARGING_STATUS_DISCHARGING)
                        power_supply_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_OFF);
        }
 
-       process_power_supply(&battery.capacity);
-
-}
-
-static int lowbat_read(int *val)
-{
-       int r;
-
-       if (!val)
-               return -EINVAL;
-
-       r = sys_get_int("/sys/class/power_supply/battery/capacity", val);
-       if (r < 0)
-               return r;
-
-       return 0;
-}
-
-static void battery_get_capacity(struct battery_info *info, void *data)
-{
-       int *capa = data;
-
-       if (info && info->capacity >= 0)
-               *capa = info->capacity;
-}
-
-static void power_supply_status_init(void)
-{
-       static int charge_now = -1;
-       static int charge_full = -1;
-       static int capacity = -1;
-       int pct;
-       int r;
+       if (ret_val == 0) {
+               battery.health = HEALTH_GOOD;
+               battery.present = PRESENT_NORMAL;
+       }
 
-       if (battery_dev && battery_dev->get_current_state) {
-               pct = -1;
-               r = battery_dev->get_current_state(battery_get_capacity, &pct);
-               if (r < 0 || pct < 0) {
-                       _E("Failed to get battery capacity (capa:%d, ret:%d)", pct, r);
-                       return;
-               }
+       if (battery.present) {
+               process_power_supply(&battery.capacity);
        } else {
-               r = lowbat_read(&pct);
-               if (r < 0) {
-                       _E("fail to read capacity data : %d", r);
-                       return;
-               }
+               CRITICAL_LOG_E("Battery disconnected. Disable the battery module.");
+               battery_disable_module(-ENODEV);
        }
+}
 
-       battery.capacity = pct;
-       battery.health = HEALTH_GOOD;
-       battery.ovp = OVP_NORMAL;
-       battery.present = PRESENT_NORMAL;
-       battery.temp = TEMP_LOW;
-
-       if (charge_now == battery.charge_now &&
-           charge_full == battery.charge_full &&
-           capacity == battery.capacity)
-               return;
-
-       _I("charging %d full %d capacity %d", battery.charge_now, battery.charge_full, battery.capacity);
+static gboolean power_supply_update_during_booting(void *data)
+{
+       int retval;
 
-       if (charge_now != battery.charge_now) {
-               vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, battery.charge_now);
-               power_supply_broadcast(CHARGE_NOW_SIGNAL, battery.charge_now);
-       }
-       if (capacity != battery.capacity) {
-               vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY, battery.capacity);
-               power_supply_broadcast(CHARGE_CAPACITY_SIGNAL, battery.capacity);
+       retval = hal_device_battery_get_current_state(battery_changed, NULL);
+       if (retval == -ENODEV) {
+               CRITICAL_LOG_E("There is no battery detected. Disable the battery module.");
+               battery_disable_module(retval);
+               return G_SOURCE_REMOVE;
        }
 
-       charge_now = battery.charge_now;
-       charge_full = battery.charge_full;
-       capacity =  battery.capacity;
-}
-
-static gboolean power_supply_update(void *data)
-{
-       power_supply_status_init();
        return G_SOURCE_CONTINUE;
 }
 
 static void power_supply_timer_start(void)
 {
-       _D("battery init timer during booting");
-       power_timer = g_timeout_add_seconds(BATTERY_CHECK_TIMER_INTERVAL,
-                               power_supply_update, NULL);
+       _D("Battery init timer during booting.");
+       power_timer = g_timeout_add(BATTERY_CHECK_TIMER_INTERVAL,
+                               power_supply_update_during_booting, NULL);
        if (power_timer == 0)
-               _E("fail to add battery init timer during booting");
+               _E("Failed to add battery init timer during booting.");
+       else
+               _I("Started battery init timer during booting.");
 }
 
-static void power_supply_timer_stop(void)
+static GVariant *dbus_get_charger_status(GDBusConnection *conn,
+       const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+       GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
 {
-       _D("battery init timer during booting");
-       if (!power_timer)
-               return;
-       g_source_remove(power_timer);
-       power_timer = 0;
+       int ret_val, status;
+
+       ret_val = vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, &status);
+       if (ret_val < 0) {
+               _E("Failed to get vconf value for charger status: %d", vconf_get_ext_errno());
+               status = -EIO;
+       }
+       return g_variant_new("(i)", status);
 }
 
-static GVariant *dbus_get_charger_status(GDBusConnection *conn,
+static GVariant *dbus_get_charger_type(GDBusConnection *conn,
        const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
        GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
 {
-       int ret;
+       int type = battery.online_type;
 
-       if (vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, &ret) < 0) {
-               _E("vconf_get_int() failed");
-               ret = -EIO;
-       }
-       return g_variant_new("(i)", ret);
+       return g_variant_new("(i)", type);
 }
 
 static GVariant *dbus_get_charge_now(GDBusConnection *conn,
@@ -917,14 +945,15 @@ static GVariant *dbus_get_charge_level(GDBusConnection *conn,
        const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
        GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
 {
-       int ret;
+       int ret, val;
 
-       if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &ret) < 0) {
-               _E("vconf_get_int() failed");
-               ret = -EIO;
+       ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &val);
+       if (ret < 0) {
+               _E("Failed to get vconf value for battery status low: %d", vconf_get_ext_errno());
+               val = -EIO;
        }
 
-       return g_variant_new("(i)", ret);
+       return g_variant_new("(i)", val);
 }
 
 static GVariant *dbus_get_percent(GDBusConnection *conn,
@@ -964,71 +993,130 @@ static GVariant *dbus_get_health(GDBusConnection *conn,
        const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
        GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
 {
+       const char *str;
+
+       str = battery.health_s;
+
+       return g_variant_new("(s)", str);
+}
+
+static GVariant *dbus_get_misc(GDBusConnection *conn,
+       const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+       GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
        int ret;
 
-       ret = battery.health;
+       ret = battery.misc;
 
        return g_variant_new("(i)", ret);
 }
 
+
+static GVariant *dbus_get_power_supply_handler(GDBusConnection *conn,
+       const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+       GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+       /* This method is for getting battery state after battery modification
+        * by battery test driver. At this point, restore uevent buffering, which
+        * had been disabled by test driver. */
+       lowbat_enable_uevent_buffering();
+
+       return g_variant_new("(iiiiiiisiiiii)", 0,
+                               battery.capacity,
+                               battery.charging_status,
+                               battery.health,
+                               battery.charger_connected,
+                               battery.present,
+                               battery.misc,
+                               battery.power_source_s,
+                               battery.voltage_now,
+                               battery.voltage_average,
+                               battery.current_now,
+                               battery.current_average,
+                               battery.temperature);
+}
+
 static GVariant *dbus_power_supply_handler(GDBusConnection *conn,
        const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
        GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
 {
        pid_t pid;
-       int ret = 0;
-       int argc = 0;
+       int ret = 0, argc = 0;
+       int charger_connected;
        char *type_str;
-       char *argv[5];
-
-       g_variant_get(param, "(sisssss)", &type_str,
-                                       &argc,
-                                       &argv[0],
-                                       &argv[1],
-                                       &argv[2],
-                                       &argv[3],
-                                       &argv[4]);
+       char *argv[13];
+       struct battery_info info = {0, };
+
+       g_variant_get(param, "(sisssisssssssss)", &type_str,
+                               &argc,
+                               &argv[0],
+                               &argv[1],
+                               &argv[2],
+                               &charger_connected,
+                               &argv[4],
+                               &argv[5],
+                               &argv[6],
+                               &argv[7],
+                               &argv[8],
+                               &argv[9],
+                               &argv[10],
+                               &argv[11],
+                               &argv[12]);
 
        if (argc < 0) {
-               _E("message is invalid!");
+               _E("Message is invalid.");
                ret = -EINVAL;
                goto out;
        }
 
-       pid = dbus_connection_get_sender_pid(conn, sender);
-       if (kill(pid, 0) == -1) {
-               _E("%d process does not exist, dbus ignored!", pid);
+       pid = gdbus_connection_get_sender_pid(conn, sender);
+       if (pid == -1 || kill(pid, 0) == -1) {
+               _E("Process(%d) does not exist, dbus ignored.", pid);
                ret = -ESRCH;
                goto out;
        }
-       check_capacity_status(argv[0]);
-       check_charge_status(argv[1]);
-       check_health_status(argv[2]);
-       check_online_status(argv[3]);
-       check_present_status(argv[4]);
-       _I("%d %d %d %d %d %d %d %d",
-               battery.capacity,
-               battery.charge_full,
-               battery.charge_now,
-               battery.health,
-               battery.online,
-               battery.ovp,
-               battery.present,
-               battery.temp);
-
-       if (battery.online > POWER_SUPPLY_TYPE_BATTERY)
-               power_supply_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_ON);
-       else
-               power_supply_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_OFF);
 
-       process_power_supply(&battery.capacity);
+       /* The battery change triggered by this dbus must be processed
+        * within a single subroutine as the objective of this method call is mostly
+        * for the testing. Therefore, do not buffering the mocked uevent so that make
+        * the test driver can get the changed battery result without waiting */
+       lowbat_disable_uevent_buffering();
+
+       info.capacity = atoi(argv[0]);
+       info.status = strdup(argv[1]);
+       info.health = strdup(argv[2]);
+       info.online = charger_connected;
+       info.present = atoi(argv[4]);
+       check_misc_status(argv[5]);
+       info.power_source = strdup(argv[7]);
+       info.voltage_now = atoi(argv[8]);
+       info.voltage_average = atoi(argv[9]);
+       info.current_now = atoi(argv[10]);
+       info.current_average = atoi(argv[11]);
+       info.temperature = atoi(argv[12]);
+       _D("C(%d) S(%s) H(%s) O(%d) P(%d) SRC(%s) Vol(%d %d) Cur(%d %d) T(%d)",
+               info.capacity, info.status, info.health, info.online, info.present, info.power_source, info.voltage_now, info.voltage_average, info.current_now, info.current_average, info.temperature);
+
+       battery_changed(&info, NULL);
+
 out:
        g_free(type_str);
        g_free(argv[0]);
        g_free(argv[1]);
        g_free(argv[2]);
-       g_free(argv[3]);
        g_free(argv[4]);
+       g_free(argv[5]);
+       g_free(argv[6]);
+       g_free(argv[7]);
+       g_free(argv[8]);
+       g_free(argv[9]);
+       g_free(argv[10]);
+       g_free(argv[11]);
+       g_free(argv[12]);
+
+       free(info.status);
+       free(info.health);
+       free(info.power_source);
 
        return g_variant_new("(i)", ret);
 }
@@ -1048,51 +1136,35 @@ static void battery_get_info(struct battery_info *info, void *data)
        bat->capacity = info->capacity;
        bat->current_now = info->current_now;
        bat->current_average = info->current_average;
+       bat->temperature = info->temperature;
+       bat->voltage_now = info->voltage_now;
+       bat->voltage_average = info->voltage_average;
 }
 
 static GVariant *dbus_get_battery_info(GDBusConnection *conn,
        const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
        GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
 {
-       int ret, val;
+       int ret = 0, val;
        const char *str;
-       struct battery_info info = { 0, };
+       struct battery_info info = {0, };
 
-       if (battery_dev && battery_dev->get_current_state) {
-               ret = battery_dev->get_current_state(battery_get_info, &info);
+       if (old_state == DEVICE_NOTIFIER_STATE_STOP)
+               goto out;
+
+       if (battery_initialized)
+               goto out;
+
+       ret = hal_device_battery_get_current_state(battery_get_info, &info);
+       if (ret != -ENODEV) {
                if (ret < 0)
-                       _E("Failed to get battery info (%d)", ret);
+                       _E("Failed to get battery info: %d", ret);
 
                battery_changed(&info, NULL);
                free(info.status);
                free(info.health);
                free(info.power_source);
        } else {
-               if (battery.charge_status == CHARGE_STATUS_FULL)
-                       str = CHARGEFULL_NAME;
-               else if (battery.charge_status == CHARGE_STATUS_CHARGING)
-                       str = CHARGENOW_NAME;
-               else if (battery.charge_status == CHARGE_STATUS_DISCHARGING)
-                       str = DISCHARGE_NAME;
-               else if (battery.charge_status == CHARGE_STATUS_NOT_CHARGING)
-                       str = NOTCHARGE_NAME;
-               else
-                       str = "Unknown";
-               snprintf(battery.status_s, sizeof(battery.status_s), "%s", str);
-
-               if (battery.health == HEALTH_GOOD) {
-                       if (battery.temp == TEMP_LOW && battery.ovp == OVP_ABNORMAL)
-                               str = OVERVOLT_NAME;
-                       else
-                               str = "Good";
-               } else { /* HEALTH_BAD */
-                       if (battery.temp == TEMP_HIGH)
-                               str = OVERHEAT_NAME;
-                       else /* TEMP_LOW */
-                               str = TEMPCOLD_NAME;
-               }
-               snprintf(battery.health_s, sizeof(battery.health_s), "%s", str);
-
                if (vconf_get_int(VCONFKEY_SYSMAN_USB_STATUS, &val) == 0 &&
                        val != VCONFKEY_SYSMAN_USB_DISCONNECTED)
                        str = POWER_SOURCE_USB;
@@ -1108,13 +1180,38 @@ static GVariant *dbus_get_battery_info(GDBusConnection *conn,
                ret = 0;
        }
 
-       return g_variant_new("(isssiiiii)", ret,
-                                       battery.status_s,
-                                       battery.health_s,
-                                       battery.power_source_s,
-                                       battery.online,
-                                       battery.present,
+out:
+       return g_variant_new("(isssiiiiiiii)", ret,
+                               battery.status_s,
+                               battery.health_s,
+                               battery.power_source_s,
+                               battery.charger_connected,
+                               battery.present,
+                               battery.capacity,
+                               battery.current_now,
+                               battery.current_average,
+                               battery.voltage_now,
+                               battery.voltage_average,
+                               battery.temperature);
+}
+
+static void update_battery_props(void)
+{
+       if (config_parse(POWER_SUPPLY_UEVENT, load_uevent, &battery) < 0)
+               _E("Failed to check power supply uevent.");
+}
+
+static GVariant *dbus_get_battery_props(GDBusConnection *conn,
+       const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
+       GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
+{
+       update_battery_props();
+
+       return g_variant_new("(iiiiii)",
                                        battery.capacity,
+                                       battery.temperature,
+                                       battery.voltage_now,
+                                       battery.voltage_average,
                                        battery.current_now,
                                        battery.current_average);
 }
@@ -1122,14 +1219,17 @@ static GVariant *dbus_get_battery_info(GDBusConnection *conn,
 static const dbus_method_s dbus_methods[] = {
        { CHARGER_STATUS_SIGNAL,      NULL, "i", dbus_get_charger_status },
        { CHARGE_NOW_SIGNAL,          NULL, "i", dbus_get_charge_now },
-       { CHARGE_LEVEL_SIGNAL,        NULL, "i", dbus_get_charge_level },
+       { CHARGE_LEVEL_SIGNAL,         NULL, "i", dbus_get_charge_level },
        { CHARGE_CAPACITY_SIGNAL,     NULL, "i", dbus_get_percent },
        { CHARGE_CAPACITY_LAW_SIGNAL, NULL, "i", dbus_get_percent_raw },
        { CHARGE_FULL_SIGNAL,         NULL, "i", dbus_is_full },
-       { CHARGE_HEALTH_SIGNAL,       NULL, "i", dbus_get_health },
-       { POWER_SUBSYSTEM,       "sisssss", "i", dbus_power_supply_handler },
-       { "GetBatteryInfo",           NULL, "isssiiiii", dbus_get_battery_info },
-       /* Add methods here */
+       { CHARGE_HEALTH_SIGNAL,        NULL, "s", dbus_get_health },
+       { POWER_SUBSYSTEM,      "sisssisssssssss", "i", dbus_power_supply_handler },
+       { GET_POWER_SUBSYSTEM,      NULL, "iiiiiiisiiiii", dbus_get_power_supply_handler },
+       { "GetBatteryInfo",           NULL, "isssiiiiiiii", dbus_get_battery_info },
+       { CHARGER_TYPE_SIGNAL,         NULL, "i", dbus_get_charger_type },
+       { CHARGE_BATTERY_PROPERTIES,   NULL, "iiiiii", dbus_get_battery_props },
+       { CHARGE_MISC_EVENT_SIGNAL,    NULL, "i", dbus_get_misc },
 };
 
 static const dbus_interface_u dbus_interface = {
@@ -1139,9 +1239,11 @@ static const dbus_interface_u dbus_interface = {
        .nr_methods = ARRAY_SIZE(dbus_methods),
 };
 
-static int booting_done(void *data)
+static int delayed_init_done(void *data)
 {
        static int done;
+       int retval;
+       device_notifier_state_e state = DEVICE_NOTIFIER_STATE_START;
 
        if (data == NULL)
                return done;
@@ -1149,24 +1251,70 @@ static int booting_done(void *data)
        if (done == 0)
                return done;
 
-       _I("booting done");
+       if (power_timer) {
+               g_source_remove(power_timer);
+               power_timer = 0;
+       }
 
-       power_supply_timer_stop();
+       /* check battery has been initialized */
+       retval = hal_device_battery_get_current_state(battery_changed, NULL);
+       if (retval == -ENODEV) {
+               CRITICAL_LOG_E("Failed to initialize battery state, %d. Disable the battery module.", retval);
+               battery_disable_module(retval);
+               return done;
+       }
+
+       event_handler_state_changed((void *)&state);
 
-       /* for simple noti change cb */
-       power_supply_status_init();
-       process_power_supply(NULL);
+       _I("booting done %s(%d) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d : %s)",
+                       CHARGER_STATUS_SIGNAL, battery.charger_connected,
+                       CHARGE_NOW_SIGNAL, battery.charge_now,
+                       CHARGE_FULL_SIGNAL, battery.charge_full,
+                       CHARGE_CAPACITY_SIGNAL, battery.capacity,
+                       CHARGE_LEVEL_SIGNAL, battery.capacity_level,
+                       CHARGE_MISC_EVENT_SIGNAL, battery.misc,
+                       CHARGE_HEALTH_SIGNAL, battery.health, battery.health_s);
+
+       unregister_notifier(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_done);
 
        return done;
 }
 
-static int display_changed(void *data)
+bool battery_do_not_disturb(void)
 {
-       if (battery.charge_now != CHARGER_ABNORMAL)
-               return 0;
-       if (battery.health != HEALTH_BAD && battery.present != PRESENT_ABNORMAL)
+       int block = 0, theater = 0, night = 0;
+       int r;
+
+       if (battery_plgn->display_changed) {
+               if (battery_plgn->display_changed(NULL) == S_LCDOFF) {
+                       r = vconf_get_bool(VCONFKEY_SETAPPL_BLOCKMODE_WEARABLE_BOOL, &block);
+                       if (r < 0)
+                               _E("Failed to set vconf value for blockmode wearable: %d", vconf_get_ext_errno());
+                       r = vconf_get_bool(VCONFKEY_SETAPPL_THEATER_MODE_ENABLE, &theater);
+                       if (r < 0)
+                               _E("Failed to set vconf value for theator mode enable: %d", vconf_get_ext_errno());
+                       r = vconf_get_bool(VCONFKEY_SETAPPL_GOODNIGHT_MODE_ENABLE, &night);
+                       if (r < 0)
+                               _E("Failed to set vconf value for goodnight mode enable: %d", vconf_get_ext_errno());
+               }
+       }
+
+       if (block != 0 || theater != 0 || night != 0) {
+               _I("Skip lcd and popup(block %d theater %d night %d).", block, theater, night);
+               return true;
+       }
+
+       return false;
+}
+
+int battery_pm_change_internal(int pid, int s_bits)
+{
+       if (battery_do_not_disturb())
                return 0;
-       pm_lock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, STAY_CUR_STATE, 0);
+
+       if (disp_plgn->pm_change_internal)
+               disp_plgn->pm_change_internal(pid, s_bits);
+
        return 0;
 }
 
@@ -1192,47 +1340,40 @@ static int load_uevent(struct parse_result *result, void *user_data)
                        info->charge_full = CHARGING_NOT_FULL;
                }
                snprintf(info->status_s, sizeof(info->status_s), "%s", result->value);
-       } else if (MATCH(result->name, CAPACITY))
+       } else if (MATCH(result->name, CAPACITY)) {
                info->capacity = atoi(result->value);
-       else if (MATCH(result->name, CHARGE_HEALTH))
+       } else if (MATCH(result->name, TEMPERATURE)) {
+               info->temperature = atoi(result->value) / 10;
+       } else if (MATCH(result->name, VOLTAGE_NOW)) {
+               info->voltage_now = atoi(result->value);
+       } else if (MATCH(result->name, VOLTAGE_AVG)) {
+               info->voltage_average = atoi(result->value);
+       } else if (MATCH(result->name, CURRENT_NOW)) {
+               info->current_now = atoi(result->value);
+       } else if (MATCH(result->name, CURRENT_AVG)) {
+               info->current_average = atoi(result->value);
+       } else if (MATCH(result->name, CHARGE_HEALTH)) {
                snprintf(info->health_s, sizeof(info->health_s), "%s", result->value);
+       }
+
        return 0;
 }
 
 static int power_supply_probe(void *data)
 {
-       struct hw_info *info;
-       int ret;
+       int ret_val, r;
 
-       if (battery_dev)
-               return 0;
-
-       ret = hw_get_info(BATTERY_HARDWARE_DEVICE_ID,
-                       (const struct hw_info **)&info);
 
-       if (ret < 0) { /* There is no HAL for battery */
+       ret_val = hal_device_battery_get_backend();
+       if (ret_val < 0) {
+               _E("There is no HAL for battery.");
                if (access(POWER_PATH, R_OK) == 0)
                        return 0; /* Just power_supply uevent is used */
-               goto out;
-       }
-
-       if (!info->open) {
-               _E("Failed to open battery device; open(NULL)");
-               return -ENODEV;
-       }
 
-       ret = info->open(info, NULL, (struct hw_common**)&battery_dev);
-       if (ret < 0) {
-               _E("Failed to get battery device structure (%d)", ret);
-               return ret;
-       }
-
-       if (!battery_dev || !battery_dev->get_current_state) {
-               _E("get_current_state() is not supported by the Battery HAL");
-               return -ENODEV;
+               goto out;
        }
 
-       _I("battery device structure load success");
+       _I("Battery device structure load success.");
        return 0;
 
 out:
@@ -1240,49 +1381,38 @@ out:
         * Set battery vconf as -ENOTSUP
         * These vconf key used by runtime-info and capi-system-device.
         */
-       vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, -ENOTSUP);
-       vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, -ENOTSUP);
-       vconf_set_int(VCONFKEY_SYSMAN_BATTERY_LEVEL_STATUS, -ENOTSUP);
-       _I("There is no battery device(%d)", ret);
+       r = vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, -ENOTSUP);
+       if (r < 0)
+               _E("Failed to set vconf value for charger status: %d", vconf_get_ext_errno());
+       r = vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, -ENOTSUP);
+       if (r < 0)
+               _E("Failed to set vconf value for battery charge now: %d", vconf_get_ext_errno());
+       r = vconf_set_int(VCONFKEY_SYSMAN_BATTERY_LEVEL_STATUS, -ENOTSUP);
+       if (r < 0)
+               _E("Failed to set vconf value for battery level status: %d", vconf_get_ext_errno());
+       _I("There is no battery device: %d", ret_val);
        return -ENODEV;
 }
 
 static void add_power_supply_handler(void)
 {
-       int ret;
-
-       if (battery_dev) {
-               if (battery_dev->register_changed_event)
-                       battery_dev->register_changed_event(battery_changed, NULL);
-               if (battery_dev->get_current_state)
-                       battery_dev->get_current_state(battery_changed, NULL);
-       } else {
-               ret = config_parse(POWER_SUPPLY_UEVENT, load_uevent, &battery);
-               if (ret < 0)
-                       _E("Failed to load %s, %d Use default value!", POWER_SUPPLY_UEVENT, ret);
-
-               /* register power subsystem */
-               register_kernel_uevent_control(&uh);
-       }
+       hal_device_battery_register_changed_event(battery_changed, NULL);
+       hal_device_battery_get_current_state(battery_changed, NULL);
 }
 
 static void remove_power_supply_handler(void)
 {
-       if (battery_dev)
-               battery_dev->unregister_changed_event(battery_changed);
-       else
-               unregister_kernel_uevent_control(&uh);
+       hal_device_battery_unregister_changed_event(battery_changed);
 }
 
 static int event_handler_state_changed(void *data)
 {
-       static device_notifier_state_e old = DEVICE_NOTIFIER_STATE_STOP;
        device_notifier_state_e state = *(device_notifier_state_e *)data;
 
-       if (old == state)
+       if (old_state == state)
                return 0;
 
-       old = state;
+       old_state = state;
 
        if (state == DEVICE_NOTIFIER_STATE_START)
                add_power_supply_handler();
@@ -1294,49 +1424,57 @@ static int event_handler_state_changed(void *data)
 
 static void power_supply_init(void *data)
 {
-       int ret;
-       device_notifier_state_e state = DEVICE_NOTIFIER_STATE_START;
+       int ret_dbus;
 
-       battery.capacity = -1;
+       memset(&battery, 0, sizeof(struct battery_status));
+       memset(&old_battery, 0, sizeof(struct battery_status));
+       battery.misc = MISC_NONE;
+       battery.charger_connected = -1;
 
-       event_handler_state_changed((void *)&state);
+       /* It will be true on initializing battery structure */
+       battery_initialized = false;
 
        /* process check battery timer until booting done */
        power_supply_timer_start();
 
-       register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
-       register_notifier(DEVICE_NOTIFIER_LCD, display_changed);
+       register_notifier(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_done);
        register_notifier(DEVICE_NOTIFIER_EVENT_HANDLER, event_handler_state_changed);
 
-       ret = dbus_handle_add_dbus_object(NULL, DEVICED_PATH_BATTERY, &dbus_interface);
-       if (ret < 0)
-               _E("fail to init dbus method(%d)", ret);
-
+       ret_dbus = gdbus_add_object(NULL, DEVICED_PATH_BATTERY, &dbus_interface);
+       if (ret_dbus < 0)
+               _E("Failed to init dbus method: %d", ret_dbus);
 
-#ifdef TIZEN_FEATURE_BATTERY_OVER_TEMPERATURE
-       ret = subscribe_dbus_signal(NULL, DEVICED_PATH_SYSNOTI,
-               DEVICED_INTERFACE_SYSNOTI, SIGNAL_CHARGEERR_RESPONSE, abnormal_popup_dbus_signal_handler, NULL, NULL);
-       if (ret <= 0)
-               _E("fail to init dbus signal(%d)", ret);
-#endif /* TIZEN_FEATURE_BATTERY_OVER_TEMPERATURE */
+       battery_ops_init((void *)battery_plgn);
 }
 
 static void power_supply_exit(void *data)
 {
        device_notifier_state_e state = DEVICE_NOTIFIER_STATE_STOP;
 
-       unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
-       unregister_notifier(DEVICE_NOTIFIER_LCD, display_changed);
+       unregister_notifier(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_done);
        unregister_notifier(DEVICE_NOTIFIER_EVENT_HANDLER, event_handler_state_changed);
 
        event_handler_state_changed((void *)&state);
+
+       battery_ops_exit(NULL);
 }
 
 static const struct device_ops power_supply_ops = {
-       .name     = "power_supply",
+       DECLARE_NAME_LEN("power_supply"),
        .probe    = power_supply_probe,
        .init     = power_supply_init,
        .exit     = power_supply_exit,
 };
 
 DEVICE_OPS_REGISTER(&power_supply_ops)
+
+static void __CONSTRUCTOR__ initialize(void)
+{
+       disp_plgn = get_var_display_plugin();
+       if (!disp_plgn)
+               _E("Failed to get display plugin variable.");
+
+       battery_plgn = get_var_battery_plugin();
+       if (!battery_plgn)
+               _E("Failed to get battery plugin variable.");
+}