• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "impl_class_mgr.h"
17 #include "image_log.h"
18 #include "impl_class.h"
19 #include "plugin.h"
20 #include "plugin_class_base.h"
21 
22 #undef LOG_DOMAIN
23 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_PLUGIN
24 
25 #undef LOG_TAG
26 #define LOG_TAG "ImplClassMgr"
27 
28 namespace OHOS {
29 namespace MultimediaPlugin {
30 using nlohmann::json;
31 using std::list;
32 using std::map;
33 using std::multimap;
34 using std::mutex;
35 using std::set;
36 using std::shared_ptr;
37 using std::string;
38 using std::weak_ptr;
39 
AddClass(weak_ptr<Plugin> & plugin,const json & classInfo)40 uint32_t ImplClassMgr::AddClass(weak_ptr<Plugin> &plugin, const json &classInfo)
41 {
42     shared_ptr<ImplClass> implClass = std::make_shared<ImplClass>();
43     if (implClass == nullptr) {
44         IMAGE_LOGE("AddClass: failed to create ImplClass.");
45         return ERR_INTERNAL;
46     }
47 
48     auto ret = implClass->Register(plugin, classInfo);
49     if (ret != SUCCESS) {
50         IMAGE_LOGE("AddClass: failed to register impClass.ERRNO: %{public}u.", ret);
51         return ret;
52     }
53 
54     const string &key = implClass->GetClassName();
55     CHECK_ERROR_RETURN_RET_LOG(key.empty(), ERR_INTERNAL, "AddClass: empty className.");
56 
57     IMAGE_LOGD("AddClass: insert Class: %{public}s.", key.c_str());
58     classMultimap_.insert(NameClassMultimap::value_type(&key, implClass));
59 
60     // for fast search by service flag
61     const set<uint32_t> &services = implClass->GetServices();
62     for (const uint32_t &srv : services) {
63         IMAGE_LOGD("AddClass: insert service: %{public}u.", srv);
64         srvSearchMultimap_.insert(ServiceClassMultimap::value_type(srv, implClass));
65     }
66 
67     return SUCCESS;
68 }
69 
DeleteClass(const weak_ptr<Plugin> & plugin)70 void ImplClassMgr::DeleteClass(const weak_ptr<Plugin> &plugin)
71 {
72     // delete all ImplClass under the specified plugin.
73     auto targetPlugin = plugin.lock();
74 
75     for (auto iter = srvSearchMultimap_.begin(); iter != srvSearchMultimap_.end();) {
76         auto tmpPlugin = iter->second->GetPluginRef().lock();
77         if (tmpPlugin != targetPlugin) {
78             ++iter;
79             continue;
80         }
81         iter = srvSearchMultimap_.erase(iter);
82     }
83 
84     for (auto iter = classMultimap_.begin(); iter != classMultimap_.end();) {
85         auto tmpPlugin = iter->second->GetPluginRef().lock();
86         if (tmpPlugin != targetPlugin) {
87             ++iter;
88             continue;
89         }
90         iter = classMultimap_.erase(iter);
91     }
92 }
93 
CreateObject(uint16_t interfaceID,const string & className,uint32_t & errorCode)94 PluginClassBase *ImplClassMgr::CreateObject(uint16_t interfaceID, const string &className, uint32_t &errorCode)
95 {
96     IMAGE_LOGD("create object iid: %{public}hu, className: %{public}s.", interfaceID, className.c_str());
97 
98     NameClassMultimap::iterator iter = classMultimap_.lower_bound(&className);
99     NameClassMultimap::iterator endIter = classMultimap_.upper_bound(&className);
100     if (iter == endIter) {
101         IMAGE_LOGE("failed to find matching class by className: %{public}s.", className.c_str());
102         errorCode = ERR_MATCHING_PLUGIN;
103         return nullptr;
104     }
105 
106     for (; iter != endIter; ++iter) {
107         CHECK_ERROR_RETURN_RET(iter->second->IsSupport(interfaceID), iter->second->CreateObject(errorCode));
108     }
109 
110     // no this class
111     IMAGE_LOGE("failed to find matching class for iid: %{public}hu, className: %{public}s.", interfaceID,
112         className.c_str());
113     errorCode = ERR_MATCHING_PLUGIN;
114     return nullptr;
115 }
116 
CreateObject(uint16_t interfaceID,uint16_t serviceType,const map<string,AttrData> & capabilities,const PriorityScheme & priorityScheme,uint32_t & errorCode)117 PluginClassBase *ImplClassMgr::CreateObject(uint16_t interfaceID, uint16_t serviceType,
118                                             const map<string, AttrData> &capabilities,
119                                             const PriorityScheme &priorityScheme, uint32_t &errorCode)
120 {
121     uint32_t serviceFlag = ImplClass::MakeServiceFlag(interfaceID, serviceType);
122     list<shared_ptr<ImplClass>> candidates;
123 
124     IMAGE_LOGD("create object iid: %{public}u, serviceType: %{public}u.", interfaceID, serviceType);
125 
126     auto iter = srvSearchMultimap_.lower_bound(serviceFlag);
127     auto endIter = srvSearchMultimap_.upper_bound(serviceFlag);
128     for (; iter != endIter; ++iter) {
129         shared_ptr<ImplClass> &temp = iter->second;
130         if ((!capabilities.empty()) && (!temp->IsCompatible(capabilities))) {
131             continue;
132         }
133         candidates.push_back(temp);
134     }
135 
136     shared_ptr<ImplClass> target = SearchByPriority(candidates, priorityScheme);
137     if (target == nullptr) {
138         IMAGE_LOGD("failed to find class by priority.");
139         errorCode = ERR_MATCHING_PLUGIN;
140         return nullptr;
141     }
142 
143     IMAGE_LOGD("search by priority result, className: %{public}s.", target->GetClassName().c_str());
144     return target->CreateObject(errorCode);
145 }
146 
ImplClassMgrGetClassInfo(uint16_t interfaceID,uint16_t serviceType,const std::map<std::string,AttrData> & capabilities,std::vector<ClassInfo> & classesInfo)147 uint32_t ImplClassMgr::ImplClassMgrGetClassInfo(uint16_t interfaceID, uint16_t serviceType,
148                                                 const std::map<std::string, AttrData> &capabilities,
149                                                 std::vector<ClassInfo> &classesInfo)
150 {
151     // get service flag by interfaceID and serviceType
152     uint32_t serviceFlag = ImplClass::MakeServiceFlag(interfaceID, serviceType);
153 
154     IMAGE_LOGD("get classinfo iid: %{public}u, serviceType: %{public}u.", interfaceID, serviceType);
155     auto iter = srvSearchMultimap_.lower_bound(serviceFlag);
156     auto endIter = srvSearchMultimap_.upper_bound(serviceFlag);
157     if (iter == endIter) {
158         IMAGE_LOGE("failed to get class by serviceFlag, iid: %{public}u, serviceType: %{public}u.",
159             interfaceID, serviceType);
160         return ERR_MATCHING_PLUGIN;
161     }
162 
163     for (; iter != endIter; ++iter) {
164         shared_ptr<ImplClass> &temp = iter->second;
165         if ((capabilities.size() != 0) && (!temp->IsCompatible(capabilities))) {
166             continue;
167         }
168         // after multiple filtering, there are only a few instances here, which will not cause massive logs.
169         IMAGE_LOGD("found by serviceFlag & capabilities, className: %{public}s.", temp->GetClassName().c_str());
170         ClassInfo classInfo;
171         classInfo.packageName = temp->GetPackageName();
172         classInfo.className = temp->GetClassName();
173         classInfo.priority = temp->GetPriority();
174         classInfo.capabilities = temp->GetCapability();
175         classesInfo.emplace_back(std::move(classInfo));
176     }
177 
178     CHECK_ERROR_RETURN_RET_LOG(classesInfo.empty(), ERR_MATCHING_PLUGIN,
179         "failed to get class by capabilities, iid: %{public}u, serviceType: %{public}u.", interfaceID, serviceType);
180 
181     return SUCCESS;
182 }
183 
GetImplClass(const string & packageName,const string & className)184 shared_ptr<ImplClass> ImplClassMgr::GetImplClass(const string &packageName, const string &className)
185 {
186     IMAGE_LOGD("search ImplClass, className: %{public}s.", className.c_str());
187     shared_ptr<ImplClass> implClass = nullptr;
188     auto iter = classMultimap_.lower_bound(&className);
189     auto endIter = classMultimap_.upper_bound(&className);
190     for (; iter != endIter; ++iter) {
191         if (packageName == iter->second->GetPackageName()) {
192             implClass = iter->second;
193             break;
194         }
195     }
196 
197     if (implClass == nullptr) {
198         IMAGE_LOGE("failed to get ImplClass, className: %{public}s.", className.c_str());
199     }
200 
201     return implClass;
202 }
203 
204 // ------------------------------- private method -------------------------------
ImplClassMgr()205 ImplClassMgr::ImplClassMgr()
206 {}
207 
~ImplClassMgr()208 ImplClassMgr::~ImplClassMgr()
209 {}
210 
SearchByPriority(const list<shared_ptr<ImplClass>> & candidates,const PriorityScheme & priorityScheme)211 shared_ptr<ImplClass> ImplClassMgr::SearchByPriority(const list<shared_ptr<ImplClass>> &candidates,
212                                                      const PriorityScheme &priorityScheme)
213 {
214     auto size = candidates.size();
215     if (size == 0) {  // 0 means class no candidate,  return empty directly.
216         IMAGE_LOGD("SearchByPriority: candidates size is zero.");
217         return nullptr;
218     }
219 
220     if (size == 1) {  // 1 means class only one candidate, no need to handle priority, return directly.
221         return candidates.front();
222     }
223 
224     if (priorityScheme.GetPriorityType() == PriorityType::PRIORITY_TYPE_NULL) {
225         // no attribute priority policy, we only compare static priority
226         return SearchSimplePriority(candidates);
227     }
228 
229     PriorityType priorityType = priorityScheme.GetPriorityType();
230     const string &attrKey = priorityScheme.GetAttrKey();
231 
232     auto targetIter = candidates.begin();
233     // targetAttr is allowed to be empty.
234     // when the target ImplClass does not have this attribute, the value of targetAttr is null,
235     // and the subsequent priority comparison process will judge and handle this situation.
236     const AttrData *targetAttr = ((*targetIter)->GetCapability)(attrKey);
237 
238     auto tempIter = targetIter;
239     for (++tempIter; tempIter != candidates.end(); ++tempIter) {
240         const AttrData *attrData = ((*tempIter)->GetCapability)(attrKey);
241         if (attrData == nullptr) {
242             continue;
243         }
244 
245         if (targetAttr == nullptr) {
246             targetIter = tempIter;
247             targetAttr = attrData;
248             continue;
249         }
250 
251         // the result value is used later, the targetIter and targetAttr assignment structures cannot be merged,
252         // and the the merged logic will not understand well.
253         uint32_t result = ComparePriority(*attrData, *targetAttr, priorityType);
254         if (result == ERR_COMP_HIGHER) {
255             targetIter = tempIter;
256             targetAttr = attrData;
257             continue;
258         }
259 
260         // if the priority attribute are equal, we further compare the static priority.
261         if (result == ERR_COMP_EQUAL) {
262             if (((*tempIter)->GetPriority()) > ((*targetIter)->GetPriority())) {
263                 targetIter = tempIter;
264                 targetAttr = attrData;
265             }
266         }
267     }
268 
269     return *targetIter;
270 }
271 
SearchSimplePriority(const list<shared_ptr<ImplClass>> & candidates)272 shared_ptr<ImplClass> ImplClassMgr::SearchSimplePriority(const list<shared_ptr<ImplClass>> &candidates)
273 {
274     if (candidates.size() == 0) {
275         IMAGE_LOGE("SearchSimplePriority: candidates size is zero.");
276         return nullptr;
277     }
278     auto targetIter = candidates.begin();
279     auto tempIter = targetIter;
280 
281     for (++tempIter; tempIter != candidates.end(); ++tempIter) {
282         if (((*tempIter)->GetPriority()) > ((*targetIter)->GetPriority())) {
283             targetIter = tempIter;
284         }
285     }
286 
287     return *targetIter;
288 }
289 
ComparePriority(const AttrData & lhs,const AttrData & rhs,PriorityType type)290 uint32_t ImplClassMgr::ComparePriority(const AttrData &lhs, const AttrData &rhs, PriorityType type)
291 {
292     if (lhs.GetType() != rhs.GetType()) {
293         IMAGE_LOGE("compare between different types, %{public}d and %{public}d.", lhs.GetType(),
294             rhs.GetType());
295         return ERR_COMP_ERROR;
296     }
297 
298     switch (lhs.GetType()) {
299         case AttrDataType::ATTR_DATA_NULL: {
300             return ERR_COMP_EQUAL;
301         }
302         case AttrDataType::ATTR_DATA_BOOL: {
303             return CompareBoolPriority(lhs, rhs, type);
304         }
305         case AttrDataType::ATTR_DATA_UINT32:
306         case AttrDataType::ATTR_DATA_UINT32_SET:
307         case AttrDataType::ATTR_DATA_UINT32_RANGE: {
308             return CompareUint32Priority(lhs, rhs, type);
309         }
310         case AttrDataType::ATTR_DATA_STRING:
311         case AttrDataType::ATTR_DATA_STRING_SET: {
312             return CompareStringPriority(lhs, rhs, type);
313         }
314         default: {
315             IMAGE_LOGE("invalid data type: %{public}d.", lhs.GetType());
316             return ERR_COMP_ERROR;
317         }
318     }
319 }
320 
321 // for the bool type, the meaning of the size is unknown. we artificially define true greater than false here.
CompareBoolPriority(const AttrData & lhs,const AttrData & rhs,PriorityType type)322 uint32_t ImplClassMgr::CompareBoolPriority(const AttrData &lhs, const AttrData &rhs, PriorityType type)
323 {
324     bool lhsValue = false;
325     bool rhsValue = false;
326 
327     if ((lhs.GetValue(lhsValue) != SUCCESS) || (rhs.GetValue(rhsValue) != SUCCESS)) {
328         IMAGE_LOGE("CompareBoolPriority: failed to get attribute value.");
329         return ERR_COMP_ERROR;
330     }
331 
332     if (type == PriorityType::PRIORITY_ORDER_BY_ATTR_ASCENDING) {
333         if (lhsValue) {
334             if (!rhsValue) {
335                 return ERR_COMP_LOWER;
336             }
337             return ERR_COMP_EQUAL;
338         }
339 
340         if (rhsValue) {
341             return ERR_COMP_HIGHER;
342         }
343 
344         return ERR_COMP_EQUAL;
345     }
346 
347     if (lhsValue) {
348         if (!rhsValue) {
349             return ERR_COMP_HIGHER;
350         }
351         return ERR_COMP_EQUAL;
352     }
353 
354     if (rhsValue) {
355         return ERR_COMP_LOWER;
356     }
357 
358     return ERR_COMP_EQUAL;
359 }
360 
CompareUint32Priority(const AttrData & lhs,const AttrData & rhs,PriorityType type)361 uint32_t ImplClassMgr::CompareUint32Priority(const AttrData &lhs, const AttrData &rhs, PriorityType type)
362 {
363     uint32_t lhsValue = 0;
364     uint32_t rhsValue = 0;
365 
366     if (type == PriorityType::PRIORITY_ORDER_BY_ATTR_ASCENDING) {
367         if ((lhs.GetMinValue(lhsValue) != SUCCESS) || (rhs.GetMinValue(rhsValue) != SUCCESS)) {
368             IMAGE_LOGE("CompareUint32Priority: failed to get attribute min value.");
369             return ERR_COMP_ERROR;
370         }
371 
372         if (lhsValue < rhsValue) {
373             return ERR_COMP_HIGHER;
374         }
375 
376         if (lhsValue == rhsValue) {
377             return ERR_COMP_EQUAL;
378         }
379 
380         return ERR_COMP_LOWER;
381     }
382 
383     bool cond = (lhs.GetMaxValue(lhsValue) != SUCCESS) || (rhs.GetMaxValue(rhsValue) != SUCCESS);
384     CHECK_ERROR_RETURN_RET_LOG(cond, ERR_COMP_ERROR, "CompareUint32Priority: failed to get attribute max value.");
385 
386     if (lhsValue < rhsValue) {
387         return ERR_COMP_LOWER;
388     }
389 
390     if (lhsValue == rhsValue) {
391         return ERR_COMP_EQUAL;
392     }
393 
394     return ERR_COMP_HIGHER;
395 }
396 
CompareStringPriority(const AttrData & lhs,const AttrData & rhs,PriorityType type)397 uint32_t ImplClassMgr::CompareStringPriority(const AttrData &lhs, const AttrData &rhs, PriorityType type)
398 {
399     const string *lhsValue = nullptr;
400     const string *rhsValue = nullptr;
401 
402     if (type == PriorityType::PRIORITY_ORDER_BY_ATTR_ASCENDING) {
403         if ((lhs.GetMinValue(lhsValue) != SUCCESS) || (rhs.GetMinValue(rhsValue) != SUCCESS)) {
404             IMAGE_LOGE("CompareStringPriority: failed to get attribute min value.");
405             return ERR_COMP_ERROR;
406         }
407 
408         if (lhsValue == nullptr || rhsValue == nullptr) {
409             IMAGE_LOGE("CompareStringPriority: value is null.");
410             return ERR_COMP_ERROR;
411         }
412 
413         if (*lhsValue < *rhsValue) {
414             return ERR_COMP_HIGHER;
415         }
416 
417         if (*lhsValue == *rhsValue) {
418             return ERR_COMP_EQUAL;
419         }
420 
421         return ERR_COMP_LOWER;
422     }
423 
424     if ((lhs.GetMaxValue(lhsValue) != SUCCESS) || (rhs.GetMaxValue(rhsValue) != SUCCESS)) {
425         IMAGE_LOGE("CompareStringPriority: failed to get attribute max value.");
426         return ERR_COMP_ERROR;
427     }
428 
429     if (lhsValue == nullptr || rhsValue == nullptr) {
430         IMAGE_LOGE("CompareStringPriority: value is null.");
431         return ERR_COMP_ERROR;
432     }
433 
434     if (*lhsValue < *rhsValue) {
435         return ERR_COMP_LOWER;
436     }
437 
438     if (*lhsValue == *rhsValue) {
439         return ERR_COMP_EQUAL;
440     }
441 
442     return ERR_COMP_HIGHER;
443 }
444 } // namespace MultimediaPlugin
445 } // namespace OHOS
446