Merge RQ2A.210305.007
Bug: 180401296
Merged-In: I0ea517cc72be1bd492f8a70f14dbb0d3295f6304
Change-Id: I03928f17ba4bf3a87c1ffd6927cf57e40db4fa64
diff --git a/health/Android.bp b/health/Android.bp
index b563b43..e954ca3 100644
--- a/health/Android.bp
+++ b/health/Android.bp
@@ -58,6 +58,7 @@
static_libs: [
"libgmock",
"libpixelhealth",
+ "libbatterymonitor",
],
shared_libs: [
diff --git a/health/BatteryDefender.cpp b/health/BatteryDefender.cpp
index 37283da..4d93741 100644
--- a/health/BatteryDefender.cpp
+++ b/health/BatteryDefender.cpp
@@ -34,10 +34,12 @@
namespace pixel {
namespace health {
-BatteryDefender::BatteryDefender(const char *pathChargeLevelStart, const char *pathChargeLevelStop,
- const int32_t timeToActivateSecs,
+BatteryDefender::BatteryDefender(const char *pathWirelessPresent, const char *pathChargeLevelStart,
+ const char *pathChargeLevelStop, const int32_t timeToActivateSecs,
const int32_t timeToClearTimerSecs)
- : kPathChargeLevelStart(pathChargeLevelStart),
+
+ : kPathWirelessPresent(pathWirelessPresent),
+ kPathChargeLevelStart(pathChargeLevelStart),
kPathChargeLevelStop(pathChargeLevelStop),
kTimeToActivateSecs(timeToActivateSecs),
kTimeToClearTimerSecs(timeToClearTimerSecs) {
@@ -75,11 +77,13 @@
str->erase(std::remove(str->begin(), str->end(), '\r'), str->end());
}
-int BatteryDefender::readFileToInt(const char *path) {
+int BatteryDefender::readFileToInt(const char *path, const bool optionalFile) {
std::string buffer;
int value = 0; // default
if (!android::base::ReadFileToString(path, &buffer)) {
- LOG(ERROR) << "Failed to read " << path;
+ if (optionalFile == false) {
+ LOG(ERROR) << "Failed to read " << path;
+ }
} else {
removeLineEndings(&buffer);
if (!android::base::ParseInt(buffer.c_str(), &value)) {
@@ -113,8 +117,20 @@
int chargeLevelStart = vendorStart;
int chargeLevelStop = vendorStop;
if (mCurrentState == STATE_ACTIVE) {
- chargeLevelStart = kChargeLevelDefenderStart;
- chargeLevelStop = kChargeLevelDefenderStop;
+ const int newDefenderLevelStart = android::base::GetIntProperty(
+ kPropBatteryDefenderCtrlStartSOC, kChargeLevelDefenderStart, 0, 100);
+ const int newDefenderLevelStop = android::base::GetIntProperty(
+ kPropBatteryDefenderCtrlStopSOC, kChargeLevelDefenderStop, 0, 100);
+ const bool overrideLevelsValid =
+ (newDefenderLevelStart <= newDefenderLevelStop) && (newDefenderLevelStop != 0);
+
+ if (overrideLevelsValid) {
+ chargeLevelStart = newDefenderLevelStart;
+ chargeLevelStop = newDefenderLevelStop;
+ } else {
+ chargeLevelStart = kChargeLevelDefenderStart;
+ chargeLevelStop = kChargeLevelDefenderStop;
+ }
}
// Disable battery defender effects in charger mode until
@@ -134,13 +150,17 @@
}
bool BatteryDefender::isChargePowerAvailable(void) {
- // USB presence is an indicator of connectivity
- const bool chargerPresentWired = readFileToInt(kPathWiredChargerPresent) != 0;
+ // USB presence is an indicator of power availability
+ const bool chargerPresentWired = readFileToInt(kPathUSBChargerPresent) != 0;
+ const bool chargerPresentWireless =
+ readFileToInt(kPathWirelessPresent, mIgnoreWirelessFileError) != 0;
+ mIsUsbPresent = chargerPresentWired;
+ mIsWirelessPresent = chargerPresentWireless;
- // Wireless online is an indicator of a device having charge power
- const bool chargerOnlineWireless = readFileToInt(kPathWirelessChargerOnline) != 0;
+ // Report wireless read error only once; some devices may not have a wireless adapter
+ mIgnoreWirelessFileError = true;
- return chargerPresentWired || chargerOnlineWireless;
+ return chargerPresentWired || chargerPresentWireless;
}
bool BatteryDefender::isDefaultChargeLevel(const int start, const int stop) {
@@ -149,11 +169,12 @@
bool BatteryDefender::isBatteryDefenderDisabled(const int vendorStart, const int vendorStop) {
const bool isDefaultVendorChargeLevel = isDefaultChargeLevel(vendorStart, vendorStop);
- const bool isExplicitlyDisabled =
+ const bool isOverrideDisabled =
android::base::GetBoolProperty(kPropBatteryDefenderDisable, false);
- const bool isDebuggable = android::base::GetBoolProperty(kPropDebuggable, false);
+ const bool isCtrlEnabled =
+ android::base::GetBoolProperty(kPropBatteryDefenderCtrlEnable, kDefaultEnable);
- return isExplicitlyDisabled || (isDefaultVendorChargeLevel == false) || (isDebuggable == false);
+ return isOverrideDisabled || (isDefaultVendorChargeLevel == false) || (isCtrlEnabled == false);
}
void BatteryDefender::addTimeToChargeTimers(void) {
@@ -170,14 +191,31 @@
int32_t BatteryDefender::getTimeToActivate(void) {
// Use the default constructor value if the modified property is not between 60 and INT_MAX
// (seconds)
- return android::base::GetIntProperty(kPropBatteryDefenderThreshold, kTimeToActivateSecs,
- (int32_t)ONE_MIN_IN_SECONDS, INT32_MAX);
+ const int32_t timeToActivateOverride =
+ android::base::GetIntProperty(kPropBatteryDefenderThreshold, kTimeToActivateSecs,
+ (int32_t)ONE_MIN_IN_SECONDS, INT32_MAX);
+
+ const bool overrideActive = timeToActivateOverride != kTimeToActivateSecs;
+ if (overrideActive) {
+ return timeToActivateOverride;
+ } else {
+ // No overrides taken; apply ctrl time to activate...
+ // Note; do not allow less than 1 day trigger time
+ return android::base::GetIntProperty(kPropBatteryDefenderCtrlActivateTime,
+ kTimeToActivateSecs, (int32_t)ONE_DAY_IN_SECONDS,
+ INT32_MAX);
+ }
}
-void BatteryDefender::stateMachine_runAction(const state_E state) {
+void BatteryDefender::stateMachine_runAction(const state_E state,
+ const struct android::BatteryProperties *props) {
switch (state) {
case STATE_INIT:
loadPersistentStorage();
+ if (props->chargerUsbOnline || props->chargerAcOnline) {
+ mWasAcOnline = props->chargerAcOnline;
+ mWasUsbOnline = props->chargerUsbOnline;
+ }
break;
case STATE_DISABLED:
@@ -185,12 +223,15 @@
clearStateData();
break;
- case STATE_CONNECTED:
+ case STATE_CONNECTED: {
addTimeToChargeTimers();
- if (readFileToInt(kPathBatteryCapacity) == kChargeHighCapacityLevel) {
+
+ const int triggerLevel = android::base::GetIntProperty(
+ kPropBatteryDefenderCtrlTriggerSOC, kChargeHighCapacityLevel, 0, 100);
+ if (props->batteryLevel >= triggerLevel) {
mHasReachedHighCapacityLevel = true;
}
- break;
+ } break;
case STATE_ACTIVE:
addTimeToChargeTimers();
@@ -237,13 +278,19 @@
case STATE_CONNECTED:
if (mTimeChargerPresentSecs > mTimeToActivateSecsModified) {
nextState = STATE_ACTIVE;
- } else if (mTimeChargerNotPresentSecs > kTimeToClearTimerSecs) {
+ }
+ FALLTHROUGH_INTENDED;
+
+ case STATE_ACTIVE: {
+ const int timeToClear = android::base::GetIntProperty(
+ kPropBatteryDefenderCtrlResumeTime, kTimeToClearTimerSecs, 0, INT32_MAX);
+
+ /* Check for mIsPowerAvailable in case timeToClear is 0 */
+ if ((mTimeChargerNotPresentSecs >= timeToClear) && (mIsPowerAvailable == false)) {
nextState = STATE_DISCONNECTED;
}
- break;
+ } break;
- case STATE_ACTIVE:
- // Latch unless disabled or unless the health module has restarted (ie. reboot)
default:
break;
}
@@ -257,9 +304,8 @@
void BatteryDefender::stateMachine_firstAction(const state_E state) {
switch (state) {
case STATE_DISABLED:
- clearStateData();
LOG(INFO) << "Disabled!";
- break;
+ FALLTHROUGH_INTENDED;
case STATE_DISCONNECTED:
clearStateData();
@@ -286,7 +332,50 @@
}
}
-void BatteryDefender::update(void) {
+void BatteryDefender::updateDefenderProperties(struct android::BatteryProperties *props) {
+ /**
+ * Override the OVERHEAT flag for UI updates to settings.
+ * Also, force AC/USB online if active and still connected to power.
+ */
+ if (mCurrentState == STATE_ACTIVE) {
+ props->batteryHealth = android::BATTERY_HEALTH_OVERHEAT;
+ }
+
+ /**
+ * If the kernel is forcing the input current limit to 0, then the online status may
+ * need to be overwritten. Also, setting a charge limit below the current charge level
+ * may disable the adapter.
+ * Note; only override "online" if necessary (all "online"s are false).
+ */
+ if (props->chargerUsbOnline == false && props->chargerAcOnline == false) {
+ /* Override if the USB is connected and a battery defender is active */
+ if (mIsUsbPresent && props->batteryHealth == android::BATTERY_HEALTH_OVERHEAT) {
+ if (mWasAcOnline) {
+ props->chargerAcOnline = true;
+ }
+ if (mWasUsbOnline) {
+ props->chargerUsbOnline = true;
+ }
+ }
+ } else {
+ /* One of these booleans will always be true if updated here */
+ mWasAcOnline = props->chargerAcOnline;
+ mWasUsbOnline = props->chargerUsbOnline;
+ }
+
+ /* Do the same as above for wireless adapters */
+ if (props->chargerWirelessOnline == false) {
+ if (mIsWirelessPresent && props->batteryHealth == android::BATTERY_HEALTH_OVERHEAT) {
+ props->chargerWirelessOnline = true;
+ }
+ }
+}
+
+void BatteryDefender::update(struct android::BatteryProperties *props) {
+ if (!props) {
+ return;
+ }
+
// Update module inputs
const int chargeLevelVendorStart =
android::base::GetIntProperty(kPropChargeLevelVendorStart, kChargeLevelDefaultStart);
@@ -297,13 +386,16 @@
mTimeBetweenUpdateCalls = getDeltaTimeSeconds(&mTimePreviousSecs);
// Run state machine
- stateMachine_runAction(mCurrentState);
+ stateMachine_runAction(mCurrentState, props);
const state_E nextState = stateMachine_getNextState(mCurrentState);
if (nextState != mCurrentState) {
stateMachine_firstAction(nextState);
}
mCurrentState = nextState;
+ // Verify/update battery defender battery properties
+ updateDefenderProperties(props); /* May override battery properties */
+
// Store outputs
writeTimeToFile(kPathPersistChargerPresentTime, mTimeChargerPresentSecs,
&mTimeChargerPresentSecsPrevious);
diff --git a/health/include/pixelhealth/BatteryDefender.h b/health/include/pixelhealth/BatteryDefender.h
index 30512c2..4a16bcc 100644
--- a/health/include/pixelhealth/BatteryDefender.h
+++ b/health/include/pixelhealth/BatteryDefender.h
@@ -17,6 +17,8 @@
#ifndef HARDWARE_GOOGLE_PIXEL_HEALTH_BATTERYDEFENDER_H
#define HARDWARE_GOOGLE_PIXEL_HEALTH_BATTERYDEFENDER_H
+#include <batteryservice/BatteryService.h>
+
#include <stdbool.h>
#include <time.h>
#include <string>
@@ -31,18 +33,19 @@
const uint32_t ONE_DAY_IN_HOURS = 24;
const uint32_t ONE_DAY_IN_SECONDS = ONE_DAY_IN_HOURS * ONE_HOUR_IN_MINUTES * ONE_MIN_IN_SECONDS;
-const uint32_t DEFAULT_TIME_TO_ACTIVATE_SECONDS = (14 * ONE_DAY_IN_SECONDS);
+const uint32_t DEFAULT_TIME_TO_ACTIVATE_SECONDS = (4 * ONE_DAY_IN_SECONDS);
const uint32_t DEFAULT_TIME_TO_CLEAR_SECONDS = (5 * ONE_MIN_IN_SECONDS);
const int DEFAULT_CHARGE_LEVEL_START = 0;
const int DEFAULT_CHARGE_LEVEL_STOP = 100;
-const int DEFAULT_CHARGE_LEVEL_DEFENDER_START = 60;
-const int DEFAULT_CHARGE_LEVEL_DEFENDER_STOP = 70;
+const int DEFAULT_CHARGE_LEVEL_DEFENDER_START = 70;
+const int DEFAULT_CHARGE_LEVEL_DEFENDER_STOP = 80;
const int DEFAULT_CAPACITY_LEVEL = 100;
class BatteryDefender {
public:
// Set default google charger paths - can be overridden for other devices
- BatteryDefender(const char *pathChargeLevelStart =
+ BatteryDefender(const char *pathWirelessPresent = "/sys/class/power_supply/wireless/present",
+ const char *pathChargeLevelStart =
"/sys/devices/platform/soc/soc:google,charger/charge_start_level",
const char *pathChargeLevelStop =
"/sys/devices/platform/soc/soc:google,charger/charge_stop_level",
@@ -50,7 +53,7 @@
const int32_t timeToClearTimerSecs = DEFAULT_TIME_TO_CLEAR_SECONDS);
// This function shall be called periodically in HealthService
- void update(void);
+ void update(struct android::BatteryProperties *props);
private:
enum state_E {
@@ -69,15 +72,14 @@
[STATE_ACTIVE] = "ACTIVE",
};
+ const char *const kPathWirelessPresent;
const char *const kPathChargeLevelStart;
const char *const kPathChargeLevelStop;
const int32_t kTimeToActivateSecs;
const int32_t kTimeToClearTimerSecs;
// Sysfs
- const char *const kPathWirelessChargerOnline = "/sys/class/power_supply/wireless/online";
- const char *const kPathWiredChargerPresent = "/sys/class/power_supply/usb/present";
- const char *const kPathBatteryCapacity = "/sys/class/power_supply/battery/capacity";
+ const char *const kPathUSBChargerPresent = "/sys/class/power_supply/usb/present";
const char *const kPathPersistChargerPresentTime =
"/mnt/vendor/persist/battery/defender_charger_time";
const char *const kPathPersistDefenderActiveTime =
@@ -89,10 +91,21 @@
const char *const kPropBatteryDefenderState = "vendor.battery.defender.state";
const char *const kPropBatteryDefenderDisable = "vendor.battery.defender.disable";
const char *const kPropBatteryDefenderThreshold = "vendor.battery.defender.threshold";
- const char *const kPropDebuggable = "ro.debuggable";
const char *const kPropBootmode = "ro.bootmode";
+ const char *const kPropBatteryDefenderCtrlEnable = "vendor.battery.defender.ctrl.enable";
+ const char *const kPropBatteryDefenderCtrlActivateTime =
+ "vendor.battery.defender.ctrl.trigger_time";
+ const char *const kPropBatteryDefenderCtrlResumeTime =
+ "vendor.battery.defender.ctrl.resume_time";
+ const char *const kPropBatteryDefenderCtrlStartSOC =
+ "vendor.battery.defender.ctrl.recharge_soc_start";
+ const char *const kPropBatteryDefenderCtrlStopSOC =
+ "vendor.battery.defender.ctrl.recharge_soc_stop";
+ const char *const kPropBatteryDefenderCtrlTriggerSOC =
+ "vendor.battery.defender.ctrl.trigger_soc";
// Default thresholds
+ const bool kDefaultEnable = true;
const int kChargeLevelDefaultStart = DEFAULT_CHARGE_LEVEL_START;
const int kChargeLevelDefaultStop = DEFAULT_CHARGE_LEVEL_STOP;
const int kChargeLevelDefenderStart = DEFAULT_CHARGE_LEVEL_DEFENDER_START;
@@ -102,6 +115,8 @@
// Inputs
int64_t mTimeBetweenUpdateCalls = 0;
int64_t mTimePreviousSecs;
+ bool mIsUsbPresent = false;
+ bool mIsWirelessPresent = false;
bool mIsPowerAvailable = false;
bool mIsDefenderDisabled = false;
int32_t mTimeToActivateSecsModified;
@@ -116,18 +131,28 @@
int mChargeLevelStartPrevious = DEFAULT_CHARGE_LEVEL_START;
int mChargeLevelStopPrevious = DEFAULT_CHARGE_LEVEL_STOP;
bool mHasReachedHighCapacityLevel = false;
+ bool mWasAcOnline = false;
+ bool mWasUsbOnline = true; /* Default; in case neither AC/USB online becomes 1 */
+ bool mIgnoreWirelessFileError = false;
- void stateMachine_runAction(const state_E state); // Process state actions
- state_E stateMachine_getNextState(const state_E state); // Check transitions
- void stateMachine_firstAction(const state_E state); // Process entry actions
+ // Process state actions
+ void stateMachine_runAction(const state_E state,
+ const struct android::BatteryProperties *props);
+ // Check state transitions
+ state_E stateMachine_getNextState(const state_E state);
+
+ // Process state entry actions
+ void stateMachine_firstAction(const state_E state);
+
+ void updateDefenderProperties(struct android::BatteryProperties *props);
void clearStateData(void);
void loadPersistentStorage(void);
int64_t getTime(void);
int64_t getDeltaTimeSeconds(int64_t *timeStartSecs);
int32_t getTimeToActivate(void);
void removeLineEndings(std::string *str);
- int readFileToInt(const char *path);
+ int readFileToInt(const char *path, const bool optionalFile = false);
bool writeIntToFile(const char *path, const int value);
void writeTimeToFile(const char *path, const int value, int64_t *previous);
void writeChargeLevelsToFile(const int vendorStart, const int vendorStop);
diff --git a/health/test/TestBatteryDefender.cpp b/health/test/TestBatteryDefender.cpp
index 50656c6..7366aab 100644
--- a/health/test/TestBatteryDefender.cpp
+++ b/health/test/TestBatteryDefender.cpp
@@ -24,6 +24,8 @@
#include <android-base/file.h>
#include <android-base/properties.h>
+#define MIN_TIME_BETWEEN_FILE_UPDATES (30 + 1)
+
class HealthInterface {
public:
virtual ~HealthInterface() {}
@@ -102,6 +104,8 @@
using ::testing::Return;
using ::testing::SetArgPointee;
+struct android::BatteryProperties props;
+
class BatteryDefenderTest : public ::testing::Test {
public:
BatteryDefenderTest() {}
@@ -109,6 +113,8 @@
void SetUp() {
mock = &mockFixture;
+ props = {};
+
EXPECT_CALL(*mock, SetProperty(_, _)).Times(AnyNumber());
EXPECT_CALL(*mock, ReadFileToString(_, _, _)).Times(AnyNumber());
EXPECT_CALL(*mock, GetIntProperty(_, _, _, _)).Times(AnyNumber());
@@ -127,9 +133,8 @@
HealthInterfaceMock mockFixture;
};
-const char *kPathWirelessChargerOnline = "/sys/class/power_supply/wireless/online";
const char *kPathWiredChargerPresent = "/sys/class/power_supply/usb/present";
-const char *kPathBatteryCapacity = "/sys/class/power_supply/battery/capacity";
+const char *kPathWirelessChargerPresent = "/sys/class/power_supply/wireless/present";
const char *kPathPersistChargerPresentTime = "/mnt/vendor/persist/battery/defender_charger_time";
const char *kPathPersistDefenderActiveTime = "/mnt/vendor/persist/battery/defender_active_time";
const char *kPathStartLevel = "/sys/devices/platform/soc/soc:google,charger/charge_start_level";
@@ -140,30 +145,62 @@
const char *kPropBatteryDefenderState = "vendor.battery.defender.state";
const char *kPropBatteryDefenderDisable = "vendor.battery.defender.disable";
const char *kPropBatteryDefenderThreshold = "vendor.battery.defender.threshold";
-const char *kPropDebuggable = "ro.debuggable";
+
+const char *kPropBatteryDefenderCtrlEnable = "vendor.battery.defender.ctrl.enable";
+const char *kPropBatteryDefenderCtrlActivateTime = "vendor.battery.defender.ctrl.trigger_time";
+const char *kPropBatteryDefenderCtrlResumeTime = "vendor.battery.defender.ctrl.resume_time";
+const char *kPropBatteryDefenderCtrlStartSOC = "vendor.battery.defender.ctrl.recharge_soc_start";
+const char *kPropBatteryDefenderCtrlStopSOC = "vendor.battery.defender.ctrl.recharge_soc_stop";
+const char *kPropBatteryDefenderCtrlTriggerSOC = "vendor.battery.defender.ctrl.trigger_soc";
static void enableDefender(void) {
ON_CALL(*mock, GetIntProperty(kPropChargeLevelVendorStart, _, _, _)).WillByDefault(Return(0));
ON_CALL(*mock, GetIntProperty(kPropChargeLevelVendorStop, _, _, _)).WillByDefault(Return(100));
ON_CALL(*mock, GetBoolProperty(kPropBatteryDefenderDisable, _)).WillByDefault(Return(false));
- ON_CALL(*mock, GetBoolProperty(kPropDebuggable, _)).WillByDefault(Return(true));
+
+ ON_CALL(*mock, GetBoolProperty(kPropBatteryDefenderCtrlEnable, _)).WillByDefault(Return(true));
}
-static void powerAvailable(void) {
- ON_CALL(*mock, ReadFileToString(kPathWirelessChargerOnline, _, _))
- .WillByDefault(DoAll(SetArgPointee<1>(std::string("1")), Return(true)));
+static void usbPresent(void) {
ON_CALL(*mock, ReadFileToString(kPathWiredChargerPresent, _, _))
.WillByDefault(DoAll(SetArgPointee<1>(std::string("1")), Return(true)));
}
-static void defaultThreshold(void) {
+static void wirelessPresent(void) {
+ ON_CALL(*mock, ReadFileToString(kPathWirelessChargerPresent, _, _))
+ .WillByDefault(DoAll(SetArgPointee<1>(std::string("1")), Return(true)));
+}
+
+static void wirelessNotPresent(void) {
+ ON_CALL(*mock, ReadFileToString(kPathWirelessChargerPresent, _, _))
+ .WillByDefault(DoAll(SetArgPointee<1>(std::string("0")), Return(true)));
+}
+
+static void powerAvailable(void) {
+ wirelessPresent();
+ usbPresent();
+}
+
+static void defaultThresholds(void) {
ON_CALL(*mock, GetIntProperty(kPropBatteryDefenderThreshold, _, _, _))
.WillByDefault(Return(DEFAULT_TIME_TO_ACTIVATE_SECONDS));
+
+ ON_CALL(*mock, GetIntProperty(kPropBatteryDefenderCtrlActivateTime, _, _, _))
+ .WillByDefault(Return(DEFAULT_TIME_TO_ACTIVATE_SECONDS));
+ ON_CALL(*mock, GetIntProperty(kPropBatteryDefenderCtrlResumeTime, _, _, _))
+ .WillByDefault(Return(DEFAULT_TIME_TO_CLEAR_SECONDS));
+
+ ON_CALL(*mock, GetIntProperty(kPropBatteryDefenderCtrlStartSOC, _, _, _))
+ .WillByDefault(Return(70));
+ ON_CALL(*mock, GetIntProperty(kPropBatteryDefenderCtrlStopSOC, _, _, _))
+ .WillByDefault(Return(80));
+
+ ON_CALL(*mock, GetIntProperty(kPropBatteryDefenderCtrlTriggerSOC, _, _, _))
+ .WillByDefault(Return(100));
}
static void capacityReached(void) {
- ON_CALL(*mock, ReadFileToString(kPathBatteryCapacity, _, _))
- .WillByDefault(DoAll(SetArgPointee<1>(std::to_string(100)), Return(true)));
+ props.batteryLevel = 100;
}
static void initToConnectedCapacityReached(void) {
@@ -186,7 +223,7 @@
// Enable Battery Defender
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "DISCONNECTED"));
- battDefender.update();
+ battDefender.update(&props);
}
TEST_F(BatteryDefenderTest, DisableNonDefaultLevels) {
@@ -197,17 +234,7 @@
EXPECT_CALL(*mock, GetIntProperty(kPropChargeLevelVendorStop, _, _, _)).WillOnce(Return(35));
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "DISABLED"));
- battDefender.update();
-}
-
-TEST_F(BatteryDefenderTest, DisableDebuggable) {
- BatteryDefender battDefender;
-
- // Enable Battery Defender
- EXPECT_CALL(*mock, GetBoolProperty(kPropDebuggable, _)).WillOnce(Return(false));
-
- EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "DISABLED"));
- battDefender.update();
+ battDefender.update(&props);
}
TEST_F(BatteryDefenderTest, DisableExplicit) {
@@ -217,7 +244,7 @@
EXPECT_CALL(*mock, GetBoolProperty(kPropBatteryDefenderDisable, _)).WillOnce(Return(true));
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "DISABLED"));
- battDefender.update();
+ battDefender.update(&props);
}
TEST_F(BatteryDefenderTest, InitActive) {
@@ -225,13 +252,13 @@
enableDefender();
powerAvailable();
- defaultThreshold();
+ defaultThresholds();
EXPECT_CALL(*mock, ReadFileToString(kPathPersistChargerPresentTime, _, _))
.WillOnce(DoAll(SetArgPointee<1>(std::to_string(DEFAULT_TIME_TO_ACTIVATE_SECONDS + 1)),
Return(true)));
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "ACTIVE"));
- battDefender.update();
+ battDefender.update(&props);
}
TEST_F(BatteryDefenderTest, InitConnectedCapacityReached) {
@@ -239,21 +266,22 @@
enableDefender();
powerAvailable();
- defaultThreshold();
+ defaultThresholds();
InSequence s;
+ int time_expected = DEFAULT_TIME_TO_ACTIVATE_SECONDS - 1;
EXPECT_CALL(*mock, ReadFileToString(kPathPersistChargerPresentTime, _, _))
- .WillOnce(DoAll(SetArgPointee<1>(std::to_string(DEFAULT_TIME_TO_ACTIVATE_SECONDS - 1)),
- Return(true)));
+ .WillOnce(DoAll(SetArgPointee<1>(std::to_string(time_expected)), Return(true)));
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
- battDefender.update();
+ battDefender.update(&props);
- testvar_systemTimeSecs++;
- EXPECT_CALL(*mock, WriteStringToFile(std::to_string(DEFAULT_TIME_TO_ACTIVATE_SECONDS),
+ testvar_systemTimeSecs += MIN_TIME_BETWEEN_FILE_UPDATES;
+ time_expected += MIN_TIME_BETWEEN_FILE_UPDATES;
+ EXPECT_CALL(*mock, WriteStringToFile(std::to_string(time_expected),
kPathPersistChargerPresentTime, _));
- EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
- battDefender.update();
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "ACTIVE"));
+ battDefender.update(&props);
}
TEST_F(BatteryDefenderTest, InitConnected) {
@@ -261,19 +289,24 @@
enableDefender();
powerAvailable();
- defaultThreshold();
+ defaultThresholds();
InSequence s;
EXPECT_CALL(*mock, ReadFileToString(kPathPersistChargerPresentTime, _, _))
.WillOnce(DoAll(SetArgPointee<1>(std::to_string(0)), Return(true)));
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
- battDefender.update();
+ battDefender.update(&props);
// mHasReachedHighCapacityLevel shall be false
testvar_systemTimeSecs += DEFAULT_TIME_TO_ACTIVATE_SECONDS + 1;
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
- battDefender.update();
+ battDefender.update(&props);
+
+ // Would be active if mHasReachedHighCapacityLevel was true
+ testvar_systemTimeSecs += DEFAULT_TIME_TO_ACTIVATE_SECONDS + 1;
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
+ battDefender.update(&props);
}
TEST_F(BatteryDefenderTest, TriggerTime) {
@@ -281,32 +314,32 @@
enableDefender();
powerAvailable();
- defaultThreshold();
+ defaultThresholds();
InSequence s;
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
- testvar_systemTimeSecs += 1;
- battDefender.update();
+ testvar_systemTimeSecs += MIN_TIME_BETWEEN_FILE_UPDATES;
+ battDefender.update(&props);
// Reached 100% capacity at least once
- EXPECT_CALL(*mock, ReadFileToString(kPathBatteryCapacity, _, _))
- .WillOnce(DoAll(SetArgPointee<1>(std::to_string(100)), Return(true)));
+ capacityReached();
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
- testvar_systemTimeSecs += 1;
- battDefender.update();
+ testvar_systemTimeSecs += MIN_TIME_BETWEEN_FILE_UPDATES;
+ battDefender.update(&props);
EXPECT_CALL(*mock, WriteStringToFile(std::to_string(DEFAULT_TIME_TO_ACTIVATE_SECONDS),
kPathPersistChargerPresentTime, _));
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
testvar_systemTimeSecs += DEFAULT_TIME_TO_ACTIVATE_SECONDS;
- battDefender.update();
+ battDefender.update(&props);
- EXPECT_CALL(*mock, WriteStringToFile(std::to_string(DEFAULT_TIME_TO_ACTIVATE_SECONDS + 1),
+ EXPECT_CALL(*mock, WriteStringToFile(std::to_string(DEFAULT_TIME_TO_ACTIVATE_SECONDS +
+ MIN_TIME_BETWEEN_FILE_UPDATES),
kPathPersistChargerPresentTime, _));
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "ACTIVE"));
- testvar_systemTimeSecs += 1;
- battDefender.update();
+ testvar_systemTimeSecs += MIN_TIME_BETWEEN_FILE_UPDATES;
+ battDefender.update(&props);
}
TEST_F(BatteryDefenderTest, ChargeLevels) {
@@ -314,7 +347,7 @@
enableDefender();
powerAvailable();
- defaultThreshold();
+ defaultThresholds();
initToConnectedCapacityReached();
InSequence s;
@@ -322,13 +355,13 @@
// No expectations needed; default values already set
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
testvar_systemTimeSecs += 0;
- battDefender.update();
+ battDefender.update(&props);
- EXPECT_CALL(*mock, WriteStringToFile(std::to_string(60), kPathStartLevel, _));
- EXPECT_CALL(*mock, WriteStringToFile(std::to_string(70), kPathStopLevel, _));
+ EXPECT_CALL(*mock, WriteStringToFile(std::to_string(70), kPathStartLevel, _));
+ EXPECT_CALL(*mock, WriteStringToFile(std::to_string(80), kPathStopLevel, _));
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "ACTIVE"));
testvar_systemTimeSecs += DEFAULT_TIME_TO_ACTIVATE_SECONDS + 1;
- battDefender.update();
+ battDefender.update(&props);
}
TEST_F(BatteryDefenderTest, ActiveTime) {
@@ -336,78 +369,425 @@
enableDefender();
powerAvailable();
- defaultThreshold();
+ defaultThresholds();
initToActive();
InSequence s;
- EXPECT_CALL(*mock, WriteStringToFile(std::to_string(60), kPathStartLevel, _));
- EXPECT_CALL(*mock, WriteStringToFile(std::to_string(70), kPathStopLevel, _));
+ EXPECT_CALL(*mock, WriteStringToFile(std::to_string(70), kPathStartLevel, _));
+ EXPECT_CALL(*mock, WriteStringToFile(std::to_string(80), kPathStopLevel, _));
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "ACTIVE"));
- battDefender.update();
+ battDefender.update(&props);
+}
+
+TEST_F(BatteryDefenderTest, ActiveTime_NonDefaultLevels) {
+ BatteryDefender battDefender;
+
+ enableDefender();
+ powerAvailable();
+ initToActive();
+ ON_CALL(*mock, GetIntProperty(kPropBatteryDefenderThreshold, _, _, _))
+ .WillByDefault(Return(DEFAULT_TIME_TO_ACTIVATE_SECONDS));
+ ON_CALL(*mock, GetIntProperty(kPropBatteryDefenderCtrlActivateTime, _, _, _))
+ .WillByDefault(Return(DEFAULT_TIME_TO_ACTIVATE_SECONDS));
+ ON_CALL(*mock, GetIntProperty(kPropBatteryDefenderCtrlResumeTime, _, _, _))
+ .WillByDefault(Return(DEFAULT_TIME_TO_CLEAR_SECONDS));
+
+ // Non-default
+ ON_CALL(*mock, GetIntProperty(kPropBatteryDefenderCtrlStartSOC, _, _, _))
+ .WillByDefault(Return(50));
+ ON_CALL(*mock, GetIntProperty(kPropBatteryDefenderCtrlStopSOC, _, _, _))
+ .WillByDefault(Return(60));
+
+ InSequence s;
+
+ EXPECT_CALL(*mock, WriteStringToFile(std::to_string(50), kPathStartLevel, _));
+ EXPECT_CALL(*mock, WriteStringToFile(std::to_string(60), kPathStopLevel, _));
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "ACTIVE"));
+ battDefender.update(&props);
+}
+
+TEST_F(BatteryDefenderTest, ActiveTime_NonDefaultLevels_invalid) {
+ BatteryDefender battDefender;
+
+ enableDefender();
+ powerAvailable();
+ initToActive();
+ ON_CALL(*mock, GetIntProperty(kPropBatteryDefenderThreshold, _, _, _))
+ .WillByDefault(Return(DEFAULT_TIME_TO_ACTIVATE_SECONDS));
+ ON_CALL(*mock, GetIntProperty(kPropBatteryDefenderCtrlActivateTime, _, _, _))
+ .WillByDefault(Return(DEFAULT_TIME_TO_ACTIVATE_SECONDS));
+ ON_CALL(*mock, GetIntProperty(kPropBatteryDefenderCtrlResumeTime, _, _, _))
+ .WillByDefault(Return(DEFAULT_TIME_TO_CLEAR_SECONDS));
+
+ // Non-default
+ ON_CALL(*mock, GetIntProperty(kPropBatteryDefenderCtrlStartSOC, _, _, _))
+ .WillByDefault(Return(30));
+ ON_CALL(*mock, GetIntProperty(kPropBatteryDefenderCtrlStopSOC, _, _, _))
+ .WillByDefault(Return(10));
+
+ InSequence s;
+
+ EXPECT_CALL(*mock, WriteStringToFile(std::to_string(70), kPathStartLevel, _));
+ EXPECT_CALL(*mock, WriteStringToFile(std::to_string(80), kPathStopLevel, _));
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "ACTIVE"));
+ battDefender.update(&props);
}
TEST_F(BatteryDefenderTest, ConnectDisconnectCycle) {
BatteryDefender battDefender;
enableDefender();
- defaultThreshold();
+ defaultThresholds();
initToConnectedCapacityReached();
InSequence s;
// Power ON
- ON_CALL(*mock, ReadFileToString(kPathWirelessChargerOnline, _, _))
- .WillByDefault(DoAll(SetArgPointee<1>(std::string("1")), Return(true)));
+ wirelessPresent();
EXPECT_CALL(*mock, WriteStringToFile(std::to_string(1000), kPathPersistChargerPresentTime, _));
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
testvar_systemTimeSecs += 60;
- battDefender.update();
+ battDefender.update(&props);
EXPECT_CALL(*mock, WriteStringToFile(std::to_string(1060), kPathPersistChargerPresentTime, _));
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
testvar_systemTimeSecs += 60;
- battDefender.update();
+ battDefender.update(&props);
// Power OFF
- ON_CALL(*mock, ReadFileToString(kPathWirelessChargerOnline, _, _))
- .WillByDefault(DoAll(SetArgPointee<1>(std::string("0")), Return(true)));
+ wirelessNotPresent();
// Maintain kPathPersistChargerPresentTime = 1060
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
testvar_systemTimeSecs += 60;
- battDefender.update();
+ battDefender.update(&props);
// Maintain kPathPersistChargerPresentTime = 1060
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
- testvar_systemTimeSecs += 60 * 4;
- battDefender.update();
+ testvar_systemTimeSecs += 60 * 4 - 1;
+ battDefender.update(&props);
+ testvar_systemTimeSecs += 1;
EXPECT_CALL(*mock, WriteStringToFile(std::to_string(0), kPathPersistChargerPresentTime, _));
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "DISCONNECTED"));
- testvar_systemTimeSecs += 1;
- battDefender.update();
+ testvar_systemTimeSecs += MIN_TIME_BETWEEN_FILE_UPDATES;
+ battDefender.update(&props);
// Power ON
- ON_CALL(*mock, ReadFileToString(kPathWirelessChargerOnline, _, _))
- .WillByDefault(DoAll(SetArgPointee<1>(std::string("1")), Return(true)));
+ wirelessPresent();
// Maintain kPathPersistChargerPresentTime = 0
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
testvar_systemTimeSecs += 60;
- battDefender.update();
+ battDefender.update(&props);
capacityReached();
// Maintain kPathPersistChargerPresentTime = 0
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
testvar_systemTimeSecs += 60;
- battDefender.update();
+ battDefender.update(&props);
EXPECT_CALL(*mock, WriteStringToFile(std::to_string(60), kPathPersistChargerPresentTime, _));
EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
testvar_systemTimeSecs += 60;
- battDefender.update();
+ battDefender.update(&props);
+}
+
+TEST_F(BatteryDefenderTest, ConnectDisconnectResumeTimeThreshold0) {
+ BatteryDefender battDefender;
+
+ enableDefender();
+ initToConnectedCapacityReached();
+ ON_CALL(*mock, GetIntProperty(kPropBatteryDefenderThreshold, _, _, _))
+ .WillByDefault(Return(DEFAULT_TIME_TO_ACTIVATE_SECONDS));
+ ON_CALL(*mock, GetIntProperty(kPropBatteryDefenderCtrlActivateTime, _, _, _))
+ .WillByDefault(Return(DEFAULT_TIME_TO_ACTIVATE_SECONDS));
+
+ // Non-default thresholds
+ ON_CALL(*mock, GetIntProperty(kPropBatteryDefenderCtrlResumeTime, _, _, _))
+ .WillByDefault(Return(0));
+
+ InSequence s;
+
+ // Power ON
+ wirelessPresent();
+
+ EXPECT_CALL(*mock, WriteStringToFile(std::to_string(1000), kPathPersistChargerPresentTime, _));
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
+ testvar_systemTimeSecs += 60;
+ battDefender.update(&props);
+
+ EXPECT_CALL(*mock, WriteStringToFile(std::to_string(1060), kPathPersistChargerPresentTime, _));
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
+ testvar_systemTimeSecs += 60;
+ battDefender.update(&props);
+
+ // Power OFF
+ wirelessNotPresent();
+
+ EXPECT_CALL(*mock, WriteStringToFile(std::to_string(0), kPathPersistChargerPresentTime, _));
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "DISCONNECTED"));
+ testvar_systemTimeSecs += MIN_TIME_BETWEEN_FILE_UPDATES;
+ battDefender.update(&props);
+}
+
+TEST_F(BatteryDefenderTest, PropsOverride_InitActive_allOnlineFalse) {
+ BatteryDefender battDefender;
+
+ enableDefender();
+ usbPresent();
+ defaultThresholds();
+ initToActive();
+
+ InSequence s;
+
+ props.chargerAcOnline = false;
+ props.chargerUsbOnline = false;
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "ACTIVE")).Times(2);
+ battDefender.update(&props);
+ ASSERT_EQ(props.chargerAcOnline, false);
+ ASSERT_EQ(props.chargerUsbOnline, true);
+
+ props.chargerAcOnline = false;
+ props.chargerUsbOnline = false;
+ battDefender.update(&props);
+ ASSERT_EQ(props.chargerAcOnline, false);
+ ASSERT_EQ(props.chargerUsbOnline, true);
+}
+
+TEST_F(BatteryDefenderTest, PropsOverride_InitActive_usbOnline) {
+ BatteryDefender battDefender;
+
+ enableDefender();
+ usbPresent();
+ defaultThresholds();
+ initToActive();
+
+ InSequence s;
+
+ props.chargerAcOnline = false;
+ props.chargerUsbOnline = true;
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "ACTIVE")).Times(2);
+ battDefender.update(&props);
+ ASSERT_EQ(props.chargerAcOnline, false);
+ ASSERT_EQ(props.chargerUsbOnline, true);
+
+ props.chargerAcOnline = false;
+ props.chargerUsbOnline = false;
+ battDefender.update(&props);
+ ASSERT_EQ(props.chargerAcOnline, false);
+ ASSERT_EQ(props.chargerUsbOnline, true);
+}
+
+TEST_F(BatteryDefenderTest, PropsOverride_InitActive_acOnline) {
+ BatteryDefender battDefender;
+
+ enableDefender();
+ usbPresent();
+ defaultThresholds();
+ initToActive();
+
+ InSequence s;
+
+ props.chargerAcOnline = true;
+ props.chargerUsbOnline = false;
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "ACTIVE")).Times(2);
+ battDefender.update(&props);
+ ASSERT_EQ(props.chargerAcOnline, true);
+ ASSERT_EQ(props.chargerUsbOnline, false);
+
+ props.chargerAcOnline = false;
+ props.chargerUsbOnline = false;
+ battDefender.update(&props);
+ ASSERT_EQ(props.chargerAcOnline, true);
+ ASSERT_EQ(props.chargerUsbOnline, false);
+}
+
+TEST_F(BatteryDefenderTest, PropsOverride_InitActive_allOnline) {
+ BatteryDefender battDefender;
+
+ enableDefender();
+ usbPresent();
+ defaultThresholds();
+ initToActive();
+
+ InSequence s;
+
+ props.chargerAcOnline = true;
+ props.chargerUsbOnline = true;
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "ACTIVE")).Times(2);
+ battDefender.update(&props);
+ ASSERT_EQ(props.chargerAcOnline, true);
+ ASSERT_EQ(props.chargerUsbOnline, true);
+
+ props.chargerAcOnline = false;
+ props.chargerUsbOnline = false;
+ battDefender.update(&props);
+ ASSERT_EQ(props.chargerAcOnline, true);
+ ASSERT_EQ(props.chargerUsbOnline, true);
+}
+
+TEST_F(BatteryDefenderTest, PropsOverride_InitConnected_allOnlineFalse) {
+ BatteryDefender battDefender;
+
+ enableDefender();
+ usbPresent();
+ defaultThresholds();
+ initToConnectedCapacityReached();
+
+ InSequence s;
+
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
+ battDefender.update(&props);
+
+ props.chargerAcOnline = false;
+ props.chargerUsbOnline = false;
+ testvar_systemTimeSecs += DEFAULT_TIME_TO_ACTIVATE_SECONDS + 1;
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "ACTIVE")).Times(2);
+ battDefender.update(&props);
+ ASSERT_EQ(props.chargerAcOnline, false);
+ ASSERT_EQ(props.chargerUsbOnline, true);
+
+ props.chargerAcOnline = false;
+ props.chargerUsbOnline = false;
+ battDefender.update(&props);
+ ASSERT_EQ(props.chargerAcOnline, false);
+ ASSERT_EQ(props.chargerUsbOnline, true);
+}
+
+TEST_F(BatteryDefenderTest, PropsOverride_InitConnected_usbOnline) {
+ BatteryDefender battDefender;
+
+ enableDefender();
+ usbPresent();
+ defaultThresholds();
+ initToConnectedCapacityReached();
+
+ InSequence s;
+
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
+ battDefender.update(&props);
+
+ props.chargerAcOnline = false;
+ props.chargerUsbOnline = true;
+ testvar_systemTimeSecs += DEFAULT_TIME_TO_ACTIVATE_SECONDS + 1;
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "ACTIVE")).Times(2);
+ battDefender.update(&props);
+ ASSERT_EQ(props.chargerAcOnline, false);
+ ASSERT_EQ(props.chargerUsbOnline, true);
+
+ props.chargerAcOnline = false;
+ props.chargerUsbOnline = false;
+ battDefender.update(&props);
+ ASSERT_EQ(props.chargerAcOnline, false);
+ ASSERT_EQ(props.chargerUsbOnline, true);
+}
+
+TEST_F(BatteryDefenderTest, PropsOverride_InitConnected_acOnline) {
+ BatteryDefender battDefender;
+
+ enableDefender();
+ usbPresent();
+ defaultThresholds();
+ initToConnectedCapacityReached();
+
+ InSequence s;
+
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
+ battDefender.update(&props);
+
+ props.chargerAcOnline = true;
+ props.chargerUsbOnline = false;
+ testvar_systemTimeSecs += DEFAULT_TIME_TO_ACTIVATE_SECONDS + 1;
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "ACTIVE")).Times(2);
+ battDefender.update(&props);
+ ASSERT_EQ(props.chargerAcOnline, true);
+ ASSERT_EQ(props.chargerUsbOnline, false);
+
+ props.chargerAcOnline = false;
+ props.chargerUsbOnline = false;
+ battDefender.update(&props);
+ ASSERT_EQ(props.chargerAcOnline, true);
+ ASSERT_EQ(props.chargerUsbOnline, false);
+}
+
+TEST_F(BatteryDefenderTest, PropsOverride_InitConnected_allOnline) {
+ BatteryDefender battDefender;
+
+ enableDefender();
+ usbPresent();
+ defaultThresholds();
+ initToConnectedCapacityReached();
+
+ InSequence s;
+
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
+ battDefender.update(&props);
+
+ props.chargerAcOnline = true;
+ props.chargerUsbOnline = true;
+ testvar_systemTimeSecs += DEFAULT_TIME_TO_ACTIVATE_SECONDS + 1;
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "ACTIVE")).Times(2);
+ battDefender.update(&props);
+ ASSERT_EQ(props.chargerAcOnline, true);
+ ASSERT_EQ(props.chargerUsbOnline, true);
+
+ props.chargerAcOnline = false;
+ props.chargerUsbOnline = false;
+ battDefender.update(&props);
+ ASSERT_EQ(props.chargerAcOnline, true);
+ ASSERT_EQ(props.chargerUsbOnline, true);
+}
+
+TEST_F(BatteryDefenderTest, PropsOverride_InitConnected_overrideHealth) {
+ BatteryDefender battDefender;
+
+ enableDefender();
+ usbPresent();
+ defaultThresholds();
+ initToConnectedCapacityReached();
+
+ InSequence s;
+
+ props.batteryHealth = android::BATTERY_HEALTH_UNKNOWN;
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED"));
+ battDefender.update(&props);
+ ASSERT_EQ(props.batteryHealth, android::BATTERY_HEALTH_UNKNOWN);
+
+ props.batteryHealth = android::BATTERY_HEALTH_UNKNOWN;
+ testvar_systemTimeSecs += DEFAULT_TIME_TO_ACTIVATE_SECONDS + 1;
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "ACTIVE"));
+ battDefender.update(&props);
+ ASSERT_EQ(props.batteryHealth, android::BATTERY_HEALTH_OVERHEAT);
+}
+
+TEST_F(BatteryDefenderTest, PropsOverride_InitConnected_kernelDefend) {
+ BatteryDefender battDefender;
+
+ enableDefender();
+ usbPresent();
+ defaultThresholds();
+ initToConnectedCapacityReached();
+
+ InSequence s;
+
+ EXPECT_CALL(*mock, SetProperty(kPropBatteryDefenderState, "CONNECTED")).Times(3);
+ battDefender.update(&props);
+
+ props.chargerAcOnline = true;
+ props.chargerUsbOnline = true;
+ props.batteryHealth = android::BATTERY_HEALTH_OVERHEAT;
+ battDefender.update(&props);
+ ASSERT_EQ(props.chargerAcOnline, true);
+ ASSERT_EQ(props.chargerUsbOnline, true);
+
+ props.chargerAcOnline = false;
+ props.chargerUsbOnline = false;
+ battDefender.update(&props);
+ ASSERT_EQ(props.chargerAcOnline, true);
+ ASSERT_EQ(props.chargerUsbOnline, true);
}
} // namespace health
diff --git a/pixelstats/Android.bp b/pixelstats/Android.bp
index 7f2ee61..94fa064 100644
--- a/pixelstats/Android.bp
+++ b/pixelstats/Android.bp
@@ -49,6 +49,7 @@
"UeventListener.cpp",
"WlcReporter.cpp",
"BatteryCapacityReporter.cpp",
+ "BatteryEEPROMReporter.cpp",
],
cflags: [
"-Wall",
diff --git a/pixelstats/BatteryEEPROMReporter.cpp b/pixelstats/BatteryEEPROMReporter.cpp
new file mode 100644
index 0000000..ab0280d
--- /dev/null
+++ b/pixelstats/BatteryEEPROMReporter.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "pixelstats: BatteryEEPROM"
+
+#include <log/log.h>
+#include <time.h>
+#include <utils/Timers.h>
+#include <cmath>
+#include <inttypes.h>
+
+#include <android-base/file.h>
+
+#include <android/frameworks/stats/1.0/IStats.h>
+#include <pixelstats/BatteryEEPROMReporter.h>
+
+#include <hardware/google/pixel/pixelstats/pixelatoms.pb.h>
+
+namespace android {
+namespace hardware {
+namespace google {
+namespace pixel {
+
+using android::base::ReadFileToString;
+using android::frameworks::stats::V1_0::IStats;
+using android::frameworks::stats::V1_0::VendorAtom;
+using android::hardware::google::pixel::PixelAtoms::BatteryEEPROM;
+
+#define LINESIZE 71
+
+BatteryEEPROMReporter::BatteryEEPROMReporter() {}
+
+void BatteryEEPROMReporter::checkAndReport(const std::string &path) {
+ std::string file_contents;
+ std::string history_each;
+
+ const int kSecondsPerMonth = 60 * 60 * 24 * 30;
+ int64_t now = getTimeSecs();
+
+ if ((report_time_ != 0) && (now - report_time_ < kSecondsPerMonth)) {
+ ALOGD("Not upload time. now:%ld, pre:%ld", now, report_time_);
+ return;
+ }
+
+ if (!ReadFileToString(path.c_str(), &file_contents)) {
+ ALOGE("Unable to read %s - %s", path.c_str(), strerror(errno));
+ return;
+ }
+ ALOGD("checkAndReport: %s", file_contents.c_str());
+
+ int16_t i, num;
+ struct BatteryHistory hist;
+ const int kHistTotalLen = strlen(file_contents.c_str());
+
+ for (i = 0; i < (LINESIZE * BATT_HIST_NUM_MAX); i = i + LINESIZE) {
+ if (i + LINESIZE > kHistTotalLen)
+ break;
+ history_each = file_contents.substr(i, LINESIZE);
+ num = sscanf(history_each.c_str(),
+ "%4" SCNx16 "%4" SCNx16 "%4" SCNx16 "%4" SCNx16
+ "%2" SCNx8 "%2" SCNx8 " %2" SCNx8 "%2" SCNx8
+ "%2" SCNx8 "%2" SCNx8 " %2" SCNx8 "%2" SCNx8
+ "%2" SCNx8 "%2" SCNx8 " %4" SCNx16 "%4" SCNx16
+ "%4" SCNx16 "%4" SCNx16 "%4" SCNx16,
+ &hist.cycle_cnt, &hist.full_cap, &hist.esr,
+ &hist.rslow, &hist.batt_temp, &hist.soh,
+ &hist.cc_soc, &hist.cutoff_soc, &hist.msoc,
+ &hist.sys_soc, &hist.reserve, &hist.batt_soc,
+ &hist.min_temp, &hist.max_temp, &hist.max_vbatt,
+ &hist.min_vbatt, &hist.max_ibatt, &hist.min_ibatt,
+ &hist.checksum);
+
+ if (num != kNumBatteryHistoryFields) {
+ ALOGE("Couldn't process %s", history_each.c_str());
+ continue;
+ }
+
+ if (checkLogEvent(hist)) {
+ reportEvent(hist);
+ report_time_ = getTimeSecs();
+ }
+ }
+}
+
+int64_t BatteryEEPROMReporter::getTimeSecs(void) {
+ return nanoseconds_to_seconds(systemTime(SYSTEM_TIME_BOOTTIME));
+}
+
+/**
+ * @return true if a log should be reported, else false.
+ * Here we use checksum to confirm the data is usable or not.
+ * The checksum mismatch when storage data overflow or corrupt.
+ * We don't need data in such cases.
+ */
+bool BatteryEEPROMReporter::checkLogEvent(struct BatteryHistory hist) {
+ int checksum = 0;
+
+ checksum = hist.cycle_cnt + hist.full_cap + hist.esr + hist.rslow
+ + hist.soh + hist.batt_temp + hist.cutoff_soc + hist.cc_soc
+ + hist.sys_soc + hist.msoc + hist.batt_soc + hist.reserve
+ + hist.max_temp + hist.min_temp + hist.max_vbatt
+ + hist.min_vbatt + hist.max_ibatt + hist.min_ibatt;
+ /* Compare with checksum data */
+ if (checksum == hist.checksum) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void BatteryEEPROMReporter::reportEvent(struct BatteryHistory hist) {
+ sp<IStats> stats_client = IStats::tryGetService();
+ // upload atom
+ std::vector<int> eeprom_history_fields = {BatteryEEPROM::kCycleCntFieldNumber,
+ BatteryEEPROM::kFullCapFieldNumber,
+ BatteryEEPROM::kEsrFieldNumber,
+ BatteryEEPROM::kRslowFieldNumber,
+ BatteryEEPROM::kSohFieldNumber,
+ BatteryEEPROM::kBattTempFieldNumber,
+ BatteryEEPROM::kCutoffSocFieldNumber,
+ BatteryEEPROM::kCcSocFieldNumber,
+ BatteryEEPROM::kSysSocFieldNumber,
+ BatteryEEPROM::kMsocFieldNumber,
+ BatteryEEPROM::kBattSocFieldNumber,
+ BatteryEEPROM::kReserveFieldNumber,
+ BatteryEEPROM::kMaxTempFieldNumber,
+ BatteryEEPROM::kMinTempFieldNumber,
+ BatteryEEPROM::kMaxVbattFieldNumber,
+ BatteryEEPROM::kMinVbattFieldNumber,
+ BatteryEEPROM::kMaxIbattFieldNumber,
+ BatteryEEPROM::kMinIbattFieldNumber,
+ BatteryEEPROM::kChecksumFieldNumber};
+ std::vector<VendorAtom::Value> values(eeprom_history_fields.size());
+ VendorAtom::Value val;
+
+ ALOGD("reportEvent: cycle_cnt:%d, full_cap:%d, esr:%d, rslow:%d, soh:%d, "
+ "batt_temp:%d, cutoff_soc:%d, cc_soc:%d, sys_soc:%d, msoc:%d, "
+ "batt_soc:%d, reserve:%d, max_temp:%d, min_temp:%d, max_vbatt:%d, "
+ "min_vbatt:%d, max_ibatt:%d, min_ibatt:%d, checksum:%d",
+ hist.cycle_cnt, hist.full_cap, hist.esr, hist.rslow, hist.soh,
+ hist.batt_temp, hist.cutoff_soc, hist.cc_soc, hist.sys_soc,
+ hist.msoc, hist.batt_soc, hist.reserve, hist.max_temp,
+ hist.min_temp, hist.max_vbatt, hist.min_vbatt, hist.max_ibatt,
+ hist.min_ibatt, hist.checksum);
+
+ val.intValue(hist.cycle_cnt);
+ values[BatteryEEPROM::kCycleCntFieldNumber - kVendorAtomOffset] = val;
+ val.intValue(hist.full_cap);
+ values[BatteryEEPROM::kFullCapFieldNumber - kVendorAtomOffset] = val;
+ val.intValue(hist.esr);
+ values[BatteryEEPROM::kEsrFieldNumber - kVendorAtomOffset] = val;
+ val.intValue(hist.rslow);
+ values[BatteryEEPROM::kRslowFieldNumber - kVendorAtomOffset] = val;
+ val.intValue(hist.soh);
+ values[BatteryEEPROM::kSohFieldNumber - kVendorAtomOffset] = val;
+ val.intValue(hist.batt_temp);
+ values[BatteryEEPROM::kBattTempFieldNumber - kVendorAtomOffset] = val;
+ val.intValue(hist.cutoff_soc);
+ values[BatteryEEPROM::kCutoffSocFieldNumber - kVendorAtomOffset] = val;
+ val.intValue(hist.cc_soc);
+ values[BatteryEEPROM::kCcSocFieldNumber - kVendorAtomOffset] = val;
+ val.intValue(hist.sys_soc);
+ values[BatteryEEPROM::kSysSocFieldNumber - kVendorAtomOffset] = val;
+ val.intValue(hist.msoc);
+ values[BatteryEEPROM::kMsocFieldNumber - kVendorAtomOffset] = val;
+ val.intValue(hist.batt_soc);
+ values[BatteryEEPROM::kBattSocFieldNumber - kVendorAtomOffset] = val;
+ val.intValue(hist.reserve);
+ values[BatteryEEPROM::kReserveFieldNumber - kVendorAtomOffset] = val;
+ val.intValue(hist.max_temp);
+ values[BatteryEEPROM::kMaxTempFieldNumber - kVendorAtomOffset] = val;
+ val.intValue(hist.min_temp);
+ values[BatteryEEPROM::kMinTempFieldNumber - kVendorAtomOffset] = val;
+ val.intValue(hist.max_vbatt);
+ values[BatteryEEPROM::kMaxVbattFieldNumber - kVendorAtomOffset] = val;
+ val.intValue(hist.min_vbatt);
+ values[BatteryEEPROM::kMinVbattFieldNumber - kVendorAtomOffset] = val;
+ val.intValue(hist.max_ibatt);
+ values[BatteryEEPROM::kMaxIbattFieldNumber - kVendorAtomOffset] = val;
+ val.intValue(hist.min_ibatt);
+ values[BatteryEEPROM::kMinIbattFieldNumber - kVendorAtomOffset] = val;
+ val.intValue(hist.checksum);
+ values[BatteryEEPROM::kChecksumFieldNumber - kVendorAtomOffset] = val;
+
+ VendorAtom event = {.reverseDomainName = PixelAtoms::ReverseDomainNames().pixel(),
+ .atomId = PixelAtoms::Ids::BATTERY_EEPROM,
+ .values = values};
+ Return<void> ret = stats_client->reportVendorAtom(event);
+ if (!ret.isOk())
+ ALOGE("Unable to report BatteryEEPROM to Stats service");
+}
+
+
+} // namespace pixel
+} // namespace google
+} // namespace hardware
+} // namespace android
diff --git a/pixelstats/SysfsCollector.cpp b/pixelstats/SysfsCollector.cpp
index bf1e3d5..29b3509 100644
--- a/pixelstats/SysfsCollector.cpp
+++ b/pixelstats/SysfsCollector.cpp
@@ -72,7 +72,8 @@
kF2fsStatsPath(sysfs_paths.F2fsStatsPath),
kUserdataBlockProp(sysfs_paths.UserdataBlockProp),
kZramMmStatPath("/sys/block/zram0/mm_stat"),
- kZramBdStatPath("/sys/block/zram0/bd_stat") {}
+ kZramBdStatPath("/sys/block/zram0/bd_stat"),
+ kEEPROMPath(sysfs_paths.EEPROMPath) {}
bool SysfsCollector::ReadFileToInt(const std::string &path, int *val) {
return ReadFileToInt(path.c_str(), val);
@@ -126,6 +127,18 @@
}
/**
+ * Read the contents of kEEPROMPath and report them.
+ */
+void SysfsCollector::logBatteryEEPROM() {
+ if (kEEPROMPath == nullptr || strlen(kEEPROMPath) == 0) {
+ ALOGV("Battery EEPROM path not specified");
+ return;
+ }
+
+ battery_EEPROM_reporter_.checkAndReport(kEEPROMPath);
+}
+
+/**
* Check the codec for failures over the past 24hr.
*/
void SysfsCollector::logCodecFailed() {
@@ -599,6 +612,7 @@
logUFSLifetime();
logF2fsStats();
logZramStats();
+ logBatteryEEPROM();
stats_.clear();
}
diff --git a/pixelstats/include/pixelstats/BatteryEEPROMReporter.h b/pixelstats/include/pixelstats/BatteryEEPROMReporter.h
new file mode 100644
index 0000000..e3ff997
--- /dev/null
+++ b/pixelstats/include/pixelstats/BatteryEEPROMReporter.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HARDWARE_GOOGLE_PIXEL_PIXELSTATS_BATTERYEEPROMREPORTER_H
+#define HARDWARE_GOOGLE_PIXEL_PIXELSTATS_BATTERYEEPROMREPORTER_H
+
+namespace android {
+namespace hardware {
+namespace google {
+namespace pixel {
+
+// The storage for save whole history is 928 byte
+// each history contains 19 items with total size 28 byte
+// hence the history number is 928/28~33
+#define BATT_HIST_NUM_MAX 33
+
+/**
+ * A class to upload battery EEPROM metrics
+ */
+class BatteryEEPROMReporter {
+ public:
+ BatteryEEPROMReporter();
+ void checkAndReport(const std::string &path);
+
+ private:
+ // Proto messages are 1-indexed and VendorAtom field numbers start at 2, so
+ // store everything in the values array at the index of the field number
+ // -2.
+ const int kVendorAtomOffset = 2;
+
+ struct BatteryHistory {
+ /* The cycle count number; record of charge/discharge times */
+ uint16_t cycle_cnt;
+ /* The current full capacity of the battery under nominal conditions */
+ uint16_t full_cap;
+ /* The battery equivalent series resistance */
+ uint16_t esr;
+ /* Battery resistance related to temperature change */
+ uint16_t rslow;
+ /* Battery health indicator reflecting the battery age state */
+ uint8_t soh;
+ /* The battery temperature */
+ int8_t batt_temp;
+
+ /* Battery state of charge (SOC) shutdown point */
+ uint8_t cutoff_soc;
+ /* Raw battery state of charge (SOC), based on battery current (CC = Coulomb Counter) */
+ uint8_t cc_soc;
+ /* Estimated battery state of charge (SOC) from batt_soc with endpoint limiting (0% and 100%) */
+ uint8_t sys_soc;
+ /* Filtered monotonic SOC, handles situations where the cutoff_soc is increased and
+ * then decreased from the battery physical properties
+ */
+ uint8_t msoc;
+ /* Estimated SOC derived from cc_soc that provides voltage loop feedback correction using
+ * battery voltage, current, and status values
+ */
+ uint8_t batt_soc;
+
+ /* Field used for data padding in the EEPROM data */
+ uint8_t reserve;
+
+ /* The maximum battery temperature ever seen */
+ int8_t max_temp;
+ /* The minimum battery temperature ever seen */
+ int8_t min_temp;
+ /* The maximum battery voltage ever seen */
+ uint16_t max_vbatt;
+ /* The minimum battery voltage ever seen */
+ uint16_t min_vbatt;
+ /* The maximum battery current ever seen */
+ int16_t max_ibatt;
+ /* The minimum battery current ever seen */
+ int16_t min_ibatt;
+ /* Field used to verify the integrity of the EEPROM data */
+ uint16_t checksum;
+ };
+ /* The number of elements in struct BatteryHistory */
+ const int kNumBatteryHistoryFields = 19;
+
+ int64_t report_time_ = 0;
+ int64_t getTimeSecs();
+
+ bool checkLogEvent(struct BatteryHistory hist);
+ void reportEvent(struct BatteryHistory hist);
+};
+
+} // namespace pixel
+} // namespace google
+} // namespace hardware
+} // namespace android
+
+#endif // HARDWARE_GOOGLE_PIXEL_PIXELSTATS_BATTERYEEPROMREPORTER_H
diff --git a/pixelstats/include/pixelstats/SysfsCollector.h b/pixelstats/include/pixelstats/SysfsCollector.h
index c6cc608..bbe116f 100644
--- a/pixelstats/include/pixelstats/SysfsCollector.h
+++ b/pixelstats/include/pixelstats/SysfsCollector.h
@@ -20,6 +20,8 @@
#include <android/frameworks/stats/1.0/IStats.h>
#include <utils/StrongPointer.h>
+#include "BatteryEEPROMReporter.h"
+
using android::sp;
using android::frameworks::stats::V1_0::IStats;
using android::frameworks::stats::V1_0::SlowIo;
@@ -50,6 +52,7 @@
const char *const UserdataBlockProp;
const char *const ZramMmStatPath;
const char *const ZramBdStatPath;
+ const char *const EEPROMPath;
};
SysfsCollector(const struct SysfsPaths &paths);
@@ -71,6 +74,7 @@
void logF2fsStats();
void logZramStats();
void logBootStats();
+ void logBatteryEEPROM();
void reportSlowIoFromFile(const char *path, const SlowIo::IoOperation &operation_s);
void reportZramMmStat();
@@ -96,8 +100,11 @@
const char *const kUserdataBlockProp;
const char *const kZramMmStatPath;
const char *const kZramBdStatPath;
+ const char *const kEEPROMPath;
sp<IStats> stats_;
+ BatteryEEPROMReporter battery_EEPROM_reporter_;
+
// Proto messages are 1-indexed and VendorAtom field numbers start at 2, so
// store everything in the values array at the index of the field number
// -2.
diff --git a/pixelstats/pixelatoms.proto b/pixelstats/pixelatoms.proto
index 857e66f..a920783 100644
--- a/pixelstats/pixelatoms.proto
+++ b/pixelstats/pixelatoms.proto
@@ -46,6 +46,8 @@
DEVICE_ORIENTATION = 105009;
FG_CAPACITY = 105010;
PD_VID_PID = 105011;
+ BATTERY_EEPROM = 105012;
+
// AOSP atom ID range ends at 109999
}
@@ -257,3 +259,51 @@
/* Product ID of wired charger */
optional int32 pid = 3;
}
+
+message BatteryEEPROM {
+ /* The cycle count number; record of charge/discharge times */
+ optional int32 cycle_cnt = 2;
+ /* The current full capacity of the battery under nominal conditions */
+ optional int32 full_cap = 3;
+ /* The battery equivalent series resistance */
+ optional int32 esr = 4;
+ /* Battery resistance related to temperature change */
+ optional int32 rslow = 5;
+ /* Battery health indicator reflecting the battery age state */
+ optional int32 soh = 6;
+ /* The battery temperature */
+ optional int32 batt_temp = 7;
+
+ /* Battery state of charge (SOC) shutdown point */
+ optional int32 cutoff_soc = 8;
+ /* Raw battery state of charge (SOC), based on battery current (CC = Coulomb Counter) */
+ optional int32 cc_soc = 9;
+ /* Estimated battery state of charge (SOC) from batt_soc with endpoint limiting (0% and 100%) */
+ optional int32 sys_soc = 10;
+ /* Filtered monotonic SOC, handles situations where the cutoff_soc is increased and
+ * then decreased from the battery physical properties
+ */
+ optional int32 msoc = 11;
+ /* Estimated SOC derived from cc_soc that provides voltage loop feedback correction using
+ * battery voltage, current, and status values
+ */
+ optional int32 batt_soc = 12;
+
+ /* Field used for data padding in the EEPROM data */
+ optional int32 reserve = 13;
+
+ /* The maximum battery temperature ever seen */
+ optional int32 max_temp = 14;
+ /* The minimum battery temperature ever seen */
+ optional int32 min_temp = 15;
+ /* The maximum battery voltage ever seen */
+ optional int32 max_vbatt = 16;
+ /* The minimum battery voltage ever seen */
+ optional int32 min_vbatt = 17;
+ /* The maximum battery current ever seen */
+ optional int32 max_ibatt = 18;
+ /* The minimum battery current ever seen */
+ optional int32 min_ibatt = 19;
+ /* Field used to verify the integrity of the EEPROM data */
+ optional int32 checksum = 20;
+}