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