Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cb5e9159 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 12609205 from 52683c69 to 25Q1-release

Change-Id: Idbbd656cf9349f16de889934cb544164899a05c6
parents 3259841d 52683c69
Loading
Loading
Loading
Loading
+110 −34
Original line number Diff line number Diff line
@@ -21,58 +21,134 @@
namespace android {
namespace battery {

template <>
bool LongArrayMultiStateCounter::delta(const std::vector<uint64_t>& previousValue,
                                       const std::vector<uint64_t>& newValue,
                                       std::vector<uint64_t>* outValue) const {
    size_t size = previousValue.size();
    if (newValue.size() != size) {
        ALOGE("Incorrect array size: %d, should be %d", (int)newValue.size(), (int)size);
        return false;
Uint64ArrayRW::Uint64ArrayRW(const Uint64Array &copy) : Uint64Array(copy.size()) {
    if (mSize != 0 && copy.data() != nullptr) {
        mData = new uint64_t[mSize];
        memcpy(mData, copy.data(), mSize * sizeof(uint64_t));
    } else {
        mData = nullptr;
    }
}

    bool is_delta_valid = true;
    for (int i = size - 1; i >= 0; i--) {
        if (newValue[i] >= previousValue[i]) {
            (*outValue)[i] = newValue[i] - previousValue[i];
uint64_t *Uint64ArrayRW::dataRW() {
    if (mData == nullptr) {
        mData = new uint64_t[mSize];
        memset(mData, 0, mSize * sizeof(uint64_t));
    }
    return mData;
}

Uint64ArrayRW &Uint64ArrayRW::operator=(const Uint64Array &t) {
    if (t.size() != mSize) {
        delete[] mData;
        mSize = t.size();
        mData = nullptr;
    }
    if (mSize != 0) {
        if (t.data() != nullptr) {
            mData = new uint64_t[mSize];
            memcpy(mData, t.data(), mSize * sizeof(uint64_t));
        } else {
            (*outValue)[i] = 0;
            is_delta_valid = false;
            mData = nullptr;
        }
    }
    return is_delta_valid;
    return *this;
}

std::ostream &operator<<(std::ostream &os, const Uint64Array &v) {
    os << "{";
    const uint64_t *data = v.data();
    if (data != nullptr) {
        bool first = true;
        for (size_t i = 0; i < v.size(); i++) {
            if (!first) {
                os << ", ";
            }
            os << data[i];
            first = false;
        }
    }
    os << "}";
    return os;
}

// Convenience constructor for tests
Uint64ArrayRW::Uint64ArrayRW(std::initializer_list<uint64_t> init) : Uint64Array(init.size()) {
    mData = new uint64_t[mSize];
    memcpy(mData, init.begin(), mSize * sizeof(uint64_t));
}

// Used in tests only.
bool Uint64Array::operator==(const Uint64Array &other) const {
    if (size() != other.size()) {
        return false;
    }
    const uint64_t* thisData = data();
    const uint64_t* thatData = other.data();
    for (size_t i = 0; i < mSize; i++) {
        const uint64_t v1 = thisData != nullptr ? thisData[i] : 0;
        const uint64_t v2 = thatData != nullptr ? thatData[i] : 0;
        if (v1 != v2) {
            return false;
        }
    }
    return true;
}

template <>
void LongArrayMultiStateCounter::add(std::vector<uint64_t>* value1,
                                     const std::vector<uint64_t>& value2, const uint64_t numerator,
                                     const uint64_t denominator) const {
void LongArrayMultiStateCounter::add(Uint64ArrayRW *value1, const Uint64Array &value2,
                                     const uint64_t numerator, const uint64_t denominator) const {
    const uint64_t* data2 = value2.data();
    if (data2 == nullptr) {
        return;
    }

    uint64_t* data1 = value1->dataRW();
    size_t size = value2.size();
    if (numerator != denominator) {
        for (int i = value2.size() - 1; i >= 0; i--) {
        for (size_t i = 0; i < size; i++) {
            // The caller ensures that denominator != 0
            (*value1)[i] += value2[i] * numerator / denominator;
            data1[i] += data2[i] * numerator / denominator;
        }
    } else {
        for (int i = value2.size() - 1; i >= 0; i--) {
            (*value1)[i] += value2[i];
        for (size_t i = 0; i < size; i++) {
            data1[i] += data2[i];
        }
    }
}

template<>
std::string LongArrayMultiStateCounter::valueToString(const std::vector<uint64_t>& v) const {
    std::stringstream s;
    s << "{";
    bool first = true;
    for (uint64_t n : v) {
        if (!first) {
            s << ", ";
bool LongArrayMultiStateCounter::delta(const Uint64ArrayRW &previousValue,
                                       const Uint64Array &newValue, Uint64ArrayRW *outValue) const {
    size_t size = previousValue.size();
    if (newValue.size() != size) {
        ALOGE("Incorrect array size: %d, should be %d", (int) newValue.size(), (int) size);
        return false;
    }
    if (outValue->size() != size) {
        ALOGE("Incorrect outValue size: %d, should be %d", (int) outValue->size(), (int) size);
        return false;
    }

    bool is_delta_valid = true;
    const uint64_t *prevData = previousValue.data();
    const uint64_t *newData = newValue.data();
    uint64_t *outData = outValue->dataRW();
    for (size_t i = 0; i < size; i++) {
        if (prevData == nullptr) {
            if (newData == nullptr) {
                outData[i] = 0;
            } else {
                outData[i] = newData[i];
            }
        } else if (newData == nullptr || newData[i] < prevData[i]) {
            outData[i] = 0;
            is_delta_valid = false;
        } else {
            outData[i] = newData[i] - prevData[i];
        }
        s << n;
        first = false;
    }
    s << "}";
    return s.str();
    return is_delta_valid;
}

} // namespace battery
+60 −1
Original line number Diff line number Diff line
@@ -23,7 +23,66 @@
namespace android {
namespace battery {

typedef MultiStateCounter<std::vector<uint64_t>> LongArrayMultiStateCounter;
/**
 * Wrapper for an array of uint64's.
 */
class Uint64Array {
  protected:
    size_t mSize;

  public:
    Uint64Array() : Uint64Array(0) {}

    Uint64Array(size_t size) : mSize(size) {}

    virtual ~Uint64Array() {}

    size_t size() const { return mSize; }

    /**
     * Returns the wrapped array.
     *
     * Nullable! Null should be interpreted the same as an array of zeros
     */
    virtual const uint64_t *data() const { return nullptr; }

    friend std::ostream &operator<<(std::ostream &os, const Uint64Array &v);

    // Test API
    bool operator==(const Uint64Array &other) const;
};

/**
 * Mutable version of Uint64Array.
 */
class Uint64ArrayRW: public Uint64Array {
    uint64_t* mData;

public:
    Uint64ArrayRW() : Uint64ArrayRW(0) {}

    Uint64ArrayRW(size_t size) : Uint64Array(size), mData(nullptr) {}

    Uint64ArrayRW(const Uint64Array &copy);

    // Need an explicit copy constructor. In the initialization context C++ does not understand that
    // a Uint64ArrayRW is a Uint64Array.
    Uint64ArrayRW(const Uint64ArrayRW &copy) : Uint64ArrayRW((const Uint64Array &) copy) {}

    // Test API
    Uint64ArrayRW(std::initializer_list<uint64_t> init);

    ~Uint64ArrayRW() override { delete[] mData; }

    const uint64_t *data() const override { return mData; }

    // NonNull. Will initialize the wrapped array if it is null.
    uint64_t *dataRW();

    Uint64ArrayRW &operator=(const Uint64Array &t);
};

typedef MultiStateCounter<Uint64ArrayRW, Uint64Array> LongArrayMultiStateCounter;

} // namespace battery
} // namespace android
+14 −14
Original line number Diff line number Diff line
@@ -24,25 +24,25 @@ namespace battery {
class LongArrayMultiStateCounterTest : public testing::Test {};

TEST_F(LongArrayMultiStateCounterTest, stateChange) {
    LongArrayMultiStateCounter testCounter(2, std::vector<uint64_t>(4));
    testCounter.updateValue(std::vector<uint64_t>({0, 0, 0, 0}), 1000);
    LongArrayMultiStateCounter testCounter(2, Uint64Array(4));
    testCounter.updateValue(Uint64ArrayRW({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.updateValue(Uint64ArrayRW({100, 200, 300, 400}), 3000);

    // Time was split in half between the two states, so the counts will be split 50:50 too
    EXPECT_EQ(std::vector<uint64_t>({50, 100, 150, 200}), testCounter.getCount(0));
    EXPECT_EQ(std::vector<uint64_t>({50, 100, 150, 200}), testCounter.getCount(1));
    EXPECT_EQ(Uint64ArrayRW({50, 100, 150, 200}), testCounter.getCount(0));
    EXPECT_EQ(Uint64ArrayRW({50, 100, 150, 200}), testCounter.getCount(1));
}

TEST_F(LongArrayMultiStateCounterTest, accumulation) {
    LongArrayMultiStateCounter testCounter(2, std::vector<uint64_t>(4));
    testCounter.updateValue(std::vector<uint64_t>({0, 0, 0, 0}), 1000);
    LongArrayMultiStateCounter testCounter(2, Uint64Array(4));
    testCounter.updateValue(Uint64ArrayRW({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.updateValue(Uint64ArrayRW({100, 200, 300, 400}), 3000);
    testCounter.setState(0, 4000);
    testCounter.updateValue(std::vector<uint64_t>({200, 300, 400, 500}), 8000);
    testCounter.updateValue(Uint64ArrayRW({200, 300, 400, 500}), 8000);

    // The first delta is split 50:50:
    //   0: {50, 100, 150, 200}
@@ -50,16 +50,16 @@ TEST_F(LongArrayMultiStateCounterTest, accumulation) {
    // The second delta is split 4:1
    //   0: {80, 80, 80, 80}
    //   1: {20, 20, 20, 20}
    EXPECT_EQ(std::vector<uint64_t>({130, 180, 230, 280}), testCounter.getCount(0));
    EXPECT_EQ(std::vector<uint64_t>({70, 120, 170, 220}), testCounter.getCount(1));
    EXPECT_EQ(Uint64ArrayRW({130, 180, 230, 280}), testCounter.getCount(0));
    EXPECT_EQ(Uint64ArrayRW({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);
    LongArrayMultiStateCounter testCounter(2, Uint64Array(4));
    testCounter.updateValue(Uint64ArrayRW({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.updateValue(Uint64ArrayRW({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());
+46 −45
Original line number Diff line number Diff line
@@ -35,12 +35,12 @@ namespace battery {

typedef uint16_t state_t;

template <class T>
template <class T, class V>
class MultiStateCounter {
    uint16_t stateCount;
    const uint16_t stateCount;
    const V emptyValue;
    state_t currentState;
    time_t lastStateChangeTimestamp;
    T emptyValue;
    T lastValue;
    time_t lastUpdateTimestamp;
    T deltaValue;
@@ -54,7 +54,7 @@ class MultiStateCounter {
    State* states;

public:
    MultiStateCounter(uint16_t stateCount, const T& emptyValue);
    MultiStateCounter(uint16_t stateCount, const V& emptyValue);

    virtual ~MultiStateCounter();

@@ -66,35 +66,35 @@ public:
     * Copies the current state and accumulated times-in-state from the source. Resets
     * the accumulated value.
     */
    void copyStatesFrom(const MultiStateCounter<T>& source);
    void copyStatesFrom(const MultiStateCounter<T, V> &source);

    void setValue(state_t state, const T& value);
    void setValue(state_t state, const V& value);

    /**
     * Updates the value by distributing the delta from the previously set value
     * among states according to their respective time-in-state.
     * Returns the delta from the previously set value.
     */
    const T& updateValue(const T& value, time_t timestamp);
    const V& updateValue(const V& value, time_t timestamp);

    /**
     * Updates the value by distributing the specified increment among states according
     * to their respective time-in-state.
     */
    void incrementValue(const T& increment, time_t timestamp);
    void incrementValue(const V& increment, time_t timestamp);

    /**
     * Adds the specified increment to the value for the current state, without affecting
     * the last updated value or timestamp.  Ignores partial time-in-state: the entirety of
     * the increment is given to the current state.
     */
    void addValue(const T& increment);
    void addValue(const V& increment);

    void reset();

    uint16_t getStateCount();

    const T& getCount(state_t state);
    const V& getCount(state_t state);

    std::string toString();

@@ -104,27 +104,25 @@ private:
     * Returns true iff the combination of previousValue and newValue is valid
     * (newValue >= prevValue)
     */
    bool delta(const T& previousValue, const T& newValue, T* outValue) const;
    bool delta(const T& previousValue, const V& newValue, T* outValue) const;

    /**
     * Adds value2 to value1 and stores the result in value1.  Denominator is
     * guaranteed to be non-zero.
     */
    void add(T* value1, const T& value2, const uint64_t numerator,
    void add(T* value1, const V& value2, const uint64_t numerator,
             const uint64_t denominator) const;

    std::string valueToString(const T& value) const;
};

// ---------------------- MultiStateCounter Implementation -------------------------
// Since MultiStateCounter is a template, the implementation must be inlined.

template <class T>
MultiStateCounter<T>::MultiStateCounter(uint16_t stateCount, const T& emptyValue)
template <class T, class V>
MultiStateCounter<T, V>::MultiStateCounter(uint16_t stateCount, const V& emptyValue)
      : stateCount(stateCount),
        emptyValue(emptyValue),
        currentState(0),
        lastStateChangeTimestamp(-1),
        emptyValue(emptyValue),
        lastValue(emptyValue),
        lastUpdateTimestamp(-1),
        deltaValue(emptyValue),
@@ -136,13 +134,13 @@ MultiStateCounter<T>::MultiStateCounter(uint16_t stateCount, const T& emptyValue
    }
}

template <class T>
MultiStateCounter<T>::~MultiStateCounter() {
template <class T, class V>
MultiStateCounter<T, V>::~MultiStateCounter() {
    delete[] states;
};

template <class T>
void MultiStateCounter<T>::setEnabled(bool enabled, time_t timestamp) {
template <class T, class V>
void MultiStateCounter<T, V>::setEnabled(bool enabled, time_t timestamp) {
    if (enabled == isEnabled) {
        return;
    }
@@ -167,8 +165,8 @@ void MultiStateCounter<T>::setEnabled(bool enabled, time_t timestamp) {
    }
}

template <class T>
void MultiStateCounter<T>::setState(state_t state, time_t timestamp) {
template <class T, class V>
void MultiStateCounter<T, V>::setState(state_t state, time_t timestamp) {
    if (isEnabled && lastStateChangeTimestamp >= 0 && lastUpdateTimestamp >= 0) {
        // If the update arrived out-of-order, just push back the timestamp to
        // avoid having the situation where timeInStateSinceUpdate > timeSinceUpdate
@@ -198,8 +196,8 @@ void MultiStateCounter<T>::setState(state_t state, time_t timestamp) {
    lastStateChangeTimestamp = timestamp;
}

template <class T>
void MultiStateCounter<T>::copyStatesFrom(const MultiStateCounter<T>& source) {
template <class T, class V>
void MultiStateCounter<T, V>::copyStatesFrom(const MultiStateCounter<T, V>& source) {
    if (stateCount != source.stateCount) {
        ALOGE("State count mismatch: %u vs. %u\n", stateCount, source.stateCount);
        return;
@@ -214,14 +212,14 @@ void MultiStateCounter<T>::copyStatesFrom(const MultiStateCounter<T>& source) {
    lastUpdateTimestamp = source.lastUpdateTimestamp;
}

template <class T>
void MultiStateCounter<T>::setValue(state_t state, const T& value) {
template <class T, class V>
void MultiStateCounter<T, V>::setValue(state_t state, const V& value) {
    states[state].counter = value;
}

template <class T>
const T& MultiStateCounter<T>::updateValue(const T& value, time_t timestamp) {
    T* returnValue = &emptyValue;
template <class T, class V>
const V& MultiStateCounter<T, V>::updateValue(const V& value, time_t timestamp) {
    const V* returnValue = &emptyValue;

    // If the counter is disabled, we ignore the update, except when the counter got disabled after
    // the previous update, in which case we still need to pick up the residual delta.
@@ -250,8 +248,8 @@ const T& MultiStateCounter<T>::updateValue(const T& value, time_t timestamp) {
                    }
                } else {
                    std::stringstream str;
                    str << "updateValue is called with a value " << valueToString(value)
                        << ", which is lower than the previous value " << valueToString(lastValue)
                    str << "updateValue is called with a value " << value
                        << ", which is lower than the previous value " << lastValue
                        << "\n";
                    ALOGE("%s", str.str().c_str());

@@ -276,23 +274,25 @@ const T& MultiStateCounter<T>::updateValue(const T& value, time_t timestamp) {
    return *returnValue;
}

template <class T>
void MultiStateCounter<T>::incrementValue(const T& increment, time_t timestamp) {
template <class T, class V>
void MultiStateCounter<T, V>::incrementValue(const V& increment, time_t timestamp) {
//    T newValue;
//    newValue = lastValue; // Copy assignment, not initialization.
    T newValue = lastValue;
    add(&newValue, increment, 1 /* numerator */, 1 /* denominator */);
    updateValue(newValue, timestamp);
}

template <class T>
void MultiStateCounter<T>::addValue(const T& value) {
template <class T, class V>
void MultiStateCounter<T, V>::addValue(const V& value) {
    if (!isEnabled) {
        return;
    }
    add(&states[currentState].counter, value, 1 /* numerator */, 1 /* denominator */);
}

template <class T>
void MultiStateCounter<T>::reset() {
template <class T, class V>
void MultiStateCounter<T, V>::reset() {
    lastStateChangeTimestamp = -1;
    lastUpdateTimestamp = -1;
    for (int i = 0; i < stateCount; i++) {
@@ -301,25 +301,26 @@ void MultiStateCounter<T>::reset() {
    }
}

template <class T>
uint16_t MultiStateCounter<T>::getStateCount() {
template <class T, class V>
uint16_t MultiStateCounter<T, V>::getStateCount() {
    return stateCount;
}

template <class T>
const T& MultiStateCounter<T>::getCount(state_t state) {
template <class T, class V>
const V& MultiStateCounter<T, V>::getCount(state_t state) {
    return states[state].counter;
}

template <class T>
std::string MultiStateCounter<T>::toString() {
template <class T, class V>
std::string MultiStateCounter<T, V>::toString() {
    std::stringstream str;
//    str << "LAST VALUE: " << valueToString(lastValue);
    str << "[";
    for (int i = 0; i < stateCount; i++) {
        if (i != 0) {
            str << ", ";
        }
        str << i << ": " << valueToString(states[i].counter);
        str << i << ": " << states[i].counter;
        if (states[i].timeInStateSinceUpdate > 0) {
            str << " timeInStateSinceUpdate: " << states[i].timeInStateSinceUpdate;
        }
+1 −6
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@
namespace android {
namespace battery {

typedef MultiStateCounter<double> DoubleMultiStateCounter;
typedef MultiStateCounter<double, double> DoubleMultiStateCounter;

template <>
bool DoubleMultiStateCounter::delta(const double& previousValue, const double& newValue,
@@ -41,11 +41,6 @@ void DoubleMultiStateCounter::add(double* value1, const double& value2, const ui
    }
}

template <>
std::string DoubleMultiStateCounter::valueToString(const double& v) const {
    return std::to_string(v);
}

class MultiStateCounterTest : public testing::Test {};

TEST_F(MultiStateCounterTest, constructor) {
Loading