395 lines
12 KiB
C
395 lines
12 KiB
C
/*
|
|
* 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;
|
|
}
|