| #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 <liblog/lynq_deflog.h> |
| |
| #include "include/libauto/lynq_autosuspend.h" |
| #ifdef MOBILETEK_TARGET_PLATFORM_T106 |
| #include <sc_bsp.h> |
| #endif |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #define USER_LOG_TAG "LIBLYNQ_AUTOSUSPEND" |
| |
| |
| |
| |
| #define SERVER_CMD_PATH "/tmp/autosuspend.cmd.server" |
| #define SERVER_DATA_PATH "/tmp/autosuspend.data.server" |
| // #define CLIENT_PATH "/tmp/autosuspend.client" |
| 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; |
| |
| 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) |
| { |
| //LYINFLOG("READ,%d\n",fd); |
| if (errno == EINTR) |
| { |
| LYINFLOG("read error eintr\n"); |
| continue; |
| } |
| else if(errno == EAGAIN || errno == EWOULDBLOCK) |
| { |
| LYINFLOG("read time out\n"); |
| return -2; |
| } |
| else |
| { |
| LYINFLOG("read error\n"); |
| return -1; |
| } |
| } |
| //sleep(2); |
| //LYINFLOG("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) |
| { |
| LYINFLOG("write error epipe\n"); |
| return -1; |
| } |
| else |
| return -1; |
| } |
| return n; |
| } |
| static int Close(int fd) |
| { |
| if (close(fd) == -1) |
| { |
| LYINFLOG("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; |
| LYINFLOG("Start bind and connect to the service.\n"); |
| /**************************************/ |
| /* Create a UNIX domain stream socket */ |
| /**************************************/ |
| *cfd = socket(AF_UNIX, SOCK_STREAM, 0); |
| if (*cfd == -1) { |
| LYINFLOG("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){ |
| LYINFLOG("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){ |
| LYINFLOG("CONNECT ERROR "); |
| Close(*cfd); |
| return -3; |
| } |
| return 0; |
| |
| } |
| static void *deal_get_feedback(void *sockfd) |
| { |
| int rc; |
| int client_sock = *((int *)sockfd); |
| // pthread_mutex_lock(&feedback_got_mutex); |
| |
| while (1) |
| { |
| // LYINFLOG("deal_get_feedback thread wait.\n"); |
| // pthread_cond_wait(&get_feedback_cond,&get_feedback_mutex); |
| LYINFLOG("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_sock,&time_info_client,sizeof(struct time_info_t)); |
| if(rc == -1) |
| { |
| LYINFLOG("client read wakeup_feedback struct fail.\n"); |
| Close(client_sock); |
| pthread_mutex_unlock(&feedback_got_mutex); |
| break ; |
| } |
| else if(rc == -2) |
| { |
| LYINFLOG("client read wakeup_feedback struct timeout.\n"); |
| pthread_mutex_unlock(&feedback_got_mutex); |
| continue; |
| } |
| LYINFLOG("system sleep_start timestamps : %ld ms\n",time_info_client.sleep_start_time); |
| LYINFLOG("system wakeup timestamps : %ld ms\n",time_info_client.wakeup_time); |
| // pthread_cond_broadcast(&feedback_got_cond); |
| 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; |
| } |
| LYINFLOG("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) |
| { |
| LYINFLOG("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) |
| { |
| LYINFLOG("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,(void*)&client_data_sock_fd); |
| 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); |
| LYINFLOG("Sending data...\n"); |
| rc = send(client_sock_fd, value, len, 0); |
| if (rc == -1) { |
| LYINFLOG("SEND ERROR "); |
| Close(client_sock_fd); |
| return -2; |
| } |
| else { |
| LYINFLOG("Data sent: %s\n",value); |
| } |
| // Close(client_sock); |
| return rc; |
| } |
| int lynq_autosleep_enable(void) |
| { |
| char value[15]="enable"; |
| char res[15]; |
| LYLOGSET(LOG_INFO); |
| LYLOGEINIT(USER_LOG_TAG); |
| |
| if(libautosuspend_init() != 0) |
| { |
| return -1; |
| } |
| // if(libautosuspend_enabled) |
| // { |
| // return 0; |
| // } |
| pthread_mutex_lock(&client_fd_mutex); |
| int rc = send_cmd(value,strlen(value)); |
| if(rc < 0) |
| { |
| LYINFLOG("libautosuspend send enable cmd fail.\n"); |
| pthread_mutex_unlock(&client_fd_mutex); |
| return -1; |
| } |
| // if(Read(client_sock_fd,res,sizeof(res)) <= 0) |
| // { |
| // LYINFLOG("libautosuspend get respond fail.\n"); |
| // pthread_mutex_unlock(&client_fd_mutex); |
| // return -1; |
| // } |
| // LYINFLOG("libautosuspend get respond : %s.\n",res); |
| // if(strcmp(res,"enabled") != 0) |
| // { |
| // pthread_mutex_unlock(&client_fd_mutex); |
| // return -1; |
| // } |
| // libautosuspend_enabled = true; |
| 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; |
| } |
| // if(!libautosuspend_enabled) |
| // { |
| // return 0; |
| // } |
| pthread_mutex_lock(&client_fd_mutex); |
| int rc = send_cmd(value,strlen(value)); |
| if(rc < 0) |
| { |
| LYINFLOG("libautosuspend send disable cmd fail.\n"); |
| pthread_mutex_unlock(&client_fd_mutex); |
| return -1; |
| } |
| // if(Read(client_sock_fd,res,sizeof(res)) <= 0) |
| // { |
| // LYINFLOG("libautosuspend get respond fail.\n"); |
| // pthread_mutex_unlock(&client_fd_mutex); |
| // return -1; |
| // } |
| // LYINFLOG("libautosuspend get respond : %s.\n",res); |
| // if(strcmp(res,"disabled") != 0) |
| // { |
| // pthread_mutex_unlock(&client_fd_mutex); |
| // return -1; |
| // } |
| // libautosuspend_enabled = false; |
| pthread_mutex_unlock(&client_fd_mutex); |
| return 1; |
| } |
| int libautosuspend_get_feedback(struct time_info_t *time_info) |
| { |
| // char value[15]="feedback"; |
| // char res[15]; |
| // if(!libautosuspend_enabled) |
| // { |
| // LYINFLOG("system autosuspend disabled, can not get wakeup feedback.\n"); |
| // return -1; |
| // } |
| LYINFLOG("start get feedback from the service.\n"); |
| memset(time_info,0,sizeof(struct time_info_t)); |
| // if(timeout == NULL) |
| // { |
| // LYINFLOG("client set timeout for receiving wakeup_feedback: NULL.\n"); |
| // } |
| // else |
| // { |
| // struct timeval recv_timeout = {(*timeout),0}; |
| // pthread_mutex_lock(&client_data_fd_mutex); |
| // if(setsockopt(client_data_sock_fd,SOL_SOCKET,SO_RCVTIMEO,(char*)&recv_timeout,sizeof(struct timeval)) == -1) |
| // { |
| // LYINFLOG("client set timeout for receiving wakeup_feedback: error.\n"); |
| // pthread_mutex_unlock(&client_data_fd_mutex); |
| // return -1; |
| // } |
| |
| // LYINFLOG("client set timeout for receiving wakeup_feedback: %d s.\n",(*timeout)); |
| // pthread_mutex_unlock(&client_data_fd_mutex); |
| |
| // } |
| // int rc = send_cmd(value,strlen(value)); |
| // if(rc < 0) |
| // { |
| // LYINFLOG("libautosuspend send feedback cmd fail.\n"); |
| // pthread_mutex_unlock(&client_fd_mutex); |
| // return -1; |
| // } |
| // if(Read(client_data_sock_fd,time_info,sizeof(struct time_info_t)) <= 0) |
| // { |
| // LYINFLOG("libautosuspend_get_feedback fail.\n"); |
| // pthread_mutex_unlock(&client_fd_mutex); |
| // return -1; |
| // } |
| LYINFLOG("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)); |
| LYINFLOG("libautosuspend_get_feedback success.\n"); |
| pthread_mutex_unlock(&feedback_got_mutex); |
| // LYINFLOG("[client] system sleep_start timestamps : %ld ms\n",time_info.sleep_start_time); |
| // LYINFLOG("[client] system wakeup timestamps : %ld ms\n",time_info.wakeup_time); |
| 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 ) |
| { |
| LYINFLOG("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; |
| } |
| |
| } |
| #ifdef MOBILETEK_TARGET_PLATFORM_T106 |
| int acquire_wake_lock(int lock, char *name) |
| { |
| int ret; |
| LYLOGSET(LOG_INFO); |
| LYLOGEINIT(USER_LOG_TAG); |
| |
| if(strlen(name) == 0) |
| { |
| return -1; |
| } |
| LYINFLOG("Get param:%s \n", name); |
| ret = sc_pm_wakelock_lock(name); |
| if (ret != 0) |
| { |
| LYINFLOG("do_wakelock failed, err:%d", ret); |
| return -1; |
| } |
| |
| LYINFLOG("do_wakelock succeed\n"); |
| return 1; |
| } |
| int release_wake_lock(char *name) |
| { |
| int ret; |
| |
| if(strlen(name) == 0) |
| { |
| return -1; |
| } |
| LYLOGSET(LOG_INFO); |
| LYLOGEINIT(USER_LOG_TAG); |
| |
| LYINFLOG("Get param:%s \n", name); |
| ret = sc_pm_wakelock_unlock(name); |
| if (ret != 0) |
| { |
| LYINFLOG("do_wakeunlock failed, err:%d", ret); |
| return -1; |
| } |
| LYINFLOG("do_wakeunlock succeed\n"); |
| return 1; |
| } |
| int lynq_set_lpmode(int lp_mode) |
| { |
| int ret; |
| LYLOGSET(LOG_INFO); |
| LYLOGEINIT(USER_LOG_TAG); |
| |
| LYINFLOG("Get param:%d \n", lp_mode); |
| ret = sc_pm_set_lp_mode(lp_mode); |
| if (ret) { |
| LYINFLOG("do_set_lpmode failed, err:%d", ret); |
| exit(1); |
| } |
| LYINFLOG("do_set_lpmode succeed\n"); |
| return ret; |
| } |
| #endif |
| |
| DEFINE_LYNQ_LIB_LOG(LIBLYNQ_AUTOSUSPEND) |
| |
| #ifdef __cplusplus |
| } |
| #endif |