diff options
author | 2021-09-03 19:07:23 -0700 | |
---|---|---|
committer | 2021-09-14 09:26:23 -0700 | |
commit | 12aaf8e35911cd5f036917de9a6f388d611ed51c (patch) | |
tree | 21fd64a578a2dd49d1d1cc5b7c47ae36c3ae4c9c | |
parent | e96c8c03858785089c3f09a52e8c2d9cdecef7cb (diff) |
Simplify initialization and add setValue to support parceling
Bug: 197162116
Test: atest libbattery_test
Change-Id: I4278206eab049d714c5278e6b10ba3155e17142f
-rw-r--r-- | libs/battery/LongArrayMultiStateCounter.cpp | 2 | ||||
-rw-r--r-- | libs/battery/LongArrayMultiStateCounterTest.cpp | 19 | ||||
-rw-r--r-- | libs/battery/MultiStateCounter.h | 107 | ||||
-rw-r--r-- | libs/battery/MultiStateCounterTest.cpp | 35 |
4 files changed, 116 insertions, 47 deletions
diff --git a/libs/battery/LongArrayMultiStateCounter.cpp b/libs/battery/LongArrayMultiStateCounter.cpp index 68e088394a..125cfaffa4 100644 --- a/libs/battery/LongArrayMultiStateCounter.cpp +++ b/libs/battery/LongArrayMultiStateCounter.cpp @@ -62,7 +62,7 @@ void LongArrayMultiStateCounter::add(std::vector<uint64_t>* value1, 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 24cb437eaa..e4e6b2a49f 100644 --- a/libs/battery/LongArrayMultiStateCounterTest.cpp +++ b/libs/battery/LongArrayMultiStateCounterTest.cpp @@ -24,7 +24,9 @@ namespace battery { 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, stateChange) { } 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 @@ TEST_F(LongArrayMultiStateCounterTest, accumulation) { 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 9f56b29dfb..40de068a95 100644 --- a/libs/battery/MultiStateCounter.h +++ b/libs/battery/MultiStateCounter.h @@ -51,15 +51,18 @@ class MultiStateCounter { 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 @@ private: // 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 @@ MultiStateCounter<T>::~MultiStateCounter() { 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 @@ void MultiStateCounter<T>::setState(state_t state, time_t timestamp) { } 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 @@ const T& MultiStateCounter<T>::getCount(state_t state) { 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 942d5cadf5..87c80c53d3 100644 --- a/libs/battery/MultiStateCounterTest.cpp +++ b/libs/battery/MultiStateCounterTest.cpp @@ -49,8 +49,9 @@ std::string DoubleMultiStateCounter::valueToString(const double& v) const { 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, constructor) { } 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, stateChange) { } 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_setState) { } 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 @@ TEST_F(MultiStateCounterTest, timeAdjustment_updateValue) { 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 |