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