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 <binder/Parcel.h>
23 #include <inttypes.h>
24 #include <utils/Errors.h>
25 #include <utils/Log.h>
26 
27 #include <string>
28 
29 #include "eco/ECODataKey.h"
30 #include "eco/ECOUtils.h"
31 
32 namespace android {
33 namespace media {
34 namespace eco {
35 
36 using namespace ::android;
37 
readFromParcel(const Parcel * parcel)38 status_t ECOData::readFromParcel(const Parcel* parcel) {
39     if (parcel == nullptr) {
40         ALOGE("readFromParcel failed. Parcel pointer can not be null");
41         return BAD_VALUE;
42     }
43 
44     // Reads the data type and time.
45     RETURN_STATUS_IF_ERROR(parcel->readInt32(&mDataType));
46     RETURN_STATUS_IF_ERROR(parcel->readInt64(&mDataTimeUs));
47 
48     // Reads the number of items.
49     uint32_t numOfItems = 0;
50     RETURN_STATUS_IF_ERROR(parcel->readUint32(&numOfItems));
51 
52     // Reads the key-value pairs one by one.
53     for (size_t i = 0; i < numOfItems; ++i) {
54         // Reads the name of the key.
55         const char* name = parcel->readCString();
56         if (name == NULL) {
57             ALOGE("Failed reading name for the key. Parsing aborted.");
58             return NAME_NOT_FOUND;
59         }
60 
61         int32_t type;
62         RETURN_STATUS_IF_ERROR(parcel->readInt32(&type));
63         switch (static_cast<ValueType>(type)) {
64         case kTypeInt32: {
65             int32_t value32;
66             RETURN_STATUS_IF_ERROR(parcel->readInt32(&value32));
67             setInt32(std::string(name), value32);
68             break;
69         }
70         case kTypeInt64: {
71             int64_t value64;
72             RETURN_STATUS_IF_ERROR(parcel->readInt64(&value64));
73             setInt64(std::string(name), value64);
74             break;
75         }
76         case kTypeSize: {
77             int32_t valueSize;
78             RETURN_STATUS_IF_ERROR(parcel->readInt32(&valueSize));
79             setInt32(std::string(name), valueSize);
80             break;
81         }
82         case kTypeFloat: {
83             float valueFloat;
84             RETURN_STATUS_IF_ERROR(parcel->readFloat(&valueFloat));
85             setFloat(std::string(name), valueFloat);
86             break;
87         }
88         case kTypeDouble: {
89             double valueDouble;
90             RETURN_STATUS_IF_ERROR(parcel->readDouble(&valueDouble));
91             setDouble(std::string(name), valueDouble);
92             break;
93         }
94         case kTypeString: {
95             const char* valueStr = parcel->readCString();
96             if (valueStr == NULL) {
97                 ALOGE("Failed reading name for the key. Parsing aborted.");
98                 return NAME_NOT_FOUND;
99             }
100             setString(std::string(name), valueStr);
101             break;
102         }
103         case kTypeInt8: {
104             int8_t value8;
105             RETURN_STATUS_IF_ERROR(parcel->readByte(&value8));
106             setInt8(std::string(name), value8);
107             break;
108         }
109         default: {
110             return BAD_TYPE;
111         }
112         }
113     }
114 
115     return NO_ERROR;
116 }
117 
writeToParcel(Parcel * parcel) const118 status_t ECOData::writeToParcel(Parcel* parcel) const {
119     if (parcel == nullptr) {
120         ALOGE("writeToParcel failed. Parcel pointer can not be null");
121         return BAD_VALUE;
122     }
123 
124     // Writes out the data type and time.
125     RETURN_STATUS_IF_ERROR(parcel->writeInt32(mDataType));
126     RETURN_STATUS_IF_ERROR(parcel->writeInt64(mDataTimeUs));
127 
128     // Writes out number of items.
129     RETURN_STATUS_IF_ERROR(parcel->writeUint32(int32_t(mKeyValueStore.size())));
130 
131     // Writes out the key-value pairs one by one.
132     for (const auto& it : mKeyValueStore) {
133         // Writes out the key.
134         RETURN_STATUS_IF_ERROR(parcel->writeCString(it.first.c_str()));
135 
136         // Writes out the data type.
137         const ECODataValueType& value = it.second;
138         RETURN_STATUS_IF_ERROR(parcel->writeInt32(static_cast<int32_t>(value.index())));
139         switch (static_cast<ValueType>(value.index())) {
140         case kTypeInt32:
141             RETURN_STATUS_IF_ERROR(parcel->writeInt32(std::get<int32_t>(it.second)));
142             break;
143 
144         case kTypeInt64:
145             RETURN_STATUS_IF_ERROR(parcel->writeInt64(std::get<int64_t>(it.second)));
146             break;
147 
148         case kTypeSize:
149             RETURN_STATUS_IF_ERROR(parcel->writeUint32(std::get<size_t>(it.second)));
150             break;
151 
152         case kTypeFloat:
153             RETURN_STATUS_IF_ERROR(parcel->writeFloat(std::get<float>(it.second)));
154             break;
155 
156         case kTypeDouble:
157             RETURN_STATUS_IF_ERROR(parcel->writeDouble(std::get<double>(it.second)));
158             break;
159 
160         case kTypeString:
161             RETURN_STATUS_IF_ERROR(parcel->writeCString(std::get<std::string>(it.second).c_str()));
162             break;
163 
164         case kTypeInt8:
165             RETURN_STATUS_IF_ERROR(parcel->writeByte(std::get<int8_t>(it.second)));
166             break;
167 
168         default:
169             return BAD_TYPE;
170         }
171     }
172 
173     return NO_ERROR;
174 }
175 
getDataType() const176 int32_t ECOData::getDataType() const {
177     return mDataType;
178 }
179 
getDataTimeUs() const180 int64_t ECOData::getDataTimeUs() const {
181     return mDataTimeUs;
182 }
183 
184 // Inserts a new key into store if the key does not exist yet. Otherwise, this will override the
185 // existing key's value.
setString(const std::string & key,const std::string & value)186 ECODataStatus ECOData::setString(const std::string& key, const std::string& value) {
187     if (key.empty() || value.empty()) {
188         return ECODataStatus::INVALID_ARGUMENT;
189     }
190 
191     mKeyValueStore[key] = value;
192 
193     // TODO(hkuang): Check the valueType is valid for the key.
194     return ECODataStatus::OK;
195 }
196 
findString(const std::string & key,std::string * value) const197 ECODataStatus ECOData::findString(const std::string& key, std::string* value) const {
198     if (key.empty()) {
199         return ECODataStatus::INVALID_ARGUMENT;
200     }
201 
202     // Check if the key exists.
203     if (mKeyValueStore.find(key) == mKeyValueStore.end()) {
204         return ECODataStatus::KEY_NOT_EXIST;
205     }
206 
207     // Safely access the value.
208     const std::string& entryValue = std::get<std::string>(mKeyValueStore.at(key));
209     value->assign(entryValue);
210 
211     return ECODataStatus::OK;
212 }
213 
214 // Inserts a new key into store if the key does not exist yet. Otherwise, this will override the
215 // existing key's value.
216 template <typename T>
setValue(const std::string & key,T value)217 ECODataStatus ECOData::setValue(const std::string& key, T value) {
218     if (key.empty()) {
219         return ECODataStatus::INVALID_ARGUMENT;
220     }
221 
222     mKeyValueStore[key] = value;
223     return ECODataStatus::OK;
224 }
225 
226 template <typename T>
findValue(const std::string & key,T * out) const227 ECODataStatus ECOData::findValue(const std::string& key, T* out) const {
228     if (key.empty() || out == nullptr) {
229         return ECODataStatus::INVALID_ARGUMENT;
230     }
231 
232     if (mKeyValueStore.find(key) == mKeyValueStore.end()) {
233         return ECODataStatus::KEY_NOT_EXIST;
234     }
235 
236     // Safely access the value.
237     *out = std::get<T>(mKeyValueStore.at(key));
238 
239     return ECODataStatus::OK;
240 }
241 
setInt32(const std::string & key,int32_t value)242 ECODataStatus ECOData::setInt32(const std::string& key, int32_t value) {
243     return setValue<int32_t>(key, value);
244 }
245 
findInt32(const std::string & key,int32_t * out) const246 ECODataStatus ECOData::findInt32(const std::string& key, int32_t* out) const {
247     return findValue<int32_t>(key, out);
248 }
249 
setInt64(const std::string & key,int64_t value)250 ECODataStatus ECOData::setInt64(const std::string& key, int64_t value) {
251     return setValue<int64_t>(key, value);
252 }
253 
findInt64(const std::string & key,int64_t * out) const254 ECODataStatus ECOData::findInt64(const std::string& key, int64_t* out) const {
255     return findValue<int64_t>(key, out);
256 }
257 
setDouble(const std::string & key,double value)258 ECODataStatus ECOData::setDouble(const std::string& key, double value) {
259     return setValue<double>(key, value);
260 }
261 
findDouble(const std::string & key,double * out) const262 ECODataStatus ECOData::findDouble(const std::string& key, double* out) const {
263     return findValue<double>(key, out);
264 }
265 
setSize(const std::string & key,size_t value)266 ECODataStatus ECOData::setSize(const std::string& key, size_t value) {
267     return setValue<size_t>(key, value);
268 }
269 
findSize(const std::string & key,size_t * out) const270 ECODataStatus ECOData::findSize(const std::string& key, size_t* out) const {
271     return findValue<size_t>(key, out);
272 }
273 
setFloat(const std::string & key,float value)274 ECODataStatus ECOData::setFloat(const std::string& key, float value) {
275     return setValue<float>(key, value);
276 }
277 
findFloat(const std::string & key,float * out) const278 ECODataStatus ECOData::findFloat(const std::string& key, float* out) const {
279     return findValue<float>(key, out);
280 }
281 
setInt8(const std::string & key,int8_t value)282 ECODataStatus ECOData::setInt8(const std::string& key, int8_t value) {
283     return setValue<int8_t>(key, value);
284 }
285 
findInt8(const std::string & key,int8_t * out) const286 ECODataStatus ECOData::findInt8(const std::string& key, int8_t* out) const {
287     return findValue<int8_t>(key, out);
288 }
289 
set(const std::string & key,const ECOData::ECODataValueType & value)290 ECODataStatus ECOData::set(const std::string& key, const ECOData::ECODataValueType& value) {
291     if (key.empty()) {
292         return ECODataStatus::INVALID_ARGUMENT;
293     }
294     mKeyValueStore[key] = value;
295     return ECODataStatus::OK;
296 }
297 
find(const std::string & key,ECOData::ECODataValueType * out) const298 ECODataStatus ECOData::find(const std::string& key, ECOData::ECODataValueType* out) const {
299     if (key.empty() || out == nullptr) {
300         return ECODataStatus::INVALID_ARGUMENT;
301     }
302 
303     if (mKeyValueStore.find(key) == mKeyValueStore.end()) {
304         return ECODataStatus::KEY_NOT_EXIST;
305     }
306 
307     // Safely access the value.
308     *out = mKeyValueStore.at(key);
309 
310     return ECODataStatus::OK;
311 }
312 
getDataTypeString() const313 std::string ECOData::getDataTypeString() const {
314     switch (mDataType) {
315     case DATA_TYPE_UNKNOWN:
316         return "DATA_TYPE_UNKNOWN";
317     case DATA_TYPE_STATS:
318         return "DATA_TYPE_STATS";
319     case DATA_TYPE_INFO:
320         return "DATA_TYPE_INFO";
321     case DATA_TYPE_STATS_PROVIDER_CONFIG:
322         return "DATA_TYPE_STATS_PROVIDER_CONFIG";
323     case DATA_TYPE_INFO_LISTENER_CONFIG:
324         return "DATA_TYPE_INFO_LISTENER_CONFIG";
325     }
326     return {};
327 }
328 
329 // TODO(hkuang): Add test for this.
hasNext()330 bool ECODataKeyValueIterator::hasNext() {
331     if (mIterator == mKeyValueStore.end()) return false;
332 
333     if (!mBeginReturned) {
334         // mIterator has been initialized to the beginning and
335         // hasn't been returned. Do not advance:
336         mBeginReturned = true;
337     } else {
338         std::advance(mIterator, 1);
339     }
340     return mIterator != mKeyValueStore.end();
341 }
342 
343 // TODO(hkuang): Add test for this.
next() const344 ECOData::ECODataKeyValuePair ECODataKeyValueIterator::next() const {
345     return ECOData::ECODataKeyValuePair(mIterator->first, mIterator->second);
346 }
347 
debugString() const348 std::string ECOData::debugString() const {
349     std::string s = "ECOData(type = ";
350 
351     std::string tmp;
352     switch (mDataType) {
353     case DATA_TYPE_UNKNOWN:
354         tmp = "Unknown";
355         break;
356     case DATA_TYPE_STATS:
357         tmp = "Stats";
358         break;
359     case DATA_TYPE_INFO:
360         tmp = "Info";
361         break;
362     case DATA_TYPE_STATS_PROVIDER_CONFIG:
363         tmp = "Stats provider config";
364         break;
365     case DATA_TYPE_INFO_LISTENER_CONFIG:
366         tmp = "Info listener config";
367         break;
368     default:
369         break;
370     }
371     s.append(tmp);
372     s.append(") = {\n  ");
373 
374     // Writes out the key-value pairs one by one.
375     for (const auto& it : mKeyValueStore) {
376         const size_t SIZE = 100;
377         char keyValue[SIZE];
378         const ECODataValueType& value = it.second;
379         switch (static_cast<ValueType>(value.index())) {
380         case kTypeInt32:
381             snprintf(keyValue, SIZE, "int32_t %s = %d, ", it.first.c_str(),
382                      std::get<int32_t>(it.second));
383             break;
384         case kTypeInt64:
385             snprintf(keyValue, SIZE, "int64_t %s = %" PRId64 ", ", it.first.c_str(),
386                      std::get<int64_t>(it.second));
387             break;
388         case kTypeSize:
389             snprintf(keyValue, SIZE, "size_t %s = %zu, ", it.first.c_str(),
390                      std::get<size_t>(it.second));
391             break;
392         case kTypeFloat:
393             snprintf(keyValue, SIZE, "float %s = %f, ", it.first.c_str(),
394                      std::get<float>(it.second));
395             break;
396         case kTypeDouble:
397             snprintf(keyValue, SIZE, "double %s = %f, ", it.first.c_str(),
398                      std::get<double>(it.second));
399             break;
400         case kTypeString:
401             snprintf(keyValue, SIZE, "string %s = %s, ", it.first.c_str(),
402                      std::get<std::string>(it.second).c_str());
403             break;
404         case kTypeInt8:
405             snprintf(keyValue, SIZE, "int8_t %s = %d, ", it.first.c_str(),
406                      std::get<int8_t>(it.second));
407             break;
408         default:
409             break;
410         }
411         s.append(keyValue);
412     }
413 
414     s.append("\n }");
415 
416     return s;
417 }
418 
419 }  // namespace eco
420 }  // namespace media
421 }  // namespace android
422