[Bugfix] fix API-235,242

Change-Id: Ic63b8be16891b9597bb9b6473763351515a36d86
diff --git a/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/autosuspend_wakeup_count.c b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/autosuspend_wakeup_count.c
index 1f8284e..d567ca3 100644
--- a/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/autosuspend_wakeup_count.c
+++ b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/autosuspend_wakeup_count.c
@@ -31,7 +31,6 @@
 #include <unistd.h>
 #include <dlfcn.h>
 //#include <cutils/properties.h>
-#define LOG_TAG "AUTOSUSPEND"
 #define USER_LOG_TAG "PMS"
 #include <liblog/lynq_deflog.h>
 #include <log/log.h>
@@ -51,6 +50,9 @@
 static int suspend_ctrl_fd;
 static pthread_t suspend_thread;
 static sem_t suspend_lockout;
+extern pthread_cond_t feedback_cond;
+extern pthread_mutex_t feedback_mutex;
+extern pthread_mutex_t time_info_mutex;
 static const char *sleep_state = "mem";
 static const char *reg_netsys[5] = {"reg_netsys_srcclkena_mask_b 0",
                                     "reg_netsys_infra_req_mask_b 0",
@@ -67,6 +69,9 @@
 int (*lynq_screen)(int num);
 int (*lynq_sim_init)(int utoken);
 
+static long start_time;  // 出错点:time_info_t 结构体两个成员都是long,因此这两个变量必须是long型,不能定义成int
+static long end_time; 
+
 
 
 # define TEMP_FAILURE_RETRY(expression) \
@@ -85,7 +90,7 @@
 
 int (*acquire_wake_lock)(int lock, const char* id);
 int (*release_wake_lock)(const char* id);
-int (*lynq_query_registration_state)(const char *type,int* regState,int* imsRegState,char * LAC,char * CID,int *netType,int *radioTechFam);
+int (*lynq_query_registration_state)(const char *type,int* regState,int* imsRegState,char * LAC,char * CID,int *netType,int *radioTechFam,int *errorCode);
 int (*lynq_network_init)(int utoken);
 
 pid_t pid = 0;
@@ -98,7 +103,15 @@
 // while you have a lock held, the device will stay on at least at the
 // level you request.
 
+struct time_info_t
+{
+    long sleep_start_time;
+    long wakeup_time;
+};
 
+extern struct time_info_t time_info;
+
+struct timeval tv;
 
 void init_wakelock_func(void)
 {
@@ -166,7 +179,8 @@
         ALOGI("Run lynq_sim_init\n");
     }else{
         ALOGI("lynq sim init error\n");
-    }    
+    }
+    sleep(1);    
 
     return;            
 }
@@ -183,7 +197,7 @@
         exit(EXIT_FAILURE);
     }
 
-    lynq_query_registration_state = (int(*)(const char,int*,int*,char *,char *,int *,int *))dlsym(dlHandle_network, "lynq_query_registration_state");
+    lynq_query_registration_state = (int(*)(const char*,int*,int*,char *,char *,int *,int *,int*))dlsym(dlHandle_network, "lynq_query_registration_state");
     if (lynq_query_registration_state == NULL) {
         ALOGI("lynq_query_registration_state not defined or exported in %s", lynqLibPath_Network);
         exit(EXIT_FAILURE);
@@ -231,6 +245,7 @@
         return -1;
     }
 
+    sleep(5);
     sleep(2);     //delay 1s for ril handling screen off
 
     for(int i = 0;i < 5;i++)  //notify spm (other core) to handle pre-sleep configuration
@@ -253,6 +268,52 @@
 }
 
 
+void wakeup_feedback(bool success)
+{
+    if (!success)
+    {
+        return ;
+    }
+
+    char buf[80];
+    
+    if (lynq_screen(1) < 0)  // notify ril for screen on
+    {
+    ALOGI("lynq_screen on fail\n");
+
+    }
+
+    system("mdlogctl start");
+
+//  sleep(1);
+
+    system("echo 8 | emdlogger_ctrl");
+    
+    sleep(2); //delay 2s for ril handling screen on
+
+    pthread_mutex_lock(&time_info_mutex);
+
+    memset(&tv,0,sizeof(struct timeval));
+    gettimeofday(&tv,NULL);
+    // time_info.wakeup_time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+    end_time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+    ALOGI("%s: wake up time: %ld ms\n", __func__,end_time);
+
+    memset(&time_info,0,sizeof(struct time_info_t));
+
+    time_info.sleep_start_time = start_time;
+    time_info.wakeup_time = end_time;
+   
+    pthread_mutex_unlock(&time_info_mutex);
+
+    if (pthread_cond_broadcast(&feedback_cond) != 0) {
+        strerror_r(errno, buf, sizeof(buf));
+        ALOGI("Error broadcast cond: %s\n", buf);
+    }   
+
+    return ;
+
+}
 
 static void update_sleep_time(bool success) {
     if (success) {
@@ -278,7 +339,22 @@
         update_sleep_time(success);
         usleep(sleep_time);
         success = false;
-        
+
+        ALOGV("%s: read wakeup_count\n", __func__);
+        lseek(wakeup_count_fd, 0, SEEK_SET);
+        wakeup_count_len = TEMP_FAILURE_RETRY(read(wakeup_count_fd, wakeup_count,
+                sizeof(wakeup_count)));
+        if (wakeup_count_len < 0) {
+            strerror_r(errno, buf, sizeof(buf));
+            ALOGE("Error reading from %s: %s\n", SYS_POWER_WAKEUP_COUNT, buf);
+            wakeup_count_len = 0;
+            continue;
+        }
+        if (!wakeup_count_len) {
+            ALOGE("Empty wakeup count\n");
+            continue;
+        }
+
         ALOGI("%s: wait\n", __func__);
         ret = sem_wait(&suspend_lockout);
         if (ret < 0) {
@@ -287,7 +363,15 @@
             continue;
         }
 
-        ALOGI("%s: [1613]start suspend_ctrl\n", __func__);
+        ALOGI("%s: start suspend_ctrl\n", __func__);
+        memset(&tv,0,sizeof(struct timeval));
+        // memset(&time_info,0 ,sizeof(struct time_info_t));
+        gettimeofday(&tv,NULL);
+
+        start_time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
+        ALOGI("%s: suspend start time: %ld ms\n", __func__,start_time);
+        // time_info.sleep_start_time = tv.tv_sec * 1000 + tv.tv_usec / 1000;         
+
         ret = suspend_ctrl();
 
         if (ret >= 0) {
@@ -307,20 +391,21 @@
             ALOGI("Error releasing semaphore: %s\n", buf);
          } 
 
-         ALOGI("%s: START SLEEP\n", __func__);
-         if (lynq_screen(1) < 0)  // notify ril for screen on
-         {
-            ALOGI("lynq_screen on fail\n");
+        //  ALOGI("%s: START SLEEP\n", __func__);
+        //  if (lynq_screen(1) < 0)  // notify ril for screen on
+        //  {
+        //     ALOGI("lynq_screen on fail\n");
        
-         }
+        //  }
 
-         system("mdlogctl start");
+        //  system("mdlogctl start");
 
-        //  sleep(1);
+        // //  sleep(1);
 
-         system("echo 8 | emdlogger_ctrl");
+        //  system("echo 8 | emdlogger_ctrl");
          
-         sleep(2); //delay 2s for ril handling screen on
+        //  sleep(2); //delay 2s for ril handling screen on
+
          if(adb_debug_mode == 1) // it's neccessary to wait for autosuspend_disable function calling in debug mode when finish resume procedure.
          {
    
diff --git a/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/main.c b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/main.c
index 0565bd2..a735b1d 100755
--- a/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/main.c
+++ b/meta/meta-mediatek-mt2735/recipes-lynq/suspend-service/files/main.c
@@ -17,6 +17,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <dlfcn.h>
 #include <string.h>
 #include <pthread.h>
@@ -24,11 +25,13 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <log/log.h>
 #include <liblog/lynq_deflog.h>
 #include <include/lynq_uci.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 
+
 #define LOG_UCI_MODULE "lynq_autosuspend"
 #define LOG_UCI_FILE "lynq_uci"
 
@@ -36,27 +39,41 @@
 
 #define USER_LOG_TAG "PMS"
 
-#define SOCK_PATH  "/tmp/autosuspend.server"  //不能在当前这个目录创建socket文件,否则报错找不到文件(可能是因为这是在共享文件夹下,不支持创建socket文件)
+#define SOCK_PATH  "/tmp/autosuspend.cmd.server"  //不能在当前这个目录创建socket文件,否则报错找不到文件(可能是因为这是在共享文件夹下,不支持创建socket文件)
+
+#define SOCK_DATA_PATH  "/tmp/autosuspend.data.server"
 
 // #define LYINFLOG(X...)  lynq_log_global_output(LOG_INFO,X)
 
 #define TIME_OUT_TIME 30
 
 
-#include <log/log.h>
-
-
 #define MAX_LIB_ARGS        16
 
 int adb_debug_mode = 0;
 
+
+pthread_cond_t feedback_cond = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t feedback_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t time_info_mutex = PTHREAD_MUTEX_INITIALIZER;
+
 extern int autosuspend_enable(void);
 extern int autosuspend_disable(void);
 extern void init_wakelock_func(void);
 extern void init_sim_func();
 extern void init_network_func();
+extern void set_wakeup_callback(void (*func)(bool success));
+extern void wakeup_feedback(bool success);
 
 
+struct time_info_t
+{
+    long sleep_start_time;
+    long wakeup_time;
+};
+
+struct time_info_t time_info; 
+
 static void usage(const char *argv0) {
     fprintf(stderr, "Usage: %s -l <possible_max_sleep_time> [-- <args for Autosuspend Service>]\n", argv0);
     exit(EXIT_FAILURE);
@@ -106,15 +123,6 @@
 	return 0;
 }
 
-static int Connect(int fd, const struct sockaddr *sa, socklen_t salen)
-{
-    if(connect(fd, sa, salen) < 0)
-    {
-        ALOGI("connect error\n");
-        return -1;
-    }
-	return 0;
-}
 
 static int Socket(int family, int type, int protocol)
 {
@@ -138,48 +146,6 @@
 	return 0;
 }
 
-static int connect_with_timeout(int sockfd, struct sockaddr *servaddr)
-{
-    int error = -1, len;
-    len = sizeof(int);
-    struct timeval tm;
-    fd_set set;
-    int flags;
-    flags = fcntl(sockfd, F_GETFL, 0);          
-	fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); 
-    int ret = -1;
-    if(connect(sockfd, servaddr, sizeof(struct sockaddr)) == -1) 
-	{
-        tm.tv_sec = TIME_OUT_TIME;  
-        tm.tv_usec = 0;
-        FD_ZERO(&set);
-        FD_SET(sockfd, &set);
-        if(select(sockfd + 1, NULL, &set, NULL, &tm) > 0)
-        {
-            //���ص�ǰsockfd����״̬����SO_ERROR
-            getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len);
-            if(error == 0)
-            {  
-                ret = 0;
-            }
-            else
-			{  
-				ALOGI("connect error\n");
-                ret = -1;
-			}
-        } 
-		else
-		{
-			ALOGI("connect time out\n");
-            ret = -1;
-		}
-    } 
-	else 
-        ret = 0;
-	fcntl(sockfd,F_SETFL,flags & ~O_NONBLOCK);
-    return ret;
-}
-
 
 static int listen_port(struct sockaddr_un *addr, char *sockpath)
 {
@@ -222,9 +188,9 @@
 			ALOGI("read error eintr\n");
             continue;
 		}
-        else if(errno == EAGAIN)
+        else if(errno == EAGAIN || errno == EWOULDBLOCK)
         {
-            //PRINTF("read time out\n");
+            ALOGI("read time out\n");
             return -1;
         }
         else
@@ -261,16 +227,18 @@
 {
     if (close(fd) == -1)
     {
-        ALOGI("close error");
+        ALOGI("close error\n");
         return -1;
     }
 	return 0;
 }
 
+
 void *deal_autosuspend(void *sockfd)
 {
     int commfd = *((int *)sockfd);
-    char buf[256];
+    char buf[20];
+    char res[15];
 
     while(1)
     {
@@ -278,8 +246,10 @@
         ALOGI("deal_autosuspend start to read.\n");
         // 错误点:read函数在对端关闭后,也会直接返回0,不会阻塞,因此要判断是否返回0,返回0表示对端已经关闭,此时要跳出while循环不再监听
         // 为什么对端会关闭?因为在客户端没有用nohup方式打开的情况下,系统睡眠后客户端进行会直接被杀死,对端会关闭,所以会导致read不阻塞,且总是返回0的现象
-        if(Read(commfd,buf,sizeof(buf)) == 0) 
+        if(Read(commfd,buf,sizeof(buf)) <= 0) 
         {
+            ALOGI("service receive suspend_cmd fail.\n");
+            Close(commfd);
             break;
         }
         if(strcmp(buf,"enable") == 0)
@@ -287,10 +257,24 @@
             if(autosuspend_enable() < 0)
             {
                 ALOGI("autosuspend_enable fail.\n");
+                strcpy(res,"fail");
+                if(Write(commfd,res,strlen(res)) <= 0)
+                {
+                    ALOGI("service send respond fail.\n");
+                    Close(commfd);
+                    break;
+                }                
             }
             else
             {
                 ALOGI("autosuspend_enable success.\n");
+                strcpy(res,"enabled");
+                if(Write(commfd,res,strlen(res)) <= 0)
+                {
+                    ALOGI("service send respond fail.\n");
+                    Close(commfd);
+                    break;
+                }
             }        
         }
         else if(strcmp(buf,"disable") == 0)
@@ -298,16 +282,60 @@
             if(autosuspend_disable() < 0)
             {
                 ALOGI("autosuspend_disable fail.\n");
+                strcpy(res,"fail");
+                if(Write(commfd,res,strlen(res)) <= 0)
+                {
+                    ALOGI("service send respond fail.\n");
+                    Close(commfd);
+                    break;
+                }                     
             }
             else
             {
                 ALOGI("autosuspend_disable success.\n");
+                strcpy(res,"disabled");
+                if(Write(commfd,res,strlen(res)) <= 0)
+                {
+                    ALOGI("service send respond fail.\n");
+                    Close(commfd);
+                    break;
+                }
             }        
         }
+        // else if(strcmp(buf,"feedback") == 0)
+        // {
+            
+        //     ALOGI("send_feedback thread wait to send.\n");
+        //     if (pthread_cond_wait(&feedback_cond,&feedback_mutex) != 0)
+        //     {
+        //         strerror_r(errno, buf, sizeof(buf));
+        //         ALOGI("Error waiting on cond: %s\n", buf);
+        //         Close(commfd);
+        //         break;
+        //     }
+
+        //     ALOGI("send_feedback thread is now sending the feedback to client.\n");
+        //     if(Write(commfd,&time_info,sizeof(struct time_info_t)) <= 0) 
+        //     {
+        //         ALOGI("service send wakeup_feedback struct fail.\n");
+        //         Close(commfd);
+        //         break ;
+        //     }
+        //     ALOGI("service send feedback success.\n");
+        //     strcpy(res,"success");
+        //     if(Write(commfd,res,strlen(res)) <= 0)
+        //     {
+        //         ALOGI("service send respond fail.\n");
+        //         Close(commfd);
+        //         break;
+        //     }
+
+        // }
         else
         {
-            ALOGI("Unknown cmd.\n");
+            ALOGI("Unknown cmd : %s\n",buf);
         }
+
     }
 
 
@@ -315,6 +343,46 @@
 }
 
 
+void *send_feedback(void *sockfd)
+{
+    int commfd = *((int *)sockfd);
+    char buf[80];
+
+    while (1)
+    {
+        memset(buf,0,sizeof(buf));
+        ALOGI("send_feedback thread wait to send.\n");
+        pthread_mutex_lock(&feedback_mutex);
+        pthread_cond_wait(&feedback_cond,&feedback_mutex);
+    
+
+        // strcpy(buf,"System is woken up!");
+
+        // if(Write(commfd,buf,sizeof(buf)) <= 0) 
+        // {
+        //     ALOGI("service send wakeup_feedback fail.\n");
+        //     return ;
+        // }
+        ALOGI("send_feedback thread is now sending the feedback to client.\n");
+        pthread_mutex_lock(&time_info_mutex);
+        if(Write(commfd,&time_info,sizeof(struct time_info_t)) <= 0) 
+        {
+            ALOGI("service send wakeup_feedback struct fail.\n");
+            Close(commfd);
+            pthread_mutex_unlock(&time_info_mutex);
+            pthread_mutex_unlock(&feedback_mutex);
+            break ;
+        }        
+        pthread_mutex_unlock(&time_info_mutex);
+
+        pthread_mutex_unlock(&feedback_mutex);
+
+
+
+    }
+
+}
+
 
 int main(int argc, char **argv) {
 
@@ -323,28 +391,45 @@
     // RLOGD("**Autosuspend Service Daemon Started**");
     // RLOGD("**Autosuspend Service param count=%d**", argc);
     char tmp[20];
-    int server_sock, commfd, len;
+
+    int commfd, commfd_data, server_sock, server_data_sock,len, len_data;
+
     struct sockaddr_un server_sockaddr;
+    struct sockaddr_un server_data_sockaddr;
     struct sockaddr_un client_sockaddr;
+
     len = sizeof(server_sockaddr);
 
+
     pthread_t tid;
     
-    int auto_enable = 0;
     LYLOGEINIT(USER_LOG_TAG);
     LYLOGSET(LOG_DEBUG);    
     // LYLOGSET(LOG_ERROR);
 
+    int auto_enable = 0;
 
     lynq_get_value(LOG_UCI_FILE, LOG_UCI_MODULE, "debug", tmp);
-    ALOGI("[1832]Autosuspend Service Daemon. debug %s\n",tmp);
+    ALOGI("Autosuspend Service Daemon. debug %s\n",tmp);
     adb_debug_mode=atoi(tmp);
     lynq_get_value(LOG_UCI_FILE, LOG_UCI_MODULE, "auto_enable", tmp);
     auto_enable=atoi(tmp);
     ALOGI("Autosuspend Service Daemon. auto_enable %s\n",tmp);
     init_wakelock_func();
     init_sim_func();
+
+    
     // init_network_func();
+
+    // if(pthread_cond_init(&feedback_cond,NULL) != 0)
+    // {
+    //     strerror_r(errno, buf, sizeof(buf));
+    //     ALOGI("Error creating cond: %s\n", buf);
+    //     return -1;
+    // }
+
+    set_wakeup_callback(wakeup_feedback);
+
    if(auto_enable==0)
    {
       if(autosuspend_disable() < 0)
@@ -373,6 +458,11 @@
     if(server_sock == -1)
         return -1;
 
+    server_data_sock = listen_port(&server_data_sockaddr,SOCK_DATA_PATH);
+    if(server_data_sock == -1)
+        return -1;
+
+
     while (1)
     {
         ALOGI("service socket listening...\n");
@@ -384,16 +474,28 @@
         if(getpeername(commfd, (struct sockaddr *)&client_sockaddr, &len) == -1)
         {
             ALOGI("GETPEERNAME ERROR.\n");
-            close(server_sock);
-            close(commfd);
+            // Close(server_sock);
+            Close(commfd);
             continue;
         }
         else
         {
             ALOGI("Client socket filepath: %s\n", client_sockaddr.sun_path);
         }
+
+        commfd_data = Accept(server_data_sock,NULL,NULL);
+        if(commfd_data == -1)
+        {
+            return -1;
+        }
+        ALOGI("data channel connected.\n");
+        
         pthread_create(&tid,NULL,deal_autosuspend,(void*)&commfd);//这里很容易错,最后一个参数要取地址,这是一个指针
-        pthread_detach(tid);    
+        pthread_detach(tid);   
+
+        pthread_create(&tid,NULL,send_feedback,(void*)&commfd_data);
+        pthread_detach(tid); 
+
 
     }
     
@@ -500,9 +602,9 @@
     rilc_thread_pool();
 
     RLOGD("RIL_Init starting sleep loop");*/
-    while (1) {
-        // ALOGI("start autosuspend_enable:%d\n",(i++));
-        sleep(5);
+    // while (1) {
+    //     // ALOGI("start autosuspend_enable:%d\n",(i++));
+    //     sleep(5);
 
-    }
+    // }
 }
diff --git a/src/lynq/lib/libautosuspend/libautosuspend.c b/src/lynq/lib/libautosuspend/libautosuspend.c
index a933e9c..2588b04 100644
--- a/src/lynq/lib/libautosuspend/libautosuspend.c
+++ b/src/lynq/lib/libautosuspend/libautosuspend.c
@@ -8,36 +8,121 @@
 #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_PATH "/tmp/autosuspend.server"
+#define SERVER_CMD_PATH "/tmp/autosuspend.cmd.server"
+#define SERVER_DATA_PATH "/tmp/autosuspend.data.server"
 // #define CLIENT_PATH "/tmp/autosuspend.client"
 
 
-static int send_cmd(char * value,int len)
+static int client_sock_fd;
+
+static int client_data_sock_fd;
+
+static bool libautosuspend_inited;
+
+// 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
 {
-    int client_sock, rc;
+    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; 
 
 
-
-    if(value == NULL)
-    {
-       return -1;
-    }
+    ALOGI("Start bind and connect to the service.\n");
 
     /**************************************/
     /* Create a UNIX domain stream socket */
     /**************************************/
-    client_sock = socket(AF_UNIX, SOCK_STREAM, 0);
-    if (client_sock == -1) {
+    *cfd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (*cfd == -1) {
         ALOGI("SOCKET ERROR ");
-        return -5;
+        return -1;
     }
 
     /***************************************/
@@ -48,17 +133,16 @@
     /* 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); 
-    sprintf(client_sockaddr.sun_path,"/tmp/suspend.%d.client",(int)getpid());
-    len = sizeof(client_sockaddr);
+    client_sockaddr.sun_family = AF_UNIX;  
+    strcpy(client_sockaddr.sun_path, client_path); 
     
     unlink(client_sockaddr.sun_path);
-    rc = bind(client_sock, (struct sockaddr *) &client_sockaddr, len);
+
+    rc = bind(*cfd, (struct sockaddr *) &client_sockaddr, sizeof(client_sockaddr));
     if (rc == -1){
         ALOGI("BIND ERROR ");
-        close(client_sock);
-        return -4;
+        Close(*cfd);
+        return -1;
     }
         
     /***************************************/
@@ -67,31 +151,145 @@
     /* to it.                              */
     /***************************************/
     server_sockaddr.sun_family = AF_UNIX;
-    strcpy(server_sockaddr.sun_path, SERVER_PATH);
-    rc = connect(client_sock, (struct sockaddr *) &server_sockaddr, len);
+    
+    strcpy(server_sockaddr.sun_path, server_path);
+
+    rc = connect(*cfd, (struct sockaddr *) &server_sockaddr, sizeof(client_sockaddr));
     if(rc == -1){
         ALOGI("CONNECT ERROR ");
-        close(client_sock);
+        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)
+    {
+        // ALOGI("deal_get_feedback thread wait.\n");
+
+        // pthread_cond_wait(&get_feedback_cond,&get_feedback_mutex);
+
+        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_sock,&time_info_client,sizeof(struct time_info_t));
+        if(rc == -1)
+        {           
+            ALOGI("client read wakeup_feedback struct fail.\n");
+            Close(client_sock);
+            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;
+        }
+
+        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_cond_broadcast(&feedback_got_cond);
+
+        pthread_mutex_unlock(&feedback_got_mutex);
+
+        sleep(1);  //给libautosuspend_get_feedback函数时间进入wait
+
+        pthread_cond_broadcast(&feedback_got_cond);
+
+        sleep(1); //希望多给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,(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);                 
-    printf("Sending data...\n");
-    rc = send(client_sock, value, len, 0);
+    // strcpy(buf, DATA);
+
+    ALOGI("Sending data...\n");
+    rc = send(client_sock_fd, value, len, 0);
     if (rc == -1) {
         ALOGI("SEND ERROR ");
-        close(client_sock);
+        Close(client_sock_fd);
         return -2;
     }   
     else {
         ALOGI("Data sent: %s\n",value);
     }
 
-    close(client_sock);
+    // Close(client_sock);
 
     return rc;
 
@@ -99,27 +297,208 @@
 
 int lynq_autosleep_enable(void)
 {
-  char value[15]="enable";
-  int rc = send_cmd(value,strlen(value));
-  if(rc < 0)
-  {
-      ALOGI("libautosleep_enable ret %d\n",rc);
-  }
-  return rc;
+    char value[15]="enable";
+    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)
+    {
+        ALOGI("libautosuspend send enable cmd fail.\n");
+        pthread_mutex_unlock(&client_fd_mutex);
+        return -1;
+    }
+
+    if(Read(client_sock_fd,res,sizeof(res)) <= 0)
+    {
+        ALOGI("libautosuspend get respond fail.\n");
+        pthread_mutex_unlock(&client_fd_mutex);
+        return -1;
+    }
+
+    ALOGI("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 0;
+  
 }
 
 int lynq_autosleep_disable(void)
 {
-  char value[15]="disable";
-  int rc = send_cmd(value,strlen(value));
-  if(rc < 0)
-  {
-      ALOGI("libautosleep_disable ret %d\n",rc);
-  }
-  return rc;
+    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)
+    {
+        ALOGI("libautosuspend send disable cmd fail.\n");
+        pthread_mutex_unlock(&client_fd_mutex);
+        return -1;
+    }
+
+    if(Read(client_sock_fd,res,sizeof(res)) <= 0)
+    {
+        ALOGI("libautosuspend get respond fail.\n");
+        pthread_mutex_unlock(&client_fd_mutex);
+        return -1;
+    }
+
+    ALOGI("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 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;
+    
+   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,socket_timeout);
+   if(ret == 0)
+   {
+     *sleep_start_time = time_info.sleep_start_time;
+	 *wakeup_time = time_info.wakeup_time;
+	 return 0;
+   }
+   else
+   {
+      return -1;
+   }
+   
+
+}
+
+int libautosuspend_get_feedback(struct time_info_t *time_info, int *timeout)
+{
+    // char value[15]="feedback";
+    // char res[15];    
+
+    // if(!libautosuspend_enabled)
+    // {
+    //     ALOGI("system autosuspend disabled, can not get wakeup feedback.\n");
+    //     return -1;
+    // }
+
+    ALOGI("start get feedback from the service.\n");
+
+    memset(time_info,0,sizeof(struct time_info_t));
+
+    if(timeout == NULL)
+    {
+        ALOGI("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)
+        {
+            ALOGI("client set timeout for receiving wakeup_feedback: error.\n");
+            pthread_mutex_unlock(&client_data_fd_mutex);
+            return -1;
+        }
+            
+        ALOGI("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)
+    // {
+    //     ALOGI("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)
+    // {
+    //     ALOGI("libautosuspend_get_feedback fail.\n");
+    //     pthread_mutex_unlock(&client_fd_mutex);
+    //     return -1;
+    // }
+
+
+    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);
+    // ALOGI("[client] system sleep_start timestamps : %ld ms\n",time_info.sleep_start_time);
+    // ALOGI("[client] system wakeup timestamps : %ld ms\n",time_info.wakeup_time);
+
+    return 0;
+
+}
+
+
+
+// static void libautosuspend_get_feedback()
+// {   
+//     pthread_t feedback_tid;
+//     pthread_create(&feedback_tid,NULL,deal_get_feedback,(void*)&client_sock);
+//     pthread_detach(&feedback_tid);
+
+//     return ;
+    
+// }
+