Files

539 lines
16 KiB
C++
Raw Permalink Normal View History

2026-09-22 09:38:26 +08:00
/*
* ThermalManager.cpp
*
* Copyright (C) 2016 Spreadtrum Communications Inc.
*/
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/un.h>
#include "ThermalSensor.h"
#include "ThermalXmlParser.h"
#include "ThermalManager.h"
#include "ThermalZoneLevel.h"
#include "ThermalTrip.h"
#include "ThermalAction.h"
#include "ThermalGovernor.h"
#include "ThermalActionFactory.h"
#include "ChargeDetect.h"
#include "alog.h"
#undef LOG_TAG
#define LOG_TAG "ThermalManager"
namespace android {
ThermalManager::ThermalManager() {
pthread_mutex_init(&mCountLock, NULL);
pthread_mutex_init(&mThreadLock, NULL);
pthread_mutex_init(&mEnCntLock, NULL);
pthread_cond_init(&mCountFlag, NULL);
mpXmlParser = new ThermalXmlParser();
mLimEnCnt = 0;
mGovEnPrst = 0;
mLimEnPrst = 0;
mGovEnCnt = 1;
mPaEnCnt = 1;
mChgEnCnt = 0;
mChgDetector = NULL;
}
ThermalManager::~ThermalManager() {
delete mpXmlParser;
delete mChgDetector;
}
void ThermalManager::run(void) {
mSensorDeque = mpXmlParser->initSensorsFromXml();
pthread_t pid;
ALOGI("create thermal monitor pthread");
int ret = pthread_create(&pid, NULL, thermalMonitor, this);
if (ret) {
ALOGE("create thermalMonitor pthread failed!");
}
#if 0
int ret = pthread_create(&pid, NULL, socketListen, this);
if (ret) {
ALOGE("create socketListen pthread failed!");
}
#endif
mChgDetector = new ChargeDetect(this);
check_property();
receiveEvent();
return;
}
void ThermalManager::check_property(void) {
#if 0
int value;
pthread_mutex_lock(&mEnCntLock);
value = property_get_int32(GOVERNOR_ENABLE, 1);
if (value == 1) {
mGovEnCnt = 1;
}
value = property_get_int32(GOVERNOR_PA_ENABLE, 1);
if (value == 1) {
mPaEnCnt = 1;
} else {
sendEvent(EVENT_PADIS);
}
if (getChargeEn()) {
mChgEnCnt = 1;
}
value = property_get_int32(LIMIT_TRIP_EN, 0);
if (value == 1) {
mLimEnCnt = 1;
}
if (mGovEnCnt < 1) {
sendEvent(EVENT_GOVDIS);
} else if (mLimEnCnt == 1) {
mGovEnCnt--;
sendEvent(EVENT_LIMEN);
} else {
sendEvent(EVENT_TRIP);
}
pthread_mutex_unlock(&mEnCntLock);
#else
if (getChargeEn()) {
mChgEnCnt = 1;
}
sendEvent(EVENT_TRIP);
#endif
return;
}
void* ThermalManager::thermalMonitor(void* ptr) {
int temp;
bool update_flag = false;
ThermalManager* handler = (ThermalManager*)(ptr);
ThermalSensor* sensor;
std::deque<ThermalSensor*>::iterator iter;
while (1) {
for (iter = handler->mSensorDeque.begin();
iter != handler->mSensorDeque.end(); iter++) {
sensor = *iter;
std::deque<ThermalZoneLevel*>& levelDeque = sensor->getThermalZoneDeque();
if (levelDeque.size() == 0) {
continue;
}
temp = sensor->fetchSensorTemp();
sensor->setCurrTemp(temp);
bool update = sensor->governorUpdate();
if (update) {
ThermalEvent* event = new ThermalEvent(EVENT_TRIP, sensor);
pthread_mutex_lock(&(handler->mCountLock));
handler->mEventQueue.push(event);
pthread_mutex_unlock(&(handler->mCountLock));
update_flag = true;
ALOGI("send event type=%d, sensor=%s", EVENT_TRIP, sensor->getName());
}
}
if (update_flag) {
pthread_cond_signal(&(handler->mCountFlag));
update_flag = false;
}
usleep(sensor->getPollingDelay() * 1000);
}
return NULL;
}
void ThermalManager::receiveEvent(void) {
while (1) {
pthread_mutex_lock(&mCountLock);
bool eventEmpty = mEventQueue.empty();
bool update = false;
pthread_mutex_unlock(&mCountLock);
while (!eventEmpty) {
pthread_mutex_lock(&mCountLock);
ThermalEvent* event = mEventQueue.front();
mEventQueue.pop();
pthread_mutex_unlock(&mCountLock);
switch (event->mType) {
case EVENT_TRIP:
ALOGI("received EVENT_TRIP, sensor=%s", event->mSensor->getName());
event->mSensor->tripActions();
break;
case EVENT_GOVDIS:
ALOGI("received EVENT_GOVDIS, sensor=%s, GovEnCnt=%d",
event->mSensor->getName(), mGovEnCnt);
pthread_mutex_lock(&mEnCntLock);
if (mGovEnCnt != 0) {
pthread_mutex_unlock(&mEnCntLock);
break;
}
pthread_mutex_unlock(&mEnCntLock);
update = event->mSensor->enabledGovernor(false);
if (update) {
event->mSensor->tripActions();
}
/*if (mGovEnPrst) {
property_set(GOVERNOR_ENABLE, "0");
}*/
break;
case EVENT_GOVEN:
ALOGI("received EVENT_GOVDEN, sensor=%s, GovEnCnt=%d",
event->mSensor->getName(), mGovEnCnt);
pthread_mutex_lock(&mEnCntLock);
if (mGovEnCnt != 1) {
pthread_mutex_unlock(&mEnCntLock);
break;
}
pthread_mutex_unlock(&mEnCntLock);
update = event->mSensor->enabledGovernor(true);
if (update) {
event->mSensor->reTripActions();
}
/*if (mGovEnPrst) {
property_set(GOVERNOR_ENABLE, "1");
}*/
break;
case EVENT_PADIS:
ALOGI("received EVENT_PADIS, sensor=%s, PaEnCnt=%d",
event->mSensor->getName(), mPaEnCnt);
pthread_mutex_lock(&mEnCntLock);
if (mPaEnCnt != 0) {
pthread_mutex_unlock(&mEnCntLock);
break;
}
pthread_mutex_unlock(&mEnCntLock);
if (!strcmp(event->mSensor->getName(), PA_SENSOR)) {
update = event->mSensor->enabledGovernor(false);
if (update) {
event->mSensor->tripActions();
}
} else {
event->mSensor->enableSensorActions(false, PA_SENSOR);
}
//property_set(GOVERNOR_PA_ENABLE, "0");
break;
case EVENT_PAEN:
ALOGI("received EVENT_PAEN, sensor=%s, PaEnCnt=%d",
event->mSensor->getName(), mPaEnCnt);
pthread_mutex_lock(&mEnCntLock);
if (mPaEnCnt != 1) {
pthread_mutex_unlock(&mEnCntLock);
break;
}
pthread_mutex_unlock(&mEnCntLock);
if (!strcmp(event->mSensor->getName(), PA_SENSOR)) {
event->mSensor->enabledGovernor(true);
} else {
event->mSensor->enableSensorActions(true, PA_SENSOR);
}
//property_set(GOVERNOR_PA_ENABLE, "1");
break;
case EVENT_CHGDIS:
ALOGI("received EVENT_CHGDIS, sensor=%s, ChgEnCnt=%d",
event->mSensor->getName(), mChgEnCnt);
if (!strcmp(event->mSensor->getName(), CHARGE_SENSOR)) {
update = event->mSensor->enabledGovernor(false);
if (update) {
event->mSensor->tripActions();
}
} else {
event->mSensor->enableSensorActions(false, CHARGE_SENSOR);
}
break;
case EVENT_CHGEN:
ALOGI("received EVENT_CHGEN, sensor=%s, ChgEnCnt=%d",
event->mSensor->getName(), mChgEnCnt);
if (!strcmp(event->mSensor->getName(), CHARGE_SENSOR)) {
event->mSensor->enabledGovernor(true);
} else {
event->mSensor->enableSensorActions(true, CHARGE_SENSOR);
}
if (mGovEnCnt < 1) {
bool ret = event->mSensor->tripPerfActions();
if (ret == true) {
break;
}
}
if (mLimEnCnt) {
event->mSensor->tripLimitActions();
break;
}
event->mSensor->tripLastChgActions();
break;
case EVENT_LIMEN:
ALOGI("received EVENT_LIMEN, sensor=%s", event->mSensor->getName());
event->mSensor->limitEnable(true);
/*if (mLimEnPrst) {
property_set(LIMIT_TRIP_EN, "1");
}*/
break;
case EVENT_LIMDIS:
ALOGI("received EVENT_LIMDIS, sensor=%s", event->mSensor->getName());
update = event->mSensor->limitEnable(false);
/*if (mLimEnPrst) {
property_set(LIMIT_TRIP_EN, "0");
}*/
if (update) {
event->mSensor->reTripActions();
}
break;
default:
break;
}
delete event;
pthread_mutex_lock(&mCountLock);
eventEmpty = mEventQueue.empty();
pthread_mutex_unlock(&mCountLock);
}
pthread_cond_wait(&mCountFlag, &mThreadLock);
}
}
ThermalManager::ThermalEvent::ThermalEvent() {}
ThermalManager::ThermalEvent::ThermalEvent(enum EventType type,
ThermalSensor* sensor) {
ThermalEvent::mType = type;
ThermalEvent::mSensor = sensor;
}
ThermalManager::ThermalEvent::~ThermalEvent() {}
void ThermalManager::sendEvent(enum EventType type) {
std::deque<ThermalSensor*>::iterator iter;
for (iter = mSensorDeque.begin(); iter != mSensorDeque.end(); iter++) {
ThermalSensor* sensor = *iter;
ThermalEvent* event = new ThermalEvent();
event->mSensor = sensor;
event->mType = type;
ALOGI("send 0x%x, sensor=%s", type, sensor->getName());
pthread_mutex_lock(&mCountLock);
mEventQueue.push(event);
pthread_mutex_unlock(&mCountLock);
pthread_cond_signal(&mCountFlag);
}
return;
}
#if 0
#define SOCKET_PATH "/tmp/thermal.domain"
void* ThermalManager::socketListen(void* ptr) {
char buf[128];
int fdListen, new_fd, ret;
struct sockaddr_un peeraddr;
socklen_t socklen = sizeof(peeraddr);
struct sockaddr_un srv_addr;
ThermalManager* handler = (ThermalManager*)ptr;
fdListen =socket(PF_UNIX,SOCK_STREAM,0);
if (fdListen < 0) {
ALOGE("get socket %s failed!", SOCKET_PATH);
return NULL;
}
srv_addr.sun_family=AF_UNIX;
strncpy(srv_addr.sun_path, SOCKET_PATH, sizeof(srv_addr.sun_path)-1);
unlink(SOCKET_PATH);
ret=bind(fdListen, (struct sockaddr*)&srv_addr, sizeof(srv_addr));
if(ret < 0) {
ALOGE("socket bind error!");
close(fdListen);
return NULL;
}
ALOGI("listen socket ...");
ret = listen(fdListen, 5);
if (ret < 0) {
ALOGE("listen socket error: %d", ret);
close(fdListen);
return NULL;
}
while (1) {
new_fd = accept(fdListen, (struct sockaddr*)&peeraddr, &socklen);
ALOGI("A client is accepted!");
memset(buf, 0, sizeof(buf));
int len = recv(new_fd, buf, sizeof(buf), 0);
if (len <= 0) {
close(new_fd);
continue;
}
int cmd = atoi(buf);
if (cmd < 0 || cmd >= THMCMD_MAX ||
(cmd == 0 && buf[0] != '0')) {
ALOGE("received cmd: %s is wrong!", buf);
close(new_fd);
continue;
}
ALOGI("received cmd:%d : %s", cmd, handler->mCmdMsg[cmd]);
switch (cmd) {
case THMCMD_SET_EN:
pthread_mutex_lock(&(handler->mEnCntLock));
handler->mGovEnCnt++;
handler->mPaEnCnt++;
handler->mChgEnCnt++;
handler->mGovEnPrst = 1;
pthread_mutex_unlock(&(handler->mEnCntLock));
handler->sendEvent(EVENT_GOVEN);
break;
case THMCMD_SET_DIS:
pthread_mutex_lock(&(handler->mEnCntLock));
handler->mGovEnCnt--;
handler->mPaEnCnt--;
handler->mChgEnCnt--;
handler->mGovEnPrst = 1;
pthread_mutex_unlock(&(handler->mEnCntLock));
handler->sendEvent(EVENT_GOVDIS);
break;
case THMCMD_SET_PERF_EN:
pthread_mutex_lock(&(handler->mEnCntLock));
handler->mGovEnCnt--;
handler->mPaEnCnt--;
handler->mChgEnCnt--;
handler->mGovEnPrst = 0;
pthread_mutex_unlock(&(handler->mEnCntLock));
handler->sendEvent(EVENT_GOVDIS);
break;
case THMCMD_SET_PERF_DIS:
pthread_mutex_lock(&(handler->mEnCntLock));
handler->mGovEnCnt++;
handler->mPaEnCnt++;
handler->mChgEnCnt++;
handler->mGovEnPrst = 0;
pthread_mutex_unlock(&(handler->mEnCntLock));
handler->sendEvent(EVENT_GOVEN);
break;
case THMCMD_GET_STAT:
pthread_mutex_lock(&(handler->mEnCntLock));
if (handler->mGovEnCnt > 0) {
snprintf(buf, sizeof(buf), "true");
} else {
snprintf(buf, sizeof(buf), "false");
}
pthread_mutex_unlock(&(handler->mEnCntLock));
len = send(new_fd, buf, strlen(buf), 0);
if (len < (int)strlen(buf)) {
ALOGE("set ThmPaEn info error: %s", buf);
}
break;
case THMCMD_SET_PA_EN:
pthread_mutex_lock(&(handler->mEnCntLock));
handler->mPaEnCnt++;
pthread_mutex_unlock(&(handler->mEnCntLock));
handler->sendEvent(EVENT_PAEN);
break;
case THMCMD_SET_PA_DIS:
pthread_mutex_lock(&(handler->mEnCntLock));
handler->mPaEnCnt--;
pthread_mutex_unlock(&(handler->mEnCntLock));
handler->sendEvent(EVENT_PADIS);
break;
case THMCMD_GET_PA_STAT:
pthread_mutex_lock(&(handler->mEnCntLock));
if (handler->mPaEnCnt > 0) {
snprintf(buf, sizeof(buf), "true");
} else {
snprintf(buf, sizeof(buf), "false");
}
pthread_mutex_unlock(&(handler->mEnCntLock));
len = send(new_fd, buf, strlen(buf), 0);
if (len < (int)strlen(buf)) {
ALOGE("set ThmPaEn info error: %s", buf);
}
break;
case THMCMD_SET_CHG_EN:
pthread_mutex_lock(&(handler->mEnCntLock));
handler->mChgEnCnt++;
pthread_mutex_unlock(&(handler->mEnCntLock));
handler->enableCharge(true);
break;
case THMCMD_SET_CHG_DIS:
pthread_mutex_lock(&(handler->mEnCntLock));
handler->mChgEnCnt--;
pthread_mutex_unlock(&(handler->mEnCntLock));
handler->enableCharge(false);
break;
case THMCMD_GET_CHG_STAT:
pthread_mutex_lock(&(handler->mEnCntLock));
if (handler->mChgEnCnt > 0) {
snprintf(buf, sizeof(buf), "true");
} else {
snprintf(buf, sizeof(buf), "false");
}
pthread_mutex_unlock(&(handler->mEnCntLock));
len = send(new_fd, buf, strlen(buf), 0);
if (len < (int)strlen(buf)) {
ALOGE("set ThmPaEn info error: %s", buf);
}
break;
case THMCMD_SET_LIM_EN:
pthread_mutex_lock(&(handler->mEnCntLock));
handler->mGovEnCnt--;
handler->mLimEnCnt = 1;
handler->mLimEnPrst = 0;
pthread_mutex_unlock(&(handler->mEnCntLock));
handler->sendEvent(EVENT_LIMEN);
break;
case THMCMD_SET_LIM_DIS:
pthread_mutex_lock(&(handler->mEnCntLock));
handler->mGovEnCnt++;
handler->mLimEnCnt = 0;
handler->mLimEnPrst = 0;
pthread_mutex_unlock(&(handler->mEnCntLock));
handler->sendEvent(EVENT_LIMDIS);
break;
case THMCMD_SET_LIM_EN_PRST:
pthread_mutex_lock(&(handler->mEnCntLock));
handler->mGovEnCnt--;
handler->mLimEnCnt = 1;
handler->mLimEnPrst = 1;
pthread_mutex_unlock(&(handler->mEnCntLock));
handler->sendEvent(EVENT_LIMEN);
break;
case THMCMD_SET_LIM_DIS_PRST:
pthread_mutex_lock(&(handler->mEnCntLock));
handler->mGovEnCnt++;
handler->mLimEnCnt = 0;
handler->mLimEnPrst = 1;
pthread_mutex_unlock(&(handler->mEnCntLock));
handler->sendEvent(EVENT_LIMDIS);
break;
default:
ALOGE("unused cmd: %d", cmd);
break;
};
close(new_fd);
}
close(fdListen);
return NULL;
}
#endif
bool ThermalManager::getChargeEn(void) {
if (mChgDetector) {
return mChgDetector->getChargeEn();
}
return false;
}
int ThermalManager::enableCharge(bool en) {
if (mChgDetector) {
return mChgDetector->enableCharge(en);
}
return -1;
}
}; // namespace android