[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/lynq/lib/liblynq-tele-ril/lynq-riltel/powerManager.cpp b/src/lynq/lib/liblynq-tele-ril/lynq-riltel/powerManager.cpp
new file mode 100644
index 0000000..efa8f6d
--- /dev/null
+++ b/src/lynq/lib/liblynq-tele-ril/lynq-riltel/powerManager.cpp
@@ -0,0 +1,506 @@
+/*
+* 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;
+}