1 /*
2 * Copyright (c) 2021-2022 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 "componentloader/component_loader.h"
17
18 #include <cinttypes>
19 #include <dlfcn.h>
20 #include <fstream>
21 #include <string>
22
23 #include "nlohmann/json.hpp"
24
25 #include "constants.h"
26 #include "dh_context.h"
27 #include "dh_utils_hitrace.h"
28 #include "dh_utils_hisysevent.h"
29 #include "dh_utils_tool.h"
30 #include "hidump_helper.h"
31 #include "distributed_hardware_log.h"
32 #include "version_info.h"
33 #include "version_info_manager.h"
34 #include "version_manager.h"
35
36 using nlohmann::json;
37
38 namespace OHOS {
39 namespace DistributedHardware {
40 #undef DH_LOG_TAG
41 #define DH_LOG_TAG "ComponentLoader"
42
43 IMPLEMENT_SINGLE_INSTANCE(ComponentLoader);
44 using GetHardwareClass = IHardwareHandler *(*)();
45 using GetSourceHardwareClass = IDistributedHardwareSource *(*)();
46 using GetSinkHardwareClass = IDistributedHardwareSink *(*)();
47 namespace {
48 const std::string COMP_NAME = "name";
49 const std::string COMP_TYPE = "type";
50 const std::string COMP_HANDLER_LOC = "comp_handler_loc";
51 const std::string COMP_HANDLER_VERSION = "comp_handler_version";
52 const std::string COMP_SOURCE_LOC = "comp_source_loc";
53 const std::string COMP_SOURCE_VERSION = "comp_source_version";
54 const std::string COMP_SOURCE_SA_ID = "comp_source_sa_id";
55 const std::string COMP_SINK_LOC = "comp_sink_loc";
56 const std::string COMP_SINK_VERSION = "comp_sink_version";
57 const std::string COMP_SINK_SA_ID = "comp_sink_sa_id";
58
59 const std::string DEFAULT_NAME = "";
60 const std::string DEFAULT_TYPE = "UNKNOWN";
61 const std::string DEFAULT_LOC = "";
62 const int32_t DEFAULT_SA_ID = -1;
63 const std::string DEFAULT_VERSION = "1.0";
64
65 #ifdef __LP64__
66 const std::string LIB_LOAD_PATH = "/system/lib64/";
67 #else
68 const std::string LIB_LOAD_PATH = "/system/lib/";
69 #endif
70
71 std::map<std::string, DHType> g_mapDhTypeName = {
72 { "UNKNOWN", DHType::UNKNOWN },
73 { "CAMERA", DHType::CAMERA },
74 { "AUDIO", DHType::AUDIO },
75 { "SCREEN", DHType::SCREEN },
76 { "GPS", DHType::GPS },
77 { "INPUT", DHType::INPUT },
78 { "HFP", DHType::HFP },
79 { "A2D", DHType::A2D },
80 { "VIRMODEM_MIC", DHType::VIRMODEM_MIC },
81 { "VIRMODEM_SPEAKER", DHType::VIRMODEM_SPEAKER },
82 };
83 }
84
Init()85 int32_t ComponentLoader::Init()
86 {
87 DHLOGI("start");
88 DHTraceStart(COMPONENT_LOAD_START);
89 int32_t ret = ParseConfig();
90 StoreLocalDHVersionInDB();
91 DHTraceEnd();
92
93 return ret;
94 }
95
GetAllCompTypes()96 std::vector<DHType> ComponentLoader::GetAllCompTypes()
97 {
98 std::vector<DHType> DHTypeALL;
99 for (std::map<DHType, CompHandler>::iterator it = compHandlerMap_.begin(); it != compHandlerMap_.end(); ++it) {
100 DHTypeALL.push_back(it->first);
101 }
102 return DHTypeALL;
103 }
104
from_json(const nlohmann::json & json,CompConfig & cfg)105 void from_json(const nlohmann::json &json, CompConfig &cfg)
106 {
107 if (!IsString(json, COMP_NAME)) {
108 DHLOGE("COMP_NAME is invalid");
109 return;
110 }
111 cfg.name = json.at(COMP_NAME).get<std::string>();
112 if (!IsString(json, COMP_TYPE)) {
113 DHLOGE("COMP_TYPE is invalid");
114 return;
115 }
116 cfg.type = g_mapDhTypeName[json.at(COMP_TYPE).get<std::string>()];
117 if (!IsString(json, COMP_HANDLER_LOC)) {
118 DHLOGE("COMP_HANDLER_LOC is invalid");
119 return;
120 }
121 cfg.compHandlerLoc = json.at(COMP_HANDLER_LOC).get<std::string>();
122 if (!IsString(json, COMP_HANDLER_VERSION)) {
123 DHLOGE("COMP_HANDLER_VERSION is invalid");
124 return;
125 }
126 cfg.compHandlerVersion = json.at(COMP_HANDLER_VERSION).get<std::string>();
127 if (!IsString(json, COMP_SOURCE_LOC)) {
128 DHLOGE("COMP_SOURCE_LOC is invalid");
129 return;
130 }
131 cfg.compSourceLoc = json.at(COMP_SOURCE_LOC).get<std::string>();
132 if (!IsString(json, COMP_SOURCE_VERSION)) {
133 return;
134 }
135 cfg.compSourceVersion = json.at(COMP_SOURCE_VERSION).get<std::string>();
136 if (!IsInt32(json, COMP_SOURCE_SA_ID)) {
137 DHLOGE("COMP_SOURCE_SA_ID is invalid");
138 return;
139 }
140 cfg.compSourceSaId = json.at(COMP_SOURCE_SA_ID).get<int32_t>();
141 if (!IsString(json, COMP_SINK_LOC)) {
142 DHLOGE("COMP_SINK_LOC is invalid");
143 return;
144 }
145 cfg.compSinkLoc = json.at(COMP_SINK_LOC).get<std::string>();
146 if (!IsString(json, COMP_SINK_VERSION)) {
147 return;
148 }
149 cfg.compSinkVersion = json.at(COMP_SINK_VERSION).get<std::string>();
150 if (!IsInt32(json, COMP_SINK_SA_ID)) {
151 DHLOGE("COMP_SINK_SA_ID is invalid");
152 return;
153 }
154 cfg.compSinkSaId = json.at(COMP_SINK_SA_ID).get<int32_t>();
155 }
156
GetCompVersionFromComConfig(const CompConfig & cCfg)157 CompVersion ComponentLoader::GetCompVersionFromComConfig(const CompConfig& cCfg)
158 {
159 CompVersion compVersions;
160 compVersions.dhType = cCfg.type;
161 compVersions.name = cCfg.name;
162 compVersions.handlerVersion = cCfg.compHandlerVersion;
163 compVersions.sinkVersion = cCfg.compSinkVersion;
164 compVersions.sourceVersion = cCfg.compSourceVersion;
165 return compVersions;
166 }
167
GetCompPathAndVersion(const std::string & jsonStr,std::map<DHType,CompConfig> & dhtypeMap)168 int32_t ComponentLoader::GetCompPathAndVersion(const std::string &jsonStr, std::map<DHType, CompConfig> &dhtypeMap)
169 {
170 auto jsonCfg = json::parse(jsonStr, nullptr, false);
171 if (jsonCfg.is_discarded()) {
172 DHLOGE("jsonStr parse failed");
173 return ERR_DH_FWK_JSON_PARSE_FAILED;
174 }
175
176 if (jsonCfg.find(COMPONENTSLOAD_DISTRIBUTED_COMPONENTS) == jsonCfg.end()) {
177 DHLOGE("not find distributed_components");
178 return ERR_DH_FWK_PARA_INVALID;
179 }
180
181 std::vector<CompConfig> vecJsnCfg =
182 jsonCfg.at(COMPONENTSLOAD_DISTRIBUTED_COMPONENTS).get<std::vector<CompConfig>>();
183 DHLOGI("get distributed_components CompConfig size is %d", vecJsnCfg.size());
184 if (vecJsnCfg.size() == 0 || vecJsnCfg.size() > MAX_COMP_SIZE) {
185 DHLOGE("CompConfig size is invalid!");
186 return ERR_DH_FWK_PARA_INVALID;
187 }
188 for (auto iter = vecJsnCfg.begin(); iter != vecJsnCfg.end(); ++iter) {
189 dhtypeMap.insert(std::pair<DHType, CompConfig>((*iter).type, (*iter)));
190 localDHVersion_.compVersions.insert(
191 std::pair<DHType, CompVersion>((*iter).type, GetCompVersionFromComConfig(*iter)));
192 }
193 isLocalVersionInit_.store(true);
194 return DH_FWK_SUCCESS;
195 }
196
GetLocalDHVersion(DHVersion & dhVersion)197 int32_t ComponentLoader::GetLocalDHVersion(DHVersion &dhVersion)
198 {
199 if (!isLocalVersionInit_.load()) {
200 DHLOGE("get local DHVersion fail");
201 return ERR_DH_FWK_LOADER_GET_LOCAL_VERSION_FAIL;
202 }
203 dhVersion = localDHVersion_;
204 return DH_FWK_SUCCESS;
205 }
206
StoreLocalDHVersionInDB()207 void ComponentLoader::StoreLocalDHVersionInDB()
208 {
209 if (!isLocalVersionInit_.load()) {
210 DHLOGE("Store local DHVersion fail");
211 return;
212 }
213 VersionInfo versionInfo;
214 versionInfo.dhVersion = VersionManager::GetInstance().GetLocalDeviceVersion();
215 versionInfo.deviceId = DHContext::GetInstance().GetDeviceInfo().deviceId;
216 versionInfo.compVersions = localDHVersion_.compVersions;
217 VersionInfoManager::GetInstance()->AddVersion(versionInfo);
218 }
219
GetHandler(const std::string & soName)220 void *ComponentLoader::GetHandler(const std::string &soName)
221 {
222 char path[PATH_MAX + 1] = {0x00};
223 if (soName.length() == 0 || (LIB_LOAD_PATH.length() + soName.length()) > PATH_MAX ||
224 realpath((LIB_LOAD_PATH + soName).c_str(), path) == nullptr) {
225 DHLOGE("File canonicalization failed");
226 return nullptr;
227 }
228 void *pHandler = dlopen(path, RTLD_LAZY | RTLD_NODELETE);
229 if (pHandler == nullptr) {
230 DHLOGE("%s handler load failed, failed reason : %s", path, dlerror());
231 HiSysEventWriteMsg(DHFWK_INIT_FAIL, OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
232 "dhfwk so open failed, soname : " + soName);
233 return nullptr;
234 }
235 return pHandler;
236 }
237
GetAllHandler(std::map<DHType,CompConfig> & dhtypeMap)238 void ComponentLoader::GetAllHandler(std::map<DHType, CompConfig> &dhtypeMap)
239 {
240 std::map<DHType, CompConfig>::iterator itor;
241 for (itor = dhtypeMap.begin(); itor != dhtypeMap.end(); ++itor) {
242 CompHandler comHandler;
243 comHandler.type = itor->second.type;
244 comHandler.hardwareHandler = GetHandler(itor->second.compHandlerLoc);
245 comHandler.sourceHandler = GetHandler(itor->second.compSourceLoc);
246 comHandler.sourceSaId = itor->second.compSourceSaId;
247 comHandler.sinkHandler = GetHandler(itor->second.compSinkLoc);
248 comHandler.sinkSaId = itor->second.compSinkSaId;
249 compHandlerMap_[itor->second.type] = comHandler;
250 }
251 }
252
GetHardwareHandler(const DHType dhType,IHardwareHandler * & hardwareHandlerPtr)253 int32_t ComponentLoader::GetHardwareHandler(const DHType dhType, IHardwareHandler *&hardwareHandlerPtr)
254 {
255 if (compHandlerMap_.find(dhType) == compHandlerMap_.end()) {
256 DHLOGE("DHType not exist, dhType: %" PRIu32, (uint32_t)dhType);
257 return ERR_DH_FWK_LOADER_HANDLER_IS_NULL;
258 }
259
260 if (compHandlerMap_[dhType].hardwareHandler == nullptr) {
261 DHLOGE("hardwareHandler is null.");
262 return ERR_DH_FWK_LOADER_HANDLER_IS_NULL;
263 }
264
265 GetHardwareClass getHardwareClassHandler = (GetHardwareClass)dlsym(compHandlerMap_[dhType].hardwareHandler,
266 COMPONENT_LOADER_GET_HARDWARE_HANDLER.c_str());
267 if (getHardwareClassHandler == nullptr) {
268 DHLOGE("get getHardwareClassHandler is null, failed reason : %s", dlerror());
269 dlclose(compHandlerMap_[dhType].hardwareHandler);
270 compHandlerMap_[dhType].hardwareHandler = nullptr;
271 return ERR_DH_FWK_LOADER_HANDLER_IS_NULL;
272 }
273 hardwareHandlerPtr = getHardwareClassHandler();
274 return DH_FWK_SUCCESS;
275 }
276
GetSource(const DHType dhType,IDistributedHardwareSource * & sourcePtr)277 int32_t ComponentLoader::GetSource(const DHType dhType, IDistributedHardwareSource *&sourcePtr)
278 {
279 if (compHandlerMap_.find(dhType) == compHandlerMap_.end()) {
280 DHLOGE("DHType not exist, dhType: %" PRIu32, (uint32_t)dhType);
281 return ERR_DH_FWK_LOADER_HANDLER_IS_NULL;
282 }
283
284 if (compHandlerMap_[dhType].sourceHandler == nullptr) {
285 DHLOGE("sourceHandler is null.");
286 return ERR_DH_FWK_LOADER_HANDLER_IS_NULL;
287 }
288
289 GetSourceHardwareClass getSourceHardClassHandler = (GetSourceHardwareClass)dlsym(
290 compHandlerMap_[dhType].sourceHandler, COMPONENT_LOADER_GET_SOURCE_HANDLER.c_str());
291 if (getSourceHardClassHandler == nullptr) {
292 DHLOGE("get getSourceHardClassHandler is null, failed reason : %s", dlerror());
293 dlclose(compHandlerMap_[dhType].sourceHandler);
294 compHandlerMap_[dhType].sourceHandler = nullptr;
295 return ERR_DH_FWK_LOADER_HANDLER_IS_NULL;
296 }
297 sourcePtr = getSourceHardClassHandler();
298 return DH_FWK_SUCCESS;
299 }
300
GetSink(const DHType dhType,IDistributedHardwareSink * & sinkPtr)301 int32_t ComponentLoader::GetSink(const DHType dhType, IDistributedHardwareSink *&sinkPtr)
302 {
303 if (compHandlerMap_.find(dhType) == compHandlerMap_.end()) {
304 DHLOGE("DHType not exist, dhType: %" PRIu32, (uint32_t)dhType);
305 return ERR_DH_FWK_LOADER_HANDLER_IS_NULL;
306 }
307
308 if (compHandlerMap_[dhType].sinkHandler == nullptr) {
309 DHLOGE("sinkHandler is null.");
310 return ERR_DH_FWK_LOADER_HANDLER_IS_NULL;
311 }
312
313 GetSinkHardwareClass getSinkHardwareClassHandler =
314 (GetSinkHardwareClass)dlsym(compHandlerMap_[dhType].sinkHandler, COMPONENT_LOADER_GET_SINK_HANDLER.c_str());
315 if (getSinkHardwareClassHandler == nullptr) {
316 DHLOGE("get getSinkHardwareClassHandler is null, failed reason : %s", dlerror());
317 dlclose(compHandlerMap_[dhType].sinkHandler);
318 compHandlerMap_[dhType].sinkHandler = nullptr;
319 return ERR_DH_FWK_LOADER_HANDLER_IS_NULL;
320 }
321 sinkPtr = getSinkHardwareClassHandler();
322 return DH_FWK_SUCCESS;
323 }
324
Readfile(const std::string & filePath)325 std::string ComponentLoader::Readfile(const std::string &filePath)
326 {
327 std::ifstream infile;
328 std::string sLine;
329 std::string sAll = "";
330 infile.open(filePath);
331 if (!infile.is_open()) {
332 DHLOGE("filePath: %s Readfile fail", filePath.c_str());
333 return sAll;
334 }
335
336 while (getline(infile, sLine)) {
337 sAll.append(sLine);
338 }
339 infile.close();
340 return sAll;
341 }
342
ParseConfig()343 int32_t ComponentLoader::ParseConfig()
344 {
345 std::map<DHType, CompConfig> dhtypeMap;
346 int32_t ret;
347 DHLOGI("ParseConfig start");
348 std::string jsonStr = Readfile(COMPONENTSLOAD_PROFILE_PATH);
349 if (jsonStr.length() == 0 || jsonStr.size() > MAX_MESSAGE_LEN) {
350 DHLOGE("ConfigJson size is invalid!");
351 return ERR_DH_FWK_LOADER_CONFIG_JSON_INVALID;
352 }
353 ret = GetCompPathAndVersion(jsonStr, dhtypeMap);
354 if (ret != DH_FWK_SUCCESS) {
355 return ret;
356 }
357 GetAllHandler(dhtypeMap);
358 return DH_FWK_SUCCESS;
359 }
360
ReleaseHandler(void * & handler)361 int32_t ComponentLoader::ReleaseHandler(void *&handler)
362 {
363 if (handler == nullptr) {
364 DHLOGE("handler is null.");
365 return ERR_DH_FWK_LOADER_HANDLER_IS_NULL;
366 }
367
368 if (dlclose(handler) != 0) {
369 DHLOGE("dlclose failed.");
370 return ERR_DH_FWK_LOADER_DLCLOSE_FAIL;
371 }
372 handler = nullptr;
373 return DH_FWK_SUCCESS;
374 }
375
UnInit()376 int32_t ComponentLoader::UnInit()
377 {
378 DHLOGI("release all handler");
379 DHTraceStart(COMPONENT_RELEASE_START);
380 int32_t ret = DH_FWK_SUCCESS;
381 for (std::map<DHType, CompHandler>::iterator iter = compHandlerMap_.begin();
382 iter != compHandlerMap_.end(); ++iter) {
383 ret += ReleaseHardwareHandler(iter->first);
384 ret += ReleaseSource(iter->first);
385 ret += ReleaseSink(iter->first);
386 }
387 compHandlerMap_.clear();
388 DHTraceEnd();
389 return ret;
390 }
391
ReleaseHardwareHandler(const DHType dhType)392 int32_t ComponentLoader::ReleaseHardwareHandler(const DHType dhType)
393 {
394 if (!IsDHTypeExist(dhType)) {
395 return ERR_DH_FWK_TYPE_NOT_EXIST;
396 }
397 int32_t ret = ReleaseHandler(compHandlerMap_[dhType].hardwareHandler);
398 if (ret) {
399 DHLOGE("fail, dhType: %#X", dhType);
400 HiSysEventWriteReleaseMsg(DHFWK_RELEASE_FAIL, OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
401 dhType, ret, "dhfwk release hardware handler failed.");
402 }
403 return ret;
404 }
405
ReleaseSource(const DHType dhType)406 int32_t ComponentLoader::ReleaseSource(const DHType dhType)
407 {
408 if (!IsDHTypeExist(dhType)) {
409 return ERR_DH_FWK_TYPE_NOT_EXIST;
410 }
411 int32_t ret = ReleaseHandler(compHandlerMap_[dhType].sourceHandler);
412 if (ret) {
413 DHLOGE("fail, dhType: %#X", dhType);
414 HiSysEventWriteReleaseMsg(DHFWK_RELEASE_FAIL, OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
415 dhType, ret, "dhfwk release source failed.");
416 }
417 return ret;
418 }
419
ReleaseSink(const DHType dhType)420 int32_t ComponentLoader::ReleaseSink(const DHType dhType)
421 {
422 if (!IsDHTypeExist(dhType)) {
423 return ERR_DH_FWK_TYPE_NOT_EXIST;
424 }
425 int32_t ret = ReleaseHandler(compHandlerMap_[dhType].sinkHandler);
426 if (ret) {
427 DHLOGE("fail, dhType: %#X", dhType);
428 HiSysEventWriteReleaseMsg(DHFWK_RELEASE_FAIL, OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
429 dhType, ret, "dhfwk release sink failed.");
430 }
431 return ret;
432 }
433
IsDHTypeExist(DHType dhType)434 bool ComponentLoader::IsDHTypeExist(DHType dhType)
435 {
436 if (compHandlerMap_.find(dhType) == compHandlerMap_.end()) {
437 DHLOGE("fail, dhType: %#X not exist", dhType);
438 return false;
439 }
440 return true;
441 }
442
GetSourceSaId(const DHType dhType)443 int32_t ComponentLoader::GetSourceSaId(const DHType dhType)
444 {
445 if (compHandlerMap_.find(dhType) == compHandlerMap_.end()) {
446 DHLOGE("DHType not exist, dhType: %" PRIu32, (uint32_t)dhType);
447 return DEFAULT_SA_ID;
448 }
449 return compHandlerMap_[dhType].sourceSaId;
450 }
451
GetDHTypeBySrcSaId(const int32_t saId)452 DHType ComponentLoader::GetDHTypeBySrcSaId(const int32_t saId)
453 {
454 DHType type = DHType::UNKNOWN;
455 for (const auto &handler : compHandlerMap_) {
456 if (handler.second.sourceSaId == saId) {
457 type = handler.second.type;
458 break;
459 }
460 }
461 return type;
462 }
463 } // namespace DistributedHardware
464 } // namespace OHOS
465