| /* | 
 | * Copyright Statement: | 
 | * | 
 | * This software/firmware and related documentation ("MediaTek Software") are | 
 | * protected under relevant copyright laws. The information contained herein is | 
 | * confidential and proprietary to MediaTek Inc. and/or its licensors. Without | 
 | * the prior written permission of MediaTek inc. and/or its licensors, any | 
 | * reproduction, modification, use or disclosure of MediaTek Software, and | 
 | * information contained herein, in whole or in part, shall be strictly | 
 | * prohibited. | 
 | * | 
 | * MediaTek Inc. (C) 2017. All rights reserved. | 
 | * | 
 | * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES | 
 | * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") | 
 | * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER | 
 | * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL | 
 | * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED | 
 | * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR | 
 | * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH | 
 | * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, | 
 | * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES | 
 | * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. | 
 | * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO | 
 | * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK | 
 | * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE | 
 | * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR | 
 | * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S | 
 | * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE | 
 | * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE | 
 | * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE | 
 | * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. | 
 | */ | 
 | #include <sys/types.h> | 
 | #include <sys/socket.h> | 
 | #include <netinet/in.h> | 
 | #include <arpa/inet.h> | 
 | #include <sys/types.h> | 
 | #include <sys/un.h> | 
 | #include <log/log.h> | 
 | #include <string.h> | 
 | #include <errno.h> | 
 | #include <unistd.h> | 
 | #include <fcntl.h> | 
 | #include <string> | 
 | #include <vector> | 
 | #include <sys/time.h> | 
 | #include <sys/select.h> | 
 | #include <vector> | 
 | #include <deque> | 
 | #include <iterator> | 
 | #include <algorithm> | 
 |  | 
 | #include "common.h" | 
 | #include "powerManager.h" | 
 | #include "util/utils.h" | 
 | #include "stateManager/stateManager.h" | 
 | #include  <vendor-ril/telephony/ril.h> | 
 |  | 
 | #undef DEMOAPP_SOCKET_NAME | 
 | #define DEMOAPP_SOCKET_NAME "/tmp/socket-demoapp" | 
 | #define SOCKET_BUF_SIZE 1024 | 
 | #define MAX_CLIENT_SIZE 30 | 
 | #undef LOG_TAG | 
 | #define LOG_TAG "DEMO_powermanager" | 
 | int cli_socket[MAX_CLIENT_SIZE]; | 
 | std::vector<int> keepalive_start; | 
 | std::vector<int> Keepalive_stop; | 
 |  | 
 | //global variable | 
 | static pthread_mutex_t s_WakeupMutex = PTHREAD_MUTEX_INITIALIZER; | 
 | static pthread_cond_t s_WakeupCond = PTHREAD_COND_INITIALIZER; | 
 | //marco define | 
 | #define LIST_LOCK()  pthread_mutex_lock(&s_WakeupMutex) | 
 | #define LIST_UNLOCK() pthread_mutex_unlock(&s_WakeupMutex) | 
 | #define WAITLIST() pthread_cond_wait(&s_WakeupCond,&s_WakeupMutex) | 
 | #define WAKEUPLIST() pthread_cond_signal(&s_WakeupCond) | 
 | #define WAKEUPREASONPATH "/sys/power/spm/wakeup_reason" | 
 | //#define WAKEUPSTATUS "/sys/power/suspend_status" | 
 |  | 
 | static std::deque<std::string> wakeup_reasons; | 
 |  | 
 | std::string read_wakeup_reason() { | 
 |     if(access(WAKEUPREASONPATH, R_OK) == -1) { | 
 |         RLOGD("read_wakeup_reason, %s cann't read(%s),just return", WAKEUPREASONPATH, strerror(errno)); | 
 |         return ""; | 
 |     } | 
 |  | 
 |     int fd; | 
 |     fd = open(WAKEUPREASONPATH , O_RDONLY); | 
 |     if(fd == -1) { | 
 |         RLOGD("read_wakeup_reason, open %s fail(%s),just return", WAKEUPREASONPATH, strerror(errno)); | 
 |         return ""; | 
 |     } | 
 |  | 
 |     ssize_t len; | 
 |     char buf[50]={0}; | 
 |     std::string reason(""); | 
 |     len = read(fd, buf,sizeof(buf) -1); | 
 |     if(len == -1) { | 
 |         RLOGD("read_wakeup_reason, read %s fail(%s),just return", WAKEUPREASONPATH, strerror(errno)); | 
 |         reason=""; | 
 |         goto fail; | 
 |     } | 
 |     RLOGD("read_wakeup_reason is %s", buf); | 
 |     reason = buf; | 
 | fail: | 
 |     close(fd); | 
 |     return reason; | 
 | } | 
 |  | 
 | void write_wakeup_reason(std::string reason) { | 
 |     int fd; | 
 |     ssize_t len; | 
 |     if(reason.empty()) { | 
 |         RLOGD("write_wakeup_reason is empty, just return"); | 
 |         return; | 
 |     } | 
 |     std::string save = read_wakeup_reason(); | 
 |     if(save == reason) { | 
 |         RLOGD("write_wakeup_reason is same, just return"); | 
 | //        return; //don't need return, handle initial reason equal to first write reason. | 
 |     } | 
 |     RLOGD("write_wakeup_reason: %s", reason.c_str()); | 
 |     if(access(WAKEUPREASONPATH, W_OK) == -1) { | 
 |         RLOGD("write_wakeup_reason, %s cann't write(%s), just return", WAKEUPREASONPATH, strerror(errno)); | 
 |         return ; | 
 |     } | 
 |     fd = open(WAKEUPREASONPATH , O_WRONLY); | 
 |     if(fd == -1) { | 
 |         RLOGD("write_wakeup_reason, open %s fail(%s), just return", WAKEUPREASONPATH,strerror(errno)); | 
 |         return ; | 
 |     } | 
 |     len = write(fd, reason.c_str(), reason.size()); | 
 |     if(len == -1) { | 
 |         RLOGD("write_wakeup_reason, write %s fail(%s)", WAKEUPREASONPATH,strerror(errno)); | 
 |     } | 
 |     close(fd); | 
 | } | 
 |  | 
 | void *wakeup_reason_loop(void *param) | 
 | { | 
 |     std::string reason(""); | 
 |     RLOGD("wakeup_reason_loop start"); | 
 |  | 
 |     prctl(PR_SET_NAME,(unsigned long)"demo_wakeup_reason_loop"); | 
 |  | 
 |     LIST_LOCK(); | 
 |     wakeup_reasons.clear(); | 
 |     LIST_UNLOCK(); | 
 |  | 
 |     for(;;){ | 
 |  | 
 |         LIST_LOCK(); | 
 |         if(wakeup_reasons.empty()) {    //if blank list  then wait | 
 |             RLOGD("wakeup reason list is empty ,then wait!"); | 
 |             while(wakeup_reasons.empty()){ | 
 |                 WAITLIST(); | 
 |             } | 
 |         } | 
 |         reason = wakeup_reasons.front(); | 
 |         wakeup_reasons.pop_front(); | 
 |         LIST_UNLOCK(); | 
 |         write_wakeup_reason(reason); | 
 |     } | 
 |     return 0; | 
 | } | 
 |  | 
 | void handle_wakeup_reason(int requestCode) { | 
 |     RLOGD("handle_wakeup_reason %s:", android::requestToString(requestCode)); | 
 |     std::string reason(""); | 
 |     switch (requestCode){ | 
 |     //CCIF_CALL | 
 |     case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: | 
 |     case RIL_UNSOL_CALL_RING: | 
 |     case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: | 
 |     case RIL_UNSOL_RINGBACK_TONE: | 
 |     case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: | 
 |     case RIL_UNSOL_SRVCC_STATE_NOTIFY: | 
 |     case RIL_UNSOL_ECONF_SRVCC_INDICATION: | 
 |     case RIL_UNSOL_ECONF_RESULT_INDICATION: | 
 |     case RIL_UNSOL_CRSS_NOTIFICATION: | 
 |     case RIL_UNSOL_INCOMING_CALL_INDICATION: | 
 |     case RIL_UNSOL_CALL_INFO_INDICATION: | 
 |     case RIL_UNSOL_SUPP_SVC_NOTIFICATION: | 
 |     { | 
 |         reason = "CCIF_CALL"; | 
 |         break; | 
 |     } | 
 |     //CCIF_NW | 
 |     case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED: | 
 |     case RIL_UNSOL_NITZ_TIME_RECEIVED: | 
 |     case RIL_UNSOL_SIGNAL_STRENGTH: | 
 |     case RIL_UNSOL_RESTRICTED_STATE_CHANGED: | 
 |     case RIL_UNSOL_CELL_INFO_LIST: | 
 |     case RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED: | 
 |     { | 
 |         reason = "CCIF_NW"; | 
 |         break; | 
 |     } | 
 |     //CCIF_Message | 
 |     case RIL_UNSOL_RESPONSE_NEW_SMS: | 
 |     case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT: | 
 |     case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM: | 
 |     case RIL_UNSOL_SIM_SMS_STORAGE_FULL: | 
 |     case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS: | 
 |     case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS: | 
 |     case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL: | 
 |     case RIL_UNSOL_SMS_READY_NOTIFICATION: | 
 |     case RIL_UNSOL_ON_USSD: | 
 |     { | 
 |         reason = "CCIF_MESSAGE"; | 
 |         break; | 
 |     } | 
 |     //CCIF_Other | 
 |     case RIL_UNSOL_DATA_CALL_LIST_CHANGED: | 
 |     case RIL_UNSOL_ECALL_MSDHACK: | 
 |     case RIL_UNSOL_SIM_REFRESH: | 
 |     case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED: | 
 |     case RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED: | 
 |     case RIL_UNSOL_STK_SESSION_END: | 
 |     case RIL_UNSOL_STK_PROACTIVE_COMMAND: | 
 |     case RIL_UNSOL_STK_EVENT_NOTIFY: | 
 |     case RIL_UNSOL_STK_CALL_SETUP: | 
 |     case RIL_UNSOL_STK_BIP_PROACTIVE_COMMAND: | 
 |     case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: | 
 |     case RIL_UNSOL_RIL_CONNECTED: | 
 |     case RIL_UNSOL_RADIO_CAPABILITY: | 
 |     { | 
 |         reason = "CCIF_OTHER"; | 
 |         break; | 
 |     } | 
 |     default: | 
 |         RLOGD("handle_wakeup_reason no wakeup reason, just return"); | 
 |         return; | 
 |     } | 
 |     if(reason.empty()) { | 
 |         RLOGE("handle_wakeup_reason error , reason is empty, return"); | 
 |         return; | 
 |     } | 
 |     LIST_LOCK(); | 
 |     wakeup_reasons.push_back(reason); | 
 |     WAKEUPLIST(); | 
 |     LIST_UNLOCK(); | 
 | } | 
 |  | 
 | int demo_open_socket(const char *path) | 
 | { | 
 |     RLOGD("demo_open_socket"); | 
 |     int sd; | 
 |     int res; | 
 |     struct sockaddr_un addr; | 
 |  | 
 |     sd = socket(AF_UNIX, SOCK_STREAM, 0); | 
 |     if (sd < 0) { | 
 |         RLOGE("socket error: %s", strerror(errno)); | 
 |         return sd; | 
 |     } | 
 |  | 
 |     if(remove(path) == -1 && errno != ENOENT) | 
 |     { | 
 |         RLOGD("remove-%s, remove error: %s", path, strerror(errno)); | 
 |     } | 
 |  | 
 |     memset(&addr, 0, sizeof(struct sockaddr_un)); | 
 |     addr.sun_family = AF_UNIX; | 
 |     strncpy(addr.sun_path, path, sizeof(addr.sun_path)-1); | 
 |  | 
 |     res = bind(sd, (struct sockaddr*)&addr, sizeof(struct sockaddr_un)); | 
 |     if (res != 0) { | 
 |         RLOGE("bind error: %s\n", strerror(errno)); | 
 |         goto error; | 
 |     } | 
 |  | 
 |     res = listen(sd, 8); | 
 |     if (res != 0) { | 
 |         RLOGE("listen error: %s\n", strerror(errno)); | 
 |         goto error; | 
 |     } | 
 |     return sd; | 
 | error: | 
 |     if (sd >=0) | 
 |         close(sd); | 
 |     return -1; | 
 | } | 
 |  | 
 | int send_data(int sockfd, const char *buf, int len) { | 
 |     int ret = 0; | 
 |     int cur_pos = 0; | 
 |  | 
 |     if (sockfd <= 0) | 
 |         return 0; | 
 |  | 
 |     while(cur_pos < len) { | 
 |         ret = send(sockfd, &buf[cur_pos], len - cur_pos, MSG_DONTWAIT); | 
 |         if (ret == len - cur_pos) | 
 |             break; | 
 |  | 
 |         if (ret <= 0) { | 
 |             RLOGE("SOCKET ERROR errno:%d,%s", errno, strerror(errno)); | 
 |             if (errno == EAGAIN || errno == EINTR) | 
 |             { | 
 |                 RLOGD("send to internet buffer full, wait(10ms)"); | 
 |                 usleep(10000); | 
 |                 continue; | 
 |             } | 
 |             if (errno == ECONNRESET || errno == EPIPE) | 
 |             { | 
 |                 sockfd = -1; | 
 |                 RLOGD("buffer client connect is reset"); | 
 |             } | 
 |             break; | 
 |         } else | 
 |             cur_pos += ret; | 
 |     } | 
 |  | 
 |     return ret; | 
 | } | 
 |  | 
 | void sendSmsMsg(RIL_SOCKET_ID soc_id) | 
 | { | 
 |     char *msg = "sms_on"; | 
 |     for (int i = 0 ; i < MAX_CLIENT_SIZE; i++) { | 
 |         if(cli_socket[i] > 0 ) { | 
 |             auto it_start = std::find(keepalive_start.begin(), keepalive_start.end(), cli_socket[i]); | 
 |             auto it_stop = std::find(Keepalive_stop.begin(), Keepalive_stop.end(), cli_socket[i]); | 
 |             if(it_start == std::end(keepalive_start) && it_stop == std::end(Keepalive_stop)) { | 
 |                 RLOGD("sendSmsMsg(%d): %s", cli_socket[i], msg); | 
 |                 send_data(cli_socket[i], msg, strlen(msg)); | 
 |             } | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | void sendCallMsg(bool call_on) | 
 | { | 
 |     char* on = "call_on"; | 
 |     char* off = "call_off"; | 
 |     char *msg = call_on ? on : off; | 
 |     for (int i = 0 ; i < MAX_CLIENT_SIZE; i++) { | 
 |         if(cli_socket[i] > 0 ) { | 
 |             auto it_start = std::find(keepalive_start.begin(), keepalive_start.end(), cli_socket[i]); | 
 |             auto it_stop = std::find(Keepalive_stop.begin(), Keepalive_stop.end(), cli_socket[i]); | 
 |             if(it_start == std::end(keepalive_start) && it_stop == std::end(Keepalive_stop)) { | 
 |                 RLOGD("sendSmsMsg(%d): %s", cli_socket[i], msg); | 
 |                 send_data(cli_socket[i], msg, strlen(msg)); | 
 |             } | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | void sendKeepAlive(const char* msg) | 
 | { | 
 |     std::string str(msg); | 
 |     if (str.find("RIL_REQUEST_START_KEEPALIVE_PRO") != std::string::npos) { | 
 |         for (auto it : keepalive_start) { | 
 |             RLOGD("sendKeepAlive response(RIL_REQUEST_START_KEEPALIVE_PRO(%d)): %s",it, msg); | 
 |             send_data(it, msg, strlen(msg)); | 
 |         } | 
 |     } | 
 |  | 
 |     if (str.find("RIL_REQUEST_STOP_KEEPALIVE_PRO") != std::string::npos) { | 
 |         for (auto it : Keepalive_stop) { | 
 |             RLOGD("sendKeepAlive response(RIL_REQUEST_STOP_KEEPALIVE_PRO(%d)): %s", it, msg); | 
 |             send_data(it, msg, strlen(msg)); | 
 |         } | 
 |     } | 
 |  | 
 |     if (str.find("RIL_UNSOL_KEEPALIVE_STATUS_PRO") != std::string::npos) { | 
 |         for (auto it : keepalive_start) { | 
 |             RLOGD("sendKeepAlive notify((start)RIL_UNSOL_KEEPALIVE_STATUS_PRO(%d)): %s", it, msg); | 
 |             send_data(it, msg, strlen(msg)); | 
 |         } | 
 |         for (auto it : Keepalive_stop) { | 
 |             RLOGD("sendKeepAlive notify((stop)RIL_UNSOL_KEEPALIVE_STATUS_PRO(%d)): %s", it, msg); | 
 |             send_data(it, msg, strlen(msg)); | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | #define SOCKET_ZERO   0 | 
 | #define SOCKET_SUCC   1 | 
 | #define SOCKET_FAIL  -1 | 
 |  | 
 | void dispatch_cmd(int fd, char* msg) { | 
 |     RLOGD("dispatch_cmd: %s", msg); | 
 |     std::vector<std::string> v; | 
 |     utils::tokenize(std::string(msg),',',v); | 
 |     int i = 0; | 
 |     for(auto s: v) { | 
 |         RLOGD("%d:%s",i, s.c_str()); | 
 |         i++; | 
 |     } | 
 |     if(v.size() != 10 && v.size() != 2) { | 
 |         RLOGE("transfer parameters num is wrong: %d", v.size()); | 
 |         return ; | 
 |     } | 
 |     int id = get_default_sim_data(); | 
 |     if(v[0] == std::string("RIL_REQUEST_START_KEEPALIVE_PRO")) { | 
 |         keepalive_start.push_back(fd); | 
 |         RLOGD("[SIM%d]start keepalive", id); | 
 |         RequestInfo *info = creatRILInfoAndInit(RIL_REQUEST_START_KEEPALIVE_PRO, OTHER, (RIL_SOCKET_ID)id); | 
 |         char* argv[10] = {0}; | 
 |         for(int i=0; i< v.size() && i < 10; i++){ | 
 |             argv[i] = const_cast<char*>(v[i].c_str()); | 
 |         } | 
 |         startKeepAlivePro(v.size(), argv, (RIL_SOCKET_ID)id, info); | 
 |     } else if(v[0] == std::string("RIL_REQUEST_STOP_KEEPALIVE_PRO")) { | 
 |         Keepalive_stop.push_back(fd); | 
 |         RLOGD("[SIM%d]stop keepalive", id); | 
 |         RequestInfo *info = creatRILInfoAndInit(RIL_REQUEST_STOP_KEEPALIVE_PRO, OTHER, (RIL_SOCKET_ID)id); | 
 |         char* argv[2] = {0}; | 
 |         for(int i=0; i< v.size() && i < 2; i++){ | 
 |             argv[i] = const_cast<char*>(v[i].c_str()); | 
 |         } | 
 |         stopKeepAlivePro(v.size(), argv, (RIL_SOCKET_ID)id, info); | 
 |     } else { | 
 |         RLOGD("dispatch_cmd(%s) error", v[0].c_str()); | 
 |     } | 
 | } | 
 |  | 
 | void eraseSocket(std::vector<int> &v, int sd) { | 
 |     auto it = std::find(v.begin(), v.end(), sd); | 
 |     if (it != std::end(v)) { | 
 |         v.erase(it); | 
 |     } | 
 | } | 
 |  | 
 | void *StartPMSocket(void *param) | 
 | { | 
 |     RLOGD("StartPMSocket start"); | 
 |     char buf[SOCKET_BUF_SIZE] = {0}; | 
 |     int max_fd; | 
 |     fd_set readfds; | 
 |     for (int i=0; i < MAX_CLIENT_SIZE; i++) { | 
 |         cli_socket[i] = 0; | 
 |     } | 
 |     int ssd = -1; | 
 |     struct sockaddr_un addr; | 
 |     socklen_t socke_len; | 
 |  | 
 |     ssd = demo_open_socket(DEMOAPP_SOCKET_NAME); | 
 |     if(ssd < 0) | 
 |     { | 
 |         RLOGE("ssd < 0, just return"); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     while (true) { | 
 |         FD_ZERO(&readfds); | 
 |         FD_SET(ssd, &readfds); | 
 |         max_fd = ssd; | 
 |         for(int i = 0; i < MAX_CLIENT_SIZE; i++) { | 
 |             int sd = cli_socket[i]; | 
 |             if(sd > 0) { | 
 |                 FD_SET(sd, &readfds); | 
 |             } | 
 |             if(sd > max_fd) { | 
 |                 max_fd = sd; | 
 |             } | 
 |         } | 
 |         int act_fd_num = select(max_fd +1, &readfds, NULL, NULL, NULL); | 
 |         if(act_fd_num < 0 && (errno != EINTR)) { | 
 |             RLOGE("select error"); | 
 |         } | 
 |         if(FD_ISSET(ssd, &readfds)) { | 
 |             int cli_soc = accept(ssd, (struct sockaddr*)&addr, &socke_len); | 
 |             if (cli_soc < 0) | 
 |             { | 
 |                 RLOGE("accept error: %s", strerror(errno)); | 
 |                 close(cli_soc); | 
 |                 return NULL; | 
 |             } | 
 |             RLOGD("Accept a client , client id is %d", cli_soc); | 
 |             //TBD send sometings. | 
 |             for(int i = 0; i < MAX_CLIENT_SIZE; i++) { | 
 |                 if(cli_socket[i] == 0) { | 
 |                     cli_socket[i] = cli_soc; | 
 |                     RLOGD("add new socket %d", cli_soc); | 
 |                     break; | 
 |                 } | 
 |             } | 
 |         } | 
 |         for(int i = 0; i < MAX_CLIENT_SIZE; i++) { | 
 |             int sd = cli_socket[i]; | 
 |             if(FD_ISSET(sd, &readfds)) { | 
 |                 memset(buf, 0, sizeof(buf)); | 
 |                 int ret = recv(sd, buf,SOCKET_BUF_SIZE, 0); | 
 |                 if (ret < 0) { | 
 |                     RLOGE("data_recv select error, ret=%d, error=%s(%d),fd=%d", ret, strerror(errno), errno, sd); | 
 |                 } else if (ret == SOCKET_ZERO) { | 
 |                     RLOGE("data_recv recv error, maybe client socket closed, ret=%d, error=%s(%d),fd=%d", ret, strerror(errno), errno, sd); | 
 |                     close(sd); | 
 |                     cli_socket[i] = 0; | 
 |                     eraseSocket(keepalive_start,sd); | 
 |                     eraseSocket(Keepalive_stop,sd); | 
 |                 } else { | 
 |                     buf[ret] = '\0'; | 
 |                     dispatch_cmd(sd, buf); | 
 |                 } | 
 |             } | 
 |         } | 
 |     } | 
 |     RLOGD("start PowerManager Done"); | 
 |     return 0; | 
 | } |