You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
422 lines
12 KiB
422 lines
12 KiB
/*
|
|
* Copyright (C) 2019 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
//#define LOG_NDEBUG 0
|
|
#define LOG_TAG "ECOData"
|
|
|
|
#include "eco/ECOData.h"
|
|
|
|
#include <binder/Parcel.h>
|
|
#include <inttypes.h>
|
|
#include <utils/Errors.h>
|
|
#include <utils/Log.h>
|
|
|
|
#include <string>
|
|
|
|
#include "eco/ECODataKey.h"
|
|
#include "eco/ECOUtils.h"
|
|
|
|
namespace android {
|
|
namespace media {
|
|
namespace eco {
|
|
|
|
using namespace ::android;
|
|
|
|
status_t ECOData::readFromParcel(const Parcel* parcel) {
|
|
if (parcel == nullptr) {
|
|
ALOGE("readFromParcel failed. Parcel pointer can not be null");
|
|
return BAD_VALUE;
|
|
}
|
|
|
|
// Reads the data type and time.
|
|
RETURN_STATUS_IF_ERROR(parcel->readInt32(&mDataType));
|
|
RETURN_STATUS_IF_ERROR(parcel->readInt64(&mDataTimeUs));
|
|
|
|
// Reads the number of items.
|
|
uint32_t numOfItems = 0;
|
|
RETURN_STATUS_IF_ERROR(parcel->readUint32(&numOfItems));
|
|
|
|
// Reads the key-value pairs one by one.
|
|
for (size_t i = 0; i < numOfItems; ++i) {
|
|
// Reads the name of the key.
|
|
const char* name = parcel->readCString();
|
|
if (name == NULL) {
|
|
ALOGE("Failed reading name for the key. Parsing aborted.");
|
|
return NAME_NOT_FOUND;
|
|
}
|
|
|
|
int32_t type;
|
|
RETURN_STATUS_IF_ERROR(parcel->readInt32(&type));
|
|
switch (static_cast<ValueType>(type)) {
|
|
case kTypeInt32: {
|
|
int32_t value32;
|
|
RETURN_STATUS_IF_ERROR(parcel->readInt32(&value32));
|
|
setInt32(std::string(name), value32);
|
|
break;
|
|
}
|
|
case kTypeInt64: {
|
|
int64_t value64;
|
|
RETURN_STATUS_IF_ERROR(parcel->readInt64(&value64));
|
|
setInt64(std::string(name), value64);
|
|
break;
|
|
}
|
|
case kTypeSize: {
|
|
int32_t valueSize;
|
|
RETURN_STATUS_IF_ERROR(parcel->readInt32(&valueSize));
|
|
setInt32(std::string(name), valueSize);
|
|
break;
|
|
}
|
|
case kTypeFloat: {
|
|
float valueFloat;
|
|
RETURN_STATUS_IF_ERROR(parcel->readFloat(&valueFloat));
|
|
setFloat(std::string(name), valueFloat);
|
|
break;
|
|
}
|
|
case kTypeDouble: {
|
|
double valueDouble;
|
|
RETURN_STATUS_IF_ERROR(parcel->readDouble(&valueDouble));
|
|
setDouble(std::string(name), valueDouble);
|
|
break;
|
|
}
|
|
case kTypeString: {
|
|
const char* valueStr = parcel->readCString();
|
|
if (valueStr == NULL) {
|
|
ALOGE("Failed reading name for the key. Parsing aborted.");
|
|
return NAME_NOT_FOUND;
|
|
}
|
|
setString(std::string(name), valueStr);
|
|
break;
|
|
}
|
|
case kTypeInt8: {
|
|
int8_t value8;
|
|
RETURN_STATUS_IF_ERROR(parcel->readByte(&value8));
|
|
setInt8(std::string(name), value8);
|
|
break;
|
|
}
|
|
default: {
|
|
return BAD_TYPE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
status_t ECOData::writeToParcel(Parcel* parcel) const {
|
|
if (parcel == nullptr) {
|
|
ALOGE("writeToParcel failed. Parcel pointer can not be null");
|
|
return BAD_VALUE;
|
|
}
|
|
|
|
// Writes out the data type and time.
|
|
RETURN_STATUS_IF_ERROR(parcel->writeInt32(mDataType));
|
|
RETURN_STATUS_IF_ERROR(parcel->writeInt64(mDataTimeUs));
|
|
|
|
// Writes out number of items.
|
|
RETURN_STATUS_IF_ERROR(parcel->writeUint32(int32_t(mKeyValueStore.size())));
|
|
|
|
// Writes out the key-value pairs one by one.
|
|
for (const auto& it : mKeyValueStore) {
|
|
// Writes out the key.
|
|
RETURN_STATUS_IF_ERROR(parcel->writeCString(it.first.c_str()));
|
|
|
|
// Writes out the data type.
|
|
const ECODataValueType& value = it.second;
|
|
RETURN_STATUS_IF_ERROR(parcel->writeInt32(static_cast<int32_t>(value.index())));
|
|
switch (static_cast<ValueType>(value.index())) {
|
|
case kTypeInt32:
|
|
RETURN_STATUS_IF_ERROR(parcel->writeInt32(std::get<int32_t>(it.second)));
|
|
break;
|
|
|
|
case kTypeInt64:
|
|
RETURN_STATUS_IF_ERROR(parcel->writeInt64(std::get<int64_t>(it.second)));
|
|
break;
|
|
|
|
case kTypeSize:
|
|
RETURN_STATUS_IF_ERROR(parcel->writeUint32(std::get<size_t>(it.second)));
|
|
break;
|
|
|
|
case kTypeFloat:
|
|
RETURN_STATUS_IF_ERROR(parcel->writeFloat(std::get<float>(it.second)));
|
|
break;
|
|
|
|
case kTypeDouble:
|
|
RETURN_STATUS_IF_ERROR(parcel->writeDouble(std::get<double>(it.second)));
|
|
break;
|
|
|
|
case kTypeString:
|
|
RETURN_STATUS_IF_ERROR(parcel->writeCString(std::get<std::string>(it.second).c_str()));
|
|
break;
|
|
|
|
case kTypeInt8:
|
|
RETURN_STATUS_IF_ERROR(parcel->writeByte(std::get<int8_t>(it.second)));
|
|
break;
|
|
|
|
default:
|
|
return BAD_TYPE;
|
|
}
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int32_t ECOData::getDataType() const {
|
|
return mDataType;
|
|
}
|
|
|
|
int64_t ECOData::getDataTimeUs() const {
|
|
return mDataTimeUs;
|
|
}
|
|
|
|
// Inserts a new key into store if the key does not exist yet. Otherwise, this will override the
|
|
// existing key's value.
|
|
ECODataStatus ECOData::setString(const std::string& key, const std::string& value) {
|
|
if (key.empty() || value.empty()) {
|
|
return ECODataStatus::INVALID_ARGUMENT;
|
|
}
|
|
|
|
mKeyValueStore[key] = value;
|
|
|
|
// TODO(hkuang): Check the valueType is valid for the key.
|
|
return ECODataStatus::OK;
|
|
}
|
|
|
|
ECODataStatus ECOData::findString(const std::string& key, std::string* value) const {
|
|
if (key.empty()) {
|
|
return ECODataStatus::INVALID_ARGUMENT;
|
|
}
|
|
|
|
// Check if the key exists.
|
|
if (mKeyValueStore.find(key) == mKeyValueStore.end()) {
|
|
return ECODataStatus::KEY_NOT_EXIST;
|
|
}
|
|
|
|
// Safely access the value.
|
|
const std::string& entryValue = std::get<std::string>(mKeyValueStore.at(key));
|
|
value->assign(entryValue);
|
|
|
|
return ECODataStatus::OK;
|
|
}
|
|
|
|
// Inserts a new key into store if the key does not exist yet. Otherwise, this will override the
|
|
// existing key's value.
|
|
template <typename T>
|
|
ECODataStatus ECOData::setValue(const std::string& key, T value) {
|
|
if (key.empty()) {
|
|
return ECODataStatus::INVALID_ARGUMENT;
|
|
}
|
|
|
|
mKeyValueStore[key] = value;
|
|
return ECODataStatus::OK;
|
|
}
|
|
|
|
template <typename T>
|
|
ECODataStatus ECOData::findValue(const std::string& key, T* out) const {
|
|
if (key.empty() || out == nullptr) {
|
|
return ECODataStatus::INVALID_ARGUMENT;
|
|
}
|
|
|
|
if (mKeyValueStore.find(key) == mKeyValueStore.end()) {
|
|
return ECODataStatus::KEY_NOT_EXIST;
|
|
}
|
|
|
|
// Safely access the value.
|
|
*out = std::get<T>(mKeyValueStore.at(key));
|
|
|
|
return ECODataStatus::OK;
|
|
}
|
|
|
|
ECODataStatus ECOData::setInt32(const std::string& key, int32_t value) {
|
|
return setValue<int32_t>(key, value);
|
|
}
|
|
|
|
ECODataStatus ECOData::findInt32(const std::string& key, int32_t* out) const {
|
|
return findValue<int32_t>(key, out);
|
|
}
|
|
|
|
ECODataStatus ECOData::setInt64(const std::string& key, int64_t value) {
|
|
return setValue<int64_t>(key, value);
|
|
}
|
|
|
|
ECODataStatus ECOData::findInt64(const std::string& key, int64_t* out) const {
|
|
return findValue<int64_t>(key, out);
|
|
}
|
|
|
|
ECODataStatus ECOData::setDouble(const std::string& key, double value) {
|
|
return setValue<double>(key, value);
|
|
}
|
|
|
|
ECODataStatus ECOData::findDouble(const std::string& key, double* out) const {
|
|
return findValue<double>(key, out);
|
|
}
|
|
|
|
ECODataStatus ECOData::setSize(const std::string& key, size_t value) {
|
|
return setValue<size_t>(key, value);
|
|
}
|
|
|
|
ECODataStatus ECOData::findSize(const std::string& key, size_t* out) const {
|
|
return findValue<size_t>(key, out);
|
|
}
|
|
|
|
ECODataStatus ECOData::setFloat(const std::string& key, float value) {
|
|
return setValue<float>(key, value);
|
|
}
|
|
|
|
ECODataStatus ECOData::findFloat(const std::string& key, float* out) const {
|
|
return findValue<float>(key, out);
|
|
}
|
|
|
|
ECODataStatus ECOData::setInt8(const std::string& key, int8_t value) {
|
|
return setValue<int8_t>(key, value);
|
|
}
|
|
|
|
ECODataStatus ECOData::findInt8(const std::string& key, int8_t* out) const {
|
|
return findValue<int8_t>(key, out);
|
|
}
|
|
|
|
ECODataStatus ECOData::set(const std::string& key, const ECOData::ECODataValueType& value) {
|
|
if (key.empty()) {
|
|
return ECODataStatus::INVALID_ARGUMENT;
|
|
}
|
|
mKeyValueStore[key] = value;
|
|
return ECODataStatus::OK;
|
|
}
|
|
|
|
ECODataStatus ECOData::find(const std::string& key, ECOData::ECODataValueType* out) const {
|
|
if (key.empty() || out == nullptr) {
|
|
return ECODataStatus::INVALID_ARGUMENT;
|
|
}
|
|
|
|
if (mKeyValueStore.find(key) == mKeyValueStore.end()) {
|
|
return ECODataStatus::KEY_NOT_EXIST;
|
|
}
|
|
|
|
// Safely access the value.
|
|
*out = mKeyValueStore.at(key);
|
|
|
|
return ECODataStatus::OK;
|
|
}
|
|
|
|
std::string ECOData::getDataTypeString() const {
|
|
switch (mDataType) {
|
|
case DATA_TYPE_UNKNOWN:
|
|
return "DATA_TYPE_UNKNOWN";
|
|
case DATA_TYPE_STATS:
|
|
return "DATA_TYPE_STATS";
|
|
case DATA_TYPE_INFO:
|
|
return "DATA_TYPE_INFO";
|
|
case DATA_TYPE_STATS_PROVIDER_CONFIG:
|
|
return "DATA_TYPE_STATS_PROVIDER_CONFIG";
|
|
case DATA_TYPE_INFO_LISTENER_CONFIG:
|
|
return "DATA_TYPE_INFO_LISTENER_CONFIG";
|
|
}
|
|
return {};
|
|
}
|
|
|
|
// TODO(hkuang): Add test for this.
|
|
bool ECODataKeyValueIterator::hasNext() {
|
|
if (mIterator == mKeyValueStore.end()) return false;
|
|
|
|
if (!mBeginReturned) {
|
|
// mIterator has been initialized to the beginning and
|
|
// hasn't been returned. Do not advance:
|
|
mBeginReturned = true;
|
|
} else {
|
|
std::advance(mIterator, 1);
|
|
}
|
|
return mIterator != mKeyValueStore.end();
|
|
}
|
|
|
|
// TODO(hkuang): Add test for this.
|
|
ECOData::ECODataKeyValuePair ECODataKeyValueIterator::next() const {
|
|
return ECOData::ECODataKeyValuePair(mIterator->first, mIterator->second);
|
|
}
|
|
|
|
std::string ECOData::debugString() const {
|
|
std::string s = "ECOData(type = ";
|
|
|
|
std::string tmp;
|
|
switch (mDataType) {
|
|
case DATA_TYPE_UNKNOWN:
|
|
tmp = "Unknown";
|
|
break;
|
|
case DATA_TYPE_STATS:
|
|
tmp = "Stats";
|
|
break;
|
|
case DATA_TYPE_INFO:
|
|
tmp = "Info";
|
|
break;
|
|
case DATA_TYPE_STATS_PROVIDER_CONFIG:
|
|
tmp = "Stats provider config";
|
|
break;
|
|
case DATA_TYPE_INFO_LISTENER_CONFIG:
|
|
tmp = "Info listener config";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
s.append(tmp);
|
|
s.append(") = {\n ");
|
|
|
|
// Writes out the key-value pairs one by one.
|
|
for (const auto& it : mKeyValueStore) {
|
|
const size_t SIZE = 100;
|
|
char keyValue[SIZE];
|
|
const ECODataValueType& value = it.second;
|
|
switch (static_cast<ValueType>(value.index())) {
|
|
case kTypeInt32:
|
|
snprintf(keyValue, SIZE, "int32_t %s = %d, ", it.first.c_str(),
|
|
std::get<int32_t>(it.second));
|
|
break;
|
|
case kTypeInt64:
|
|
snprintf(keyValue, SIZE, "int64_t %s = %" PRId64 ", ", it.first.c_str(),
|
|
std::get<int64_t>(it.second));
|
|
break;
|
|
case kTypeSize:
|
|
snprintf(keyValue, SIZE, "size_t %s = %zu, ", it.first.c_str(),
|
|
std::get<size_t>(it.second));
|
|
break;
|
|
case kTypeFloat:
|
|
snprintf(keyValue, SIZE, "float %s = %f, ", it.first.c_str(),
|
|
std::get<float>(it.second));
|
|
break;
|
|
case kTypeDouble:
|
|
snprintf(keyValue, SIZE, "double %s = %f, ", it.first.c_str(),
|
|
std::get<double>(it.second));
|
|
break;
|
|
case kTypeString:
|
|
snprintf(keyValue, SIZE, "string %s = %s, ", it.first.c_str(),
|
|
std::get<std::string>(it.second).c_str());
|
|
break;
|
|
case kTypeInt8:
|
|
snprintf(keyValue, SIZE, "int8_t %s = %d, ", it.first.c_str(),
|
|
std::get<int8_t>(it.second));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
s.append(keyValue);
|
|
}
|
|
|
|
s.append("\n }");
|
|
|
|
return s;
|
|
}
|
|
|
|
} // namespace eco
|
|
} // namespace media
|
|
} // namespace android
|