blob: c8f8d0cf077a052ebe0ebafafb9279512ab5f219 [file] [log] [blame]
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <dlfcn.h>
#include <pthread.h>
#include <stdbool.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#define LOG_TAG "libautosuspend"
// #include <liblog/lynq_deflog.h>
#include <log/log.h>
#define SERVER_CMD_PATH "/tmp/autosuspend.cmd.server"
#define SERVER_DATA_PATH "/tmp/autosuspend.data.server"
// #define CLIENT_PATH "/tmp/autosuspend.client"
typedef void (*lynq_lpm_Handler_t)(int lpm_edge);
lynq_lpm_Handler_t g_lpm_handler = NULL;
pthread_t dtr_thid;
int g_init_flag;
static int client_sock_fd;
static int client_data_sock_fd;
static bool libautosuspend_inited;
bool feedback_flag = true; //add for after sleeping once calling lynq_wailt_wakeup_event does not return sleep time
// static bool libautosuspend_enabled;
// static pthread_mutex_t get_feedback_mutex = PTHREAD_MUTEX_INITIALIZER;
// static pthread_cond_t get_feedback_cond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t client_fd_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t client_data_fd_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t feedback_got_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t feedback_got_cond = PTHREAD_COND_INITIALIZER;
struct time_info_t
{
long sleep_start_time;
long wakeup_time;
};
static struct time_info_t time_info_client;
static ssize_t Read(int fd, void *ptr, size_t nbytes)
{
ssize_t n;
while((n = read(fd, ptr, nbytes)) == -1)
{
//printf("READ,%d\n",fd);
if (errno == EINTR)
{
ALOGI("read error eintr\n");
continue;
}
else if(errno == EAGAIN || errno == EWOULDBLOCK)
{
ALOGI("read time out\n");
return -2;
}
else
{
ALOGI("read error\n");
return -1;
}
}
//sleep(2);
//printf("READ1,%d\n", fd);
return n;
}
static ssize_t Write(int fd, const void *ptr, size_t nbytes)
{
ssize_t n;
while((n = write(fd, ptr, nbytes)) == -1)
{
if (errno == EINTR)
continue;
else if(errno == EPIPE)
{
ALOGI("write error epipe\n");
return -1;
}
else
return -1;
}
return n;
}
static int Close(int fd)
{
if (close(fd) == -1)
{
ALOGI("Close error\n");
return -1;
}
return 0;
}
static int connect_to_server(int *cfd, char *client_path, char *server_path)
{
int rc;
struct sockaddr_un server_sockaddr;
struct sockaddr_un client_sockaddr;
ALOGI("Start bind and connect to the service.\n");
/**************************************/
/* Create a UNIX domain stream socket */
/**************************************/
*cfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (*cfd == -1) {
ALOGI("SOCKET ERROR ");
return -1;
}
/***************************************/
/* Set up the UNIX sockaddr structure */
/* by using AF_UNIX for the family and */
/* giving it a filepath to bind to. */
/* */
/* Unlink the file so the bind will */
/* succeed, then bind to that file. */
/***************************************/
client_sockaddr.sun_family = AF_UNIX;
strcpy(client_sockaddr.sun_path, client_path);
unlink(client_sockaddr.sun_path);
rc = bind(*cfd, (struct sockaddr *) &client_sockaddr, sizeof(client_sockaddr));
if (rc == -1){
ALOGI("BIND ERROR ");
Close(*cfd);
return -1;
}
/***************************************/
/* Set up the UNIX sockaddr structure */
/* for the server socket and connect */
/* to it. */
/***************************************/
server_sockaddr.sun_family = AF_UNIX;
strcpy(server_sockaddr.sun_path, server_path);
rc = connect(*cfd, (struct sockaddr *) &server_sockaddr, sizeof(client_sockaddr));
if(rc == -1){
ALOGI("CONNECT ERROR ");
Close(*cfd);
return -3;
}
return 0;
}
static void *deal_get_feedback(void *sockfd)
{
int rc;
int ret;
int num[10]={5,5,10,10,30,30,60,60,90,90};
int i = 0;
while (1)
{
ALOGI("start get feedback from the service.\n");
pthread_mutex_lock(&feedback_got_mutex);
memset(&time_info_client,0,sizeof(struct time_info_t));
rc = Read(client_data_sock_fd,&time_info_client,sizeof(struct time_info_t));
ALOGI("deal_get_feedback: rc=%d, client_data_sock_fd=%d.\n", rc, client_data_sock_fd);
if(rc == -1)
{
ALOGI("client read wakeup_feedback struct fail.\n");
Close(client_data_sock_fd);
pthread_mutex_unlock(&feedback_got_mutex);
break ;
}
else if(rc == -2)
{
ALOGI("client read wakeup_feedback struct timeout.\n");
pthread_mutex_unlock(&feedback_got_mutex);
continue;
}
else if(rc == 0)
{
if(i<10)
{
sleep(num[i]);
}
else
{
sleep(120);
}
i++;
system("rm -rf /tmp/*data.client");
system("rm -rf /tmp/*cmd.client");
ret = lynq_autosleep_retry();
if(ret > 0)
{
ALOGI("lynq autosuspend retry success\n");
i = 0;
}
pthread_mutex_unlock(&feedback_got_mutex);
continue;
}
ALOGI("system sleep_start timestamps : %ld ms\n",time_info_client.sleep_start_time);
ALOGI("system wakeup timestamps : %ld ms\n",time_info_client.wakeup_time);
pthread_mutex_unlock(&feedback_got_mutex);
usleep(10000); //给libautosuspend_get_feedback函数时间进入wait,不可删除,但可以减少
pthread_cond_broadcast(&feedback_got_cond);
usleep(10000); //希望多给libautosuspend_get_feedback函数拿到锁的机会,不可删除,但可以减少
}
}
static int libautosuspend_init()
{
if (libautosuspend_inited)
{
return 0;
}
ALOGI("Start libautosuspend_init.\n");
char client_cmd_path[40];
char client_data_path[40];
sprintf(client_cmd_path,"/tmp/autosuspend.%d.cmd.client",(int)getpid());
sprintf(client_data_path,"/tmp/autosuspend.%d.data.client",(int)getpid());
pthread_mutex_lock(&client_fd_mutex);
if(connect_to_server(&client_sock_fd,client_cmd_path,SERVER_CMD_PATH) < 0)
{
ALOGI("cmd channel connect error.\n");
pthread_mutex_unlock(&client_fd_mutex);
return -1;
}
if(connect_to_server(&client_data_sock_fd,client_data_path,SERVER_DATA_PATH) < 0)
{
ALOGI("data channel connect error.\n");
pthread_mutex_unlock(&client_fd_mutex);
return -1;
}
pthread_t feedback_tid;
pthread_create(&feedback_tid,NULL,deal_get_feedback,NULL);
pthread_detach(feedback_tid);
libautosuspend_inited = true;
pthread_mutex_unlock(&client_fd_mutex);
return 0;
}
static int send_cmd(char * value,int len)
{
int rc;
if(value == NULL)
{
return -1;
}
/************************************/
/* Copy the data to the buffer and */
/* send it to the server socket. */
/************************************/
// strcpy(buf, DATA);
ALOGI("Sending data...\n");
rc = send(client_sock_fd, value, len, 0);
if (rc == -1) {
ALOGI("SEND ERROR ");
Close(client_sock_fd);
return -2;
}
else {
ALOGI("Data sent: %s\n",value);
}
// Close(client_sock);
return rc;
}
static int libautosuspend_reconnect(void)
{
ALOGI("Start libautosuspend_init.\n");
char client_cmd_path[40];
char client_data_path[40];
sprintf(client_cmd_path,"/tmp/autosuspend.%d.cmd.client",(int)getpid());
sprintf(client_data_path,"/tmp/autosuspend.%d.data.client",(int)getpid());
pthread_mutex_lock(&client_fd_mutex);
if(connect_to_server(&client_sock_fd,client_cmd_path,SERVER_CMD_PATH) < 0)
{
ALOGI("cmd channel connect error.\n");
pthread_mutex_unlock(&client_fd_mutex);
return -1;
}
if(connect_to_server(&client_data_sock_fd,client_data_path,SERVER_DATA_PATH) < 0)
{
ALOGI("data channel connect error.\n");
pthread_mutex_unlock(&client_fd_mutex);
return -1;
}
pthread_mutex_unlock(&client_fd_mutex);
return 0;
}
int lynq_autosleep_retry(void)
{
char value[15]="enable";
char res[15];
if(libautosuspend_reconnect() != 0)
{
return -1;
}
pthread_mutex_lock(&client_fd_mutex);
int rc = send_cmd(value,strlen(value));
if(rc < 0)
{
ALOGI("libautosuspend send enable cmd fail.\n");
pthread_mutex_unlock(&client_fd_mutex);
return -1;
}
pthread_mutex_unlock(&client_fd_mutex);
return 1;
}
int lynq_autosleep_enable(void)
{
char value[15]="enable";
char res[15];
if(libautosuspend_init() != 0)
{
return -1;
}
pthread_mutex_lock(&client_fd_mutex);
int rc = send_cmd(value,strlen(value));
if(rc < 0)
{
ALOGI("libautosuspend send enable cmd fail.\n");
pthread_mutex_unlock(&client_fd_mutex);
return -1;
}
pthread_mutex_unlock(&client_fd_mutex);
return 1;
}
int lynq_autosleep_disable(void)
{
char value[15]="disable";
char res[15];
if(libautosuspend_init() != 0)
{
return -1;
}
pthread_mutex_lock(&client_fd_mutex);
int rc = send_cmd(value,strlen(value));
if(rc < 0)
{
ALOGI("libautosuspend send disable cmd fail.\n");
pthread_mutex_unlock(&client_fd_mutex);
return -1;
}
pthread_mutex_unlock(&client_fd_mutex);
return 1;
}
int libautosuspend_get_feedback(struct time_info_t *time_info)
{
ALOGI("start get feedback from the service.\n");
memset(time_info,0,sizeof(struct time_info_t));
ALOGI("libautosuspend_get_feedback wait.\n");
pthread_mutex_lock(&feedback_got_mutex);
pthread_cond_wait(&feedback_got_cond,&feedback_got_mutex);
memcpy(time_info,&time_info_client,sizeof(struct time_info_t));
ALOGI("libautosuspend_get_feedback success.\n");
pthread_mutex_unlock(&feedback_got_mutex);
return 0;
}
int lynq_wait_wakeup_event(long *sleep_start_time, long * wakeup_time)
{
int *socket_timeout = NULL;
struct time_info_t time_info;
int ret = 0;
/*add for after sleeping once calling lynq_wailt_wakeup_event does not return sleep time start*/
if(feedback_flag == true)
{
if(libautosuspend_init() != 0)
{
return -1;
}
}
feedback_flag = false;
/*add for after sleeping once calling lynq_wailt_wakeup_event does not return sleep time end*/
memset(&time_info,0,sizeof(struct time_info_t));
if(sleep_start_time == NULL || wakeup_time == NULL )
{
ALOGI("lynq_wait_wakeup_event input errors.\n");
return -1;
}
ret=libautosuspend_get_feedback(&time_info);
if(ret == 0)
{
*sleep_start_time = time_info.sleep_start_time;
*wakeup_time = time_info.wakeup_time;
return 0;
}
else
{
return -1;
}
}
static void *check_dtr(void * arg)
{
int lpm_edge;
char msg[32];
int fd=0;
int ret=0;
while(1)
{
fd = open("/dev/wakeup_dtr_dev", O_RDONLY);
ret=read(fd, &msg,31);
ALOGI("wakeup_dtr_dev: %s\n", msg);
close(fd);
if(msg[14] == '0')
{
lpm_edge = 0;
}
else if(msg[14] =='1')
{
lpm_edge = 1;
}
else
{
continue;
}
ALOGI("dtr status: %d\n", lpm_edge);
g_lpm_handler(lpm_edge);
}
return 0;
}
int lynq_dtr_register(lynq_lpm_Handler_t qser_lpm_handler)
{
int ret;
if(lynq_lpm_handler == NULL)
{
RLOGI("lynq_lpm_handler is NULL\n");
return -1;
}
if(g_init_flag != 0)
{
RLOGI("g_init_flag is error\n");
return -1;
}
g_init_flag = 1;
g_lpm_handler = qser_lpm_handler;
ret = pthread_create(&dtr_thid,NULL,check_dtr,NULL);
if(ret != 0)
{
RLOGI("pthread create fail, qser_lpm_init fail\n");
}
return ret;
}
int qser_dtr_deregister(void)
{
int ret;
if(g_init_flag != 1)
{
RLOGI("g_init_flag is error");
return -1;
}
g_init_flag = 0;
g_lpm_handler=NULL;
ret = pthread_cancel(dtr_thid);
if(!ret)
{
RLOGI("pthread cancel success, lpm deinit success\n");
}
else
{
RLOGI("pthread cancel fail, lpm deinit fail\n");
}
return ret;
}