1 /*
2 * Copyright (c) 2021-2023 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 #include "hiview_platform.h"
16 #ifndef _WIN32
17 #include <dlfcn.h>
18 #include <sys/stat.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21 #endif
22 #include <cinttypes>
23 #include <csignal>
24 #include <fstream>
25 #include <functional>
26
27 #include "audit.h"
28 #include "common_utils.h"
29 #include "defines.h"
30 #include "dynamic_module.h"
31 #include "file_util.h"
32 #include "hiview_event_report.h"
33 #include "hiview_global.h"
34 #include "hiview_platform_config.h"
35 #include "logger.h"
36 #include "parameter_ex.h"
37 #include "plugin_config.h"
38 #include "plugin_factory.h"
39 #include "string_util.h"
40 #include "time_util.h"
41
42 namespace OHOS {
43 namespace HiviewDFX {
44 namespace {
45 constexpr uint32_t AID_SYSTEM = 1000;
46 static const char VERSION[] = "1.0.0.0";
47 static const char SEPARATOR_VERSION[] = " ";
48 static const char RECORDER_VERSION[] = "01.00";
49 static const char PLUGIN_CONFIG_NAME[] = "plugin_config";
50 static const char HIVIEW_PID_FILE_NAME[] = "hiview.pid";
51 static const char DEFAULT_CONFIG_DIR[] = "/system/etc/hiview/";
52 static const char CHIPSET_HISYSEVENT_DEF_PATH[] = "/vendor/etc/hiview/hisysevent.def";
53 static const char PIPELINE_RULE_CONFIG_DIR[] = "/system/etc/hiview/dispatch_rule/";
54 static const char DISPATCH_RULE_CONFIG_DIR[] = "/system/etc/hiview/listener_rule/";
55 static const char DEFAULT_WORK_DIR[] = "/data/log/hiview/";
56 static const char DEFAULT_COMMERCIAL_WORK_DIR[] = "/log/LogService/";
57 static const char DEFAULT_PERSIST_DIR[] = "/log/hiview/";
58 static const char LIB_SEARCH_DIR[] = "/system/lib/";
59 static const char LIB64_SEARCH_DIR[] = "/system/lib64/";
60 }
61 DEFINE_LOG_TAG("HiView-HiviewPlatform");
HiviewPlatform()62 HiviewPlatform::HiviewPlatform()
63 : isReady_(false),
64 defaultConfigDir_(DEFAULT_CONFIG_DIR),
65 defaultWorkDir_(DEFAULT_WORK_DIR),
66 defaultCommercialWorkDir_(DEFAULT_COMMERCIAL_WORK_DIR),
67 defaultPersistDir_(DEFAULT_PERSIST_DIR),
68 defaultConfigName_(PLUGIN_CONFIG_NAME),
69 unorderQueue_(nullptr),
70 sharedWorkLoop_(nullptr)
71 {
72 dynamicLibSearchDir_.push_back(LIB_SEARCH_DIR);
73 dynamicLibSearchDir_.push_back(LIB64_SEARCH_DIR);
74 }
75
~HiviewPlatform()76 HiviewPlatform::~HiviewPlatform()
77 {
78 if (unorderQueue_ != nullptr) {
79 unorderQueue_->Stop();
80 }
81
82 if (sharedWorkLoop_ != nullptr) {
83 sharedWorkLoop_->StopLoop();
84 }
85 HiviewGlobal::ReleaseInstance();
86 }
87
SetMaxProxyIdleTime(time_t idleTime)88 void HiviewPlatform::SetMaxProxyIdleTime(time_t idleTime)
89 {
90 maxIdleTime_ = idleTime;
91 }
92
SetCheckProxyIdlePeriod(time_t period)93 void HiviewPlatform::SetCheckProxyIdlePeriod(time_t period)
94 {
95 checkIdlePeriod_ = period;
96 }
97
InitEnvironment(const std::string & platformConfigDir)98 bool HiviewPlatform::InitEnvironment(const std::string& platformConfigDir)
99 {
100 // wait util the samgr is ready
101 if (auto res = Parameter::WaitParamSync("bootevent.samgr.ready", "true", 5); res != 0) { // timeout is 5s
102 HIVIEW_LOGE("Fail to wait the samgr, err=%{public}d", res);
103 return false;
104 }
105 CreateWorkingDirectories(platformConfigDir);
106
107 // update beta config
108 UpdateBetaConfigIfNeed();
109
110 // check whether hiview is already started
111 ExitHiviewIfNeed();
112
113 std::string cfgPath = GetPluginConfigPath();
114 PluginConfig config(cfgPath);
115 if (!config.StartParse()) {
116 HIVIEW_LOGE("Fail to parse plugin config. exit!, cfgPath %{public}s", cfgPath.c_str());
117 return false;
118 }
119 StartPlatformDispatchQueue();
120
121 // init global context helper, remove in the future
122 HiviewGlobal::CreateInstance(static_cast<HiviewContext&>(*this));
123 InitSysEventParser();
124 LoadBusinessPlugin(config);
125
126 // start load plugin bundles
127 LoadPluginBundles();
128
129 // maple delay start eventsource
130 for (const auto& plugin : eventSourceList_) {
131 auto sharedSource = std::static_pointer_cast<EventSource>(plugin);
132 if (sharedSource == nullptr) {
133 HIVIEW_LOGE("Fail to cast plugin to event source!");
134 continue;
135 }
136 StartEventSource(sharedSource);
137 }
138 eventSourceList_.clear();
139 isReady_ = true;
140 NotifyPluginReady();
141 ScheduleCheckUnloadablePlugins();
142 return true;
143 }
144
CreateWorkingDirectories(const std::string & platformConfigDir)145 void HiviewPlatform::CreateWorkingDirectories(const std::string& platformConfigDir)
146 {
147 HiviewPlatformConfig platformConfig = HiviewPlatformConfig(platformConfigDir);
148 HiviewPlatformConfig::PlatformConfigInfo platformConfigInfo;
149 bool state = platformConfig.ParsesConfig(platformConfigInfo);
150 if (state) {
151 if (platformConfigInfo.defaultPluginConfigName != "") {
152 defaultConfigName_ = platformConfigInfo.defaultPluginConfigName;
153 }
154 if (FileUtil::IsDirectory(platformConfigInfo.commercialWorkDir)) {
155 defaultCommercialWorkDir_ = platformConfigInfo.commercialWorkDir;
156 }
157 if (platformConfigInfo.dynamicLib64SearchDir != ""
158 || platformConfigInfo.dynamicLibSearchDir != "") {
159 dynamicLibSearchDir_.clear();
160 }
161 if (platformConfigInfo.dynamicLib64SearchDir != "") {
162 dynamicLibSearchDir_.push_back(platformConfigInfo.dynamicLib64SearchDir);
163 }
164 if (platformConfigInfo.dynamicLibSearchDir != "") {
165 dynamicLibSearchDir_.push_back(platformConfigInfo.dynamicLibSearchDir);
166 }
167 ValidateAndCreateDirectories(platformConfigInfo.pluginConfigFileDir,
168 platformConfigInfo.workDir,
169 platformConfigInfo.persistDir);
170 }
171 }
172
InitSysEventParser()173 void HiviewPlatform::InitSysEventParser()
174 {
175 if (sysEventParser_ == nullptr) {
176 std::string systemDefineFile = (defaultConfigDir_.back() != '/') ? (defaultConfigDir_ + "/hisysevent.def") :
177 (defaultConfigDir_ + "hisysevent.def");
178 HIVIEW_LOGI("path of hisysevent.def for system components is %{public}s", systemDefineFile.c_str());
179 std::vector<std::string> allDefineFiles;
180 allDefineFiles.emplace_back(systemDefineFile);
181 allDefineFiles.emplace_back(CHIPSET_HISYSEVENT_DEF_PATH);
182 HIVIEW_LOGI("path of hisysevent.def for chipset components is %{public}s", CHIPSET_HISYSEVENT_DEF_PATH);
183 sysEventParser_ = std::make_shared<EventJsonParser>(allDefineFiles);
184 }
185 }
186
UpdateBetaConfigIfNeed()187 void HiviewPlatform::UpdateBetaConfigIfNeed()
188 {
189 }
190
LoadBusinessPlugin(const PluginConfig & config)191 void HiviewPlatform::LoadBusinessPlugin(const PluginConfig& config)
192 {
193 // start to load plugin
194 // 1. create plugin
195 auto const& pluginInfoList = config.GetPluginInfoList();
196 for (auto const& pluginInfo : pluginInfoList) {
197 HIVIEW_LOGI("Start to create plugin %{public}s delay:%{public}d", pluginInfo.name.c_str(),
198 pluginInfo.loadDelay);
199 if (pluginInfo.loadDelay > 0) {
200 auto task = std::bind(&HiviewPlatform::ScheduleCreateAndInitPlugin, this, pluginInfo);
201 sharedWorkLoop_->AddTimerEvent(nullptr, nullptr, task, pluginInfo.loadDelay, false);
202 } else {
203 CreatePlugin(pluginInfo);
204 }
205 }
206 // 2. create pipelines
207 auto const& pipelineInfoList = config.GetPipelineInfoList();
208 for (auto const& pipelineInfo : pipelineInfoList) {
209 HIVIEW_LOGI("Start to create pipeline %{public}s", pipelineInfo.name.c_str());
210 CreatePipeline(pipelineInfo);
211 }
212
213 // 3. bind pipeline and call onload of event source
214 for (auto const& pluginInfo : pluginInfoList) {
215 HIVIEW_LOGI("Start to Load plugin %{public}s", pluginInfo.name.c_str());
216 InitPlugin(config, pluginInfo);
217 }
218
219 // 4. delay start EventSource
220 for (auto const& pluginInfo : pluginInfoList) {
221 if (pluginInfo.isEventSource) {
222 HIVIEW_LOGI("Start to Load eventSource %{public}s", pluginInfo.name.c_str());
223 auto& plugin = pluginMap_[pluginInfo.name];
224 auto sharedSource = std::static_pointer_cast<EventSource>(plugin);
225 if (sharedSource == nullptr) {
226 HIVIEW_LOGE("Fail to cast plugin to event source!");
227 continue;
228 }
229 eventSourceList_.push_back(plugin);
230 }
231 }
232
233 CleanupUnusedResources();
234 }
235
SplitBundleNameFromPath(const std::string & filePath)236 std::string HiviewPlatform::SplitBundleNameFromPath(const std::string& filePath)
237 {
238 // the path should be like /system/etc/hiview/bundleName_plugin_config
239 auto pos = filePath.find_last_of("/\\");
240 if (pos == std::string::npos) {
241 return "";
242 }
243
244 std::string fileName = filePath.substr(pos + 1);
245 pos = fileName.find(defaultConfigName_);
246 if (pos == std::string::npos || pos == 0) {
247 return "";
248 }
249
250 pos = fileName.find_first_of("_");
251 if (pos == std::string::npos) {
252 return "";
253 }
254
255 return fileName.substr(0, pos);
256 }
257
SearchPluginBundle(const std::string & name) const258 std::string HiviewPlatform::SearchPluginBundle(const std::string& name) const
259 {
260 for (const auto& pathPrefix : dynamicLibSearchDir_) {
261 std::string bundlePath = pathPrefix + GetDynamicLibName(name, true);
262 printf("bundlePath is %s\n", bundlePath.c_str());
263 if (FileUtil::FileExists(bundlePath)) {
264 return bundlePath;
265 }
266 }
267 return "";
268 }
269
LoadPluginBundle(const std::string & bundleName,const std::string & filePath)270 void HiviewPlatform::LoadPluginBundle(const std::string& bundleName, const std::string& filePath)
271 {
272 PluginConfig config(filePath);
273 if (!config.StartParse()) {
274 HIVIEW_LOGE("Fail to parse plugin config %{public}s, filePath is %{public}s",
275 bundleName.c_str(), filePath.c_str());
276 return;
277 }
278
279 std::string bundlePath = SearchPluginBundle(bundleName);
280 if (bundlePath == "") {
281 HIVIEW_LOGE("bundleName: %{public}s doesn't exist", bundleName.c_str());
282 return;
283 }
284 auto handle = LoadModule(bundlePath);
285 if (handle == DynamicModuleDefault) {
286 return;
287 }
288
289 LoadBusinessPlugin(config);
290 std::shared_ptr<PluginBundle> bundle = std::make_shared<PluginBundle>(bundleName, config, handle);
291 pluginBundleInfos_.insert(std::pair<std::string, std::shared_ptr<PluginBundle>>(bundleName, bundle));
292 }
293
LoadPluginBundles()294 void HiviewPlatform::LoadPluginBundles()
295 {
296 std::vector<std::string> configFiles;
297 FileUtil::GetDirFiles(defaultConfigDir_, configFiles);
298 for (const auto& filePath : configFiles) {
299 auto bundleName = SplitBundleNameFromPath(filePath);
300 if (bundleName.empty()) {
301 continue;
302 }
303 LoadPluginBundle(bundleName, filePath);
304 }
305 }
306
ProcessArgsRequest(int argc,char * argv[])307 void HiviewPlatform::ProcessArgsRequest(int argc, char* argv[])
308 {
309 #ifndef _WIN32
310 umask(0002); // 0002 is block other write permissions, -------w-
311 signal(SIGPIPE, SIG_IGN);
312 int ch = -1;
313 while ((ch = getopt(argc, argv, "v")) != -1) {
314 if (ch == 'v') {
315 HIVIEW_LOGI("hiview version: %s%s%s", VERSION, SEPARATOR_VERSION,
316 RECORDER_VERSION);
317 printf("hiview version: %s%s%s\n", VERSION, SEPARATOR_VERSION, RECORDER_VERSION);
318 _exit(1);
319 }
320 }
321 #endif // !_WIN32
322 }
323
LoadDynamicPlugin(const std::string & name) const324 DynamicModule HiviewPlatform::LoadDynamicPlugin(const std::string& name) const
325 {
326 // if the plugin Class is AbcPlugin, the so name should be libabcplugin.z.so
327 std::string dynamicPluginName = GetDynamicLibName(name, true);
328 auto handle = LoadModule(dynamicPluginName.c_str());
329 if (handle == nullptr) {
330 // retry load library
331 dynamicPluginName = GetDynamicLibName(name, false);
332 handle = LoadModule(dynamicPluginName.c_str());
333 }
334 return handle;
335 }
336
GetDynamicLibName(const std::string & name,bool hasOhosSuffix) const337 std::string HiviewPlatform::GetDynamicLibName(const std::string& name, bool hasOhosSuffix) const
338 {
339 #ifdef __HIVIEW_OHOS__
340 std::string tmp = "lib" + name;
341 if (hasOhosSuffix) {
342 tmp.append(".z.so");
343 } else {
344 tmp.append(".so");
345 }
346
347 for (unsigned i = 0; i < tmp.length(); i++) {
348 tmp[i] = std::tolower(tmp[i]);
349 }
350 return tmp;
351 #elif defined(_WIN32)
352 std::string dynamicLibName = "";
353 dynamicLibName.append(name);
354 dynamicLibName.append(".dll");
355 return dynamicLibName;
356 #else
357 // dynamic plugins feature is only enabled in double framework version
358 (void)hasOhosSuffix;
359 HIVIEW_LOGI("could not load dynamic lib %s, not supported yet.", name.c_str());
360 return "";
361 #endif
362 }
363
CreatePlugin(const PluginConfig::PluginInfo & pluginInfo)364 void HiviewPlatform::CreatePlugin(const PluginConfig::PluginInfo& pluginInfo)
365 {
366 if (pluginInfo.name.empty()) {
367 return;
368 }
369 if (pluginMap_.find(pluginInfo.name) != pluginMap_.end()) {
370 HiviewEventReport::ReportPluginLoad(pluginInfo.name, PluginEventSpace::LOAD_DUPLICATE_NAME);
371 HIVIEW_LOGW("plugin %{public}s already exists! create plugin failed", pluginInfo.name.c_str());
372 return;
373 }
374 // the dynamic plugin will register it's constructor to factory automatically after opening the binary
375 // if we get null in factory, it means something must go wrong.
376 DynamicModule handle = DynamicModuleDefault;
377 if (!pluginInfo.isStatic) {
378 handle = LoadDynamicPlugin(pluginInfo.name);
379 }
380
381 std::shared_ptr<PluginRegistInfo> registInfo = PluginFactory::GetGlobalPluginInfo(pluginInfo.name);
382 if (registInfo == nullptr) {
383 HiviewEventReport::ReportPluginLoad(pluginInfo.name, PluginEventSpace::LOAD_UNREGISTERED);
384 if (handle != DynamicModuleDefault) {
385 UnloadModule(handle);
386 }
387 return;
388 }
389
390 std::shared_ptr<Plugin> plugin = nullptr;
391 if (registInfo->needCreateProxy) {
392 plugin = std::make_shared<PluginProxy>();
393 plugin->SetType(Plugin::PluginType::PROXY);
394 (std::static_pointer_cast<PluginProxy>(plugin))->SetPluginConfig(pluginInfo);
395 } else {
396 plugin = registInfo->getPluginObject();
397 }
398
399 // Initialize plugin parameters
400 plugin->SetName(pluginInfo.name);
401 plugin->SetHandle(handle);
402 plugin->SetHiviewContext(this);
403
404 // call preload, check whether we should release at once
405 if (!plugin->ReadyToLoad()) {
406 // if the plugin is a dynamic loaded library, the handle will be closed when calling the destructor
407 return;
408 }
409 // hold the global reference of the plugin
410 pluginMap_[pluginInfo.name] = std::move(plugin);
411 HiviewEventReport::ReportPluginLoad(pluginInfo.name, PluginEventSpace::LOAD_SUCCESS);
412 }
413
CreatePipeline(const PluginConfig::PipelineInfo & pipelineInfo)414 void HiviewPlatform::CreatePipeline(const PluginConfig::PipelineInfo& pipelineInfo)
415 {
416 if (pipelines_.find(pipelineInfo.name) != pipelines_.end()) {
417 HIVIEW_LOGW("pipeline %{public}s already exists! create pipeline failed", pipelineInfo.name.c_str());
418 return;
419 }
420
421 std::list<std::weak_ptr<Plugin>> pluginList;
422 for (auto& pluginName : pipelineInfo.pluginNameList) {
423 if (pluginMap_.find(pluginName) == pluginMap_.end()) {
424 HIVIEW_LOGI("could not find plugin(%{public}s), skip adding to pipeline(%{public}s).",
425 pluginName.c_str(), pipelineInfo.name.c_str());
426 continue;
427 }
428 pluginList.push_back(pluginMap_[pluginName]);
429 }
430 std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>(pipelineInfo.name, pluginList);
431 std::string pipelineConfigPath = PIPELINE_RULE_CONFIG_DIR + pipelineInfo.name;
432 HIVIEW_LOGI("pipelineConfigPath = %{public}s", pipelineConfigPath.c_str());
433 if (FileUtil::FileExists(pipelineConfigPath)) {
434 HiviewRuleParser ruleParser(pipelineConfigPath);
435 pipelineRules_[pipelineInfo.name] = ruleParser.getRule();
436 }
437 pipelines_[pipelineInfo.name] = std::move(pipeline);
438 }
439
InitPlugin(const PluginConfig & config __UNUSED,const PluginConfig::PluginInfo & pluginInfo)440 void HiviewPlatform::InitPlugin(const PluginConfig& config __UNUSED, const PluginConfig::PluginInfo& pluginInfo)
441 {
442 if (pluginMap_.find(pluginInfo.name) == pluginMap_.end()) {
443 return;
444 }
445 auto& plugin = pluginMap_[pluginInfo.name];
446
447 if (pluginInfo.workHandlerType == "thread") {
448 auto workLoop = GetAvaliableWorkLoop(pluginInfo.workHandlerName);
449 plugin->BindWorkLoop(workLoop);
450 }
451
452 auto begin = TimeUtil::GenerateTimestamp();
453 plugin->OnLoad();
454 std::string dispatchConfiPath = DISPATCH_RULE_CONFIG_DIR + pluginInfo.name;
455 if (FileUtil::FileExists(dispatchConfiPath)) {
456 HiviewRuleParser ruleParser(dispatchConfiPath);
457 auto dispatchConfig = ruleParser.getRule();
458 AddDispatchInfo(std::weak_ptr<Plugin>(plugin), dispatchConfig->typeList, dispatchConfig->eventList,
459 dispatchConfig->tagList, dispatchConfig->domainRuleMap);
460 }
461 if (pluginInfo.isEventSource) {
462 auto sharedSource = std::static_pointer_cast<EventSource>(plugin);
463 if (sharedSource == nullptr) {
464 HIVIEW_LOGE("Fail to cast plugin to event source!");
465 return;
466 }
467 for (auto& pipelineName : pluginInfo.pipelineNameList) {
468 sharedSource->AddPipeline(pipelines_[pipelineName]);
469 }
470 }
471
472 std::shared_ptr<PluginRegistInfo> registInfo = PluginFactory::GetGlobalPluginInfo(pluginInfo.name);
473 if (plugin->GetType() == Plugin::PluginType::PROXY && registInfo->needStartupLoading) {
474 std::shared_ptr<PluginProxy> pluginProxy = std::static_pointer_cast<PluginProxy>(plugin);
475 pluginProxy->LoadPluginIfNeed();
476 }
477
478 auto end = TimeUtil::GenerateTimestamp();
479 HIVIEW_LOGI("Plugin %{public}s loadtime:%{public}" PRIu64 ".", pluginInfo.name.c_str(), end - begin);
480 }
481
NotifyPluginReady()482 void HiviewPlatform::NotifyPluginReady()
483 {
484 auto event = std::make_shared<Event>("platform");
485 event->messageType_ = Event::MessageType::PLUGIN_MAINTENANCE;
486 event->eventId_ = Event::EventId::PLUGIN_LOADED;
487 PostUnorderedEvent(nullptr, event);
488 }
489
StartEventSource(std::shared_ptr<EventSource> source)490 void HiviewPlatform::StartEventSource(std::shared_ptr<EventSource> source)
491 {
492 auto workLoop = source->GetWorkLoop();
493 auto name = source->GetName();
494 if (workLoop == nullptr) {
495 HIVIEW_LOGW("No work loop available, start event source[%s] in current thead!", name.c_str());
496 source->StartEventSource();
497 } else {
498 HIVIEW_LOGI("Start event source[%s] in thead[%s].", name.c_str(), workLoop->GetName().c_str());
499 auto task = std::bind(&EventSource::StartEventSource, source.get());
500 workLoop->AddEvent(nullptr, nullptr, task);
501 }
502 HIVIEW_LOGI("Start event source[%s] in current thead done.", name.c_str());
503 }
504
505 // only call from main thread
GetAvaliableWorkLoop(const std::string & name)506 std::shared_ptr<EventLoop> HiviewPlatform::GetAvaliableWorkLoop(const std::string& name)
507 {
508 auto it = privateWorkLoopMap_.find(name);
509 if (it != privateWorkLoopMap_.end()) {
510 return it->second;
511 }
512
513 auto privateLoop = std::make_shared<EventLoop>(name);
514 if (privateLoop != nullptr) {
515 privateWorkLoopMap_.insert(std::make_pair(name, privateLoop));
516 privateLoop->StartLoop();
517 }
518 return privateLoop;
519 }
520
CleanupUnusedResources()521 void HiviewPlatform::CleanupUnusedResources()
522 {
523 auto iter = pluginMap_.begin();
524 while (iter != pluginMap_.end()) {
525 if (iter->second == nullptr) {
526 iter = pluginMap_.erase(iter);
527 } else {
528 ++iter;
529 }
530 }
531 }
532
ScheduleCreateAndInitPlugin(const PluginConfig::PluginInfo & pluginInfo)533 void HiviewPlatform::ScheduleCreateAndInitPlugin(const PluginConfig::PluginInfo& pluginInfo)
534 {
535 // only support thread type
536 CreatePlugin(pluginInfo);
537 if (pluginMap_.find(pluginInfo.name) == pluginMap_.end()) {
538 return;
539 }
540 auto& plugin = pluginMap_[pluginInfo.name];
541
542 if (pluginInfo.workHandlerType == "thread") {
543 auto workLoop = GetAvaliableWorkLoop(pluginInfo.workHandlerName);
544 plugin->BindWorkLoop(workLoop);
545 }
546 plugin->OnLoad();
547 }
548
StartLoop()549 void HiviewPlatform::StartLoop()
550 {
551 // empty implementation
552 }
553
StartPlatformDispatchQueue()554 void HiviewPlatform::StartPlatformDispatchQueue()
555 {
556 if (unorderQueue_ == nullptr) {
557 unorderQueue_ = std::make_unique<EventDispatchQueue>("plat_unorder", Event::ManageType::UNORDERED, this);
558 unorderQueue_->Start();
559 }
560
561 if (sharedWorkLoop_ == nullptr) {
562 sharedWorkLoop_ = std::make_shared<EventLoop>("plat_shared");
563 sharedWorkLoop_->StartLoop();
564 }
565 }
566
GetPipelineSequenceByName(const std::string & name)567 std::list<std::weak_ptr<Plugin>> HiviewPlatform::GetPipelineSequenceByName(const std::string& name)
568 {
569 if (!isReady_) {
570 return std::list<std::weak_ptr<Plugin>>();
571 }
572
573 auto it = pipelines_.find(name);
574 if (it != pipelines_.end()) {
575 return it->second->GetProcessSequence();
576 }
577 return std::list<std::weak_ptr<Plugin>>(0);
578 }
579
PostUnorderedEvent(std::shared_ptr<Plugin> plugin,std::shared_ptr<Event> event)580 void HiviewPlatform::PostUnorderedEvent(std::shared_ptr<Plugin> plugin, std::shared_ptr<Event> event)
581 {
582 if (!isReady_) {
583 return;
584 }
585
586 if (plugin == nullptr) {
587 HIVIEW_LOGI("maybe platform send event");
588 }
589
590 if (unorderQueue_ != nullptr && event != nullptr) {
591 event->processType_ = Event::ManageType::UNORDERED;
592 unorderQueue_->Enqueue(event);
593 }
594 }
595
RegisterUnorderedEventListener(std::weak_ptr<EventListener> listener)596 void HiviewPlatform::RegisterUnorderedEventListener(std::weak_ptr<EventListener> listener)
597 {
598 auto ptr = listener.lock();
599 if (ptr == nullptr) {
600 return;
601 }
602 auto name = ptr->GetListenerName();
603 auto itListenerInfo = listeners_.find(name);
604 if (itListenerInfo == listeners_.end()) {
605 auto tmp = std::make_shared<ListenerInfo>();
606 tmp->listener_ = listener;
607 listeners_[name] = tmp;
608 } else {
609 auto tmp = listeners_[name];
610 tmp->listener_ = listener;
611 }
612 }
613
PostSyncEventToTarget(std::shared_ptr<Plugin> caller,const std::string & calleeName,std::shared_ptr<Event> event)614 bool HiviewPlatform::PostSyncEventToTarget(std::shared_ptr<Plugin> caller, const std::string& calleeName,
615 std::shared_ptr<Event> event)
616 {
617 if (!isReady_) {
618 return false;
619 }
620
621 auto it = pluginMap_.find(calleeName);
622 if (it == pluginMap_.end()) {
623 return false;
624 }
625
626 auto callee = it->second;
627 if (callee == nullptr) {
628 return false;
629 }
630
631 auto workLoop = callee->GetWorkLoop();
632 std::future<bool> ret;
633 if (workLoop == nullptr) {
634 ret = sharedWorkLoop_->AddEventForResult(callee, event);
635 } else {
636 ret = workLoop->AddEventForResult(callee, event);
637 }
638 return ret.get();
639 }
640
PostAsyncEventToTarget(std::shared_ptr<Plugin> caller,const std::string & calleeName,std::shared_ptr<Event> event)641 void HiviewPlatform::PostAsyncEventToTarget(std::shared_ptr<Plugin> caller, const std::string& calleeName,
642 std::shared_ptr<Event> event)
643 {
644 if (!isReady_) {
645 return;
646 }
647
648 auto it = pluginMap_.find(calleeName);
649 if (it == pluginMap_.end()) {
650 return;
651 }
652
653 auto callee = it->second;
654 if (callee == nullptr) {
655 return;
656 }
657
658 auto workLoop = callee->GetWorkLoop();
659 if (workLoop == nullptr) {
660 sharedWorkLoop_->AddEvent(callee, event);
661 } else {
662 workLoop->AddEvent(callee, event);
663 }
664 HIVIEW_LOGI("Post async event to %{public}s successfully", calleeName.c_str());
665 }
666
GetSharedWorkLoop()667 std::shared_ptr<EventLoop> HiviewPlatform::GetSharedWorkLoop()
668 {
669 return sharedWorkLoop_;
670 }
671
IsReady()672 bool HiviewPlatform::IsReady()
673 {
674 return isReady_;
675 }
676
RequestUnloadPlugin(std::shared_ptr<Plugin> caller)677 void HiviewPlatform::RequestUnloadPlugin(std::shared_ptr<Plugin> caller)
678 {
679 if (caller == nullptr) {
680 HiviewEventReport::ReportPluginUnload("", PluginEventSpace::UNLOAD_INVALID);
681 return;
682 }
683
684 std::string name = caller->GetName();
685 auto task = std::bind(&HiviewPlatform::UnloadPlugin, this, name);
686 // delay 1s to unload target plugin
687 const int unloadDelay = 1;
688 sharedWorkLoop_->AddTimerEvent(nullptr, nullptr, task, unloadDelay, false);
689 }
690
UnloadPlugin(const std::string & name)691 void HiviewPlatform::UnloadPlugin(const std::string& name)
692 {
693 auto it = pluginMap_.find(name);
694 if (it == pluginMap_.end()) {
695 HiviewEventReport::ReportPluginUnload(name, PluginEventSpace::UNLOAD_NOT_FOUND);
696 return;
697 }
698
699 auto target = it->second;
700 if (target == nullptr) {
701 return;
702 }
703
704 auto count = target.use_count();
705 // two counts for 1.current ref 2.map holder ref
706 if (count > 2) {
707 HIVIEW_LOGW("Plugin %{public}s has more refs(%l{public}d), may caused by unfinished task. unload failed.",
708 name.c_str(), count);
709 HiviewEventReport::ReportPluginUnload(name, PluginEventSpace::UNLOAD_IN_USE);
710 return;
711 }
712
713 pluginMap_.erase(name);
714 target->OnUnload();
715 HiviewEventReport::ReportPluginUnload(name, PluginEventSpace::UNLOAD_SUCCESS);
716 auto looper = target->GetWorkLoop();
717 if (looper == nullptr) {
718 return;
719 }
720
721 auto looperName = looper->GetName();
722 // three counts for 1.current ref 2.plugin ref 3.map holder ref
723 if (looper.use_count() <= 3) {
724 HIVIEW_LOGI("%s has refs(%ld).", looperName.c_str(), looper.use_count());
725 looper->StopLoop();
726 privateWorkLoopMap_.erase(looperName);
727 HIVIEW_LOGI("Stop %s done.", looperName.c_str());
728 }
729
730 if (target->GetType() == Plugin::PluginType::DYNAMIC) {
731 // remove static register before closing the dynamic library handle
732 PluginFactory::UnregisterPlugin(target->GetName());
733 }
734 }
735
GetHiViewDirectory(HiviewContext::DirectoryType type)736 std::string HiviewPlatform::GetHiViewDirectory(HiviewContext::DirectoryType type)
737 {
738 switch (type) {
739 case HiviewContext::DirectoryType::CONFIG_DIRECTORY:
740 return defaultConfigDir_;
741 case HiviewContext::DirectoryType::WORK_DIRECTORY:
742 return defaultWorkDir_;
743 case HiviewContext::DirectoryType::PERSIST_DIR:
744 return defaultPersistDir_;
745 default:
746 break;
747 }
748 return "";
749 }
750
ValidateAndCreateDirectory(std::string & defaultPath,const std::string & realPath)751 void HiviewPlatform::ValidateAndCreateDirectory(std::string& defaultPath, const std::string& realPath)
752 {
753 if (defaultPath != realPath) {
754 defaultPath = realPath;
755 }
756 if (FileUtil::IsDirectory(defaultPath)) {
757 return;
758 }
759 FileUtil::CreateDirWithDefaultPerm(defaultPath, AID_SYSTEM, AID_SYSTEM);
760 }
761
ValidateAndCreateDirectories(const std::string & localPath,const std::string & workPath,const std::string & persistPath)762 void HiviewPlatform::ValidateAndCreateDirectories(const std::string& localPath, const std::string& workPath,
763 const std::string& persistPath)
764 {
765 ValidateAndCreateDirectory(defaultConfigDir_, localPath);
766 ValidateAndCreateDirectory(defaultWorkDir_, workPath);
767 ValidateAndCreateDirectory(defaultPersistDir_, persistPath);
768 }
769
770 #ifndef _WIN32
ExitHiviewIfNeed()771 void HiviewPlatform::ExitHiviewIfNeed()
772 {
773 int selfPid = getpid();
774 std::string selfProcName = CommonUtils::GetProcNameByPid(selfPid);
775 if (selfProcName != "hiview") {
776 return;
777 }
778
779 std::string pidFile = defaultWorkDir_ + "/" + std::string(HIVIEW_PID_FILE_NAME);
780 if (!FileUtil::FileExists(pidFile)) {
781 return;
782 }
783
784 std::string content;
785 FileUtil::LoadStringFromFile(pidFile, content);
786 int32_t pid = -1;
787 if (!StringUtil::StrToInt(content, pid)) {
788 return;
789 }
790
791 std::string procName = CommonUtils::GetProcNameByPid(pid);
792 if (procName == "hiview") {
793 printf("Hiview is already started, exit! \n");
794 exit(1);
795 }
796 FileUtil::SaveStringToFile(pidFile, std::to_string(selfPid));
797 }
798 #else
ExitHiviewIfNeed()799 void HiviewPlatform::ExitHiviewIfNeed()
800 {
801 }
802 #endif
803
GetPluginConfigPath()804 std::string HiviewPlatform::GetPluginConfigPath()
805 {
806 return defaultConfigDir_ + defaultConfigName_;
807 }
808
PublishPluginCapacity(PluginCapacityInfo & pluginCapacityInfo)809 void HiviewPlatform::PublishPluginCapacity(PluginCapacityInfo& pluginCapacityInfo)
810 {
811 auto it = pluginMap_.find(DISTRIBUTED_COMMUNICATOR_PLUGIN);
812 if (it == pluginMap_.end()) {
813 return;
814 }
815 auto callee = it->second;
816 if (callee == nullptr) {
817 return;
818 }
819 auto event = std::make_shared<CapacityPublishEvent>(pluginCapacityInfo.name_, pluginCapacityInfo);
820 event->messageType_ = Event::MessageType::CROSS_PLATFORM;
821 event->eventId_ = CapacityEventId::CAP_PUBLISH;
822 auto eventParent = std::dynamic_pointer_cast<Event>(event);
823 callee->OnEvent(eventParent);
824 }
825
GetRemoteByCapacity(const std::string & plugin,const std::string & capacity,std::list<std::string> & deviceIdList)826 void HiviewPlatform::GetRemoteByCapacity(const std::string& plugin, const std::string& capacity,
827 std::list<std::string>& deviceIdList)
828 {
829 auto it = pluginMap_.find(DISTRIBUTED_COMMUNICATOR_PLUGIN);
830 if (it == pluginMap_.end()) {
831 return;
832 }
833 auto callee = it->second;
834 if (callee == nullptr) {
835 return;
836 }
837 auto event = std::make_shared<CapacityObtainEvent>(plugin, capacity);
838 event->messageType_ = Event::MessageType::CROSS_PLATFORM;
839 event->eventId_ = CapacityEventId::CAP_OBTAIN;
840 auto eventParent = std::dynamic_pointer_cast<Event>(event);
841 if (!callee->OnEvent(eventParent)) {
842 return;
843 }
844 deviceIdList = event->deviceList_;
845 }
846
PostEventToRemote(std::shared_ptr<Plugin> caller,const std::string & deviceId,const std::string & targetPlugin,std::shared_ptr<Event> event)847 int32_t HiviewPlatform::PostEventToRemote(std::shared_ptr<Plugin> caller, const std::string& deviceId,
848 const std::string& targetPlugin, std::shared_ptr<Event> event)
849 {
850 if (event == nullptr) {
851 return -1;
852 }
853 event->SetValue("targetPlugin", targetPlugin);
854 event->SetValue("deviceId", deviceId);
855 if (PostSyncEventToTarget(caller, DISTRIBUTED_COMMUNICATOR_PLUGIN, event)) {
856 return event->GetIntValue("result");
857 }
858 return -1;
859 }
860
AppendPluginToPipeline(const std::string & pluginName,const std::string & pipelineName)861 void HiviewPlatform::AppendPluginToPipeline(const std::string& pluginName, const std::string& pipelineName)
862 {
863 auto it = pipelines_.find(pipelineName);
864 if (it == pipelines_.end()) {
865 HIVIEW_LOGW("Fail to find pipeline with name :%{public}s", pipelineName.c_str());
866 return;
867 }
868 auto ptr = GetPluginByName(pluginName);
869 if (ptr == nullptr) {
870 HIVIEW_LOGW("Fail to find plugin with name :%{public}s", pluginName.c_str());
871 return;
872 }
873 it->second->AppendProcessor(ptr);
874 HIVIEW_LOGI("plugin %{public}s add to pipeline %{public}s succeed.", pluginName.c_str(), pipelineName.c_str());
875 }
876
RequestLoadBundle(const std::string & bundleName)877 void HiviewPlatform::RequestLoadBundle(const std::string& bundleName)
878 {
879 if (pluginBundleInfos_.find(bundleName) != pluginBundleInfos_.end()) {
880 HIVIEW_LOGW("Bundle already loaded.");
881 return;
882 }
883
884 std::string configPath = defaultConfigDir_ + bundleName + "_plugin_config";
885 LoadPluginBundle(bundleName, configPath);
886 }
887
RequestUnloadBundle(const std::string & bundleName,uint64_t delay)888 void HiviewPlatform::RequestUnloadBundle(const std::string& bundleName, uint64_t delay)
889 {
890 auto task = [this, bundleName]() {
891 HIVIEW_LOGI("start to unload the bundle %{public}s.", bundleName.c_str());
892 if (pluginBundleInfos_.find(bundleName) != pluginBundleInfos_.end()) {
893 pluginBundleInfos_.erase(bundleName);
894 }
895 };
896 sharedWorkLoop_->AddTimerEvent(nullptr, nullptr, task, delay, false);
897 }
898
InstancePluginByProxy(std::shared_ptr<Plugin> proxy)899 std::shared_ptr<Plugin> HiviewPlatform::InstancePluginByProxy(std::shared_ptr<Plugin> proxy)
900 {
901 if (proxy == nullptr) {
902 return nullptr;
903 }
904
905 auto proxyPtr = std::static_pointer_cast<PluginProxy>(proxy);
906 std::shared_ptr<PluginRegistInfo> registInfo = PluginFactory::GetGlobalPluginInfo(proxyPtr->GetName());
907 if (registInfo == nullptr) {
908 HIVIEW_LOGE("Failed to find registInfo:%{public}s", proxyPtr->GetName().c_str());
909 return nullptr;
910 }
911
912 auto plugin = registInfo->getPluginObject();
913 plugin->SetName(proxyPtr->GetName());
914 plugin->SetHiviewContext(this);
915 plugin->BindWorkLoop(proxyPtr->GetWorkLoop());
916 plugin->OnLoad();
917 auto config = proxyPtr->GetPluginConfig();
918 if (config.isEventSource) {
919 auto sharedSource = std::static_pointer_cast<EventSource>(plugin);
920 for (auto& pipelineName : config.pipelineNameList) {
921 sharedSource->AddPipeline(pipelines_[pipelineName]);
922 }
923 eventSourceList_.push_back(plugin);
924 }
925 return plugin;
926 }
927
GetPluginByName(const std::string & name)928 std::shared_ptr<Plugin> HiviewPlatform::GetPluginByName(const std::string& name)
929 {
930 auto it = pluginMap_.find(name);
931 if (it == pluginMap_.end()) {
932 return nullptr;
933 }
934 return it->second;
935 }
936
GetHiviewProperty(const std::string & key,const std::string & defaultValue)937 std::string HiviewPlatform::GetHiviewProperty(const std::string& key, const std::string& defaultValue)
938 {
939 auto propPair = hiviewProperty_.find(key);
940 if (propPair != hiviewProperty_.end()) {
941 return propPair->second;
942 }
943 return Parameter::GetString(key, defaultValue);
944 }
945
SetHiviewProperty(const std::string & key,const std::string & value,bool forceUpdate)946 bool HiviewPlatform::SetHiviewProperty(const std::string& key, const std::string& value, bool forceUpdate)
947 {
948 auto propPair = hiviewProperty_.find(key);
949 if (forceUpdate || (propPair == hiviewProperty_.end())) {
950 hiviewProperty_[key] = value;
951 return true;
952 }
953 return Parameter::SetProperty(key, value);
954 }
955
CheckUnloadablePlugins()956 void HiviewPlatform::CheckUnloadablePlugins()
957 {
958 for (auto const &pluginKv : pluginMap_) {
959 if (pluginKv.second->GetType() != Plugin::PluginType::PROXY) {
960 continue;
961 }
962 auto ptr = std::static_pointer_cast<PluginProxy>(pluginKv.second);
963 if (ptr == nullptr) {
964 continue;
965 }
966 std::shared_ptr<EventLoop> eventloop = ptr->GetWorkLoop();
967 if (eventloop != nullptr) {
968 auto task = std::bind(&PluginProxy::DestroyInstanceIfNeed, ptr.get(), maxIdleTime_);
969 if (eventloop->AddEvent(nullptr, nullptr, task) != 0) {
970 continue;
971 }
972 HIVIEW_LOGW("AddEvent failed");
973 }
974 ptr->DestroyInstanceIfNeed(maxIdleTime_);
975 }
976 }
977
ScheduleCheckUnloadablePlugins()978 void HiviewPlatform::ScheduleCheckUnloadablePlugins()
979 {
980 auto task = std::bind(&HiviewPlatform::CheckUnloadablePlugins, this);
981 sharedWorkLoop_->AddTimerEvent(nullptr, nullptr, task, checkIdlePeriod_, true);
982 }
983
AddDispatchInfo(std::weak_ptr<Plugin> plugin,const std::unordered_set<uint8_t> & types,const std::unordered_set<std::string> & eventNames,const std::unordered_set<std::string> & tags,const std::unordered_map<std::string,DomainRule> & domainRulesMap)984 void HiviewPlatform::AddDispatchInfo(std::weak_ptr<Plugin> plugin, const std::unordered_set<uint8_t>& types,
985 const std::unordered_set<std::string>& eventNames, const std::unordered_set<std::string>& tags,
986 const std::unordered_map<std::string, DomainRule>& domainRulesMap)
987 {
988 auto ptr = plugin.lock();
989 if (ptr == nullptr) {
990 return;
991 }
992 auto name = ptr->GetName();
993 auto itDispatchInfo = dispatchers_.find(name);
994 std::shared_ptr<DispatchInfo> data = nullptr;
995 if (itDispatchInfo == dispatchers_.end()) {
996 auto tmp = std::make_shared<DispatchInfo>();
997 tmp->plugin_ = plugin;
998 dispatchers_[name] = tmp;
999 data = dispatchers_[name];
1000 } else {
1001 data = itDispatchInfo->second;
1002 }
1003 if (!types.empty()) {
1004 data->typesInfo_.insert(types.begin(), types.end());
1005 }
1006 if (!tags.empty()) {
1007 data->tagsInfo_.insert(tags.begin(), tags.end());
1008 }
1009 if (!eventNames.empty()) {
1010 data->eventsInfo_.insert(eventNames.begin(), eventNames.end());
1011 }
1012 if (!domainRulesMap.empty()) {
1013 data->domainsInfo_.insert(domainRulesMap.begin(), domainRulesMap.end());
1014 }
1015 }
1016
AddListenerInfo(uint32_t type,const std::string & name,const std::set<std::string> & eventNames,const std::map<std::string,DomainRule> & domainRulesMap)1017 void HiviewPlatform::AddListenerInfo(uint32_t type, const std::string& name, const std::set<std::string>& eventNames,
1018 const std::map<std::string, DomainRule>& domainRulesMap)
1019 {
1020 auto itListenerInfo = listeners_.find(name);
1021 std::shared_ptr<ListenerInfo> data = nullptr;
1022 if (itListenerInfo == listeners_.end()) {
1023 auto tmp = std::make_shared<ListenerInfo>();
1024 listeners_[name] = tmp;
1025 data = listeners_[name];
1026 } else {
1027 data = itListenerInfo->second;
1028 }
1029 if (!eventNames.empty()) {
1030 auto it = data->eventsInfo_.find(type);
1031 if (it != data->eventsInfo_.end()) {
1032 it->second.insert(eventNames.begin(), eventNames.end());
1033 } else {
1034 data->eventsInfo_[type] = eventNames;
1035 }
1036 }
1037 if (!domainRulesMap.empty()) {
1038 auto it = data->domainsInfo_.find(type);
1039 if (it != data->domainsInfo_.end()) {
1040 it->second.insert(domainRulesMap.begin(), domainRulesMap.end());
1041 } else {
1042 data->domainsInfo_[type] = domainRulesMap;
1043 }
1044 }
1045 }
1046
AddListenerInfo(uint32_t type,const std::string & name)1047 void HiviewPlatform::AddListenerInfo(uint32_t type, const std::string& name)
1048 {
1049 auto itListenerInfo = listeners_.find(name);
1050 std::shared_ptr<ListenerInfo> data = nullptr;
1051 if (itListenerInfo == listeners_.end()) {
1052 auto tmp = std::make_shared<ListenerInfo>();
1053 listeners_[name] = tmp;
1054 data = listeners_[name];
1055 } else {
1056 data = itListenerInfo->second;
1057 }
1058 data->messageTypes_.push_back(type);
1059 }
1060
GetListenerInfo(uint32_t type,const std::string & eventName,const std::string & domain)1061 std::vector<std::weak_ptr<EventListener>> HiviewPlatform::GetListenerInfo(uint32_t type,
1062 const std::string& eventName, const std::string& domain)
1063 {
1064 std::vector<std::weak_ptr<EventListener>> ret;
1065 for (auto& pairListener : listeners_) {
1066 auto listenerInfo = pairListener.second;
1067 if (listenerInfo->Match(type, eventName, domain)) {
1068 ret.push_back(listenerInfo->listener_);
1069 }
1070 }
1071 return ret;
1072 }
1073
GetDisPatcherInfo(uint32_t type,const std::string & eventName,const std::string & tag,const std::string & domain)1074 std::vector<std::weak_ptr<Plugin>> HiviewPlatform::GetDisPatcherInfo(uint32_t type,
1075 const std::string& eventName, const std::string& tag, const std::string& domain)
1076 {
1077 std::vector<std::weak_ptr<Plugin>> ret;
1078 for (auto& pairDispatcher : dispatchers_) {
1079 auto dispatcherInfo = pairDispatcher.second;
1080 if (dispatcherInfo->Match(type, eventName, tag, domain)) {
1081 ret.push_back(dispatcherInfo->plugin_);
1082 }
1083 }
1084 return ret;
1085 }
1086 } // namespace HiviewDFX
1087 } // namespace OHOS
1088