177 lines
3.6 KiB
C++
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
|