Files
2026-09-22 09:38:26 +08:00

177 lines
3.6 KiB
C++

/*
* ChargeDetect.cpp
*
* Copyright (C) 2017 Spreadtrum Communications Inc.
*/
#include <unistd.h>
#include <stdio.h>
#include <poll.h>
#include <fcntl.h>
#include <string.h>
#include "ThermalManager.h"
#include "ChargeDetect.h"
#include "uevent.h"
#include "alog.h"
#undef LOG_TAG
#define LOG_TAG "ThermalChargeDetect"
namespace android {
ChargeDetect::ChargeDetect(ThermalManager* handler) {
pthread_t pid;
mManager = handler;
#if 0
int value = property_get_int32(GOVERNOR_CHARGE_ENABLE, 1);
if (value == 1) {
mChargeEn = true;
} else {
mChargeEn = false;
}
#else
mChargeEn = true;
#endif
mIsCharging = getChargeStatus();
ALOGI("init status: ChargeEn=%d, IsCharging=%d", mChargeEn, mIsCharging);
if (!mChargeEn || !mIsCharging) {
ALOGI("send EVENT_CHGDIS");
mChgActionEn = false;
mManager->sendEvent(ThermalManager::EVENT_CHGDIS);
} else {
mChgActionEn = true;
}
int ret = pthread_create(&pid, NULL, chargeMonitor, this);
if (ret) {
ALOGE("create chargeMonitor pthread failed!");
}
}
ChargeDetect::~ChargeDetect() {
close(mUeventFd);
}
#define UEVENT_MSG_LEN 1024
void* ChargeDetect::chargeMonitor(void* ptr) {
ChargeDetect* detector = (ChargeDetect*)ptr;
ThermalManager* manager = detector->mManager;
struct pollfd pfd;
int fd;
char msg[UEVENT_MSG_LEN + 2];
char* cp;
int n;
fd = uevent_open_socket(2 * 1024, true);
if (fd < 0) {
ALOGE("uevent_init: uevent_open_socket failed: %d\n", fd);
return NULL;
}
detector->mUeventFd = fd;
pfd.fd = fd;
pfd.events = POLLIN;
while (1) {
n = poll(&pfd, 1, -1);
if (n < 1){
continue;
}
n = uevent_kernel_multicast_recv(fd, msg, UEVENT_MSG_LEN);
if (n <= 0 || n >= UEVENT_MSG_LEN) {
continue;
}
msg[n] = '\0';
msg[n + 1] = '\0';
cp = msg;
while (*cp) {
if (!strcmp(cp, "SUBSYSTEM=power_supply")) {
detector->chargeEvent();
break;
}
/* advance to after the next \0 */
while (*cp++)
;
}
}
return NULL;
}
int ChargeDetect::chargeEvent(void) {
if (mChargeEn == false) {
return 0;
}
bool isChg = getChargeStatus();
if (mIsCharging == isChg) {
return 0;
}
mIsCharging = isChg;
if (isChg && !mChgActionEn) {
ALOGI("send EVENT_CHGEN");
mChgActionEn = true;
mManager->sendEvent(ThermalManager::EVENT_CHGEN);
return 1;
}
if (!isChg && mChgActionEn) {
ALOGI("send EVENT_CHGDIS");
mChgActionEn = false;
mManager->sendEvent(ThermalManager::EVENT_CHGDIS);
return 1;
}
return 0;
}
bool ChargeDetect::getChargeStatus(void) {
int fd, len;
char buf[20];
fd = open(STAT_PATH, O_RDONLY);
if (fd < 0) {
ALOGE("open %s failed: %d", STAT_PATH, fd);
return false;
}
len = read(fd, buf, sizeof(buf));
close(fd);
buf[len - 1] = '\0';
ALOGI("charge status: %s", buf);
if (!strcmp(buf, "Charging") || !strcmp(buf, "Full")) {
return true;
} else {
return false;
}
}
bool ChargeDetect::getChargeEn(void) { return mChargeEn; }
int ChargeDetect::enableCharge(bool en) {
if (mChargeEn == en) {
return 0;
}
mChargeEn = en;
/*if (en) {
property_set(GOVERNOR_CHARGE_ENABLE, "1");
} else {
property_set(GOVERNOR_CHARGE_ENABLE, "0");
}*/
if (en && mIsCharging && !mChgActionEn) {
mChgActionEn = true;
ALOGI("send EVENT_CHGEN");
mManager->sendEvent(ThermalManager::EVENT_CHGEN);
return 1;
}
if ((!en || !mIsCharging) && mChgActionEn) {
mChgActionEn = false;
ALOGI("send EVENT_CHGDIS");
mManager->sendEvent(ThermalManager::EVENT_CHGDIS);
return 1;
}
return 0;
}
}; // namespace android