#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 "shared/eventsystem.h"
+#include "shared/plugin.h"
+#include "shared/apps.h"
#include "display/core.h"
#include "display/display-ops.h"
-#include "apps/apps.h"
#include "power-supply.h"
#include "battery.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"
#define OVERVOLT_NAME "Over voltage"
#define GOOD_NAME "Good"
-#define REMOVE_POPUP "remove_battery_popups"
-#define DISCONNECT_POPUP "battdisconnect"
-
#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 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 500 /* 0.5 second */
#define LCD_DIM_TIME_IN_BATTERY_HEALTH 10000 /* ms */
-#define HEALTH_POPUP_TERMINATE_TIMEOUT 10
-#define HEALTH_POPUP_RELAUNCH_TIMEOUT 3600
-
-enum charger_type {
- CHARGER_TYPE_NONE = 0,
- CHARGER_TYPE_WIRE,
- CHARGER_TYPE_WIRELESS,
- CHARGER_TYPE_INCOMPATIBLE,
-};
-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;
+static struct battery_status battery;
+struct battery_status old_battery;
static int noti_id;
-static int online_status;
+static int abnormal_health_popup_timer;
+static bool launching_health_popup;
static guint power_timer;
-static guint abnormal_timer;
-static guint health_popup_timer;
-static struct timespec health_relaunch_start_st;
-static struct timespec health_relaunch_end_st;
-
-bool battery_do_not_disturb(void);
-static int battery_pm_change_internal(int pid, int s_bits);
-static int display_changed(void *data);
-static void health_popup_timer_init(const char *func);
-static void update_health_popup_relaunch_time(int timeout);
-static void change_health_popup_timer(enum battery_noti_status status);
-static int booting_done(void *data);
+static device_notifier_state_e old_state = -1;
-static struct battery_device *battery_dev;
+bool battery_initialized;
+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);
+
+inline struct battery_status *get_var_battery_status(void)
+{
+ return &battery;
+}
static int lowbat_execute(void *data)
{
str = status;
- ret = dbus_handle_emit_dbus_signal(NULL,
+ ret = gdbus_signal_emit(NULL,
DEVICED_PATH_BATTERY,
DEVICED_INTERFACE_BATTERY,
sig,
battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
}
-static void abnormal_popup_timer_init(void)
-{
- if (abnormal_timer == 0)
- return;
- g_source_remove(abnormal_timer);
- abnormal_timer = 0;
- _I("Delete health timer.");
-}
-
static void health_status_broadcast(void)
{
- dbus_handle_emit_dbus_signal(NULL,
+ gdbus_signal_emit(NULL,
DEVICED_PATH_BATTERY,
DEVICED_INTERFACE_BATTERY,
SIGNAL_TEMP_GOOD,
NULL);
}
-
-static void health_timer_reset(void)
-{
- abnormal_timer = 0;
-}
-
-static gboolean health_timer_cb(void *data)
-{
- health_timer_reset();
-
- if (battery.health != HEALTH_LOW && battery.health != HEALTH_HIGH)
- return G_SOURCE_REMOVE;
-
- _I("Popup: Battery health status is not good.");
- device_notify(DEVICE_NOTIFIER_BATTERY_HEALTH, (void *)&battery.health);
- 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, 0);
- if (battery.health == HEALTH_LOW)
- battery_charge_err_low_act(NULL);
- else if (battery.health == HEALTH_HIGH)
- battery_charge_err_high_act(NULL);
- return G_SOURCE_REMOVE;
-}
-
-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)
-
-{
- 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 == 0)
- _E("Failed to add abnormal check timer.");
-}
-
static void full_noti_cb(GVariant *var, void *user_data, GError *err)
{
int id = 0;
if (!var)
return;
- if (!dh_get_param_from_var(var, "(i)", &id)) {
+ if (!g_variant_get_safe(var, "(i)", &id)) {
_E("Failed to notify full: no message(%s)", g_variant_get_type_string(var));
goto out;
}
static void noti_off_cb(GVariant *var, void *user_data, GError *err)
{
- int ret = 0;
+ int val = 0;
- if (!dh_get_param_from_var(var, "(i)", &ret)) {
+ if (!g_variant_get_safe(var, "(i)", &val)) {
_E("Failed to off notification: no message(%s)", g_variant_get_type_string(var));
goto out;
}
- _D("Noti off: %d", ret);
+ _D("Noti off: %d", val);
out:
g_variant_unref(var);
}
-int check_power_supply_noti(void)
-{
- int block;
-
- if (vconf_get_bool("db/setting/blockmode_wearable", &block) != 0)
- return 1;
- if (block == 0)
- return 1;
- return 0;
-}
-
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_handle_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.");
return ret;
}
}
_E("Failed to call dbus method: %d", ret);
- break;
+ break;
case CHARGING_NOT_FULL:
if (noti_id <= 0)
return -EPERM;
for (retry = RETRY_MAX; retry > 0; retry--) {
- ret = dbus_handle_method_async_with_reply_var(POPUP_BUS_NAME,
+ ret = gdbus_call_async_with_reply(POPUP_BUS_NAME,
POPUP_PATH_NOTI,
POPUP_INTERFACE_NOTI,
METHOD_FULL_NOTI_OFF,
}
}
_E("Failed to call dbus method: %d", ret);
- break;
+ break;
}
return ret;
}
if (!var)
return;
- if (!dh_get_param_from_var(var, "(i)", &id)) {
+ if (!g_variant_get_safe(var, "(i)", &id)) {
_E("Failed to notify charge: no message(%s)", g_variant_get_type_string(var));
goto out;
}
int retry;
for (retry = RETRY_MAX; retry > 0; retry--) {
- ret = dbus_handle_method_async_with_reply(POPUP_BUS_NAME,
+ ret = gdbus_call_async_with_reply(POPUP_BUS_NAME,
POPUP_PATH_NOTI,
POPUP_INTERFACE_NOTI,
METHOD_CHARGE_NOTI_ON,
- NULL, NULL, charge_noti_on, -1, NULL);
+ NULL, charge_noti_on, -1, NULL);
if (ret == 0) {
- _D("Created battery charge noti.");
+ _I("Created battery charge noti.");
return ret;
}
}
{
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) {
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;
}
}
static int old;
static char sig_old[32];
int ret;
- int chg_on;
if (!sig) {
_E("There is no signal name.");
old = status;
- if (battery.charger_charging == CHARGER_DISABLED) {
- ret = sys_get_int(CHARGER_CHARGE_ON_NODE, &chg_on);
- if (ret == 0 && battery.charger_charging != chg_on) {
- ret = sys_set_int(CHARGER_CHARGE_ON_NODE, battery.charger_charging);
- _I("%s to change status with %d", ((ret == 0) ? "success" : "fail"), battery.charger_charging);
- }
- if (strncmp(sig, CHARGE_NOW_SIGNAL, strlen(CHARGE_NOW_SIGNAL)) == 0) {
- _I("Skip signal while charger disabled.");
- return 0;
- }
- }
-
snprintf(sig_old, sizeof(sig_old), "%s", sig);
- ret = dbus_handle_emit_dbus_signal(NULL,
+ ret = gdbus_signal_emit(NULL,
DEVICED_PATH_BATTERY,
DEVICED_INTERFACE_BATTERY,
sig,
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);
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) {
+ /* 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.");
static void check_power_supply(int state)
{
pm_check_and_change(state);
- if (disp_plgn.update_pm_setting)
- disp_plgn.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)
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);
return;
}
- _D("System_event: %s", str);
-
event_system_send(SYS_EVENT_BATTERY_CHARGER_STATUS, EVT_KEY_BATTERY_CHARGER_STATUS, str);
}
-int changed_battery_cf(int status)
-{
- if (status == PRESENT_ABNORMAL)
- return launch_system_app(APP_ABNORMAL, 2, APP_KEY_TYPE, DISCONNECT_POPUP);
- return launch_system_app(APP_REMOVE, 2, APP_KEY_TYPE, REMOVE_POPUP);
-}
-
static void update_present(enum battery_noti_status status)
{
- _I("Charge(%d) present(%d)", battery.charge_now, battery.present);
+ 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) {
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);
+ if (disp_plgn->pm_lock_internal)
+ disp_plgn->pm_lock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, STAY_CUR_STATE, 0);
} else {
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);
+ if (disp_plgn->pm_unlock_internal)
+ disp_plgn->pm_unlock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, PM_SLEEP_MARGIN);
}
- changed_battery_cf(battery.present);
+ if (battery_plgn->changed_battery_cf)
+ battery_plgn->changed_battery_cf(battery.present);
}
-void remove_health_popup(void)
+static void launch_health_popup(void)
{
- launch_system_app(APP_REMOVE, 2, APP_KEY_TYPE, REMOVE_POPUP);
+ if (launching_health_popup)
+ return;
+
+ 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;
+}
+
+/* Warning popup for every 1 minutes until
+ * battery health returns to normal. */
+static gboolean health_popup_cb(void *data)
+{
+ launch_health_popup();
+ battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
+ return G_SOURCE_CONTINUE;
}
static void update_health(enum battery_noti_status status)
{
- _I("Charge(%d) health(%d)", battery.charge_now, battery.health);
+ _I("Charge(%d) health(%d, old: %d)", battery.charge_now, battery.health, old_battery.health);
+ old_battery.health = battery.health;
if (status == DEVICE_NOTI_ON) {
- _I("Popup: Battery health status is not good.");
- battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_DIM);
- if (disp_plgn.pm_change_internal)
- disp_plgn.pm_change_internal(INTERNAL_LOCK_POPUP, LCD_DIM);
- device_notify(DEVICE_NOTIFIER_BATTERY_HEALTH, (void *)&battery.health);
- 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, 0);
- change_health_popup_timer(status);
- if (battery.health == HEALTH_LOW)
- battery_charge_err_low_act(NULL);
- else if (battery.health == HEALTH_HIGH)
- battery_charge_err_high_act(NULL);
+ 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);
+ 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);
}
- change_health_popup_timer(status);
health_status_broadcast();
- abnormal_popup_timer_init();
- remove_health_popup();
+ 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();
}
}
-void update_health_popup_relaunch(void)
+void relaunch_health_popup(void)
{
- int delta;
-
- _D("update_health_popup_relaunch()");
- clock_gettime(CLOCK_REALTIME, &health_relaunch_end_st);
- delta = health_relaunch_end_st.tv_sec - health_relaunch_start_st.tv_sec;
- if (delta <= 0 || delta >= HEALTH_POPUP_RELAUNCH_TIMEOUT)
+ if (launching_health_popup)
return;
- update_health_popup_relaunch_time((HEALTH_POPUP_RELAUNCH_TIMEOUT - delta));
-}
+ launching_health_popup = true;
-static void update_ovp(enum battery_noti_status status)
-{
- static int old = DEVICE_NOTI_OFF;
+ if (abnormal_health_popup_timer)
+ g_source_remove(abnormal_health_popup_timer);
- if (old == status)
- return;
+ 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);
- old = status;
- _I("Charge(%d) ovp(%d) with lcd(%s)", battery.charge_now, battery.health,
- (status == DEVICE_NOTI_ON) ? "dim" : "normal");
+ abnormal_health_popup_timer = g_timeout_add_seconds(ABNORMAL_CHECK_TIMER_INTERVAL, health_popup_cb, NULL);
- device_notify(DEVICE_NOTIFIER_BATTERY_OVP, (void *)&battery.health);
- battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
+ launching_health_popup = false;
}
static void check_abnormal_status(void)
{
- if (battery.health == HEALTH_LOW || battery.health == HEALTH_HIGH)
- update_health_popup_relaunch();
-
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 (battery.present != PRESENT_ABNORMAL && old_battery.present == PRESENT_ABNORMAL)
update_present(DEVICE_NOTI_OFF);
- if (old_battery.health != HEALTH_OVP && battery.health == HEALTH_OVP)
- update_ovp(DEVICE_NOTI_ON);
- else if (battery.health != HEALTH_OVP && old_battery.health == HEALTH_OVP)
- update_ovp(DEVICE_NOTI_OFF);
-}
-
-static bool update_online(void)
-{
- int chg_on;
- int ret;
- bool broadcast = false;
-
- if (battery.online <= POWER_SUPPLY_TYPE_BATTERY &&
- battery.charger_charging == CHARGER_DISABLED) {
- battery.charger_charging = CHARGER_ENABLED;
- ret = sys_get_int(CHARGER_CHARGE_ON_NODE, &chg_on);
- if (ret == 0 && battery.charger_charging != chg_on) {
- ret = sys_set_int(CHARGER_CHARGE_ON_NODE, battery.charger_charging);
- _I("%s to change status with %d", ((ret == 0) ? "success" : "fail"), battery.charger_charging);
- }
- }
-
- if (battery.online > POWER_SUPPLY_TYPE_BATTERY &&
- online_status == VCONFKEY_SYSMAN_CHARGER_DISCONNECTED) {
- online_status = VCONFKEY_SYSMAN_CHARGER_CONNECTED;
- check_power_supply(online_status);
- charger_state_send_system_event(CHARGE_STATUS_CONNECTED);
- if (old_battery.charge_status != battery.charge_status)
- charger_state_send_system_event(battery.charge_status);
- broadcast = true;
- } else if (battery.online <= POWER_SUPPLY_TYPE_BATTERY &&
- online_status == VCONFKEY_SYSMAN_CHARGER_CONNECTED) {
- online_status = VCONFKEY_SYSMAN_CHARGER_DISCONNECTED;
- check_power_supply(online_status);
- if (old_battery.charge_status != battery.charge_status)
- charger_state_send_system_event(battery.charge_status);
- charger_state_send_system_event(CHARGE_STATUS_DISCONNECTED);
- broadcast = true;
- } else {
- if (old_battery.charge_status != battery.charge_status)
- charger_state_send_system_event(battery.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);
}
-
- if (battery.online <= POWER_SUPPLY_TYPE_BATTERY)
- battery.online_type = CHARGER_TYPE_NONE;
- else if (battery.online == CHARGER_WIRELESS_TYPE_BT ||
- battery.online == CHARGER_WIRELESS_TYPE_3G)
- battery.online_type = CHARGER_TYPE_WIRELESS;
- else if (battery.online == CHARGER_INCOMPATIBLE_TYPE)
- battery.online_type = CHARGER_TYPE_INCOMPATIBLE;
- else
- battery.online_type = CHARGER_TYPE_WIRE;
-
- return broadcast;
}
-static void check_charge_status(const char *env_value)
+static void check_charging_status(const char *env_value)
{
int len;
len = strlen(env_value);
if (strncmp(env_value, CHARGEFULL_NAME, len) == 0)
- battery.charge_status = CHARGE_STATUS_FULL;
+ battery.charging_status = CHARGING_STATUS_FULL;
else if (strncmp(env_value, CHARGENOW_NAME, len) == 0)
- battery.charge_status = CHARGE_STATUS_CHARGING;
+ battery.charging_status = CHARGING_STATUS_CHARGING;
else if (strncmp(env_value, DISCHARGE_NAME, len) == 0)
- battery.charge_status = CHARGE_STATUS_DISCHARGING;
+ battery.charging_status = CHARGING_STATUS_DISCHARGING;
else if (strncmp(env_value, NOTCHARGE_NAME, len) == 0)
- battery.charge_status = CHARGE_STATUS_NOT_CHARGING;
+ 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 {
battery.health = HEALTH_NO_OPT;
}
-static void check_misc_status(const char *env_value)
+static void check_power_source(const char *env_value)
{
- if (env_value == NULL) {
- battery.misc = MISC_NONE;
- return;
- }
- battery.misc = atoi(env_value);
-}
+ int maxlen = sizeof(battery.power_source_s);
-static void check_online_status(const char *env_value)
-{
- if (env_value == NULL)
+ if (!env_value)
return;
- battery.online = atoi(env_value);
-}
-static void check_present_status(const char *env_value)
-{
- if (env_value == NULL) {
- battery.present = PRESENT_NORMAL;
- return;
+ 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;
}
- battery.present = atoi(env_value);
}
-static void check_capacity_status(const char *env_value)
+static void check_misc_status(const char *env_value)
{
- if (env_value == NULL)
+ if (env_value == NULL) {
+ battery.misc = MISC_NONE;
return;
- battery.capacity = atoi(env_value);
+ }
+ battery.misc = atoi(env_value);
}
static void process_power_supply(void *data)
{
bool broadcasted = true;
- int lock = -1;
- int ret;
+ int ret_lock = -1;
+ int ret_val;
+
+ if (disp_plgn->pm_lock_internal)
+ ret_lock = disp_plgn->pm_lock_internal(INTERNAL_LOCK_BATTERY, LCD_OFF, STAY_CUR_STATE, 0);
- _D("process_power_supply()");
- if (disp_plgn.pm_lock_internal) {
- lock = disp_plgn.pm_lock_internal(INTERNAL_LOCK_BATTERY, LCD_OFF, STAY_CUR_STATE, 0);
if (old_battery.charge_now != battery.charge_now || battery.charge_now == CHARGER_ABNORMAL) {
- ret = vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, battery.charge_now);
- if (ret < 0)
- _E("Failed to set vconf value for battery charge now: %d", vconf_get_ext_errno());
+ 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;
- }
+ if (power_supply_broadcast(CHARGE_NOW_SIGNAL, battery.charge_now) < 0)
+ broadcasted = false;
+ }
+
+ 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)))
+ 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 = vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY, battery.capacity);
- if (ret < 0)
+ 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;
}
- battery.charging_level = lowbat_execute(data);
- if (battery.charging_level > 0 && old_battery.charging_level != battery.charging_level) {
- ret = vconf_set_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, battery.charging_level);
- if (ret < 0)
- _E("Failed to set vconf value for battery capacity: %d", vconf_get_ext_errno());
- if (power_supply_broadcast(CHARGE_LEVEL_SIGNAL, battery.charging_level) < 0)
- broadcasted = false;
- }
+ (void)lowbat_execute(data);
- if (update_online()) {
- ret = vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, online_status);
- if (ret < 0)
+ 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 (power_supply_broadcast(CHARGER_STATUS_SIGNAL, online_status) < 0)
- broadcasted = false;
+ 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");
+ }
}
+ 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;
}
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, online_status,
+ 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.charging_level,
+ 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.charging_level = battery.charging_level;
- old_battery.online = battery.online;
+ old_battery.capacity_level = battery.capacity_level;
+ old_battery.charger_connected = battery.charger_connected;
old_battery.online_type = battery.online_type;
- old_battery.charge_status = battery.charge_status;
+ old_battery.charging_status = battery.charging_status;
old_battery.charge_full = battery.charge_full;
- check_abnormal_status();
-
- old_battery.health = battery.health;
old_battery.misc = battery.misc;
- old_battery.present = battery.present;
- snprintf(old_battery.health_s, sizeof(old_battery.health_s), "%s", battery.health_s);
+ snprintf(old_battery.status_s, sizeof(old_battery.status_s), "%s", battery.status_s);
+
+ check_abnormal_status();
device_notify(DEVICE_NOTIFIER_POWER_SUPPLY, NULL);
if (old_battery.charge_now != battery.charge_now) {
- device_notify(DEVICE_NOTIFIER_BATTERY_CHARGING, &battery.charge_now);
+ device_notify(DEVICE_NOTIFIER_BATTERY_CHARGING, &battery.charge_now);
old_battery.charge_now = battery.charge_now;
}
- if (lock == 0) {
- if (disp_plgn.pm_unlock_internal)
- disp_plgn.pm_unlock_internal(INTERNAL_LOCK_BATTERY, LCD_OFF, PM_SLEEP_MARGIN);
- }
-}
-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;
-
- 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;
- }
+ 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;
-
- 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_MISC_EVENT);
- check_misc_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);
- }
-
- process_power_supply(&battery.capacity);
}
static int battery_state(struct battery_info *info)
return 0;
}
- if (prev_status.capacity == battery.capacity &&
- prev_status.charge_status == battery.charge_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.online == battery.online)
+ 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;
prev_status.capacity = battery.capacity;
- prev_status.charge_status = battery.charge_status;
+ 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.online = battery.online;
+ prev_status.charger_connected = battery.charger_connected;
_I("%s(%s) %s(%d) Capa(%d) Hth(%s,%d) Pres(%d) Curr(%d,%d)",
info->status,
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) {
(void)battery_state(NULL);
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';
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_initialized = true;
- ret = battery_state(info);
- if (ret != 1)
+ ret_val = battery_state(info);
+ if (ret_val != 1)
return;
- ret = booting_done(NULL);
- if (ret && old_battery.online != battery.online) {
- if (battery.online > POWER_SUPPLY_TYPE_BATTERY && battery.charge_now == CHARGER_CHARGING)
+ 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);
}
- if (ret == 0) {
+
+ if (ret_val == 0) {
battery.health = HEALTH_GOOD;
battery.present = PRESENT_NORMAL;
}
- process_power_supply(&battery.capacity);
-
+ if (battery.present) {
+ process_power_supply(&battery.capacity);
+ } else {
+ CRITICAL_LOG_E("Battery disconnected. Disable the battery module.");
+ battery_disable_module(-ENODEV);
+ }
}
-static void power_supply_status_init(void)
+static gboolean power_supply_update_during_booting(void *data)
{
- int r;
+ int retval;
- if (battery_dev && battery_dev->get_current_state) {
- r = battery_dev->get_current_state(battery_changed, NULL);
- if (r < 0 || battery.capacity < 0) {
- _E("Failed to get battery capacity (capa: %d, ret: %d)", battery.capacity, r);
- return;
- }
- } else {
- r = config_parse(POWER_SUPPLY_UEVENT, load_uevent, &battery);
- if (r < 0) {
- _E("Failed to load %s, %d Use default value.", POWER_SUPPLY_UEVENT, r);
- return;
- }
- battery.health = HEALTH_GOOD;
- battery.present = PRESENT_NORMAL;
- process_power_supply(&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;
}
-}
-static gboolean power_supply_update(void *data)
-{
- power_supply_status_init();
return G_SOURCE_CONTINUE;
}
{
_D("Battery init timer during booting.");
power_timer = g_timeout_add(BATTERY_CHECK_TIMER_INTERVAL,
- power_supply_update, NULL);
+ power_supply_update_during_booting, NULL);
if (power_timer == 0)
_E("Failed to add battery init timer during booting.");
else
_I("Started battery init timer during booting.");
}
-static void power_supply_timer_stop(void)
-{
- if (power_timer == 0)
- return;
- _I("Stop battery init timer during booting.");
- g_source_remove(power_timer);
- power_timer = 0;
-}
-
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)
{
- int ret, status;
+ int ret_val, status;
- ret = vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, &status);
- if (ret < 0) {
+ 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)", type);
}
-static GVariant *dbus_charger_charging(GDBusConnection *conn,
- const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
- GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
-{
- int ret = 0;
- int val;
- int chg_on;
-
- g_variant_get(param, "(i)", &val);
-
- if (val != CHARGER_ENABLED && val != CHARGER_DISABLED) {
- _E("There is no valid input: %d", battery.charger_charging);
- ret = -EINVAL;
- goto out;
- }
- if (battery.online <= POWER_SUPPLY_TYPE_BATTERY) {
- _E("There is no charger(%d) input(%d).", battery.online, battery.charger_charging);
- ret = -EACCES;
- goto out;
- }
- ret = sys_get_int(CHARGER_CHARGE_ON_NODE, &chg_on);
- if (ret == 0 && val != chg_on) {
- battery.charger_charging = val;
- ret = sys_set_int(CHARGER_CHARGE_ON_NODE, battery.charger_charging);
- _I("%s to change status with %d.", ((ret == 0) ? "success" : "fail"), battery.charger_charging);
- } else {
- _I("Skip change status with %d (ret %d prev %d)", val, ret, battery.charger_charging);
- }
-out:
- return g_variant_new("(i)", ret);
-}
-
static GVariant *dbus_get_charge_now(GDBusConnection *conn,
const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
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[6];
+ char *argv[13];
+ struct battery_info info = {0, };
- g_variant_get(param, "(sissssss)", &type_str,
- &argc,
- &argv[0],
- &argv[1],
- &argv[2],
- &argv[3],
- &argv[4],
- &argv[5]);
+ 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.");
goto out;
}
- pid = dbus_connection_get_sender_pid(conn, sender);
- if (kill(pid, 0) == -1) {
+ 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]);
+
+ /* 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]);
- if (battery_dev)
- battery_changed(NULL, NULL);
- snprintf(battery.status_s, sizeof(battery.status_s), "%s",
- (battery.charge_now == CHARGER_CHARGING) ? "Charging" :
- (battery.charge_now == CHARGER_ABNORMAL) ? "Not Charging" :
- (battery.charge_full == CHARGING_FULL) ? "Full" :
- "Discharging");
- _I("%s(%d) %s(f:%d n:%d) %s(%d) %s(%d) %s(%d) %s(%d)",
- argv[0],
- battery.capacity,
- argv[1],
- battery.charge_full,
- battery.charge_now,
- argv[2],
- battery.health,
- argv[3],
- battery.online,
- argv[4],
- battery.present,
- argv[5],
- battery.misc);
-
- 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);
+ 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);
- process_power_supply(&battery.capacity);
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);
}
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, };
- if (battery_dev && battery_dev->get_current_state) {
- ret = battery_dev->get_current_state(battery_get_info, &info);
- if (ret < 0)
- _E("Failed to get battery info: %d", ret);
+ if (old_state == DEVICE_NOTIFIER_STATE_STOP)
+ goto out;
- battery_changed(&info, NULL);
- free(info.status);
- free(info.health);
- free(info.power_source);
+ 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);
+
+ battery_changed(&info, NULL);
+ free(info.status);
+ free(info.health);
+ free(info.power_source);
} else {
if (vconf_get_int(VCONFKEY_SYSMAN_USB_STATUS, &val) == 0 &&
val != VCONFKEY_SYSMAN_USB_DISCONNECTED)
ret = 0;
}
+out:
return g_variant_new("(isssiiiiiiii)", ret,
- battery.status_s,
- battery.health_s,
- battery.power_source_s,
- battery.online,
- battery.present,
- battery.capacity,
- battery.current_now,
- battery.current_average,
- battery.voltage_now,
- battery.voltage_average,
- battery.temperature);
+ 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)
{ CHARGE_CAPACITY_LAW_SIGNAL, NULL, "i", dbus_get_percent_raw },
{ CHARGE_FULL_SIGNAL, NULL, "i", dbus_is_full },
{ CHARGE_HEALTH_SIGNAL, NULL, "s", dbus_get_health },
- { POWER_SUBSYSTEM, "sissssss", "i", dbus_power_supply_handler },
+ { 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 },
- { "ChargerCharging", "i", "i", dbus_charger_charging },
{ CHARGE_BATTERY_PROPERTIES, NULL, "iiiiii", dbus_get_battery_props },
{ CHARGE_MISC_EVENT_SIGNAL, NULL, "i", dbus_get_misc },
};
.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)
if (done == 0)
return done;
- power_supply_timer_stop();
+ if (power_timer) {
+ g_source_remove(power_timer);
+ power_timer = 0;
+ }
+
+ /* 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);
_I("booting done %s(%d) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d : %s)",
- CHARGER_STATUS_SIGNAL, online_status,
+ 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.charging_level,
+ CHARGE_LEVEL_SIGNAL, battery.capacity_level,
CHARGE_MISC_EVENT_SIGNAL, battery.misc,
CHARGE_HEALTH_SIGNAL, battery.health, battery.health_s);
- unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
+ unregister_notifier(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_done);
return done;
}
-static gboolean update_health_pm_status(void *data)
-{
- battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_OFF);
- 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);
- }
-
- return G_SOURCE_REMOVE;
-}
-
-static void change_health_popup_timer(enum battery_noti_status status)
-{
- if (status == DEVICE_NOTI_ON) {
- health_popup_timer = g_timeout_add_seconds(HEALTH_POPUP_TERMINATE_TIMEOUT, update_health_pm_status, NULL);
- if (health_popup_timer == 0)
- _E("Failed to add battery init timer during booting.");
- else
- _I("Turn off after %d sec by abnormal health condition.", HEALTH_POPUP_TERMINATE_TIMEOUT);
- return;
- }
- health_popup_timer_init(__func__);
-}
-
-static void launch_health_popup(void)
-{
- _I("Popup - Health is not good(health %s)", (battery.health == HEALTH_HIGH) ? "TempHigh" : "TempLow");
- health_popup_timer_init(__func__);
- 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);
- change_health_popup_timer(DEVICE_NOTI_ON);
- if (battery.health == HEALTH_LOW)
- battery_charge_err_low_act(NULL);
- else if (battery.health == HEALTH_HIGH)
- battery_charge_err_high_act(NULL);
-}
-
bool battery_do_not_disturb(void)
{
- int block = 0;
+ int block = 0, theater = 0, night = 0;
int r;
- if (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, &block);
- 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, &block);
- if (r < 0)
- _E("Failed to set vconf value for goodnight mode enable: %d", vconf_get_ext_errno());
+ 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) {
- _I("Skip lcd and popup(block %d).", block);
+ 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;
}
-static int battery_pm_change_internal(int pid, int s_bits)
+int battery_pm_change_internal(int pid, int s_bits)
{
if (battery_do_not_disturb())
return 0;
- if (disp_plgn.pm_change_internal)
- disp_plgn.pm_change_internal(pid, s_bits);
-
- return 0;
-}
-
-static gboolean change_health_pm_normal(void *data)
-{
- battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
- return G_SOURCE_REMOVE;
-}
-
-static void update_health_popup_relaunch_time(int timeout)
-{
- if (timeout <= 0)
- return;
-
- health_popup_timer_init(__func__);
- health_popup_timer = g_timeout_add(timeout, change_health_pm_normal, NULL);
- if (health_popup_timer == 0)
- _E("Failed to add battery init timer during booting.");
- else
- _D("Relaunch timeout with %d sec.", timeout);
-}
-
-static void health_popup_timer_init(const char *func)
-{
- if (health_popup_timer == 0)
- return;
-
- g_source_remove(health_popup_timer);
- health_popup_timer = 0;
- _D("init by %s", func);
-}
-
-static int display_changed(void *data)
-{
- static enum state_t old;
- static enum state_t state;
+ if (disp_plgn->pm_change_internal)
+ disp_plgn->pm_change_internal(pid, s_bits);
- if (!data)
- return state;
-
- state = *(int *)data;
-
- if (battery.health != HEALTH_LOW && battery.health != HEALTH_HIGH)
- goto out;
-
- if (old != S_LCDOFF || state != S_LCDON) {
- if (state == S_LCDOFF) {
- health_popup_timer_init(__func__);
- clock_gettime(CLOCK_REALTIME, &health_relaunch_start_st);
- update_health_popup_relaunch_time(HEALTH_POPUP_RELAUNCH_TIMEOUT);
- }
- goto out;
- }
- launch_health_popup();
-
-out:
- old = state;
return 0;
}
} else if (MATCH(result->name, CAPACITY)) {
info->capacity = atoi(result->value);
} else if (MATCH(result->name, TEMPERATURE)) {
- info->temperature = atoi(result->value);
+ 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)) {
static int power_supply_probe(void *data)
{
- struct hw_info *info;
- int ret, r;
+ 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.");
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);
+ _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();
static void power_supply_init(void *data)
{
- int ret;
+ int ret_dbus;
memset(&battery, 0, sizeof(struct battery_status));
memset(&old_battery, 0, sizeof(struct battery_status));
- battery.capacity = -1;
- battery.charger_charging = CHARGER_ENABLED;
battery.misc = MISC_NONE;
+ battery.charger_connected = -1;
+
+ /* 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("Failed 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);
- 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("Failed to init dbus signal: %d", ret);
+ 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_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 = {
};
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.");
+}