| |
| #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> |
| |
| #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" |
| |
| |
| 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; |
| } |
| |
| |
| } |
| |
| |