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