4 * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
24 #include <eventsystem.h>
25 #include <hal/device/hal-battery.h>
27 #include <libsyscommon/ini-parser.h>
28 #include <system/syscommon-plugin-deviced-common-interface.h>
30 #include "shared/devices.h"
31 #include "shared/device-notifier.h"
32 #include "core/udev.h"
36 #include "shared/eventsystem.h"
37 #include "shared/plugin.h"
38 #include "shared/apps.h"
39 #include "shared/event.h"
41 #include "display-lock.h"
42 #include "display-ops.h"
43 #include "display-state-transition.h"
44 #include "power-supply.h"
46 #include "battery-ops.h"
47 #include "extcon/extcon.h"
48 #include "lowbat-handler.h"
49 #include "battery-parser.h"
51 #ifndef VCONFKEY_SETAPPL_BLOCKMODE_WEARABLE_BOOL
52 #define VCONFKEY_SETAPPL_BLOCKMODE_WEARABLE_BOOL "db/setting/blockmode_wearable"
55 #ifndef VCONFKEY_SETAPPL_THEATER_MODE_ENABLE
56 #define VCONFKEY_SETAPPL_THEATER_MODE_ENABLE "db/setting/theater_mode_enable"
59 #ifndef VCONFKEY_SETAPPL_GOODNIGHT_MODE_ENABLE
60 #define VCONFKEY_SETAPPL_GOODNIGHT_MODE_ENABLE "db/setting/goodnight_mode_enable"
63 #define BATTERY_NAME "battery"
64 #define CHARGEFULL_NAME "Full"
65 #define CHARGENOW_NAME "Charging"
66 #define DISCHARGE_NAME "Discharging"
67 #define NOTCHARGE_NAME "Not charging"
68 #define OVERHEAT_NAME "Overheat"
69 #define TEMPCOLD_NAME "Cold"
70 #define OVERVOLT_NAME "Over voltage"
71 #define GOOD_NAME "Good"
73 #define CHARGER_WIRELESS_TYPE_BT 10
74 #define CHARGER_WIRELESS_TYPE_3G 22
75 #define CHARGER_INCOMPATIBLE_TYPE 11
76 #define CHARGER_D2D_TYPE 110
77 #define WIRELESS_CHARGER_CONNECTED 2
79 #define SIGNAL_TEMP_GOOD "TempGood"
81 #define METHOD_FULL_NOTI_ON "BatteryFullNotiOn"
82 #define METHOD_FULL_NOTI_OFF "BatteryFullNotiOff"
83 #define METHOD_CHARGE_NOTI_ON "BatteryChargeNotiOn"
85 #define CHARGER_CHARGE_ON_NODE "/sys/class/power_supply/battery/chg_on"
88 #define BATTERY_CHECK_TIMER_INTERVAL 500 /* 0.5 second */
89 #define LCD_DIM_TIME_IN_BATTERY_HEALTH 10000 /* ms */
91 static struct battery_plugin *battery_plgn;
93 static struct battery_status battery;
94 struct battery_status old_battery;
96 static int abnormal_health_popup_timer;
97 static bool launching_health_popup;
99 static guint power_timer;
100 static device_notifier_state_e old_state = -1;
102 static enum deviced_display_state g_display_state = DEVICED_DISPLAY_STATE_ON;
104 static struct battery_config_info g_battery_info;
106 bool battery_initialized;
108 bool battery_do_not_disturb(void);
109 int battery_pm_change_internal(int pid, int s_bits);
110 static int delayed_init_done(void *data);
111 static void update_health(enum battery_noti_status status);
112 static int load_uevent(struct parse_result *result, void *user_data);
113 static int event_handler_state_changed(void *data);
114 static void power_supply_exit(void *data);
116 inline struct battery_status *get_var_battery_status(void)
121 static int lowbat_execute(void *data)
123 static const struct device_ops *lowbat_ops;
125 FIND_DEVICE_INT(lowbat_ops, "lowbat");
126 return device_execute(lowbat_ops, data);
129 static int power_supply_broadcast_str(char *sig, char *status)
131 static char old_sig[32];
132 static char old_status[32];
136 if (!sig || !status) {
137 _E("there is no signal name");
141 if (strncmp(old_sig, sig, strlen(sig)) == 0 && strncmp(old_status, status, strlen(status)) == 0)
144 snprintf(old_sig, sizeof(old_sig), "%s", sig);
145 snprintf(old_status, sizeof(old_status), "%s", status);
149 ret = gdbus_signal_emit(NULL,
150 DEVICED_PATH_BATTERY,
151 DEVICED_INTERFACE_BATTERY,
153 g_variant_new("(s)", str));
161 static void pm_check_and_change(int bInserted)
165 if (old == bInserted)
168 battery_pm_change_internal(DEVICED_EVENT_MISC_POPUP, LCD_NORMAL);
171 static void health_status_broadcast(void)
173 gdbus_signal_emit(NULL,
174 DEVICED_PATH_BATTERY,
175 DEVICED_INTERFACE_BATTERY,
180 static void full_noti_cb(GVariant *var, void *user_data, GError *err)
187 if (!g_variant_get_safe(var, "(i)", &id)) {
188 _E("Failed to notify full: no message(%s)", g_variant_get_type_string(var));
193 _D("Inserted battery full noti(%d).", noti_id);
196 g_variant_unref(var);
199 static void noti_off_cb(GVariant *var, void *user_data, GError *err)
203 if (!g_variant_get_safe(var, "(i)", &val)) {
204 _E("Failed to off notification: no message(%s)", g_variant_get_type_string(var));
208 _D("Noti off: %d", val);
211 g_variant_unref(var);
214 static int send_full_noti(enum charge_full_type state)
220 if (battery_plgn->check_power_supply_noti)
221 noti = battery_plgn->check_power_supply_noti();
228 for (retry = RETRY_MAX; retry > 0; retry--) {
229 ret = gdbus_call_async_with_reply(POPUP_BUS_NAME,
231 POPUP_INTERFACE_NOTI,
233 NULL, full_noti_cb, -1, NULL);
235 _D("Created battery full noti.");
239 _E("Failed to call dbus method: %d", ret);
241 case CHARGING_NOT_FULL:
244 for (retry = RETRY_MAX; retry > 0; retry--) {
245 ret = gdbus_call_async_with_reply(POPUP_BUS_NAME,
247 POPUP_INTERFACE_NOTI,
248 METHOD_FULL_NOTI_OFF,
249 g_variant_new("(i)", noti_id),
250 noti_off_cb, -1, NULL);
252 _D("Deleted battery full noti.");
257 _E("Failed to call dbus method: %d", ret);
263 static void charge_noti_on(GVariant *var, void *user_data, GError *err)
270 if (!g_variant_get_safe(var, "(i)", &id)) {
271 _E("Failed to notify charge: no message(%s)", g_variant_get_type_string(var));
275 _D("Inserted battery charge noti: %d", id);
278 g_variant_unref(var);
281 static int send_charge_noti(void)
286 for (retry = RETRY_MAX; retry > 0; retry--) {
287 ret = gdbus_call_async_with_reply(POPUP_BUS_NAME,
289 POPUP_INTERFACE_NOTI,
290 METHOD_CHARGE_NOTI_ON,
291 NULL, charge_noti_on, -1, NULL);
293 _I("Created battery charge noti.");
297 _E("Failed to call dbus method: %d", ret);
301 static void power_supply_noti(enum battery_noti_type type, enum battery_noti_status status)
303 static int charger = CHARGER_DISCHARGING;
304 static int full = CHARGING_NOT_FULL;
307 if (type == DEVICE_NOTI_BATT_CHARGE) {
308 if (status == DEVICE_NOTI_ON && charger == CHARGER_DISCHARGING) {
310 charger = CHARGER_CHARGING;
311 } else if (status == DEVICE_NOTI_OFF && charger == CHARGER_CHARGING)
312 charger = CHARGER_DISCHARGING;
313 } else if (type == DEVICE_NOTI_BATT_FULL) {
314 if (status == DEVICE_NOTI_ON && full == CHARGING_NOT_FULL) {
315 ret_val = send_full_noti(CHARGING_FULL);
317 full = CHARGING_FULL;
318 } else if (status == DEVICE_NOTI_OFF && full == CHARGING_FULL) {
319 ret_val = send_full_noti(CHARGING_NOT_FULL);
321 full = CHARGING_NOT_FULL;
326 int power_supply_broadcast(char *sig, int status)
329 static char sig_old[32];
333 _E("There is no signal name.");
336 if (strncmp(sig_old, sig, strlen(sig)) == 0 && old == status) {
337 _D("Skip broadcasting same signal(%s) and status(%d).", sig, status);
343 snprintf(sig_old, sizeof(sig_old), "%s", sig);
345 ret = gdbus_signal_emit(NULL,
346 DEVICED_PATH_BATTERY,
347 DEVICED_INTERFACE_BATTERY,
349 g_variant_new("(i)", status));
356 static void noti_batt_full(void)
358 static int bat_full_noti;
360 if (!battery.charge_full && bat_full_noti == 1) {
361 power_supply_noti(DEVICE_NOTI_BATT_FULL, DEVICE_NOTI_OFF);
363 /* off the full charge state */
364 syscommon_notifier_emit_notify(DEVICE_NOTIFIER_FULLBAT, (void *)&bat_full_noti);
366 if (battery.charge_full && bat_full_noti == 0) {
367 power_supply_noti(DEVICE_NOTI_BATT_FULL, DEVICE_NOTI_ON);
369 /* turn on LCD, if battery is fully charged */
370 if (battery_plgn->check_power_supply_noti && battery_plgn->check_power_supply_noti()) {
371 battery_pm_change_internal(DEVICED_EVENT_BATTERY_CAPACITY_FULL, LCD_NORMAL);
375 /* on the full charge state */
376 syscommon_notifier_emit_notify(DEVICE_NOTIFIER_FULLBAT, (void *)&bat_full_noti);
380 static void check_power_supply(int state)
382 pm_check_and_change(state);
383 display_setting_update_pm_setting(SETTING_CHARGING, state);
386 static void charger_state_send_system_event(int state)
391 case CHARGING_STATUS_CHARGING:
392 str = EVT_VAL_BATTERY_CHARGER_CHARGING;
394 case CHARGING_STATUS_FULL:
395 str = EVT_VAL_BATTERY_CHARGER_DISCHARGING;
396 CRITICAL_LOG("Battery charger: %s", str);
398 case CHARGING_STATUS_DISCHARGING:
399 str = EVT_VAL_BATTERY_CHARGER_DISCHARGING;
400 CRITICAL_LOG("Battery charger: %s", str);
403 _E("Invalid parameter: %d", state);
407 event_system_send(SYS_EVENT_BATTERY_CHARGER_STATUS, EVT_KEY_BATTERY_CHARGER_STATUS, str);
410 static void update_present(enum battery_noti_status status)
413 CRITICAL_LOG("Charge(%d) present(%d, old: %d)", battery.charge_now, battery.present, old_battery.present);
415 old_battery.present = battery.present;
416 if (status == DEVICE_NOTI_ON) {
417 battery_pm_change_internal(DEVICED_EVENT_MISC_POPUP, LCD_DIM);
418 syscommon_notifier_emit_notify(DEVICE_NOTIFIER_BATTERY_PRESENT, (void *)&battery.present);
419 display_lock_request_lock_with_option(DEVICED_EVENT_MISC_POPUP, LCD_DIM, STAY_CUR_STATE, 0);
421 battery_pm_change_internal(DEVICED_EVENT_MISC_POPUP, LCD_NORMAL);
422 syscommon_notifier_emit_notify(DEVICE_NOTIFIER_BATTERY_PRESENT, (void *)&battery.present);
423 display_lock_request_unlock_with_option(DEVICED_EVENT_MISC_POPUP, LCD_DIM, PM_SLEEP_MARGIN);
425 if (battery_plgn->changed_battery_cf)
426 battery_plgn->changed_battery_cf(battery.present);
429 static void launch_health_popup(void)
431 if (launching_health_popup)
434 launching_health_popup = true;
436 syscommon_notifier_emit_notify(DEVICE_NOTIFIER_BATTERY_HEALTH, (void *)&battery.health);
437 battery_pm_change_internal(DEVICED_EVENT_MISC_POPUP, LCD_NORMAL);
438 battery_pm_change_internal(DEVICED_EVENT_MISC_POPUP, LCD_DIM);
439 display_lock_request_unlock_with_option(DEVICED_EVENT_MISC_POPUP, LCD_OFF, PM_SLEEP_MARGIN);
440 display_lock_request_lock_with_option(DEVICED_EVENT_MISC_POPUP, LCD_DIM, STAY_CUR_STATE, LCD_DIM_TIME_IN_BATTERY_HEALTH);
441 if (battery.health == HEALTH_LOW)
442 battery_charge_err_low_act(NULL);
443 else if (battery.health == HEALTH_HIGH)
444 battery_charge_err_high_act(NULL);
446 launching_health_popup = false;
449 /* Warning popup for every 1 minutes until
450 * battery health returns to normal. */
451 static gboolean health_popup_cb(void *data)
453 launch_health_popup();
454 battery_pm_change_internal(DEVICED_EVENT_MISC_POPUP, LCD_NORMAL);
455 return G_SOURCE_CONTINUE;
458 static void update_health(enum battery_noti_status status)
460 _I("Charge(%d) health(%d, old: %d)", battery.charge_now, battery.health, old_battery.health);
462 old_battery.health = battery.health;
463 if (status == DEVICE_NOTI_ON) {
464 CRITICAL_LOG("Popup: Battery health status is not good, %s.", battery.health_s);
465 launch_health_popup();
466 if (!abnormal_health_popup_timer)
467 abnormal_health_popup_timer = g_timeout_add_seconds(ABNORMAL_CHECK_TIMER_INTERVAL, health_popup_cb, NULL);
469 battery_pm_change_internal(DEVICED_EVENT_MISC_POPUP, LCD_NORMAL);
470 syscommon_notifier_emit_notify(DEVICE_NOTIFIER_BATTERY_HEALTH, (void *)&battery.health);
471 display_lock_request_unlock_with_option(DEVICED_EVENT_MISC_POPUP, LCD_DIM, PM_SLEEP_MARGIN);
472 display_lock_request_unlock_with_option(DEVICED_EVENT_MISC_POPUP, LCD_OFF, PM_SLEEP_MARGIN);
473 health_status_broadcast();
474 if (abnormal_health_popup_timer) {
475 CRITICAL_LOG("Battery health returned to normal. Stop abnormal popup.");
476 g_source_remove(abnormal_health_popup_timer);
477 abnormal_health_popup_timer = 0;
479 if (battery_plgn->remove_health_popup)
480 battery_plgn->remove_health_popup();
484 void relaunch_health_popup(void)
486 if (launching_health_popup)
489 launching_health_popup = true;
491 if (abnormal_health_popup_timer)
492 g_source_remove(abnormal_health_popup_timer);
494 display_lock_request_unlock_with_option(DEVICED_EVENT_MISC_POPUP, LCD_OFF, PM_SLEEP_MARGIN);
495 display_lock_request_lock_with_option(DEVICED_EVENT_MISC_POPUP, LCD_DIM, STAY_CUR_STATE, LCD_DIM_TIME_IN_BATTERY_HEALTH);
496 if (battery.health == HEALTH_LOW)
497 battery_charge_err_low_act(NULL);
498 else if (battery.health == HEALTH_HIGH)
499 battery_charge_err_high_act(NULL);
501 abnormal_health_popup_timer = g_timeout_add_seconds(ABNORMAL_CHECK_TIMER_INTERVAL, health_popup_cb, NULL);
503 launching_health_popup = false;
506 static void check_abnormal_status(void)
508 static int notify_status = DEVICE_NOTI_OFF;
510 if (old_battery.health != HEALTH_LOW && old_battery.health != HEALTH_HIGH &&
511 (battery.health == HEALTH_LOW || battery.health == HEALTH_HIGH))
512 update_health(DEVICE_NOTI_ON);
513 else if ((old_battery.health == HEALTH_LOW || old_battery.health == HEALTH_HIGH) &&
514 battery.health != HEALTH_LOW && battery.health != HEALTH_HIGH)
515 update_health(DEVICE_NOTI_OFF);
517 if (old_battery.present != PRESENT_ABNORMAL && battery.present == PRESENT_ABNORMAL)
518 update_present(DEVICE_NOTI_ON);
519 else if (battery.present != PRESENT_ABNORMAL && old_battery.present == PRESENT_ABNORMAL)
520 update_present(DEVICE_NOTI_OFF);
522 if (old_battery.health != HEALTH_OVP && battery.health == HEALTH_OVP) {
523 _I("Charge %d OVP %d(old %d)",
524 battery.charge_now, battery.health, old_battery.health);
526 old_battery.health = battery.health;
528 if (notify_status == DEVICE_NOTI_ON)
530 notify_status = DEVICE_NOTI_ON;
532 syscommon_notifier_emit_notify(DEVICE_NOTIFIER_BATTERY_OVP, (void *)&battery.health);
534 if (battery_plgn->update_ovp)
535 battery_plgn->update_ovp(DEVICE_NOTI_ON);
536 } else if (battery.health != HEALTH_OVP && old_battery.health == HEALTH_OVP) {
537 _I("Charge %d OVP %d(old %d)",
538 battery.charge_now, battery.health, old_battery.health);
540 old_battery.health = battery.health;
542 if (notify_status == DEVICE_NOTI_OFF)
544 notify_status = DEVICE_NOTI_OFF;
546 syscommon_notifier_emit_notify(DEVICE_NOTIFIER_BATTERY_OVP, (void *)&battery.health);
548 if (battery_plgn->update_ovp)
549 battery_plgn->update_ovp(DEVICE_NOTI_OFF);
553 static void check_charging_status(const char *env_value)
557 if (env_value == NULL)
560 len = strlen(env_value);
561 if (strncmp(env_value, CHARGEFULL_NAME, len) == 0)
562 battery.charging_status = CHARGING_STATUS_FULL;
563 else if (strncmp(env_value, CHARGENOW_NAME, len) == 0)
564 battery.charging_status = CHARGING_STATUS_CHARGING;
565 else if (strncmp(env_value, DISCHARGE_NAME, len) == 0)
566 battery.charging_status = CHARGING_STATUS_DISCHARGING;
567 else if (strncmp(env_value, NOTCHARGE_NAME, len) == 0)
568 battery.charging_status = CHARGING_STATUS_NOT_CHARGING;
570 battery.charging_status = CHARGING_STATUS_UNKNOWN;
572 if (battery.charging_status == CHARGING_STATUS_FULL) {
573 battery.charge_full = CHARGING_FULL;
574 battery.charge_now = CHARGER_DISCHARGING;
575 } else if (battery.charging_status == CHARGING_STATUS_CHARGING) {
576 battery.charge_full = CHARGING_NOT_FULL;
577 battery.charge_now = CHARGER_CHARGING;
578 } else if (battery.charging_status == CHARGING_STATUS_DISCHARGING) {
579 battery.charge_full = CHARGING_NOT_FULL;
580 battery.charge_now = CHARGER_DISCHARGING;
581 } else if (battery.charging_status == CHARGING_STATUS_NOT_CHARGING) {
582 battery.charge_full = CHARGING_NOT_FULL;
583 battery.charge_now = CHARGER_ABNORMAL;
585 battery.charge_full = CHARGING_NOT_FULL;
586 battery.charge_now = CHARGER_DISCHARGING;
590 static void check_health_status(const char *env_value)
594 if (env_value == NULL) {
595 battery.health = HEALTH_GOOD;
599 snprintf(battery.health_s, sizeof(battery.health_s), "%s", env_value);
601 len = strlen(env_value);
602 if (strncmp(env_value, OVERHEAT_NAME, len) == 0)
603 battery.health = HEALTH_HIGH;
604 else if (strncmp(env_value, TEMPCOLD_NAME, len) == 0)
605 battery.health = HEALTH_LOW;
606 else if (strncmp(env_value, OVERVOLT_NAME, len) == 0)
607 battery.health = HEALTH_OVP;
608 else if (strncmp(env_value, GOOD_NAME, len) == 0)
609 battery.health = HEALTH_GOOD;
611 battery.health = HEALTH_NO_OPT;
614 static void check_power_source(const char *env_value)
616 int maxlen = sizeof(battery.power_source_s);
621 snprintf(battery.power_source_s, maxlen, "%s", env_value);
622 battery.power_source_s[maxlen - 1] = '\0';
624 if (strncmp(battery.power_source_s, "ac", sizeof("ac")) == 0) {
625 battery.online_type = CHARGER_TYPE_AC;
626 } else if (strncmp(battery.power_source_s, "usb", sizeof("usb")) == 0) {
627 battery.online_type = CHARGER_TYPE_USB;
628 } else if (strncmp(battery.power_source_s, "wireless", sizeof("wireless")) == 0) {
629 battery.online_type = CHARGER_TYPE_WIRELESS;
631 battery.online_type = CHARGER_TYPE_NONE;
635 static void check_misc_status(const char *env_value)
637 if (env_value == NULL) {
638 battery.misc = MISC_NONE;
641 battery.misc = atoi(env_value);
644 static void notify_charger_event(int notifier)
646 struct battery_config_charger_event_handler **event_handlers =
647 g_battery_info.event_handlers;
648 int event_handler_number = g_battery_info.event_handler_number;
650 if (!event_handlers || event_handler_number <= 0) {
651 _D("There is no charger event handler");
655 for (int i = 0; i < event_handler_number; ++i) {
656 if (!event_handlers[i])
659 if (event_handlers[i]->notifier == notifier) {
660 _D("Battery charger event=%s(%d)",
661 event_handlers[i]->name,
662 event_handlers[i]->id);
664 if (event_handlers[i]->wakelock_duration)
665 event_acquire_wakelock(event_handlers[i]->id,
666 event_handlers[i]->wakelock_duration);
668 if (event_handlers[i]->broadcast)
669 event_broadcast_id(event_handlers[i]->id);
674 static void process_power_supply(void *data)
676 bool broadcasted = true;
680 ret_lock = display_lock_request_lock_with_option(DEVICED_EVENT_BATTERY, LCD_OFF, STAY_CUR_STATE, 0);
682 if (old_battery.charge_now != battery.charge_now || battery.charge_now == CHARGER_ABNORMAL) {
683 ret_val = vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, battery.charge_now);
685 _E("Failed to set vconf value for battery charge now: %d", vconf_get_ext_errno());
687 if (power_supply_broadcast(CHARGE_NOW_SIGNAL, battery.charge_now) < 0)
691 if (!strcmp(old_battery.status_s, CHARGEFULL_NAME) &&
692 !strcmp(battery.status_s, CHARGENOW_NAME)) {
693 battery_pm_change_internal(DEVICED_EVENT_BATTERY, LCD_NORMAL);
696 if (old_battery.charge_full != battery.charge_full)
697 if (power_supply_broadcast(CHARGE_FULL_SIGNAL, battery.charge_full) < 0)
700 if (strncmp(old_battery.health_s, battery.health_s, strlen(battery.health_s))) {
701 snprintf(old_battery.health_s, sizeof(old_battery.health_s), "%s", battery.health_s);
702 if (power_supply_broadcast_str(CHARGE_HEALTH_SIGNAL, battery.health_s) < 0)
706 if (old_battery.capacity != battery.capacity) {
707 ret_val = vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY, battery.capacity);
709 _E("Failed to set vconf value for battery capacity: %d", vconf_get_ext_errno());
711 if (power_supply_broadcast(CHARGE_CAPACITY_SIGNAL, battery.capacity) < 0)
715 (void)lowbat_execute(data);
717 if (old_battery.charger_connected != battery.charger_connected) {
718 check_power_supply(battery.charger_connected);
719 ret_val = vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, battery.charger_connected);
721 _E("Failed to set vconf value for charger status: %d", vconf_get_ext_errno());
722 if (battery.charger_connected == 0) {
723 CRITICAL_LOG("Battery charger disconnected");
724 event_system_send(SYS_EVENT_BATTERY_CHARGER_STATUS, EVT_KEY_BATTERY_CHARGER_STATUS, EVT_VAL_BATTERY_CHARGER_CONNECTED);
725 syscommon_notifier_emit_notify(DEVICE_NOTIFIER_BATTERY_CHARGER_DISCONNECTED, NULL);
726 notify_charger_event(DEVICE_NOTIFIER_BATTERY_CHARGER_DISCONNECTED);
727 } else if (battery.charger_connected == 1) {
728 CRITICAL_LOG("Battery charger connected");
729 event_system_send(SYS_EVENT_BATTERY_CHARGER_STATUS, EVT_KEY_BATTERY_CHARGER_STATUS, EVT_VAL_BATTERY_CHARGER_DISCONNECTED);
730 syscommon_notifier_emit_notify(DEVICE_NOTIFIER_BATTERY_CHARGER_CONNECTED, NULL);
731 notify_charger_event(DEVICE_NOTIFIER_BATTERY_CHARGER_CONNECTED);
733 _E("Invalid charger connected");
737 if (old_battery.charging_status != battery.charging_status)
738 charger_state_send_system_event(battery.charging_status);
740 if (old_battery.online_type != battery.online_type) {
741 ret_val = vconf_set_int(VCONFKEY_SYSMAN_CHARGER_TYPE, battery.online_type);
743 _E("Failed to set vconf value for charger type: %d", vconf_get_ext_errno());
745 if (power_supply_broadcast(CHARGER_TYPE_SIGNAL, battery.online_type) < 0)
749 if (old_battery.misc != battery.misc)
750 if (power_supply_broadcast(CHARGE_MISC_EVENT_SIGNAL, battery.misc) < 0)
753 if (old_battery.charge_full != battery.charge_full)
756 if (old_battery.charge_now != battery.charge_now ||
757 old_battery.charge_full != battery.charge_full ||
758 old_battery.capacity != battery.capacity ||
759 old_battery.health != battery.health ||
760 old_battery.misc != battery.misc ||
761 old_battery.online_type != battery.online_type)
762 _I("Signal(%d) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d : %s)",
764 CHARGER_STATUS_SIGNAL, battery.charger_connected,
765 CHARGER_TYPE_SIGNAL, battery.online_type,
766 CHARGE_NOW_SIGNAL, battery.charge_now,
767 CHARGE_FULL_SIGNAL, battery.charge_full,
768 CHARGE_CAPACITY_SIGNAL, battery.capacity,
769 CHARGE_LEVEL_SIGNAL, battery.capacity_level,
770 CHARGE_MISC_EVENT_SIGNAL, battery.misc,
771 CHARGE_HEALTH_SIGNAL, battery.health, battery.health_s);
773 old_battery.capacity = battery.capacity;
774 old_battery.capacity_level = battery.capacity_level;
775 old_battery.charger_connected = battery.charger_connected;
776 old_battery.online_type = battery.online_type;
777 old_battery.charging_status = battery.charging_status;
778 old_battery.charge_full = battery.charge_full;
780 old_battery.misc = battery.misc;
781 snprintf(old_battery.status_s, sizeof(old_battery.status_s), "%s", battery.status_s);
783 check_abnormal_status();
785 syscommon_notifier_emit_notify(DEVICE_NOTIFIER_POWER_SUPPLY, NULL);
786 if (old_battery.charge_now != battery.charge_now) {
787 syscommon_notifier_emit_notify(DEVICE_NOTIFIER_BATTERY_CHARGING, &battery.charge_now);
788 old_battery.charge_now = battery.charge_now;
792 display_lock_request_unlock_with_option(DEVICED_EVENT_BATTERY, LCD_OFF, PM_SLEEP_MARGIN);
796 static int battery_state(struct battery_info *info)
798 static struct battery_status prev_status;
801 memcpy(&prev_status, &battery, sizeof(battery));
805 if (battery.capacity != 0 && prev_status.capacity == battery.capacity &&
806 prev_status.charging_status == battery.charging_status &&
807 prev_status.online_type == battery.online_type &&
808 prev_status.charge_full == battery.charge_full &&
809 prev_status.charge_now == battery.charge_now &&
810 prev_status.health == battery.health &&
811 prev_status.present == battery.present &&
812 prev_status.current_now == battery.current_now &&
813 prev_status.current_average == battery.current_average &&
814 prev_status.charger_connected == battery.charger_connected)
817 prev_status.capacity = battery.capacity;
818 prev_status.charging_status = battery.charging_status;
819 prev_status.charge_full = battery.charge_full;
820 prev_status.charge_now = battery.charge_now;
821 prev_status.health = battery.health;
822 prev_status.present = battery.present;
823 prev_status.charger_connected = battery.charger_connected;
825 _I("%s(%s) %s(%d) Capa(%d) Hth(%s,%d) Pres(%d) Curr(%d,%d)",
827 battery.charge_now == CHARGER_CHARGING ? "Charging"
828 : (battery.charge_now == CHARGER_DISCHARGING ? "Discharging" : "Abnormal"),
836 info->current_average);
840 static void battery_disable_module(int value)
843 static const struct invalidate_list {
844 const char *vconfkey;
847 { VCONFKEY_SYSMAN_BATTERY_CAPACITY, &old_battery.capacity },
848 { VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &old_battery.capacity_level },
849 { VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, &old_battery.charge_now },
850 { VCONFKEY_SYSMAN_BATTERY_LEVEL_STATUS, NULL },
853 _D("Invalidate battery value to %d", value);
855 for (int i = 0; i < ARRAY_SIZE(list); ++i) {
856 if (list[i].vconfkey) {
857 retval = vconf_set_int(list[i].vconfkey, value);
859 _D("Set vconf %s to %d", list[i].vconfkey, value);
861 _E("Failed to set %s to %d, %d", list[i].vconfkey, value, retval);
864 *(list[i].member) = value;
867 power_supply_exit(NULL);
870 static void battery_changed(struct battery_info *info, void *data)
875 (void)battery_state(NULL);
880 snprintf(battery.status_s, sizeof(battery.status_s),
882 check_charging_status(info->status);
884 battery.status_s[0] = '\0';
887 snprintf(battery.health_s, sizeof(battery.health_s),
889 check_health_status(info->health);
891 battery.health_s[0] = '\0';
893 if (info->power_source)
894 check_power_source(info->power_source);
896 battery.power_source_s[0] = '\0';
898 battery.charger_connected = info->online;
899 battery.present = info->present;
900 battery.capacity = info->capacity;
901 battery.current_now = info->current_now;
902 battery.current_average = info->current_average;
903 battery.temperature = info->temperature;
904 battery.voltage_now = info->voltage_now;
905 battery.voltage_average = info->voltage_average;
907 battery_initialized = true;
909 ret_val = battery_state(info);
913 ret_val = delayed_init_done(NULL);
915 /* If the same notification is requested repeatedly, it is ignored by power_supply_noti().
916 * A notification will be triggered only when charging_status changes between
917 * CHARGING_STATUS_CHARGING/FULL <-> CHARGING_STATUS_DISCHARGING. */
918 if (battery.charging_status == CHARGING_STATUS_CHARGING || battery.charging_status == CHARGING_STATUS_FULL)
919 power_supply_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_ON);
920 else if (battery.charging_status == CHARGING_STATUS_DISCHARGING)
921 power_supply_noti(DEVICE_NOTI_BATT_CHARGE, DEVICE_NOTI_OFF);
925 battery.health = HEALTH_GOOD;
926 battery.present = PRESENT_NORMAL;
929 if (battery.present) {
930 process_power_supply(&battery.capacity);
932 CRITICAL_LOG_E("Battery disconnected. Disable the battery module.");
933 battery_disable_module(-ENODEV);
937 static gboolean power_supply_update_during_booting(void *data)
941 retval = hal_device_battery_get_current_state(battery_changed, NULL);
942 if (retval == -ENODEV) {
943 CRITICAL_LOG_E("There is no battery detected. Disable the battery module.");
944 battery_disable_module(retval);
945 return G_SOURCE_REMOVE;
948 return G_SOURCE_CONTINUE;
951 static void power_supply_timer_start(void)
953 _D("Battery init timer during booting.");
954 power_timer = g_timeout_add(BATTERY_CHECK_TIMER_INTERVAL,
955 power_supply_update_during_booting, NULL);
956 if (power_timer == 0)
957 _E("Failed to add battery init timer during booting.");
959 _I("Started battery init timer during booting.");
962 static GVariant *dbus_get_charger_status(GDBusConnection *conn,
963 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
964 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
968 ret_val = vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, &status);
970 _E("Failed to get vconf value for charger status: %d", vconf_get_ext_errno());
973 return g_variant_new("(i)", status);
976 static GVariant *dbus_get_charger_type(GDBusConnection *conn,
977 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
978 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
980 int type = battery.online_type;
982 return g_variant_new("(i)", type);
985 static GVariant *dbus_get_charge_now(GDBusConnection *conn,
986 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
987 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
991 ret = battery.charge_now;
993 return g_variant_new("(i)", ret);
996 static GVariant *dbus_get_charge_level(GDBusConnection *conn,
997 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
998 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1002 ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &val);
1004 _E("Failed to get vconf value for battery status low: %d", vconf_get_ext_errno());
1008 return g_variant_new("(i)", val);
1011 static GVariant *dbus_get_percent(GDBusConnection *conn,
1012 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1013 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1017 ret = battery.capacity;
1019 return g_variant_new("(i)", ret);
1022 static GVariant *dbus_get_percent_raw(GDBusConnection *conn,
1023 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1024 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1030 return g_variant_new("(i)", ret);
1033 static GVariant *dbus_is_full(GDBusConnection *conn,
1034 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1035 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1039 ret = battery.charge_full;
1041 return g_variant_new("(i)", ret);
1044 static GVariant *dbus_get_health(GDBusConnection *conn,
1045 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1046 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1050 str = battery.health_s;
1052 return g_variant_new("(s)", str);
1055 static GVariant *dbus_get_misc(GDBusConnection *conn,
1056 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1057 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1063 return g_variant_new("(i)", ret);
1067 static GVariant *dbus_get_power_supply_handler(GDBusConnection *conn,
1068 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1069 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1071 /* This method is for getting battery state after battery modification
1072 * by battery test driver. At this point, restore uevent buffering, which
1073 * had been disabled by test driver. */
1074 lowbat_enable_uevent_buffering();
1076 return g_variant_new("(iiiiiiisiiiii)", 0,
1078 battery.charging_status,
1080 battery.charger_connected,
1083 battery.power_source_s,
1084 battery.voltage_now,
1085 battery.voltage_average,
1086 battery.current_now,
1087 battery.current_average,
1088 battery.temperature);
1091 static GVariant *dbus_power_supply_handler(GDBusConnection *conn,
1092 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1093 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1096 int ret = 0, argc = 0;
1097 int charger_connected;
1100 struct battery_info info = {0, };
1102 g_variant_get(param, "(sisssisssssssss)", &type_str,
1119 _E("Message is invalid.");
1124 pid = gdbus_connection_get_sender_pid(conn, sender);
1125 if (pid == -1 || kill(pid, 0) == -1) {
1126 _E("Process(%d) does not exist, dbus ignored.", pid);
1131 /* The battery change triggered by this dbus must be processed
1132 * within a single subroutine as the objective of this method call is mostly
1133 * for the testing. Therefore, do not buffering the mocked uevent so that make
1134 * the test driver can get the changed battery result without waiting */
1135 lowbat_disable_uevent_buffering();
1137 info.capacity = atoi(argv[0]);
1138 info.status = strdup(argv[1]);
1139 info.health = strdup(argv[2]);
1140 info.online = charger_connected;
1141 info.present = atoi(argv[4]);
1142 check_misc_status(argv[5]);
1143 info.power_source = strdup(argv[7]);
1144 info.voltage_now = atoi(argv[8]);
1145 info.voltage_average = atoi(argv[9]);
1146 info.current_now = atoi(argv[10]);
1147 info.current_average = atoi(argv[11]);
1148 info.temperature = atoi(argv[12]);
1149 _D("C(%d) S(%s) H(%s) O(%d) P(%d) SRC(%s) Vol(%d %d) Cur(%d %d) T(%d)",
1150 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);
1152 battery_changed(&info, NULL);
1171 free(info.power_source);
1173 return g_variant_new("(i)", ret);
1176 static void battery_get_info(struct battery_info *info, void *data)
1178 struct battery_info *bat = data;
1183 bat->status = strdup(info->status);
1184 bat->health = strdup(info->health);
1185 bat->power_source = strdup(info->power_source);
1186 bat->online = info->online;
1187 bat->present = info->present;
1188 bat->capacity = info->capacity;
1189 bat->current_now = info->current_now;
1190 bat->current_average = info->current_average;
1191 bat->temperature = info->temperature;
1192 bat->voltage_now = info->voltage_now;
1193 bat->voltage_average = info->voltage_average;
1196 static GVariant *dbus_get_battery_info(GDBusConnection *conn,
1197 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1198 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1202 struct battery_info info = {0, };
1204 if (old_state == DEVICE_NOTIFIER_STATE_STOP)
1207 if (battery_initialized)
1210 ret = hal_device_battery_get_current_state(battery_get_info, &info);
1211 if (ret != -ENODEV) {
1213 _E("Failed to get battery info: %d", ret);
1215 battery_changed(&info, NULL);
1218 free(info.power_source);
1220 if (vconf_get_int(VCONFKEY_SYSMAN_USB_STATUS, &val) == 0 &&
1221 val != VCONFKEY_SYSMAN_USB_DISCONNECTED)
1222 str = POWER_SOURCE_USB;
1223 else if (vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, &val) == 0 &&
1224 val == VCONFKEY_SYSMAN_CHARGER_CONNECTED)
1225 str = POWER_SOURCE_AC;
1227 str = POWER_SOURCE_NONE;
1228 snprintf(battery.power_source_s, sizeof(battery.power_source_s), "%s", str);
1230 battery.current_now = -1; /* Not supported */
1231 battery.current_average = -1; /* Not supported */
1236 return g_variant_new("(isssiiiiiiii)", ret,
1239 battery.power_source_s,
1240 battery.charger_connected,
1243 battery.current_now,
1244 battery.current_average,
1245 battery.voltage_now,
1246 battery.voltage_average,
1247 battery.temperature);
1250 static void update_battery_props(void)
1252 if (config_parse(POWER_SUPPLY_UEVENT, load_uevent, &battery) < 0)
1253 _E("Failed to check power supply uevent.");
1256 static GVariant *dbus_get_battery_props(GDBusConnection *conn,
1257 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1258 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1260 update_battery_props();
1262 return g_variant_new("(iiiiii)",
1264 battery.temperature,
1265 battery.voltage_now,
1266 battery.voltage_average,
1267 battery.current_now,
1268 battery.current_average);
1271 static const dbus_method_s dbus_methods[] = {
1272 { CHARGER_STATUS_SIGNAL, NULL, "i", dbus_get_charger_status },
1273 { CHARGE_NOW_SIGNAL, NULL, "i", dbus_get_charge_now },
1274 { CHARGE_LEVEL_SIGNAL, NULL, "i", dbus_get_charge_level },
1275 { CHARGE_CAPACITY_SIGNAL, NULL, "i", dbus_get_percent },
1276 { CHARGE_CAPACITY_LAW_SIGNAL, NULL, "i", dbus_get_percent_raw },
1277 { CHARGE_FULL_SIGNAL, NULL, "i", dbus_is_full },
1278 { CHARGE_HEALTH_SIGNAL, NULL, "s", dbus_get_health },
1279 { POWER_SUBSYSTEM, "sisssisssssssss", "i", dbus_power_supply_handler },
1280 { GET_POWER_SUBSYSTEM, NULL, "iiiiiiisiiiii", dbus_get_power_supply_handler },
1281 { "GetBatteryInfo", NULL, "isssiiiiiiii", dbus_get_battery_info },
1282 { CHARGER_TYPE_SIGNAL, NULL, "i", dbus_get_charger_type },
1283 { CHARGE_BATTERY_PROPERTIES, NULL, "iiiiii", dbus_get_battery_props },
1284 { CHARGE_MISC_EVENT_SIGNAL, NULL, "i", dbus_get_misc },
1287 static const dbus_interface_u dbus_interface = {
1289 .name = DEVICED_INTERFACE_BATTERY,
1290 .methods = dbus_methods,
1291 .nr_methods = ARRAY_SIZE(dbus_methods),
1294 static int delayed_init_done(void *data)
1298 device_notifier_state_e state = DEVICE_NOTIFIER_STATE_START;
1302 done = *(int *)data;
1307 g_source_remove(power_timer);
1311 /* check battery has been initialized */
1312 retval = hal_device_battery_get_current_state(battery_changed, NULL);
1313 if (retval == -ENODEV) {
1314 CRITICAL_LOG_E("Failed to initialize battery state, %d. Disable the battery module.", retval);
1315 battery_disable_module(retval);
1319 event_handler_state_changed((void *)&state);
1321 _I("booting done %s(%d) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d) %s(%d : %s)",
1322 CHARGER_STATUS_SIGNAL, battery.charger_connected,
1323 CHARGE_NOW_SIGNAL, battery.charge_now,
1324 CHARGE_FULL_SIGNAL, battery.charge_full,
1325 CHARGE_CAPACITY_SIGNAL, battery.capacity,
1326 CHARGE_LEVEL_SIGNAL, battery.capacity_level,
1327 CHARGE_MISC_EVENT_SIGNAL, battery.misc,
1328 CHARGE_HEALTH_SIGNAL, battery.health, battery.health_s);
1330 syscommon_notifier_unsubscribe_notify(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_done);
1336 * FIXME: Getting display state shoule be done by display module function.
1337 * After refactoring display module, it should be changed to use getter in display module.
1339 static int handle_display_state_changed(void *data)
1342 _E("Invalid parameter");
1346 g_display_state = *(int *)data;
1348 if (battery_plgn->launch_health_popup_by_display_state)
1349 battery_plgn->launch_health_popup_by_display_state(g_display_state);
1354 bool battery_do_not_disturb(void)
1356 int block = 0, theater = 0, night = 0;
1359 if (g_display_state == DEVICED_DISPLAY_STATE_OFF) {
1360 r = vconf_get_bool(VCONFKEY_SETAPPL_BLOCKMODE_WEARABLE_BOOL, &block);
1362 _E("Failed to set vconf value for blockmode wearable: %d", vconf_get_ext_errno());
1363 r = vconf_get_bool(VCONFKEY_SETAPPL_THEATER_MODE_ENABLE, &theater);
1365 _E("Failed to set vconf value for theator mode enable: %d", vconf_get_ext_errno());
1366 r = vconf_get_bool(VCONFKEY_SETAPPL_GOODNIGHT_MODE_ENABLE, &night);
1368 _E("Failed to set vconf value for goodnight mode enable: %d", vconf_get_ext_errno());
1371 if (block != 0 || theater != 0 || night != 0) {
1372 _I("Skip lcd and popup(block %d theater %d night %d).", block, theater, night);
1379 int battery_pm_change_internal(int pid, int s_bits)
1381 if (battery_do_not_disturb())
1384 display_state_transition_request_state_transition_with_option(pid, s_bits);
1389 static int load_uevent(struct parse_result *result, void *user_data)
1391 struct battery_status *info = user_data;
1396 if (MATCH(result->name, CHARGE_STATUS)) {
1397 if (strstr(result->value, "Charging")) {
1398 info->charge_now = CHARGER_CHARGING;
1399 info->charge_full = CHARGING_NOT_FULL;
1400 } else if (strstr(result->value, "Discharging")) {
1401 info->charge_now = CHARGER_DISCHARGING;
1402 info->charge_full = CHARGING_NOT_FULL;
1403 } else if (strstr(result->value, "Full")) {
1404 info->charge_now = CHARGER_DISCHARGING;
1405 info->charge_full = CHARGING_FULL;
1406 } else if (strstr(result->value, "Not charging")) {
1407 info->charge_now = CHARGER_ABNORMAL;
1408 info->charge_full = CHARGING_NOT_FULL;
1410 snprintf(info->status_s, sizeof(info->status_s), "%s", result->value);
1411 } else if (MATCH(result->name, CAPACITY)) {
1412 info->capacity = atoi(result->value);
1413 } else if (MATCH(result->name, TEMPERATURE)) {
1414 info->temperature = atoi(result->value) / 10;
1415 } else if (MATCH(result->name, VOLTAGE_NOW)) {
1416 info->voltage_now = atoi(result->value);
1417 } else if (MATCH(result->name, VOLTAGE_AVG)) {
1418 info->voltage_average = atoi(result->value);
1419 } else if (MATCH(result->name, CURRENT_NOW)) {
1420 info->current_now = atoi(result->value);
1421 } else if (MATCH(result->name, CURRENT_AVG)) {
1422 info->current_average = atoi(result->value);
1423 } else if (MATCH(result->name, CHARGE_HEALTH)) {
1424 snprintf(info->health_s, sizeof(info->health_s), "%s", result->value);
1430 static int power_supply_probe(void *data)
1435 ret_val = hal_device_battery_get_backend();
1437 _E("There is no HAL for battery.");
1438 if (access(POWER_PATH, R_OK) == 0)
1439 return 0; /* Just power_supply uevent is used */
1444 _I("Battery device structure load success.");
1449 * Set battery vconf as -ENOTSUP
1450 * These vconf key used by runtime-info and capi-system-device.
1452 r = vconf_set_int(VCONFKEY_SYSMAN_CHARGER_STATUS, -ENOTSUP);
1454 _E("Failed to set vconf value for charger status: %d", vconf_get_ext_errno());
1455 r = vconf_set_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, -ENOTSUP);
1457 _E("Failed to set vconf value for battery charge now: %d", vconf_get_ext_errno());
1458 r = vconf_set_int(VCONFKEY_SYSMAN_BATTERY_LEVEL_STATUS, -ENOTSUP);
1460 _E("Failed to set vconf value for battery level status: %d", vconf_get_ext_errno());
1461 _I("There is no battery device: %d", ret_val);
1465 static void add_power_supply_handler(void)
1467 hal_device_battery_register_changed_event(battery_changed, NULL);
1468 hal_device_battery_get_current_state(battery_changed, NULL);
1471 static void remove_power_supply_handler(void)
1473 hal_device_battery_unregister_changed_event(battery_changed);
1476 static int event_handler_state_changed(void *data)
1478 device_notifier_state_e state = *(device_notifier_state_e *)data;
1480 if (old_state == state)
1485 if (state == DEVICE_NOTIFIER_STATE_START)
1486 add_power_supply_handler();
1487 else if (state == DEVICE_NOTIFIER_STATE_STOP)
1488 remove_power_supply_handler();
1493 static void power_supply_init(void *data)
1497 memset(&battery, 0, sizeof(struct battery_status));
1498 memset(&old_battery, 0, sizeof(struct battery_status));
1499 battery.misc = MISC_NONE;
1500 battery.charger_connected = -1;
1502 /* It will be true on initializing battery structure */
1503 battery_initialized = false;
1505 /* process check battery timer until booting done */
1506 power_supply_timer_start();
1508 syscommon_notifier_subscribe_notify(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_done);
1509 syscommon_notifier_subscribe_notify(DEVICE_NOTIFIER_EVENT_HANDLER, event_handler_state_changed);
1510 syscommon_notifier_subscribe_notify(DEVICE_NOTIFIER_LCD, handle_display_state_changed);
1512 ret = gdbus_add_object(NULL, DEVICED_PATH_BATTERY, &dbus_interface);
1514 _E("Failed to init dbus method: %d", ret);
1516 battery_ops_init((void *)battery_plgn);
1518 battery_parser_load_config(&g_battery_info);
1521 static void power_supply_exit(void *data)
1523 device_notifier_state_e state = DEVICE_NOTIFIER_STATE_STOP;
1525 syscommon_notifier_unsubscribe_notify(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_done);
1526 syscommon_notifier_unsubscribe_notify(DEVICE_NOTIFIER_EVENT_HANDLER, event_handler_state_changed);
1528 event_handler_state_changed((void *)&state);
1530 battery_ops_exit(NULL);
1532 battery_parser_unload_config(&g_battery_info);
1535 static const struct device_ops power_supply_ops = {
1536 DECLARE_NAME_LEN("power_supply"),
1537 .probe = power_supply_probe,
1538 .init = power_supply_init,
1539 .exit = power_supply_exit,
1542 DEVICE_OPS_REGISTER(&power_supply_ops)
1544 static void __CONSTRUCTOR__ initialize(void)
1546 battery_plgn = get_var_battery_plugin();
1548 _E("Failed to get battery plugin variable.");