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