Simplify initialization and add setValue to support parceling
Bug: 197162116
Test: atest libbattery_test
Change-Id: I4278206eab049d714c5278e6b10ba3155e17142f
diff --git a/libs/battery/LongArrayMultiStateCounter.cpp b/libs/battery/LongArrayMultiStateCounter.cpp
index 68e0883..125cfaf 100644
--- a/libs/battery/LongArrayMultiStateCounter.cpp
+++ b/libs/battery/LongArrayMultiStateCounter.cpp
@@ -62,7 +62,7 @@
template <>
std::string LongArrayMultiStateCounter::valueToString(const std::vector<uint64_t>& v) const {
std::stringstream s;
- s << "{ ";
+ s << "{";
bool first = true;
for (uint64_t n : v) {
if (!first) {
diff --git a/libs/battery/LongArrayMultiStateCounterTest.cpp b/libs/battery/LongArrayMultiStateCounterTest.cpp
index 24cb437..e4e6b2a 100644
--- a/libs/battery/LongArrayMultiStateCounterTest.cpp
+++ b/libs/battery/LongArrayMultiStateCounterTest.cpp
@@ -24,7 +24,9 @@
class LongArrayMultiStateCounterTest : public testing::Test {};
TEST_F(LongArrayMultiStateCounterTest, stateChange) {
- LongArrayMultiStateCounter testCounter(2, 0, std::vector<uint64_t>(4), 1000);
+ LongArrayMultiStateCounter testCounter(2, std::vector<uint64_t>(4));
+ testCounter.updateValue(std::vector<uint64_t>({0, 0, 0, 0}), 1000);
+ testCounter.setState(0, 1000);
testCounter.setState(1, 2000);
testCounter.updateValue(std::vector<uint64_t>({100, 200, 300, 400}), 3000);
@@ -34,7 +36,9 @@
}
TEST_F(LongArrayMultiStateCounterTest, accumulation) {
- LongArrayMultiStateCounter testCounter(2, 0, std::vector<uint64_t>(4), 1000);
+ LongArrayMultiStateCounter testCounter(2, std::vector<uint64_t>(4));
+ testCounter.updateValue(std::vector<uint64_t>({0, 0, 0, 0}), 1000);
+ testCounter.setState(0, 1000);
testCounter.setState(1, 2000);
testCounter.updateValue(std::vector<uint64_t>({100, 200, 300, 400}), 3000);
testCounter.setState(0, 4000);
@@ -50,5 +54,16 @@
EXPECT_EQ(std::vector<uint64_t>({70, 120, 170, 220}), testCounter.getCount(1));
}
+TEST_F(LongArrayMultiStateCounterTest, toString) {
+ LongArrayMultiStateCounter testCounter(2, std::vector<uint64_t>(4));
+ testCounter.updateValue(std::vector<uint64_t>({0, 0, 0, 0}), 1000);
+ testCounter.setState(0, 1000);
+ testCounter.setState(1, 2000);
+ testCounter.updateValue(std::vector<uint64_t>({100, 200, 300, 400}), 3000);
+
+ EXPECT_STREQ("[0: {50, 100, 150, 200}, 1: {50, 100, 150, 200}] updated: 3000 currentState: 1",
+ testCounter.toString().c_str());
+}
+
} // namespace battery
} // namespace android
diff --git a/libs/battery/MultiStateCounter.h b/libs/battery/MultiStateCounter.h
index 9f56b29..40de068 100644
--- a/libs/battery/MultiStateCounter.h
+++ b/libs/battery/MultiStateCounter.h
@@ -51,15 +51,18 @@
State* states;
public:
- MultiStateCounter(uint16_t stateCount, state_t initialState, const T& emptyValue,
- time_t timestamp);
+ MultiStateCounter(uint16_t stateCount, const T& emptyValue);
virtual ~MultiStateCounter();
void setState(state_t state, time_t timestamp);
+ void setValue(state_t state, const T& value);
+
void updateValue(const T& value, time_t timestamp);
+ uint16_t getStateCount();
+
const T& getCount(state_t state);
std::string toString();
@@ -86,14 +89,13 @@
// Since MultiStateCounter is a template, the implementation must be inlined.
template <class T>
-MultiStateCounter<T>::MultiStateCounter(uint16_t stateCount, state_t initialState,
- const T& emptyValue, time_t timestamp)
+MultiStateCounter<T>::MultiStateCounter(uint16_t stateCount, const T& emptyValue)
: stateCount(stateCount),
- currentState(initialState),
- lastStateChangeTimestamp(timestamp),
+ currentState(0),
+ lastStateChangeTimestamp(-1),
emptyValue(emptyValue),
lastValue(emptyValue),
- lastUpdateTimestamp(timestamp),
+ lastUpdateTimestamp(-1),
deltaValue(emptyValue) {
states = new State[stateCount];
for (int i = 0; i < stateCount; i++) {
@@ -109,17 +111,19 @@
template <class T>
void MultiStateCounter<T>::setState(state_t state, time_t timestamp) {
- if (timestamp >= lastStateChangeTimestamp) {
- states[currentState].timeInStateSinceUpdate += timestamp - lastStateChangeTimestamp;
- } else {
- ALOGE("setState is called with an earlier timestamp: %lu, previous timestamp: %lu\n",
- (unsigned long)timestamp, (unsigned long)lastStateChangeTimestamp);
- // The accumulated durations have become unreliable. For example, if the timestamp
- // sequence was 1000, 2000, 1000, 3000, if we accumulated the positive deltas,
- // we would get 4000, which is greater than (last - first). This could lead to
- // counts exceeding 100%.
- for (int i = 0; i < stateCount; i++) {
- states[i].timeInStateSinceUpdate = 0;
+ if (lastStateChangeTimestamp >= 0) {
+ if (timestamp >= lastStateChangeTimestamp) {
+ states[currentState].timeInStateSinceUpdate += timestamp - lastStateChangeTimestamp;
+ } else {
+ ALOGE("setState is called with an earlier timestamp: %lu, previous timestamp: %lu\n",
+ (unsigned long)timestamp, (unsigned long)lastStateChangeTimestamp);
+ // The accumulated durations have become unreliable. For example, if the timestamp
+ // sequence was 1000, 2000, 1000, 3000, if we accumulated the positive deltas,
+ // we would get 4000, which is greater than (last - first). This could lead to
+ // counts exceeding 100%.
+ for (int i = 0; i < stateCount; i++) {
+ states[i].timeInStateSinceUpdate = 0;
+ }
}
}
currentState = state;
@@ -127,36 +131,49 @@
}
template <class T>
+void MultiStateCounter<T>::setValue(state_t state, const T& value) {
+ states[state].counter = value;
+}
+
+template <class T>
void MultiStateCounter<T>::updateValue(const T& value, time_t timestamp) {
// Confirm the current state for the side-effect of updating the time-in-state
// counter for the current state.
setState(currentState, timestamp);
- if (timestamp > lastUpdateTimestamp) {
- if (delta(lastValue, value, &deltaValue)) {
- time_t timeSinceUpdate = timestamp - lastUpdateTimestamp;
- for (int i = 0; i < stateCount; i++) {
- time_t timeInState = states[i].timeInStateSinceUpdate;
- if (timeInState) {
- add(&states[i].counter, deltaValue, timeInState, timeSinceUpdate);
- states[i].timeInStateSinceUpdate = 0;
+ if (lastUpdateTimestamp >= 0) {
+ if (timestamp > lastUpdateTimestamp) {
+ if (delta(lastValue, value, &deltaValue)) {
+ time_t timeSinceUpdate = timestamp - lastUpdateTimestamp;
+ for (int i = 0; i < stateCount; i++) {
+ time_t timeInState = states[i].timeInStateSinceUpdate;
+ if (timeInState) {
+ add(&states[i].counter, deltaValue, timeInState, timeSinceUpdate);
+ states[i].timeInStateSinceUpdate = 0;
+ }
}
+ } else {
+ std::stringstream str;
+ str << "updateValue is called with a value " << valueToString(value)
+ << ", which is lower than the previous value " << valueToString(lastValue)
+ << "\n";
+ ALOGE("%s", str.str().c_str());
}
- } else {
- std::stringstream str;
- str << "updateValue is called with a value " << valueToString(value)
- << ", which is lower than the previous value " << valueToString(lastValue) << "\n";
- ALOGE("%s", str.str().c_str());
+ } else if (timestamp < lastUpdateTimestamp) {
+ ALOGE("updateValue is called with an earlier timestamp: %lu, previous timestamp: %lu\n",
+ (unsigned long)timestamp, (unsigned long)lastUpdateTimestamp);
}
- } else if (timestamp < lastUpdateTimestamp) {
- ALOGE("updateValue is called with an earlier timestamp: %lu, previous timestamp: %lu\n",
- (unsigned long)timestamp, (unsigned long)lastUpdateTimestamp);
}
lastValue = value;
lastUpdateTimestamp = timestamp;
}
template <class T>
+uint16_t MultiStateCounter<T>::getStateCount() {
+ return stateCount;
+}
+
+template <class T>
const T& MultiStateCounter<T>::getCount(state_t state) {
return states[state].counter;
}
@@ -164,17 +181,29 @@
template <class T>
std::string MultiStateCounter<T>::toString() {
std::stringstream str;
- str << "currentState: " << currentState
- << " lastStateChangeTimestamp: " << lastStateChangeTimestamp
- << " lastUpdateTimestamp: " << lastUpdateTimestamp << " states: [";
+ str << "[";
for (int i = 0; i < stateCount; i++) {
if (i != 0) {
str << ", ";
}
- str << i << ": time: " << states[i].timeInStateSinceUpdate
- << " counter: " << valueToString(states[i].counter);
+ str << i << ": " << valueToString(states[i].counter);
+ if (states[i].timeInStateSinceUpdate > 0) {
+ str << " timeInStateSinceUpdate: " << states[i].timeInStateSinceUpdate;
+ }
}
str << "]";
+ if (lastUpdateTimestamp >= 0) {
+ str << " updated: " << lastUpdateTimestamp;
+ }
+ if (lastStateChangeTimestamp >= 0) {
+ str << " currentState: " << currentState;
+ if (lastStateChangeTimestamp > lastUpdateTimestamp) {
+ str << " stateChanged: " << lastStateChangeTimestamp;
+ }
+ } else {
+ str << " currentState: none";
+ }
+
return str.str();
}
diff --git a/libs/battery/MultiStateCounterTest.cpp b/libs/battery/MultiStateCounterTest.cpp
index 942d5ca..87c80c5 100644
--- a/libs/battery/MultiStateCounterTest.cpp
+++ b/libs/battery/MultiStateCounterTest.cpp
@@ -49,8 +49,9 @@
class MultiStateCounterTest : public testing::Test {};
TEST_F(MultiStateCounterTest, constructor) {
- DoubleMultiStateCounter testCounter(3, 1, 0, 1000);
- testCounter.setState(1, 2000);
+ DoubleMultiStateCounter testCounter(3, 0);
+ testCounter.updateValue(0, 0);
+ testCounter.setState(1, 0);
testCounter.updateValue(3.14, 3000);
EXPECT_DOUBLE_EQ(0, testCounter.getCount(0));
@@ -59,7 +60,9 @@
}
TEST_F(MultiStateCounterTest, stateChange) {
- DoubleMultiStateCounter testCounter(3, 1, 0, 0);
+ DoubleMultiStateCounter testCounter(3, 0);
+ testCounter.updateValue(0, 0);
+ testCounter.setState(1, 0);
testCounter.setState(2, 1000);
testCounter.updateValue(6.0, 3000);
@@ -69,7 +72,9 @@
}
TEST_F(MultiStateCounterTest, timeAdjustment_setState) {
- DoubleMultiStateCounter testCounter(3, 1, 0, 0);
+ DoubleMultiStateCounter testCounter(3, 0);
+ testCounter.updateValue(0, 0);
+ testCounter.setState(1, 0);
testCounter.setState(2, 2000);
// Time moves back
@@ -88,7 +93,9 @@
}
TEST_F(MultiStateCounterTest, timeAdjustment_updateValue) {
- DoubleMultiStateCounter testCounter(1, 0, 0, 0);
+ DoubleMultiStateCounter testCounter(1, 0);
+ testCounter.updateValue(0, 0);
+ testCounter.setState(0, 0);
testCounter.updateValue(6.0, 2000);
// Time moves back. The negative delta from 2000 to 1000 is ignored
@@ -101,5 +108,23 @@
EXPECT_DOUBLE_EQ(9.0, testCounter.getCount(0));
}
+TEST_F(MultiStateCounterTest, toString) {
+ DoubleMultiStateCounter testCounter(2, 0);
+
+ EXPECT_STREQ("[0: 0.000000, 1: 0.000000] currentState: none", testCounter.toString().c_str());
+
+ testCounter.updateValue(0, 0);
+ testCounter.setState(1, 0);
+ testCounter.setState(1, 2000);
+ EXPECT_STREQ("[0: 0.000000, 1: 0.000000 timeInStateSinceUpdate: 2000]"
+ " updated: 0 currentState: 1 stateChanged: 2000",
+ testCounter.toString().c_str());
+
+ testCounter.updateValue(3.14, 3000);
+
+ EXPECT_STREQ("[0: 0.000000, 1: 3.140000] updated: 3000 currentState: 1",
+ testCounter.toString().c_str());
+}
+
} // namespace battery
} // namespace android