• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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