1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "capability.h"
17 #include "image_log.h"
18 #include "json_helper.h"
19 #include "plugin_common_type.h"
20 
21 #undef LOG_DOMAIN
22 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_PLUGIN
23 
24 #undef LOG_TAG
25 #define LOG_TAG "Capability"
26 
27 namespace OHOS {
28 namespace MultimediaPlugin {
29 using nlohmann::json;
30 using std::map;
31 using std::size_t;
32 using std::string;
33 const string Capability::CAPABILITY_BOOL_TRUE = "true";
34 const string Capability::CAPABILITY_BOOL_FALSE = "false";
35 
Capability(const map<string,AttrData> & caps)36 Capability::Capability(const map<string, AttrData> &caps) : caps_(caps)
37 {}
38 
Capability(map<string,AttrData> && caps)39 Capability::Capability(map<string, AttrData> &&caps) : caps_(std::move(caps))
40 {}
41 
SetCapability(const json & capsInfo)42 uint32_t Capability::SetCapability(const json &capsInfo)
43 {
44     if (!capsInfo.is_array()) {
45         IMAGE_LOGE("not a array type value.");
46         return ERR_INVALID_PARAMETER;
47     }
48 
49     if (!caps_.empty()) {
50         caps_.clear();
51     }
52 
53     size_t capNum = capsInfo.size();
54     IMAGE_LOGD("class cap num: %{public}zu.", capNum);
55     string name;
56     for (size_t i = 0; i < capNum; i++) {
57         const json &capabilityInfo = capsInfo[i];
58         if (JsonHelper::GetStringValue(capabilityInfo, "name", name) != SUCCESS) {
59             IMAGE_LOGE("failed to analysis cap name.");
60             continue;
61         }
62 
63         IMAGE_LOGD("get new cap, name: %{public}s.", name.c_str());
64         AttrData attrData;
65         if (AnalyzeAttrData(capabilityInfo, attrData) != SUCCESS) {
66             IMAGE_LOGE("failed to analysis cap value.");
67             continue;
68         }
69 
70         caps_.emplace(std::move(name), std::move(attrData));
71     }
72 
73     return SUCCESS;
74 }
75 
IsCompatible(const map<string,AttrData> & caps) const76 bool Capability::IsCompatible(const map<string, AttrData> &caps) const
77 {
78     for (const auto &capability : caps) {
79         auto iter = caps_.find(capability.first);
80         if (iter == caps_.end()) {
81             return false;
82         }
83 
84         if (!iter->second.InRange(capability.second)) {
85             return false;
86         }
87     }
88 
89     return true;
90 }
91 
GetCapability(const string & key) const92 const AttrData *Capability::GetCapability(const string &key) const
93 {
94     auto iter = caps_.find(key);
95     if (iter == caps_.end()) {
96         return nullptr;
97     }
98 
99     return &(iter->second);
100 }
101 
GetCapability() const102 const std::map<std::string, AttrData> &Capability::GetCapability() const
103 {
104     return caps_;
105 }
106 
107 // ------------------------------- private method -------------------------------
AnalyzeAttrData(const json & capInfo,AttrData & attrData)108 uint32_t Capability::AnalyzeAttrData(const json &capInfo, AttrData &attrData)
109 {
110     string type;
111     if (JsonHelper::GetStringValue(capInfo, "type", type) != SUCCESS) {
112         IMAGE_LOGE("failed to analysis data type.");
113         return ERR_INVALID_PARAMETER;
114     }
115 
116     std::map<string, AttrDataType> typeMap_ = {
117         { "bool", AttrDataType::ATTR_DATA_BOOL },
118         { "uint32", AttrDataType::ATTR_DATA_UINT32 },
119         { "string", AttrDataType::ATTR_DATA_STRING },
120         { "uint32Set", AttrDataType::ATTR_DATA_UINT32_SET },
121         { "stringSet", AttrDataType::ATTR_DATA_STRING_SET },
122         { "uint32Range", AttrDataType::ATTR_DATA_UINT32_RANGE }
123     };
124 
125     auto iter = typeMap_.find(type);
126     if (iter == typeMap_.end()) {
127         IMAGE_LOGE("unknown cap value type: %{public}s.", type.c_str());
128         return ERR_INVALID_PARAMETER;
129     }
130 
131     switch (iter->second) {
132         case AttrDataType::ATTR_DATA_BOOL: {
133             return AnalyzeBool(capInfo, attrData);
134         }
135         case AttrDataType::ATTR_DATA_UINT32: {
136             return AnalyzeUint32(capInfo, attrData);
137         }
138         case AttrDataType::ATTR_DATA_STRING: {
139             return AnalyzeString(capInfo, attrData);
140         }
141         case AttrDataType::ATTR_DATA_UINT32_SET: {
142             return AnalyzeUint32Set(capInfo, attrData);
143         }
144         case AttrDataType::ATTR_DATA_STRING_SET: {
145             return AnalyzeStringSet(capInfo, attrData);
146         }
147         case AttrDataType::ATTR_DATA_UINT32_RANGE: {
148             return AnalyzeUint32Range(capInfo, attrData);
149         }
150         default: {
151             IMAGE_LOGE("unexpected cap value type: %{public}d.", iter->second);
152             return ERR_INTERNAL;
153         }
154     }
155 
156     return SUCCESS;
157 }
158 
AnalyzeBool(const json & capInfo,AttrData & attrData)159 uint32_t Capability::AnalyzeBool(const json &capInfo, AttrData &attrData)
160 {
161     string value;
162     if (JsonHelper::GetStringValue(capInfo, "value", value) != SUCCESS) {
163         IMAGE_LOGE("failed to analysis bool value.");
164         return ERR_INVALID_PARAMETER;
165     }
166 
167     bool attrValue = false;
168     if (value == CAPABILITY_BOOL_TRUE) {
169         attrValue = true;
170     } else if (value == CAPABILITY_BOOL_FALSE) {
171         attrValue = false;
172     } else {
173         IMAGE_LOGE("failed to analyze bool value: %{public}s.", value.c_str());
174         return ERR_INVALID_PARAMETER;
175     }
176 
177     IMAGE_LOGD("get bool AttrData: %{public}s.", value.c_str());
178     attrData.SetData(attrValue);
179 
180     return SUCCESS;
181 }
182 
AnalyzeUint32(const json & capInfo,AttrData & attrData)183 uint32_t Capability::AnalyzeUint32(const json &capInfo, AttrData &attrData)
184 {
185     uint32_t value;
186     if (JsonHelper::GetUint32Value(capInfo, "value", value) != SUCCESS) {
187         IMAGE_LOGE("failed to analysis uint32 value.");
188         return ERR_INVALID_PARAMETER;
189     }
190 
191     IMAGE_LOGD("get uint32 AttrData: %{public}u.", value);
192     attrData.SetData(value);
193 
194     return SUCCESS;
195 }
196 
AnalyzeString(const json & capInfo,AttrData & attrData)197 uint32_t Capability::AnalyzeString(const json &capInfo, AttrData &attrData)
198 {
199     string value;
200     if (JsonHelper::GetStringValue(capInfo, "value", value) != SUCCESS) {
201         IMAGE_LOGE("failed to analysis string value.");
202         return ERR_INVALID_PARAMETER;
203     }
204 
205     if (value.empty()) {
206         IMAGE_LOGE("failed to analyze string value.");
207         return ERR_INVALID_PARAMETER;
208     }
209 
210     IMAGE_LOGD("get string AttrData: %{public}s.", value.c_str());
211     if (attrData.SetData(std::move(value)) != SUCCESS) {
212         IMAGE_LOGE("AnalyzeString: failed to call SetData for string type.");
213         return ERR_INTERNAL;
214     }
215 
216     return SUCCESS;
217 }
218 
AnalyzeUint32Set(const json & capInfo,AttrData & attrData)219 uint32_t Capability::AnalyzeUint32Set(const json &capInfo, AttrData &attrData)
220 {
221     size_t arraySize;
222     if (JsonHelper::GetArraySize(capInfo, "value", arraySize) != SUCCESS) {
223         IMAGE_LOGE("failed to analysis uint32Set value.");
224         return ERR_INVALID_PARAMETER;
225     }
226     IMAGE_LOGD("uint32Set size: %{public}zu.", arraySize);
227 
228     if (arraySize < SET_MIN_VALUE_NUM) {
229         IMAGE_LOGE("invalid uint32Set size: %{public}zu.", arraySize);
230         return ERR_INVALID_PARAMETER;
231     }
232 
233     uint32_t value;
234     const json &valueArray = capInfo["value"];
235     for (size_t i = 0; i < arraySize; i++) {
236         if (JsonHelper::GetUint32Value(valueArray[i], value) != SUCCESS) {
237             IMAGE_LOGE("fail to analyze uint32Set[%{public}zu]: %{public}u.", i, value);
238             attrData.ClearData();
239             return ERR_INVALID_PARAMETER;
240         }
241         IMAGE_LOGD("get uint32Set[%{public}zu]: %{public}u.", i, value);
242         if (attrData.InsertSet(value) != SUCCESS) {
243             IMAGE_LOGE("AnalyzeUint32Set: failed to call InsertSet.");
244             attrData.ClearData();
245             return ERR_INTERNAL;
246         }
247     }
248 
249     return SUCCESS;
250 }
251 
AnalyzeUint32Range(const json & capInfo,AttrData & attrData)252 uint32_t Capability::AnalyzeUint32Range(const json &capInfo, AttrData &attrData)
253 {
254     size_t arraySize;
255     if (JsonHelper::GetArraySize(capInfo, "value", arraySize) != SUCCESS) {
256         IMAGE_LOGE("failed to analysis uint32Range value.");
257         return ERR_INVALID_PARAMETER;
258     }
259     IMAGE_LOGD("uint32Range size: %{public}zu.", arraySize);
260 
261     if (arraySize != AttrData::RANGE_ARRAY_SIZE) {
262         IMAGE_LOGE("invalid uint32Range size: %{public}zu.", arraySize);
263         return ERR_INVALID_PARAMETER;
264     }
265 
266     const json &valueArray = capInfo["value"];
267     uint32_t lowerBound = 0;
268     if (JsonHelper::GetUint32Value(valueArray[AttrData::LOWER_BOUND_INDEX], lowerBound) != SUCCESS) {
269         IMAGE_LOGE("fail to analyze uint32 value of lowerBound: %{public}u.", lowerBound);
270         return ERR_INVALID_PARAMETER;
271     }
272 
273     uint32_t upperBound = 0;
274     if (JsonHelper::GetUint32Value(valueArray[AttrData::UPPER_BOUND_INDEX], upperBound) != SUCCESS) {
275         IMAGE_LOGE("fail to analyze uint32 value of upperBound: %{public}u.", upperBound);
276         return ERR_INVALID_PARAMETER;
277     }
278 
279     IMAGE_LOGD("AnalyzeUint32Range: get lowerBound: %{public}u, upperBound: %{public}u.", lowerBound, upperBound);
280     if (attrData.SetData(lowerBound, upperBound) != SUCCESS) {
281         IMAGE_LOGE("AnalyzeUint32Range: failed to call SetData.");
282         return ERR_INTERNAL;
283     }
284 
285     return SUCCESS;
286 }
287 
AnalyzeStringSet(const json & capInfo,AttrData & attrData)288 uint32_t Capability::AnalyzeStringSet(const json &capInfo, AttrData &attrData)
289 {
290     size_t arraySize;
291     if (JsonHelper::GetArraySize(capInfo, "value", arraySize) != SUCCESS) {
292         IMAGE_LOGE("failed to analysis stringSet value.");
293         return ERR_INVALID_PARAMETER;
294     }
295     IMAGE_LOGD("stringSet size: %{public}zu.", arraySize);
296 
297     if (arraySize < SET_MIN_VALUE_NUM) {
298         IMAGE_LOGE("invalid stringSet size: %{public}zu.", arraySize);
299         return ERR_INVALID_PARAMETER;
300     }
301 
302     const json &valueArray = capInfo["value"];
303     string value;
304     for (size_t i = 0; i < arraySize; i++) {
305         if (JsonHelper::GetStringValue(valueArray[i], value) != SUCCESS) {
306             IMAGE_LOGE("failed to analyze string value in stringSet[%{public}zu].", i);
307             attrData.ClearData();
308             return ERR_INVALID_PARAMETER;
309         }
310 
311         IMAGE_LOGD("AnalyzeStringSet: get stringSet[%{public}zu]: %{public}s.", i, value.c_str());
312         if (attrData.InsertSet(std::move(value)) != SUCCESS) {
313             IMAGE_LOGE("AnalyzeStringSet: failed to call InsertSet.");
314             attrData.ClearData();
315             return ERR_INTERNAL;
316         }
317     }
318 
319     return SUCCESS;
320 }
321 } // namespace MultimediaPlugin
322 } // namespace OHOS
323