ADD_SUBDIRECTORY(plugins/tv/display)
ADD_SUBDIRECTORY(plugins/iot/display)
ADD_SUBDIRECTORY(plugins/mobile/battery)
+ADD_SUBDIRECTORY(plugins/wearable/battery)
INSTALL_CONF(conf mobile-display)
INSTALL_CONF(conf wearable-display)
INSTALL_CONF(conf tv-display)
mv %{_sysconfdir}/deviced/wearable-display.conf %{_sysconfdir}/deviced/display.conf
mkdir -p %{_libdir}/deviced
mv %{_libdir}/wearable-display.so %{_libdir}/deviced/display.so
+mv %{_libdir}/wearable-battery.so %{_libdir}/deviced/battery.so
%post plugin-profile-tv
mv %{_sysconfdir}/deviced/tv-display.conf %{_sysconfdir}/deviced/display.conf
%defattr(-,root,root,-)
%config %{_sysconfdir}/deviced/wearable-display.conf
%{_libdir}/wearable-display.so
+%{_libdir}/wearable-battery.so
%{_unitdir}/rndis.service
%{_bindir}/rndis.sh
#include "power-supply.h"
#include "lowbat-handler.h"
#include "battery-ops.h"
+#include "display/core.h"
#include "display/display-ops.h"
#include "display/poll.h"
#include "shared/eventsystem.h"
+#include "core/device-notifier.h"
+
#define METHOD_LOW_NOTI_ON "BatteryLowNotiOn"
#define METHOD_LOW_NOTI_UPDATE "BatteryLowNotiUpdate"
NOTI_UPDATE = 0,
};
+static guint abnormal_timer;
+
static int noti_low = NOTI_NONE;
static int noti_crit = NOTI_NONE;
_E("Failed to launch remove battery popup(%d)", ret);
}
+static int check_power_supply_noti(void)
+{
+ return 1;
+}
+
+static void update_ovp(enum battery_noti_status status)
+{
+ _I("charge %d ovp %d(old %d)", battery.charge_now, battery.health, old_battery.health);
+
+ old_battery.health = battery.health;
+ if (status == DEVICE_NOTI_ON)
+ battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_DIM);
+ else
+ battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
+ device_notify(DEVICE_NOTIFIER_BATTERY_OVP, (void *)&battery.health);
+}
+
+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;
+
+ CRITICAL_LOG("Popup: Battery health status is not good, %s.", battery.health_s);
+ 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 int display_changed(void *data)
+{
+ static enum state_t state;
+
+ if (!data)
+ return state;
+
+ state = *(int *)data;
+
+ return state;
+}
+
static void battery_notification_init(void *data)
{
struct battery_plugin *plugin = (struct battery_plugin *)data;
+ int ret;
if (!plugin)
return;
plugin->changed_battery_cf = changed_battery_cf;
plugin->remove_health_popup = remove_health_popup;
+ plugin->check_power_supply_noti = check_power_supply_noti;
+ plugin->update_ovp = update_ovp;
+
+ plugin->display_changed = display_changed;
+
+ 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);
+
+ register_notifier(DEVICE_NOTIFIER_LCD, display_changed);
}
static const struct battery_ops battery_notification_ops = {
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(wearable-battery C)
+
+FILE(GLOB ALL_SRCS "*.c")
+SET(SRCS ${ALL_SRCS})
+ADD_SOURCE(${CMAKE_SOURCE_DIR}/src/battery COMMON_SRCS)
+SET(SRCS ${SRCS} ${COMMON_SRCS})
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/core ${CMAKE_SOURCE_DIR}/src/battery)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(libpkgs REQUIRED
+ dlog
+ glib-2.0
+ gio-2.0
+ gio-unix-2.0
+ libinput)
+
+FOREACH(flag ${libpkgs_CFLAGS})
+ SET(EXTRA_LIB_CFLAGS "${EXTRA_LIB_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_LIB_CFLAGS}")
+
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${libpkgs_LDFLAGS} shared)
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES PREFIX "")
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES OUTPUT_NAME wearable-battery)
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries)
--- /dev/null
+/*
+ * deviced
+ *
+ * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <time.h>
+#include <glib.h>
+
+#include "display/core.h"
+#include "core/log.h"
+#include "core/device-notifier.h"
+#include "power-supply.h"
+#include "battery-ops.h"
+#include "battery.h"
+#include "dd-display.h"
+
+static int display_changed(void *data)
+{
+ static enum state_t old;
+ static enum state_t state;
+
+ if (!data)
+ return state;
+
+ old = state;
+ state = *(int *)data;
+
+ if (battery.health != HEALTH_LOW && battery.health != HEALTH_HIGH)
+ return state;
+
+ /* relaunch health popup on LCDON */
+ if ((old == S_SLEEP || old == S_LCDOFF)
+ && (state == S_LCDDIM || state == S_NORMAL))
+ relaunch_health_popup();
+
+ return state;
+}
+
+static 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 void update_ovp(enum battery_noti_status status)
+{
+ static int old = DEVICE_NOTI_OFF;
+
+ if (old == status)
+ return;
+
+ old = status;
+ _I("Charge(%d) ovp(%d, old: %d) with lcd(%s)", battery.charge_now, battery.health,
+ old_battery.health, (status == DEVICE_NOTI_ON) ? "dim" : "normal");
+
+ old_battery.health = battery.health;
+ device_notify(DEVICE_NOTIFIER_BATTERY_OVP, (void *)&battery.health);
+ battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
+}
+
+static void battery_notification_init(void *data)
+{
+ struct battery_plugin *plugin = (struct battery_plugin *)data;
+
+ if (!plugin)
+ return;
+
+ _D("Add plugins for battery notification.");
+ plugin->check_power_supply_noti = check_power_supply_noti;
+ plugin->update_ovp = update_ovp;
+
+ plugin->display_changed = display_changed;
+
+ register_notifier(DEVICE_NOTIFIER_LCD, display_changed);
+}
+
+static const struct battery_ops battery_notification_ops = {
+ .name = "battery_notification",
+ .init = battery_notification_init,
+};
+
+BATTERY_OPS_REGISTER(&battery_notification_ops)
#include <errno.h>
#include "core/common.h"
+#include "power-supply.h"
+#include <libsyscommon/dbus-system.h>
struct battery_ops {
char *name;
int (*changed_battery_cf) (int status);
void (*remove_health_popup) (void);
+
+ int (*display_changed) (void *);
+ int (*check_power_supply_noti) (void);
+ void (*update_ovp) (enum battery_noti_status status);
/* Add plugins here */
};
extern struct battery_plugin battery_plgn;
#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"
static int noti_id;
static int online_status;
static int abnormal_health_popup_timer;
+static bool launching_health_popup;
static guint power_timer;
static device_notifier_state_e old_state = -1;
bool battery_do_not_disturb(void);
-static int battery_pm_change_internal(int pid, int s_bits);
-static int display_changed(void *data);
+int battery_pm_change_internal(int pid, int s_bits);
static int booting_done(void *data);
static void update_health(enum battery_noti_status status);
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:
}
}
_E("Failed to call dbus method: %d", ret);
- break;
+ break;
case CHARGING_NOT_FULL:
if (noti_id <= 0)
return -EPERM;
}
}
_E("Failed to call dbus method: %d", ret);
- break;
+ break;
}
return ret;
}
static void noti_batt_full(void)
{
static int bat_full_noti;
- int noti;
if (!battery.charge_full && bat_full_noti == 1) {
power_supply_noti(DEVICE_NOTI_BATT_FULL, DEVICE_NOTI_OFF);
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 launch_health_popup(void)
{
+ 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);
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
}
}
-static void update_ovp(enum battery_noti_status status)
+void relaunch_health_popup(void)
{
- static int old = DEVICE_NOTI_OFF;
-
- if (old == status)
+ if (launching_health_popup)
return;
- old = status;
- _I("Charge(%d) ovp(%d, old: %d) with lcd(%s)", battery.charge_now, battery.health,
- old_battery.health, (status == DEVICE_NOTI_ON) ? "dim" : "normal");
+ launching_health_popup = true;
- old_battery.health = battery.health;
- device_notify(DEVICE_NOTIFIER_BATTERY_OVP, (void *)&battery.health);
- battery_pm_change_internal(INTERNAL_LOCK_POPUP, LCD_NORMAL);
+ if (abnormal_health_popup_timer)
+ g_source_remove(abnormal_health_popup_timer);
+
+ if (disp_plgn.pm_unlock_internal)
+ disp_plgn.pm_unlock_internal(INTERNAL_LOCK_POPUP, LCD_OFF, PM_SLEEP_MARGIN);
+ if (disp_plgn.pm_lock_internal)
+ disp_plgn.pm_lock_internal(INTERNAL_LOCK_POPUP, LCD_DIM, STAY_CUR_STATE, LCD_DIM_TIME_IN_BATTERY_HEALTH);
+ if (battery.health == HEALTH_LOW)
+ battery_charge_err_low_act(NULL);
+ else if (battery.health == HEALTH_HIGH)
+ battery_charge_err_high_act(NULL);
+
+ abnormal_health_popup_timer = g_timeout_add_seconds(ABNORMAL_CHECK_TIMER_INTERVAL, health_popup_cb, NULL);
+
+ launching_health_popup = false;
}
static void check_abnormal_status(void)
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);
+ 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);
+ }
}
static bool update_online(void)
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;
return 0;
}
-static int display_changed(void *data)
-{
- static enum state_t state;
-
- if (!data)
- return state;
-
- state = *(int *)data;
-
- return state;
-}
-
static int load_uevent(struct parse_result *result, void *user_data)
{
struct battery_status *info = user_data;
power_supply_timer_start();
register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
- register_notifier(DEVICE_NOTIFIER_LCD, display_changed);
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);
- if (ret <= 0)
- _E("Failed to init dbus signal: %d", ret);
-
battery_ops_init((void *)&battery_plgn);
}
#define __POWER_SUPPLY_H__
#define CHARGER_TYPE_SIGNAL "ChargerType"
+#define SIGNAL_CHARGEERR_RESPONSE "ChargeErrResponse"
+
+#define ABNORMAL_CHECK_TIMER_INTERVAL 60
enum device_change_type {
DEVICE_CHANGE_ABNORMAL,
extern struct battery_status old_battery;
int power_supply_broadcast(char *sig, int status);
+int battery_pm_change_internal(int pid, int s_bits);
+void relaunch_health_popup(void);
#define CHARGER_STATUS_SIGNAL "ChargerStatus"
#define CHARGE_NOW_SIGNAL "ChargeNow"