1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "ECOData"
19 
20 #include "eco/ECOData.h"
21 
22 #include <android/binder_parcel.h>
23 #include <android/binder_parcel_utils.h>
24 #include <inttypes.h>
25 #include <utils/Errors.h>
26 #include <utils/Log.h>
27 
28 #include <string>
29 
30 #include "eco/ECODataKey.h"
31 #include "eco/ECOUtils.h"
32 
33 namespace aidl {
34 namespace android {
35 namespace media {
36 namespace eco {
37 
38 using namespace ::android;
39 
readFromParcel(const AParcel * parcel)40 binder_status_t ECOData::readFromParcel(const AParcel* parcel) {
41     if (parcel == nullptr) {
42         ALOGE("readFromParcel failed. Parcel pointer can not be null");
43         return BAD_VALUE;
44     }
45 
46     // Reads the data type and time.
47     RETURN_STATUS_IF_ERROR(AParcel_readInt32(parcel, &mDataType));
48     RETURN_STATUS_IF_ERROR(AParcel_readInt64(parcel, &mDataTimeUs));
49 
50     // Reads the number of items.
51     uint32_t numOfItems = 0;
52     RETURN_STATUS_IF_ERROR(AParcel_readUint32(parcel, &numOfItems));
53 
54     // Reads the key-value pairs one by one.
55     for (size_t i = 0; i < numOfItems; ++i) {
56         // Reads the name of the key.
57         std::string name;
58         AParcel_readString(parcel, &name, ndk::AParcel_stdStringAllocator);
59 
60         int32_t type;
61         RETURN_STATUS_IF_ERROR(AParcel_readInt32(parcel, &type));
62         switch (static_cast<ValueType>(type)) {
63         case kTypeInt32: {
64             int32_t value32;
65             RETURN_STATUS_IF_ERROR(AParcel_readInt32(parcel, &value32));
66             setInt32(name, value32);
67             break;
68         }
69         case kTypeInt64: {
70             int64_t value64;
71             RETURN_STATUS_IF_ERROR(AParcel_readInt64(parcel, &value64));
72             setInt64(name, value64);
73             break;
74         }
75         case kTypeSize: {
76             int32_t valueSize;
77             RETURN_STATUS_IF_ERROR(AParcel_readInt32(parcel, &valueSize));
78             setInt32(name, valueSize);
79             break;
80         }
81         case kTypeFloat: {
82             float valueFloat;
83             RETURN_STATUS_IF_ERROR(AParcel_readFloat(parcel, &valueFloat));
84             setFloat(name, valueFloat);
85             break;
86         }
87         case kTypeDouble: {
88             double valueDouble;
89             RETURN_STATUS_IF_ERROR(AParcel_readDouble(parcel, &valueDouble));
90             setDouble(name, valueDouble);
91             break;
92         }
93         case kTypeString: {
94             std::string valueString;
95             AParcel_readString(parcel, &valueString, ndk::AParcel_stdStringAllocator);
96             setString(name, valueString);
97             break;
98         }
99         case kTypeInt8: {
100             int8_t value8;
101             RETURN_STATUS_IF_ERROR(AParcel_readByte(parcel, &value8));
102             setInt8(name, value8);
103             break;
104         }
105         default: {
106             return BAD_TYPE;
107         }
108         }
109     }
110 
111     return NO_ERROR;
112 }
113 
writeToParcel(AParcel * parcel) const114 binder_status_t ECOData::writeToParcel(AParcel* parcel) const {
115     if (parcel == nullptr) {
116         ALOGE("writeToParcel failed. Parcel pointer can not be null");
117         return BAD_VALUE;
118     }
119 
120     // Writes out the data type and time.
121     RETURN_STATUS_IF_ERROR(AParcel_writeInt32(parcel, mDataType));
122     RETURN_STATUS_IF_ERROR(AParcel_writeInt64(parcel, mDataTimeUs));
123 
124     // Writes out number of items.
125     RETURN_STATUS_IF_ERROR(AParcel_writeUint32(parcel, int32_t(mKeyValueStore.size())));
126 
127     // Writes out the key-value pairs one by one.
128     for (const auto& it : mKeyValueStore) {
129         // Writes out the key.
130         RETURN_STATUS_IF_ERROR(AParcel_writeString(parcel, it.first.c_str(),
131                                                    static_cast<int32_t>(it.first.size())));
132 
133         // Writes out the data type.
134         const ECODataValueType& value = it.second;
135         RETURN_STATUS_IF_ERROR(AParcel_writeInt32(parcel, static_cast<int32_t>(value.index())));
136         switch (static_cast<ValueType>(value.index())) {
137         case kTypeInt32:
138             RETURN_STATUS_IF_ERROR(AParcel_writeInt32(parcel, std::get<int32_t>(it.second)));
139             break;
140 
141         case kTypeInt64:
142             RETURN_STATUS_IF_ERROR(AParcel_writeInt64(parcel, std::get<int64_t>(it.second)));
143             break;
144 
145         case kTypeSize:
146             RETURN_STATUS_IF_ERROR(AParcel_writeUint32(parcel, std::get<size_t>(it.second)));
147             break;
148 
149         case kTypeFloat:
150             RETURN_STATUS_IF_ERROR(AParcel_writeFloat(parcel, std::get<float>(it.second)));
151             break;
152 
153         case kTypeDouble:
154             RETURN_STATUS_IF_ERROR(AParcel_writeDouble(parcel, std::get<double>(it.second)));
155             break;
156 
157         case kTypeString:
158             RETURN_STATUS_IF_ERROR(AParcel_writeString(
159                     parcel, std::get<std::string>(it.second).c_str(),
160                     static_cast<int32_t>(std::get<std::string>(it.second).size())));
161             break;
162 
163         case kTypeInt8:
164             RETURN_STATUS_IF_ERROR(AParcel_writeByte(parcel, std::get<int8_t>(it.second)));
165             break;
166 
167         default:
168             return BAD_TYPE;
169         }
170     }
171 
172     return NO_ERROR;
173 }
174 
getDataType() const175 int32_t ECOData::getDataType() const {
176     return mDataType;
177 }
178 
getDataTimeUs() const179 int64_t ECOData::getDataTimeUs() const {
180     return mDataTimeUs;
181 }
182 
183 // Inserts a new key into store if the key does not exist yet. Otherwise, this will override the
184 // existing key's value.
setString(const std::string & key,const std::string & value)185 ECODataStatus ECOData::setString(const std::string& key, const std::string& value) {
186     if (key.empty() || value.empty()) {
187         return ECODataStatus::INVALID_ARGUMENT;
188     }
189 
190     mKeyValueStore[key] = value;
191 
192     // TODO(hkuang): Check the valueType is valid for the key.
193     return ECODataStatus::OK;
194 }
195 
findString(const std::string & key,std::string * value) const196 ECODataStatus ECOData::findString(const std::string& key, std::string* value) const {
197     if (key.empty()) {
198         return ECODataStatus::INVALID_ARGUMENT;
199     }
200 
201     // Check if the key exists.
202     if (mKeyValueStore.find(key) == mKeyValueStore.end()) {
203         return ECODataStatus::KEY_NOT_EXIST;
204     }
205 
206     // Safely access the value.
207     const std::string& entryValue = std::get<std::string>(mKeyValueStore.at(key));
208     value->assign(entryValue);
209 
210     return ECODataStatus::OK;
211 }
212 
213 // Inserts a new key into store if the key does not exist yet. Otherwise, this will override the
214 // existing key's value.
215 template <typename T>
setValue(const std::string & key,T value)216 ECODataStatus ECOData::setValue(const std::string& key, T value) {
217     if (key.empty()) {
218         return ECODataStatus::INVALID_ARGUMENT;
219     }
220 
221     mKeyValueStore[key] = value;
222     return ECODataStatus::OK;
223 }
224 
225 template <typename T>
findValue(const std::string & key,T * out) const226 ECODataStatus ECOData::findValue(const std::string& key, T* out) const {
227     if (key.empty() || out == nullptr) {
228         return ECODataStatus::INVALID_ARGUMENT;
229     }
230 
231     if (mKeyValueStore.find(key) == mKeyValueStore.end()) {
232         return ECODataStatus::KEY_NOT_EXIST;
233     }
234 
235     // Safely access the value.
236     *out = std::get<T>(mKeyValueStore.at(key));
237 
238     return ECODataStatus::OK;
239 }
240 
setInt32(const std::string & key,int32_t value)241 ECODataStatus ECOData::setInt32(const std::string& key, int32_t value) {
242     return setValue<int32_t>(key, value);
243 }
244 
findInt32(const std::string & key,int32_t * out) const245 ECODataStatus ECOData::findInt32(const std::string& key, int32_t* out) const {
246     return findValue<int32_t>(key, out);
247 }
248 
setInt64(const std::string & key,int64_t value)249 ECODataStatus ECOData::setInt64(const std::string& key, int64_t value) {
250     return setValue<int64_t>(key, value);
251 }
252 
findInt64(const std::string & key,int64_t * out) const253 ECODataStatus ECOData::findInt64(const std::string& key, int64_t* out) const {
254     return findValue<int64_t>(key, out);
255 }
256 
setDouble(const std::string & key,double value)257 ECODataStatus ECOData::setDouble(const std::string& key, double value) {
258     return setValue<double>(key, value);
259 }
260 
findDouble(const std::string & key,double * out) const261 ECODataStatus ECOData::findDouble(const std::string& key, double* out) const {
262     return findValue<double>(key, out);
263 }
264 
setSize(const std::string & key,size_t value)265 ECODataStatus ECOData::setSize(const std::string& key, size_t value) {
266     return setValue<size_t>(key, value);
267 }
268 
findSize(const std::string & key,size_t * out) const269 ECODataStatus ECOData::findSize(const std::string& key, size_t* out) const {
270     return findValue<size_t>(key, out);
271 }
272 
setFloat(const std::string & key,float value)273 ECODataStatus ECOData::setFloat(const std::string& key, float value) {
274     return setValue<float>(key, value);
275 }
276 
findFloat(const std::string & key,float * out) const277 ECODataStatus ECOData::findFloat(const std::string& key, float* out) const {
278     return findValue<float>(key, out);
279 }
280 
setInt8(const std::string & key,int8_t value)281 ECODataStatus ECOData::setInt8(const std::string& key, int8_t value) {
282     return setValue<int8_t>(key, value);
283 }
284 
findInt8(const std::string & key,int8_t * out) const285 ECODataStatus ECOData::findInt8(const std::string& key, int8_t* out) const {
286     return findValue<int8_t>(key, out);
287 }
288 
set(const std::string & key,const ECOData::ECODataValueType & value)289 ECODataStatus ECOData::set(const std::string& key, const ECOData::ECODataValueType& value) {
290     if (key.empty()) {
291         return ECODataStatus::INVALID_ARGUMENT;
292     }
293     mKeyValueStore[key] = value;
294     return ECODataStatus::OK;
295 }
296 
find(const std::string & key,ECOData::ECODataValueType * out) const297 ECODataStatus ECOData::find(const std::string& key, ECOData::ECODataValueType* out) const {
298     if (key.empty() || out == nullptr) {
299         return ECODataStatus::INVALID_ARGUMENT;
300     }
301 
302     if (mKeyValueStore.find(key) == mKeyValueStore.end()) {
303         return ECODataStatus::KEY_NOT_EXIST;
304     }
305 
306     // Safely access the value.
307     *out = mKeyValueStore.at(key);
308 
309     return ECODataStatus::OK;
310 }
311 
getDataTypeString() const312 std::string ECOData::getDataTypeString() const {
313     switch (mDataType) {
314     case DATA_TYPE_UNKNOWN:
315         return "DATA_TYPE_UNKNOWN";
316     case DATA_TYPE_STATS:
317         return "DATA_TYPE_STATS";
318     case DATA_TYPE_INFO:
319         return "DATA_TYPE_INFO";
320     case DATA_TYPE_STATS_PROVIDER_CONFIG:
321         return "DATA_TYPE_STATS_PROVIDER_CONFIG";
322     case DATA_TYPE_INFO_LISTENER_CONFIG:
323         return "DATA_TYPE_INFO_LISTENER_CONFIG";
324     }
325     return {};
326 }
327 
328 // TODO(hkuang): Add test for this.
hasNext()329 bool ECODataKeyValueIterator::hasNext() {
330     if (mIterator == mKeyValueStore.end()) return false;
331 
332     if (!mBeginReturned) {
333         // mIterator has been initialized to the beginning and
334         // hasn't been returned. Do not advance:
335         mBeginReturned = true;
336     } else {
337         std::advance(mIterator, 1);
338     }
339     return mIterator != mKeyValueStore.end();
340 }
341 
342 // TODO(hkuang): Add test for this.
next() const343 ECOData::ECODataKeyValuePair ECODataKeyValueIterator::next() const {
344     return ECOData::ECODataKeyValuePair(mIterator->first, mIterator->second);
345 }
346 
debugString() const347 std::string ECOData::debugString() const {
348     std::string s = "ECOData(type = ";
349 
350     std::string tmp;
351     switch (mDataType) {
352     case DATA_TYPE_UNKNOWN:
353         tmp = "Unknown";
354         break;
355     case DATA_TYPE_STATS:
356         tmp = "Stats";
357         break;
358     case DATA_TYPE_INFO:
359         tmp = "Info";
360         break;
361     case DATA_TYPE_STATS_PROVIDER_CONFIG:
362         tmp = "Stats provider config";
363         break;
364     case DATA_TYPE_INFO_LISTENER_CONFIG:
365         tmp = "Info listener config";
366         break;
367     default:
368         break;
369     }
370     s.append(tmp);
371     s.append(") = {\n  ");
372 
373     // Writes out the key-value pairs one by one.
374     for (const auto& it : mKeyValueStore) {
375         const size_t SIZE = 100;
376         char keyValue[SIZE];
377         const ECODataValueType& value = it.second;
378         switch (static_cast<ValueType>(value.index())) {
379         case kTypeInt32:
380             snprintf(keyValue, SIZE, "int32_t %s = %d, ", it.first.c_str(),
381                      std::get<int32_t>(it.second));
382             break;
383         case kTypeInt64:
384             snprintf(keyValue, SIZE, "int64_t %s = %" PRId64 ", ", it.first.c_str(),
385                      std::get<int64_t>(it.second));
386             break;
387         case kTypeSize:
388             snprintf(keyValue, SIZE, "size_t %s = %zu, ", it.first.c_str(),
389                      std::get<size_t>(it.second));
390             break;
391         case kTypeFloat:
392             snprintf(keyValue, SIZE, "float %s = %f, ", it.first.c_str(),
393                      std::get<float>(it.second));
394             break;
395         case kTypeDouble:
396             snprintf(keyValue, SIZE, "double %s = %f, ", it.first.c_str(),
397                      std::get<double>(it.second));
398             break;
399         case kTypeString:
400             snprintf(keyValue, SIZE, "string %s = %s, ", it.first.c_str(),
401                      std::get<std::string>(it.second).c_str());
402             break;
403         case kTypeInt8:
404             snprintf(keyValue, SIZE, "int8_t %s = %d, ", it.first.c_str(),
405                      std::get<int8_t>(it.second));
406             break;
407         default:
408             break;
409         }
410         s.append(keyValue);
411     }
412 
413     s.append("\n }");
414 
415     return s;
416 }
417 
toString() const418 std::string ECOData::toString() const {
419     return debugString();
420 }
421 
422 }  // namespace eco
423 }  // namespace media
424 }  // namespace android
425 }  // namespace aidl
426