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