[Feature][ZXW-68][AUTOSUSPEND]add wakelock api and autosuspend api

Only Configure:No
Affected branch:master
Affected module:autosuspend
Is it affected on both ZXIC and MTK: only ZXIC and MTK
Self-test: Yes
Doc Update:Yes

Change-Id: I389ac6629a628d3cf197bea5809882c25f408439
diff --git a/cap/zx297520v3/src/lynq/lib/liblynq-autosuspend/lynq-autosuspend.cpp b/cap/zx297520v3/src/lynq/lib/liblynq-autosuspend/lynq-autosuspend.cpp
new file mode 100644
index 0000000..54c88fd
--- /dev/null
+++ b/cap/zx297520v3/src/lynq/lib/liblynq-autosuspend/lynq-autosuspend.cpp
@@ -0,0 +1,445 @@
+#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 "include/libauto/lynq_autosuspend.h"
+#ifdef MOBILETEK_TARGET_PLATFORM_T106
+#include <sc_bsp.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#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;
+
+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)
+        {    
+            printf("read error eintr\n");
+            continue;
+        }
+        else if(errno == EAGAIN || errno == EWOULDBLOCK)
+        {
+            printf("read time out\n");
+            return -2;
+        }
+        else
+        {
+            printf("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)
+        {
+            printf("write error epipe\n");
+            return -1;
+        }  
+        else
+            return -1;
+    }
+    return n;
+}
+static int Close(int fd)
+{
+    if (Close(fd) == -1)
+    {
+        printf("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; 
+    printf("Start bind and connect to the service.\n");
+    /**************************************/
+    /* Create a UNIX domain stream socket */
+    /**************************************/
+    *cfd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (*cfd == -1) {
+        printf("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){
+        printf("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){
+        printf("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)
+    {
+        // printf("deal_get_feedback thread wait.\n");
+        // pthread_cond_wait(&get_feedback_cond,&get_feedback_mutex);
+        printf("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)
+        {           
+            printf("client read wakeup_feedback struct fail.\n");
+            Close(client_sock);
+            pthread_mutex_unlock(&feedback_got_mutex);
+            break ;
+        }
+        else if(rc == -2)
+        {
+            printf("client read wakeup_feedback struct timeout.\n");
+            pthread_mutex_unlock(&feedback_got_mutex);
+            continue;
+        }
+        printf("system sleep_start timestamps : %ld ms\n",time_info_client.sleep_start_time);
+        printf("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;
+    }
+    printf("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)
+    {
+        printf("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)
+    {
+        printf("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_fd, value, len, 0);
+    if (rc == -1) {
+        printf("SEND ERROR ");
+        Close(client_sock_fd);
+        return -2;
+    }   
+    else {
+        printf("Data sent: %s\n",value);
+    }
+    // Close(client_sock);
+    return rc;
+}
+int lynq_autosleep_enable(void)
+{
+    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)
+    {
+        printf("libautosuspend send enable cmd fail.\n");
+        pthread_mutex_unlock(&client_fd_mutex);
+        return -1;
+    }
+    // if(Read(client_sock_fd,res,sizeof(res)) <= 0)
+    // {
+    //     printf("libautosuspend get respond fail.\n");
+    //     pthread_mutex_unlock(&client_fd_mutex);
+    //     return -1;
+    // }
+    // printf("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)
+    {
+        printf("libautosuspend send disable cmd fail.\n");
+        pthread_mutex_unlock(&client_fd_mutex);
+        return -1;
+    }
+    // if(Read(client_sock_fd,res,sizeof(res)) <= 0)
+    // {
+    //     printf("libautosuspend get respond fail.\n");
+    //     pthread_mutex_unlock(&client_fd_mutex);
+    //     return -1;
+    // }
+    // printf("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)
+    // {
+    //     printf("system autosuspend disabled, can not get wakeup feedback.\n");
+    //     return -1;
+    // }
+    printf("start get feedback from the service.\n");
+    memset(time_info,0,sizeof(struct time_info_t));
+    // if(timeout == NULL)
+    // {
+    //     printf("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)
+    //     {
+    //         printf("client set timeout for receiving wakeup_feedback: error.\n");
+    //         pthread_mutex_unlock(&client_data_fd_mutex);
+    //         return -1;
+    //     }
+            
+    //     printf("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)
+    // {
+    //     printf("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)
+    // {
+    //     printf("libautosuspend_get_feedback fail.\n");
+    //     pthread_mutex_unlock(&client_fd_mutex);
+    //     return -1;
+    // }
+    printf("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));
+    printf("libautosuspend_get_feedback success.\n");
+    pthread_mutex_unlock(&feedback_got_mutex);
+    // printf("[client] system sleep_start timestamps : %ld ms\n",time_info.sleep_start_time);
+    // printf("[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 )
+   {
+      printf("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;
+    printf("Get param:%s \n", name);
+    ret = sc_pm_wakelock_lock(name);
+    if (ret)
+    {
+        printf("do_wakelock failed, err:%d", ret);
+        return ret;
+    }
+    printf("do_wakelock succeed\n");
+    return ret;
+}
+int release_wake_lock(char *name)
+{
+    int ret;
+    printf("Get param:%s \n", name);
+    ret = sc_pm_wakelock_unlock(name);
+    if (ret)
+    {
+        printf("do_wakeunlock failed, err:%d", ret);
+        return ret;
+    }
+    printf("do_wakeunlock succeed\n");
+    return ret;
+}
+int lynq_set_lpmode(int lp_mode)
+{
+    int ret;
+    printf("Get param:%d \n", lp_mode);
+    ret = sc_pm_set_lp_mode(lp_mode);
+    if (ret) {
+        printf("do_set_lpmode failed, err:%d", ret);
+        exit(1);
+    }
+    printf("do_set_lpmode succeed\n");
+    return ret;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif