* Copyright (C) 2021 Huawei Device Co., Ltd.
* 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.
*/
#include "capability.h"
#include "image_log.h"
#include "json_helper.h"
#include "plugin_common_type.h"
#undef LOG_DOMAIN
#define LOG_DOMAIN LOG_TAG_DOMAIN_ID_PLUGIN
#undef LOG_TAG
#define LOG_TAG "Capability"
namespace OHOS {
namespace MultimediaPlugin {
using nlohmann::json;
using std::map;
using std::size_t;
using std::string;
const string Capability::CAPABILITY_BOOL_TRUE = "true";
const string Capability::CAPABILITY_BOOL_FALSE = "false";
Capability::Capability(const map<string, AttrData> &caps) : caps_(caps)
{}
Capability::Capability(map<string, AttrData> &&caps) : caps_(std::move(caps))
{}
uint32_t Capability::SetCapability(const json &capsInfo)
{
if (!capsInfo.is_array()) {
IMAGE_LOGE("not a array type value.");
return ERR_INVALID_PARAMETER;
}
if (!caps_.empty()) {
caps_.clear();
}
size_t capNum = capsInfo.size();
IMAGE_LOGD("class cap num: %{public}zu.", capNum);
string name;
for (size_t i = 0; i < capNum; i++) {
const json &capabilityInfo = capsInfo[i];
if (JsonHelper::GetStringValue(capabilityInfo, "name", name) != SUCCESS) {
IMAGE_LOGE("failed to analysis cap name.");
continue;
}
IMAGE_LOGD("get new cap, name: %{public}s.", name.c_str());
AttrData attrData;
if (AnalyzeAttrData(capabilityInfo, attrData) != SUCCESS) {
IMAGE_LOGE("failed to analysis cap value.");
continue;
}
caps_.emplace(std::move(name), std::move(attrData));
}
return SUCCESS;
}
bool Capability::IsCompatible(const map<string, AttrData> &caps) const
{
for (const auto &capability : caps) {
auto iter = caps_.find(capability.first);
if (iter == caps_.end()) {
return false;
}
if (!iter->second.InRange(capability.second)) {
return false;
}
}
return true;
}
const AttrData *Capability::GetCapability(const string &key) const
{
auto iter = caps_.find(key);
if (iter == caps_.end()) {
return nullptr;
}
return &(iter->second);
}
const std::map<std::string, AttrData> &Capability::GetCapability() const
{
return caps_;
}
uint32_t Capability::AnalyzeAttrData(const json &capInfo, AttrData &attrData)
{
string type;
if (JsonHelper::GetStringValue(capInfo, "type", type) != SUCCESS) {
IMAGE_LOGE("failed to analysis data type.");
return ERR_INVALID_PARAMETER;
}
std::map<string, AttrDataType> typeMap_ = {
{ "bool", AttrDataType::ATTR_DATA_BOOL },
{ "uint32", AttrDataType::ATTR_DATA_UINT32 },
{ "string", AttrDataType::ATTR_DATA_STRING },
{ "uint32Set", AttrDataType::ATTR_DATA_UINT32_SET },
{ "stringSet", AttrDataType::ATTR_DATA_STRING_SET },
{ "uint32Range", AttrDataType::ATTR_DATA_UINT32_RANGE }
};
auto iter = typeMap_.find(type);
if (iter == typeMap_.end()) {
IMAGE_LOGE("unknown cap value type: %{public}s.", type.c_str());
return ERR_INVALID_PARAMETER;
}
switch (iter->second) {
case AttrDataType::ATTR_DATA_BOOL: {
return AnalyzeBool(capInfo, attrData);
}
case AttrDataType::ATTR_DATA_UINT32: {
return AnalyzeUint32(capInfo, attrData);
}
case AttrDataType::ATTR_DATA_STRING: {
return AnalyzeString(capInfo, attrData);
}
case AttrDataType::ATTR_DATA_UINT32_SET: {
return AnalyzeUint32Set(capInfo, attrData);
}
case AttrDataType::ATTR_DATA_STRING_SET: {
return AnalyzeStringSet(capInfo, attrData);
}
case AttrDataType::ATTR_DATA_UINT32_RANGE: {
return AnalyzeUint32Range(capInfo, attrData);
}
default: {
IMAGE_LOGE("unexpected cap value type: %{public}d.", iter->second);
return ERR_INTERNAL;
}
}
return SUCCESS;
}
uint32_t Capability::AnalyzeBool(const json &capInfo, AttrData &attrData)
{
string value;
if (JsonHelper::GetStringValue(capInfo, "value", value) != SUCCESS) {
IMAGE_LOGE("failed to analysis bool value.");
return ERR_INVALID_PARAMETER;
}
bool attrValue = false;
if (value == CAPABILITY_BOOL_TRUE) {
attrValue = true;
} else if (value == CAPABILITY_BOOL_FALSE) {
attrValue = false;
} else {
IMAGE_LOGE("failed to analyze bool value: %{public}s.", value.c_str());
return ERR_INVALID_PARAMETER;
}
IMAGE_LOGD("get bool AttrData: %{public}s.", value.c_str());
attrData.SetData(attrValue);
return SUCCESS;
}
uint32_t Capability::AnalyzeUint32(const json &capInfo, AttrData &attrData)
{
uint32_t value;
if (JsonHelper::GetUint32Value(capInfo, "value", value) != SUCCESS) {
IMAGE_LOGE("failed to analysis uint32 value.");
return ERR_INVALID_PARAMETER;
}
IMAGE_LOGD("get uint32 AttrData: %{public}u.", value);
attrData.SetData(value);
return SUCCESS;
}
uint32_t Capability::AnalyzeString(const json &capInfo, AttrData &attrData)
{
string value;
if (JsonHelper::GetStringValue(capInfo, "value", value) != SUCCESS) {
IMAGE_LOGE("failed to analysis string value.");
return ERR_INVALID_PARAMETER;
}
if (value.empty()) {
IMAGE_LOGE("failed to analyze string value.");
return ERR_INVALID_PARAMETER;
}
IMAGE_LOGD("get string AttrData: %{public}s.", value.c_str());
if (attrData.SetData(std::move(value)) != SUCCESS) {
IMAGE_LOGE("AnalyzeString: failed to call SetData for string type.");
return ERR_INTERNAL;
}
return SUCCESS;
}
uint32_t Capability::AnalyzeUint32Set(const json &capInfo, AttrData &attrData)
{
size_t arraySize;
if (JsonHelper::GetArraySize(capInfo, "value", arraySize) != SUCCESS) {
IMAGE_LOGE("failed to analysis uint32Set value.");
return ERR_INVALID_PARAMETER;
}
IMAGE_LOGD("uint32Set size: %{public}zu.", arraySize);
bool cond = arraySize < SET_MIN_VALUE_NUM;
CHECK_ERROR_RETURN_RET_LOG(cond, ERR_INVALID_PARAMETER, "invalid uint32Set size: %{public}zu.", arraySize);
uint32_t value;
const json &valueArray = capInfo["value"];
for (size_t i = 0; i < arraySize; i++) {
if (JsonHelper::GetUint32Value(valueArray[i], value) != SUCCESS) {
IMAGE_LOGE("fail to analyze uint32Set[%{public}zu]: %{public}u.", i, value);
attrData.ClearData();
return ERR_INVALID_PARAMETER;
}
IMAGE_LOGD("get uint32Set[%{public}zu]: %{public}u.", i, value);
if (attrData.InsertSet(value) != SUCCESS) {
IMAGE_LOGE("AnalyzeUint32Set: failed to call InsertSet.");
attrData.ClearData();
return ERR_INTERNAL;
}
}
return SUCCESS;
}
uint32_t Capability::AnalyzeUint32Range(const json &capInfo, AttrData &attrData)
{
size_t arraySize;
if (JsonHelper::GetArraySize(capInfo, "value", arraySize) != SUCCESS) {
IMAGE_LOGE("failed to analysis uint32Range value.");
return ERR_INVALID_PARAMETER;
}
IMAGE_LOGD("uint32Range size: %{public}zu.", arraySize);
bool cond = arraySize != AttrData::RANGE_ARRAY_SIZE;
CHECK_ERROR_RETURN_RET_LOG(cond, ERR_INVALID_PARAMETER, "invalid uint32Range size: %{public}zu.", arraySize);
const json &valueArray = capInfo["value"];
uint32_t lowerBound = 0;
if (JsonHelper::GetUint32Value(valueArray[AttrData::LOWER_BOUND_INDEX], lowerBound) != SUCCESS) {
IMAGE_LOGE("fail to analyze uint32 value of lowerBound: %{public}u.", lowerBound);
return ERR_INVALID_PARAMETER;
}
uint32_t upperBound = 0;
if (JsonHelper::GetUint32Value(valueArray[AttrData::UPPER_BOUND_INDEX], upperBound) != SUCCESS) {
IMAGE_LOGE("fail to analyze uint32 value of upperBound: %{public}u.", upperBound);
return ERR_INVALID_PARAMETER;
}
IMAGE_LOGD("AnalyzeUint32Range: get lowerBound: %{public}u, upperBound: %{public}u.", lowerBound, upperBound);
cond = attrData.SetData(lowerBound, upperBound) != SUCCESS;
CHECK_ERROR_RETURN_RET_LOG(cond, ERR_INTERNAL, "AnalyzeUint32Range: failed to call SetData.");
return SUCCESS;
}
uint32_t Capability::AnalyzeStringSet(const json &capInfo, AttrData &attrData)
{
size_t arraySize;
if (JsonHelper::GetArraySize(capInfo, "value", arraySize) != SUCCESS) {
IMAGE_LOGE("failed to analysis stringSet value.");
return ERR_INVALID_PARAMETER;
}
IMAGE_LOGD("stringSet size: %{public}zu.", arraySize);
bool cond = arraySize < SET_MIN_VALUE_NUM;
CHECK_ERROR_RETURN_RET_LOG(cond, ERR_INVALID_PARAMETER, "invalid stringSet size: %{public}zu.", arraySize);
const json &valueArray = capInfo["value"];
string value;
for (size_t i = 0; i < arraySize; i++) {
if (JsonHelper::GetStringValue(valueArray[i], value) != SUCCESS) {
IMAGE_LOGE("failed to analyze string value in stringSet[%{public}zu].", i);
attrData.ClearData();
return ERR_INVALID_PARAMETER;
}
IMAGE_LOGD("AnalyzeStringSet: get stringSet[%{public}zu]: %{public}s.", i, value.c_str());
if (attrData.InsertSet(std::move(value)) != SUCCESS) {
IMAGE_LOGE("AnalyzeStringSet: failed to call InsertSet.");
attrData.ClearData();
return ERR_INTERNAL;
}
}
return SUCCESS;
}
}
}