/* * Copyright (c) 2022 by UNISOC Technology(Shanghai), Inc. ALL RIGHTS RESERVED. * * These coded instructions, statements, and computer programs are the * copyrighted works and confidential proprietary information of * UNISOC Technology(Shanghai), Inc. They may not be modified, copied, reproduced, * distributed, or disclosed to third parties in any manner, medium, or form, * in whole or in part, without the prior written consent of UNISOC Technology(Shanghai), Inc. */ #include "power_manager_api.h" #include "power_manager.h" #include "display_manager.h" #include "inputmanager/input_manager.h" #include "battery_manager.h" #include "utils.h" #include "ledservice/src/ledservice.h" #include "power_save_controller.h" #define DBUS_OFONO_VOICECALL_MANAGER_INTERFACE "org.ofono.VoiceCallManager" #define DBUS_OFONO_MESSAGE_MANAGER_INTERFACE "org.ofono.MessageManager" #define DBUS_INTERFACE_POWERSAVE "com.unisoc.powersavectl" #define REQUEST_MODE_AQUIRE 0 #define REQUEST_MODE_RELEASE 1 //dbus listen thread pthread_t dbus_ptid; //loop check calling, false while reboot or shutdown static bool loop = true; //configuration dictionary static dictionary* s_cfg_dict; //time out static int s_autosuspend_timeout; static int s_screen_timeout; static int s_poweroff_timeout; int pms_loglevel = PMS_LOG_WARN; //battery config static int s_bms_cap_low_level; static int s_bms_cap_urgent_level; static int s_bms_high_temp_value; DBusConnection *connection; //match rules char* match_rules[] = {"type='signal',interface='org.ofono.MessageManager'", "type='signal',interface='org.ofono.VoiceCallManager'", "type='signal',interface='com.unisoc.powersavectl'"}; /* *sig_hander handle shutdown signal and * set loop flag false. *@param sig_number: signal number input */ static void sig_handler(int sig_number) { if((SIGTERM == sig_number) || (SIGKILL == sig_number)) { loop = false; YLOGI("%s received signal %d, loop be set false.", __func__, sig_number); }else{ YLOGD("%s received signal %d.", __func__, sig_number); } } static void get_ini_para(dictionary *config) { s_screen_timeout = iniparser_getint(config, KEY_SCREEN_TIMEOUT, DEFAULT_SCREEN_TIMEOUT); s_autosuspend_timeout = iniparser_getint(config, KEY_AUTOSUSPEND_TIMEOUT, DEFAULT_AUTOSUSPEND_TIMEOUT); s_poweroff_timeout = iniparser_getint(config, KEY_POWEROFF_TIMEOUT, DEFAULT_POWEROFF_TIMEOUT); pms_loglevel = iniparser_getint(config, KEY_LOG_LEVEL, DEFAULT_LOG_LEVEL); s_bms_cap_low_level = iniparser_getint(config, KEY_BMS_CAP_LOW_LEVEL, BMS_CAPACITY_LOW_LEVEL_DEF); s_bms_cap_urgent_level = iniparser_getint(config, KEY_BMS_CAP_URGENT_LEVEL, BMS_CAPACITY_URGENT_LEVEL_DEF); s_bms_high_temp_value = iniparser_getint(config, KEY_BMS_HIGH_TEMP_VALUE, BMS_HIGH_TEMP_VALUE_DEF); YLOGI("screen timeout =%d Sec", s_screen_timeout); YLOGI("autosuspend timeout =%d Sec", s_autosuspend_timeout); YLOGI("poweroff timeout =%d Sec", s_poweroff_timeout); YLOGI("pms loglevel =%d", pms_loglevel); YLOGI("bms_cap_low_level =%d", s_bms_cap_low_level); YLOGI("bms_cap_urgent_level =%d", s_bms_cap_urgent_level); YLOGI("bms_high_temp_value =%d", s_bms_high_temp_value); } static int get_dbus_message_basic(DBusMessageIter iter, char **val_char) { int ret = dbus_message_iter_get_arg_type(&iter); if (ret != DBUS_TYPE_INVALID) { YLOGD("get_dbus_message_basic is %d", ret); if (ret == DBUS_TYPE_STRING) { // dbus_message_iter_next(&iter); dbus_message_iter_get_basic(&iter, val_char); YLOGD("name:%s", *val_char); } else { YLOGE("argument not string!"); return -1; } } else{ YLOGE("Argument is invalid!"); return -1; } return 0; } static void reply_method_call(DBusConnection *connection, DBusMessage *message, int ret) { DBusMessage *reply = NULL; DBusMessage *msg = message; reply = dbus_message_new_method_return(msg); DBusMessageIter args; dbus_message_iter_init_append(reply, &args); dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &ret); dbus_connection_send(connection, reply, NULL); dbus_connection_flush(connection); dbus_message_unref(reply); YLOGD("reply done"); } /* * handle any method call to powermanager * as a callback function for dbushandler. *@param msg: message object from dbus, using for get member. *@param conn: connection object from dbus, using form reply if exist. *@return: 0-sucess otherwise-fail * */ static int handle_method_call(DBusMessage* msg, DBusConnection* conn) { DBusMessageIter iter; const char *path = NULL; const char *iface = NULL; const char *member = NULL; char* message_name = NULL; int ret = -1; //check dbus calling parameters if ((iface = dbus_message_get_interface (msg))) { YLOGI("Dbus-interface: %s", iface); } else { YLOGE("Dbus-interface is NULL!"); return -1; } if ((member = dbus_message_get_member (msg))) { YLOGD("Dbus-member: %s", member); } else { YLOGE("Dbus-member is NULL!"); return -1; } if ((path = dbus_message_get_path (msg))) { YLOGD("Dbus-path: %s", path); } else { YLOGE("Dbus-path is NULL!"); return -1; } //handle aquire or release wakelock request if (!strcmp(iface, DBUS_INTERFACE_PM) && !strcmp(path, DBUS_PATH_PM)) { if (dbus_message_is_method_call(msg, DBUS_INTERFACE_PM, DBUS_PM_ACQUIRE_LOCK)) { if (!dbus_message_iter_init(msg, &iter)) { YLOGE("no Argument"); } else { //get name from iter dbus_message_iter_get_basic(&iter, &message_name); YLOGI("acquire wakelock by %s", message_name); ret = power_manager_acquire_wakelock(message_name); reply_method_call(conn, msg, ret); } } else if(dbus_message_is_method_call(msg, DBUS_INTERFACE_PM, DBUS_PM_RELEASE_LOCK)) { if (!dbus_message_iter_init(msg, &iter)) { YLOGE("no Argument"); }else { //get name from iter dbus_message_iter_get_basic(&iter, &message_name); YLOGI("release wakelock by %s", message_name); ret = power_manager_release_wakelock(message_name); reply_method_call(conn, msg, ret); } } else if(dbus_message_is_method_call(msg, DBUS_INTERFACE_PM, DBUS_PM_ACQUIRE_BRIGHTLOCK)) { if (!dbus_message_iter_init(msg, &iter)) { YLOGE("no Argument"); }else { get_dbus_message_basic(iter, &message_name); YLOGI("%s acquire brightlock by dbus", message_name); ret = handle_brightlock_request(message_name, true); reply_method_call(conn, msg, ret); } } else if(dbus_message_is_method_call(msg, DBUS_INTERFACE_PM, DBUS_PM_RELEASE_BRIGHTLOCK)) { if (!dbus_message_iter_init(msg, &iter)) { YLOGE("no Argument"); }else { get_dbus_message_basic(iter, &message_name); YLOGI("%s release brightlock by dbus", message_name); ret = handle_brightlock_request(message_name, false); reply_method_call(conn, msg, ret); } } else if(dbus_message_is_method_call(msg, DBUS_INTERFACE_PM, DBUS_PM_SCREEN_ON)) { //need receive parameters to be the reason of wakeup if (!dbus_message_iter_init(msg, &iter)) { YLOGE("no Argument"); return -1; } else { get_dbus_message_basic(iter, &message_name); YLOGI("%s turn screen on by dbus", message_name); ret = handle_screen_on_request(); reply_method_call(conn, msg, ret); } } else if(dbus_message_is_method_call(msg, DBUS_INTERFACE_PM, DBUS_PM_SCREEN_OFF)) { //need receive parameters to be the reason of wakeup if (!dbus_message_iter_init(msg, &iter)) { YLOGE("no Argument"); return -1; } else { get_dbus_message_basic(iter, &message_name); YLOGI("%s turn screen off by dbus", message_name); ret = handle_screen_off_request(); reply_method_call(conn, msg, ret); } } else { YLOGE("not method call!"); } YLOGE("dbus_message is not pm call"); } return 0; } /* *signal handle function. process the received signal * * */ static int handle_signal_received(DBusMessage* msg) { //DBusMessageIter iter; const char *path = NULL; const char *iface = NULL; const char *member = NULL; //check dbus calling parameters if ((iface = dbus_message_get_interface (msg))) { YLOGI("Dbus-interface: %s", iface); } else { YLOGE("Dbus-interface is NULL!"); return -1; } if ((member = dbus_message_get_member (msg))) { YLOGI("Dbus-member: %s", member); } else { YLOGE("Dbus-member is NULL!"); return -1; } if ((path = dbus_message_get_path (msg))) { YLOGD("Dbus-path: %s", path); } else { YLOGE("Dbus-path is NULL!"); return -1; } if (iface != NULL) { if (!strcmp(iface, DBUS_OFONO_VOICECALL_MANAGER_INTERFACE)) { YLOGD("OFFNO VOICECALL MESSAGE"); handle_screen_state_for_callsms(member, iface); } else if (!strcmp(iface, DBUS_OFONO_MESSAGE_MANAGER_INTERFACE)){ YLOGD("OFFNO MESSAGE SIGNAL-"); handle_screen_state_for_callsms(member, iface); #ifdef CONFIG_POWERSAVE_ENABLE } else if (!strcmp(iface, DBUS_INTERFACE_POWERSAVE) && strstr(member, "PowerSave")){ handle_power_save_state(member); #endif } else { YLOGE("not matched signal"); } } return 0; } /* *dbus_thread_start_routine process incoming method request * that wakelock and autosuspend related *@param conn: dbus connection initialized * */ static void* dbus_thread_start_routine(void *arg __attribute__((unused))) { dh_monitor_ms(DBUS_BUS_SYSTEM, DBUS_NAME_PM, handle_method_call, match_rules, 3, handle_signal_received, 200); return NULL; } void uevent_listener_init() { if (uevent_init()) { YLOGE("uevent init fail! "); return; } if (uevent_register_listener(input_uevent_listener)) { YLOGE("uevent register listener fail! "); return; } #if defined (CONFIG_BATTERY_ENABLED) if (uevent_register_listener(battery_uevent_listener)) { YLOGE("uevent register listener fail! "); return; } #endif if (uevent_start_loop()) { YLOGE("start uevent listen fail! "); return; } } /* *main thread, quit while autosuspend thread exit. *@param: void *@return: 0-sucess otherwise-fail */ int main(int argc, char *argv[]){ if (signal(SIGINT, sig_handler) == SIG_ERR){ YLOGE("can not catch signal"); } s_cfg_dict = load_config(DEFAULT_CFG_PATH_SYS, DEFAULT_CFG_PATH_USR); get_ini_para(s_cfg_dict); input_init(s_poweroff_timeout); #if defined(CONFIG_LED_ENABLED) led_init(); #endif #if defined(CONFIG_BATTERY_ENABLED) batterymanager_init(s_bms_cap_low_level,s_bms_cap_urgent_level,s_bms_high_temp_value); #endif uevent_listener_init(); #if defined(CONFIG_POWERSAVE_ENABLE) power_save_ctl_init(); #endif #if defined(CONFIG_DISPLAY_ENABLED) display_manager_init(s_screen_timeout); #endif power_manager_init(s_autosuspend_timeout); #if (!defined CONFIG_ENABLE_PERIODIC_AUTOSUSPEND) && (!defined CONFIG_SUSPEND_BLOCKER) pm_enable_auto_suspend(); #endif //dbus handler if (pthread_create(&dbus_ptid, NULL, dbus_thread_start_routine, NULL) < 0) { YLOGE("%s: Failed to create dbus_handler", __FUNCTION__); return -1; } YLOGD("dbus thread create success!"); pthread_join(dbus_ptid, NULL); /* wait "dbus" thread exit. */ YLOGE("dbus thread exit..."); return 0; }