xref: /aosp_15_r20/frameworks/native/libs/battery/LongArrayMultiStateCounter.cpp (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  * Android BPF library - public API
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include "LongArrayMultiStateCounter.h"
19 #include <log/log.h>
20 
21 namespace android {
22 namespace battery {
23 
Uint64ArrayRW(const Uint64Array & copy)24 Uint64ArrayRW::Uint64ArrayRW(const Uint64Array &copy) : Uint64Array(copy.size()) {
25     if (mSize != 0 && copy.data() != nullptr) {
26         mData = new uint64_t[mSize];
27         memcpy(mData, copy.data(), mSize * sizeof(uint64_t));
28     } else {
29         mData = nullptr;
30     }
31 }
32 
dataRW()33 uint64_t *Uint64ArrayRW::dataRW() {
34     if (mData == nullptr) {
35         mData = new uint64_t[mSize];
36         memset(mData, 0, mSize * sizeof(uint64_t));
37     }
38     return mData;
39 }
40 
operator =(const Uint64Array & t)41 Uint64ArrayRW &Uint64ArrayRW::operator=(const Uint64Array &t) {
42     if (t.size() != mSize) {
43         delete[] mData;
44         mSize = t.size();
45         mData = nullptr;
46     }
47     if (mSize != 0) {
48         if (t.data() != nullptr) {
49             if (mData == nullptr) {
50                 mData = new uint64_t[mSize];
51             }
52             memcpy(mData, t.data(), mSize * sizeof(uint64_t));
53         } else {
54             delete[] mData;
55             mData = nullptr;
56         }
57     }
58     return *this;
59 }
60 
operator <<(std::ostream & os,const Uint64Array & v)61 std::ostream &operator<<(std::ostream &os, const Uint64Array &v) {
62     os << "{";
63     const uint64_t *data = v.data();
64     if (data != nullptr) {
65         bool first = true;
66         for (size_t i = 0; i < v.size(); i++) {
67             if (!first) {
68                 os << ", ";
69             }
70             os << data[i];
71             first = false;
72         }
73     }
74     os << "}";
75     return os;
76 }
77 
78 // Convenience constructor for tests
Uint64ArrayRW(std::initializer_list<uint64_t> init)79 Uint64ArrayRW::Uint64ArrayRW(std::initializer_list<uint64_t> init) : Uint64Array(init.size()) {
80     mData = new uint64_t[mSize];
81     memcpy(mData, init.begin(), mSize * sizeof(uint64_t));
82 }
83 
84 // Used in tests only.
operator ==(const Uint64Array & other) const85 bool Uint64Array::operator==(const Uint64Array &other) const {
86     if (size() != other.size()) {
87         return false;
88     }
89     const uint64_t* thisData = data();
90     const uint64_t* thatData = other.data();
91     for (size_t i = 0; i < mSize; i++) {
92         const uint64_t v1 = thisData != nullptr ? thisData[i] : 0;
93         const uint64_t v2 = thatData != nullptr ? thatData[i] : 0;
94         if (v1 != v2) {
95             return false;
96         }
97     }
98     return true;
99 }
100 
101 template <>
add(Uint64ArrayRW * value1,const Uint64Array & value2,const uint64_t numerator,const uint64_t denominator) const102 void LongArrayMultiStateCounter::add(Uint64ArrayRW *value1, const Uint64Array &value2,
103                                      const uint64_t numerator, const uint64_t denominator) const {
104     const uint64_t* data2 = value2.data();
105     if (data2 == nullptr) {
106         return;
107     }
108 
109     uint64_t* data1 = value1->dataRW();
110     size_t size = value2.size();
111     if (numerator != denominator) {
112         for (size_t i = 0; i < size; i++) {
113             // The caller ensures that denominator != 0
114             data1[i] += data2[i] * numerator / denominator;
115         }
116     } else {
117         for (size_t i = 0; i < size; i++) {
118             data1[i] += data2[i];
119         }
120     }
121 }
122 
123 template<>
delta(const Uint64ArrayRW & previousValue,const Uint64Array & newValue,Uint64ArrayRW * outValue) const124 bool LongArrayMultiStateCounter::delta(const Uint64ArrayRW &previousValue,
125                                        const Uint64Array &newValue, Uint64ArrayRW *outValue) const {
126     size_t size = previousValue.size();
127     if (newValue.size() != size) {
128         ALOGE("Incorrect array size: %d, should be %d", (int) newValue.size(), (int) size);
129         return false;
130     }
131     if (outValue->size() != size) {
132         ALOGE("Incorrect outValue size: %d, should be %d", (int) outValue->size(), (int) size);
133         return false;
134     }
135 
136     bool is_delta_valid = true;
137     const uint64_t *prevData = previousValue.data();
138     const uint64_t *newData = newValue.data();
139     uint64_t *outData = outValue->dataRW();
140     for (size_t i = 0; i < size; i++) {
141         if (prevData == nullptr) {
142             if (newData == nullptr) {
143                 outData[i] = 0;
144             } else {
145                 outData[i] = newData[i];
146             }
147         } else if (newData == nullptr || newData[i] < prevData[i]) {
148             outData[i] = 0;
149             is_delta_valid = false;
150         } else {
151             outData[i] = newData[i] - prevData[i];
152         }
153     }
154     return is_delta_valid;
155 }
156 
157 } // namespace battery
158 } // namespace android
159