• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 "audit.h"
30 #include "common_utils.h"
31 #include "defines.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 "logger.h"
38 #include "parameter_ex.h"
39 #include "plugin_config.h"
40 #include "plugin_factory.h"
41 #include "string_util.h"
42 #include "time_util.h"
43 
44 namespace OHOS {
45 namespace HiviewDFX {
46 namespace {
47 constexpr uint32_t AID_SYSTEM = 1000;
48 static const char VERSION[] = "1.0.0.0";
49 static const char SEPARATOR_VERSION[] = " ";
50 static const char RECORDER_VERSION[] = "01.00";
51 static const char PLUGIN_CONFIG_NAME[] = "plugin_config";
52 static const char HIVIEW_PID_FILE_NAME[] = "hiview.pid";
53 static const char DEFAULT_CONFIG_DIR[] = "/system/etc/hiview/";
54 static const char PIPELINE_RULE_CONFIG_DIR[] = "/system/etc/hiview/dispatch_rule/";
55 static const char DISPATCH_RULE_CONFIG_DIR[] = "/system/etc/hiview/listener_rule/";
56 static const char DEFAULT_WORK_DIR[] = "/data/log/hiview/";
57 static const char DEFAULT_COMMERCIAL_WORK_DIR[] = "/log/LogService/";
58 static const char DEFAULT_PERSIST_DIR[] = "/log/hiview/";
59 static const char LIB_SEARCH_DIR[] = "/system/lib/";
60 static const char LIB64_SEARCH_DIR[] = "/system/lib64/";
61 }
62 DEFINE_LOG_TAG("HiView-HiviewPlatform");
HiviewPlatform()63 HiviewPlatform::HiviewPlatform()
64     : isReady_(false),
65       defaultConfigDir_(DEFAULT_CONFIG_DIR),
66       defaultWorkDir_(DEFAULT_WORK_DIR),
67       defaultCommercialWorkDir_(DEFAULT_COMMERCIAL_WORK_DIR),
68       defaultPersistDir_(DEFAULT_PERSIST_DIR),
69       defaultConfigName_(PLUGIN_CONFIG_NAME),
70       unorderQueue_(nullptr),
71       sharedWorkLoop_(nullptr)
72 {
73     dynamicLibSearchDir_.push_back(LIB_SEARCH_DIR);
74     dynamicLibSearchDir_.push_back(LIB64_SEARCH_DIR);
75 }
76 
~HiviewPlatform()77 HiviewPlatform::~HiviewPlatform()
78 {
79     if (unorderQueue_ != nullptr) {
80         unorderQueue_->Stop();
81     }
82 
83     if (sharedWorkLoop_ != nullptr) {
84         sharedWorkLoop_->StopLoop();
85     }
86     HiviewGlobal::ReleaseInstance();
87 }
88 
SetMaxProxyIdleTime(time_t idleTime)89 void HiviewPlatform::SetMaxProxyIdleTime(time_t idleTime)
90 {
91     maxIdleTime_ = idleTime;
92 }
93 
SetCheckProxyIdlePeriod(time_t period)94 void HiviewPlatform::SetCheckProxyIdlePeriod(time_t period)
95 {
96     checkIdlePeriod_ = period;
97 }
98 
InitEnvironment(const std::string & platformConfigDir)99 bool HiviewPlatform::InitEnvironment(const std::string& platformConfigDir)
100 {
101     // wait util the samgr is ready
102     if (auto res = Parameter::WaitParamSync("bootevent.samgr.ready", "true", 5); res != 0) { // timeout is 5s
103         HIVIEW_LOGE("Fail to wait the samgr, err=%{public}d", res);
104         return false;
105     }
106     CreateWorkingDirectories(platformConfigDir);
107 
108     // update beta config
109     UpdateBetaConfigIfNeed();
110 
111     // check whether hiview is already started
112     ExitHiviewIfNeed();
113 
114     std::string cfgPath = GetPluginConfigPath();
115     PluginConfig config(cfgPath);
116     if (!config.StartParse()) {
117         HIVIEW_LOGE("Fail to parse plugin config. exit!, cfgPath %{public}s", cfgPath.c_str());
118         return false;
119     }
120     StartPlatformDispatchQueue();
121 
122     // init global context helper, remove in the future
123     HiviewGlobal::CreateInstance(static_cast<HiviewContext&>(*this));
124     InitSysEventParser();
125     LoadBusinessPlugin(config);
126 
127     // start load plugin bundles
128     LoadPluginBundles();
129 
130     // maple delay start eventsource
131     for (const auto& plugin : eventSourceList_) {
132         auto sharedSource = std::static_pointer_cast<EventSource>(plugin);
133         if (sharedSource == nullptr) {
134             HIVIEW_LOGE("Fail to cast plugin to event source!");
135             continue;
136         }
137         StartEventSource(sharedSource);
138     }
139     eventSourceList_.clear();
140     isReady_ = true;
141     NotifyPluginReady();
142     ScheduleCheckUnloadablePlugins();
143     paramEventManager.SubscriberEvent();
144     return true;
145 }
146 
CreateWorkingDirectories(const std::string & platformConfigDir)147 void HiviewPlatform::CreateWorkingDirectories(const std::string& platformConfigDir)
148 {
149     HiviewPlatformConfig platformConfig = HiviewPlatformConfig(platformConfigDir);
150     HiviewPlatformConfig::PlatformConfigInfo platformConfigInfo;
151     bool state = platformConfig.ParsesConfig(platformConfigInfo);
152     if (state) {
153         if (platformConfigInfo.defaultPluginConfigName != "") {
154         defaultConfigName_ = platformConfigInfo.defaultPluginConfigName;
155         }
156         if (FileUtil::IsDirectory(platformConfigInfo.commercialWorkDir)) {
157             defaultCommercialWorkDir_ = platformConfigInfo.commercialWorkDir;
158         }
159         if (platformConfigInfo.dynamicLib64SearchDir != ""
160             || platformConfigInfo.dynamicLibSearchDir != "") {
161             dynamicLibSearchDir_.clear();
162         }
163         if (platformConfigInfo.dynamicLib64SearchDir != "") {
164             dynamicLibSearchDir_.push_back(platformConfigInfo.dynamicLib64SearchDir);
165         }
166         if (platformConfigInfo.dynamicLibSearchDir != "") {
167             dynamicLibSearchDir_.push_back(platformConfigInfo.dynamicLibSearchDir);
168         }
169         ValidateAndCreateDirectories(platformConfigInfo.pluginConfigFileDir,
170                                      platformConfigInfo.workDir,
171                                      platformConfigInfo.persistDir);
172     }
173 }
174 
InitSysEventParser()175 void HiviewPlatform::InitSysEventParser()
176 {
177     if (sysEventParser_ == nullptr) {
178         std::string systemDefineFile = (defaultConfigDir_.back() != '/') ? (defaultConfigDir_ + "/hisysevent.def") :
179             (defaultConfigDir_ + "hisysevent.def");
180         HIVIEW_LOGI("path of hisysevent.def is %{public}s", systemDefineFile.c_str());
181         std::vector<std::string> allDefineFiles;
182         allDefineFiles.emplace_back(systemDefineFile);
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     // app event publisher
400     if (AppEventPublisherFactory::IsPublisher(pluginInfo.name)) {
401         auto appEventHandler = std::make_shared<AppEventHandler>();
402         (std::static_pointer_cast<AppEventPublisher>(plugin))->AddAppEventHandler(appEventHandler);
403     }
404 
405     // Initialize plugin parameters
406     plugin->SetName(pluginInfo.name);
407     plugin->SetHandle(handle);
408     plugin->SetHiviewContext(this);
409 
410     // call preload, check whether we should release at once
411     if (!plugin->ReadyToLoad()) {
412         // if the plugin is a dynamic loaded library, the handle will be closed when calling the destructor
413         return;
414     }
415     // hold the global reference of the plugin
416     pluginMap_[pluginInfo.name] = std::move(plugin);
417     HiviewEventReport::ReportPluginLoad(pluginInfo.name, PluginEventSpace::LOAD_SUCCESS);
418 }
419 
CreatePipeline(const PluginConfig::PipelineInfo & pipelineInfo)420 void HiviewPlatform::CreatePipeline(const PluginConfig::PipelineInfo& pipelineInfo)
421 {
422     if (pipelines_.find(pipelineInfo.name) != pipelines_.end()) {
423         HIVIEW_LOGW("pipeline %{public}s already exists! create pipeline failed", pipelineInfo.name.c_str());
424         return;
425     }
426 
427     std::list<std::weak_ptr<Plugin>> pluginList;
428     for (auto& pluginName : pipelineInfo.pluginNameList) {
429         if (pluginMap_.find(pluginName) == pluginMap_.end()) {
430             HIVIEW_LOGI("could not find plugin(%{public}s), skip adding to pipeline(%{public}s).",
431                 pluginName.c_str(), pipelineInfo.name.c_str());
432             continue;
433         }
434         pluginList.push_back(pluginMap_[pluginName]);
435     }
436     std::shared_ptr<Pipeline> pipeline = std::make_shared<Pipeline>(pipelineInfo.name, pluginList);
437     std::string pipelineConfigPath = PIPELINE_RULE_CONFIG_DIR + pipelineInfo.name;
438     HIVIEW_LOGI("pipelineConfigPath = %{public}s", pipelineConfigPath.c_str());
439     if (FileUtil::FileExists(pipelineConfigPath)) {
440         HiviewRuleParser ruleParser(pipelineConfigPath);
441         pipelineRules_[pipelineInfo.name] = ruleParser.getRule();
442     }
443     pipelines_[pipelineInfo.name] = std::move(pipeline);
444 }
445 
InitPlugin(const PluginConfig & config __UNUSED,const PluginConfig::PluginInfo & pluginInfo)446 void HiviewPlatform::InitPlugin(const PluginConfig& config __UNUSED, const PluginConfig::PluginInfo& pluginInfo)
447 {
448     if (pluginMap_.find(pluginInfo.name) == pluginMap_.end()) {
449         return;
450     }
451     auto& plugin = pluginMap_[pluginInfo.name];
452 
453     if (pluginInfo.workHandlerType == "thread") {
454         auto workLoop = GetAvaliableWorkLoop(pluginInfo.workHandlerName);
455         plugin->BindWorkLoop(workLoop);
456     }
457 
458     auto begin = TimeUtil::GenerateTimestamp();
459     plugin->OnLoad();
460     std::string dispatchConfiPath = DISPATCH_RULE_CONFIG_DIR + pluginInfo.name;
461     if (FileUtil::FileExists(dispatchConfiPath)) {
462         HiviewRuleParser ruleParser(dispatchConfiPath);
463         auto dispatchConfig = ruleParser.getRule();
464         AddDispatchInfo(std::weak_ptr<Plugin>(plugin), dispatchConfig->typeList, dispatchConfig->eventList,
465             dispatchConfig->tagList, dispatchConfig->domainRuleMap);
466     }
467     if (pluginInfo.isEventSource) {
468         auto sharedSource = std::static_pointer_cast<EventSource>(plugin);
469         if (sharedSource == nullptr) {
470             HIVIEW_LOGE("Fail to cast plugin to event source!");
471             return;
472         }
473         for (auto& pipelineName : pluginInfo.pipelineNameList) {
474             sharedSource->AddPipeline(pipelines_[pipelineName]);
475         }
476     }
477 
478     std::shared_ptr<PluginRegistInfo> registInfo = PluginFactory::GetGlobalPluginInfo(pluginInfo.name);
479     if (plugin->GetType() == Plugin::PluginType::PROXY && registInfo->needStartupLoading) {
480         std::shared_ptr<PluginProxy> pluginProxy = std::static_pointer_cast<PluginProxy>(plugin);
481         pluginProxy->LoadPluginIfNeed();
482     }
483 
484     auto end = TimeUtil::GenerateTimestamp();
485     HIVIEW_LOGI("Plugin %{public}s loadtime:%{public}" PRIu64 ".", pluginInfo.name.c_str(), end - begin);
486 }
487 
NotifyPluginReady()488 void HiviewPlatform::NotifyPluginReady()
489 {
490     auto event = std::make_shared<Event>("platform");
491     event->messageType_ = Event::MessageType::PLUGIN_MAINTENANCE;
492     event->eventId_ = Event::EventId::PLUGIN_LOADED;
493     PostUnorderedEvent(nullptr, event);
494 }
495 
StartEventSource(std::shared_ptr<EventSource> source)496 void HiviewPlatform::StartEventSource(std::shared_ptr<EventSource> source)
497 {
498     auto workLoop = source->GetWorkLoop();
499     auto name = source->GetName();
500     if (workLoop == nullptr) {
501         HIVIEW_LOGW("No work loop available, start event source[%s] in current thead!", name.c_str());
502         source->StartEventSource();
503     } else {
504         HIVIEW_LOGI("Start event source[%s] in thead[%s].", name.c_str(), workLoop->GetName().c_str());
505         auto task = std::bind(&EventSource::StartEventSource, source.get());
506         workLoop->AddEvent(nullptr, nullptr, task);
507     }
508     HIVIEW_LOGI("Start event source[%s] in current thead done.", name.c_str());
509 }
510 
511 // only call from main thread
GetAvaliableWorkLoop(const std::string & name)512 std::shared_ptr<EventLoop> HiviewPlatform::GetAvaliableWorkLoop(const std::string& name)
513 {
514     auto it = privateWorkLoopMap_.find(name);
515     if (it != privateWorkLoopMap_.end()) {
516         return it->second;
517     }
518 
519     auto privateLoop = std::make_shared<EventLoop>(name);
520     if (privateLoop != nullptr) {
521         privateWorkLoopMap_.insert(std::make_pair(name, privateLoop));
522         privateLoop->StartLoop();
523     }
524     return privateLoop;
525 }
526 
CleanupUnusedResources()527 void HiviewPlatform::CleanupUnusedResources()
528 {
529     auto iter = pluginMap_.begin();
530     while (iter != pluginMap_.end()) {
531         if (iter->second == nullptr) {
532             iter = pluginMap_.erase(iter);
533         } else {
534             ++iter;
535         }
536     }
537 }
538 
ScheduleCreateAndInitPlugin(const PluginConfig::PluginInfo & pluginInfo)539 void HiviewPlatform::ScheduleCreateAndInitPlugin(const PluginConfig::PluginInfo& pluginInfo)
540 {
541     // only support thread type
542     CreatePlugin(pluginInfo);
543     if (pluginMap_.find(pluginInfo.name) == pluginMap_.end()) {
544         return;
545     }
546     auto& plugin = pluginMap_[pluginInfo.name];
547 
548     if (pluginInfo.workHandlerType == "thread") {
549         auto workLoop = GetAvaliableWorkLoop(pluginInfo.workHandlerName);
550         plugin->BindWorkLoop(workLoop);
551     }
552     plugin->OnLoad();
553 }
554 
StartLoop()555 void HiviewPlatform::StartLoop()
556 {
557     // empty implementation
558 }
559 
StartPlatformDispatchQueue()560 void HiviewPlatform::StartPlatformDispatchQueue()
561 {
562     if (unorderQueue_ == nullptr) {
563         unorderQueue_ = std::make_unique<EventDispatchQueue>("plat_unorder", Event::ManageType::UNORDERED, this);
564         unorderQueue_->Start();
565     }
566 
567     if (sharedWorkLoop_ == nullptr) {
568         sharedWorkLoop_ = std::make_shared<EventLoop>("plat_shared");
569         sharedWorkLoop_->StartLoop();
570     }
571 }
572 
GetPipelineSequenceByName(const std::string & name)573 std::list<std::weak_ptr<Plugin>> HiviewPlatform::GetPipelineSequenceByName(const std::string& name)
574 {
575     if (!isReady_) {
576         return std::list<std::weak_ptr<Plugin>>();
577     }
578 
579     auto it = pipelines_.find(name);
580     if (it != pipelines_.end()) {
581         return it->second->GetProcessSequence();
582     }
583     return std::list<std::weak_ptr<Plugin>>(0);
584 }
585 
PostUnorderedEvent(std::shared_ptr<Plugin> plugin,std::shared_ptr<Event> event)586 void HiviewPlatform::PostUnorderedEvent(std::shared_ptr<Plugin> plugin, std::shared_ptr<Event> event)
587 {
588     if (!isReady_) {
589         return;
590     }
591 
592     if (plugin == nullptr) {
593         HIVIEW_LOGI("maybe platform send event");
594     }
595 
596     if (unorderQueue_ != nullptr && event != nullptr) {
597         event->processType_ = Event::ManageType::UNORDERED;
598         unorderQueue_->Enqueue(event);
599     }
600 }
601 
RegisterUnorderedEventListener(std::weak_ptr<EventListener> listener)602 void HiviewPlatform::RegisterUnorderedEventListener(std::weak_ptr<EventListener> listener)
603 {
604     auto ptr = listener.lock();
605     if (ptr == nullptr) {
606         return;
607     }
608     auto name = ptr->GetListenerName();
609     auto itListenerInfo = listeners_.find(name);
610     if (itListenerInfo == listeners_.end()) {
611         auto tmp = std::make_shared<ListenerInfo>();
612         tmp->listener_ = listener;
613         listeners_[name] = tmp;
614     } else {
615         auto tmp = listeners_[name];
616         tmp->listener_ = listener;
617     }
618 }
619 
PostSyncEventToTarget(std::shared_ptr<Plugin> caller,const std::string & calleeName,std::shared_ptr<Event> event)620 bool HiviewPlatform::PostSyncEventToTarget(std::shared_ptr<Plugin> caller, const std::string& calleeName,
621                                            std::shared_ptr<Event> event)
622 {
623     if (!isReady_) {
624         return false;
625     }
626 
627     auto it = pluginMap_.find(calleeName);
628     if (it == pluginMap_.end()) {
629         return false;
630     }
631 
632     auto callee = it->second;
633     if (callee == nullptr) {
634         return false;
635     }
636 
637     auto workLoop = callee->GetWorkLoop();
638     std::future<bool> ret;
639     if (workLoop == nullptr) {
640         ret = sharedWorkLoop_->AddEventForResult(callee, event);
641     } else {
642         ret = workLoop->AddEventForResult(callee, event);
643     }
644     return ret.get();
645 }
646 
PostAsyncEventToTarget(std::shared_ptr<Plugin> caller,const std::string & calleeName,std::shared_ptr<Event> event)647 void HiviewPlatform::PostAsyncEventToTarget(std::shared_ptr<Plugin> caller, const std::string& calleeName,
648                                             std::shared_ptr<Event> event)
649 {
650     if (!isReady_) {
651         return;
652     }
653 
654     auto it = pluginMap_.find(calleeName);
655     if (it == pluginMap_.end()) {
656         return;
657     }
658 
659     auto callee = it->second;
660     if (callee == nullptr) {
661         return;
662     }
663 
664     auto workLoop = callee->GetWorkLoop();
665     if (workLoop == nullptr) {
666         sharedWorkLoop_->AddEvent(callee, event);
667     } else {
668         workLoop->AddEvent(callee, event);
669     }
670     HIVIEW_LOGI("Post async event to %{public}s successfully", calleeName.c_str());
671 }
672 
GetSharedWorkLoop()673 std::shared_ptr<EventLoop> HiviewPlatform::GetSharedWorkLoop()
674 {
675     return sharedWorkLoop_;
676 }
677 
IsReady()678 bool HiviewPlatform::IsReady()
679 {
680     return isReady_;
681 }
682 
RequestUnloadPlugin(std::shared_ptr<Plugin> caller)683 void HiviewPlatform::RequestUnloadPlugin(std::shared_ptr<Plugin> caller)
684 {
685     if (caller == nullptr) {
686         HiviewEventReport::ReportPluginUnload("", PluginEventSpace::UNLOAD_INVALID);
687         return;
688     }
689 
690     std::string name = caller->GetName();
691     auto task = std::bind(&HiviewPlatform::UnloadPlugin, this, name);
692     // delay 1s to unload target plugin
693     const int unloadDelay = 1;
694     sharedWorkLoop_->AddTimerEvent(nullptr, nullptr, task, unloadDelay, false);
695 }
696 
UnloadPlugin(const std::string & name)697 void HiviewPlatform::UnloadPlugin(const std::string& name)
698 {
699     auto it = pluginMap_.find(name);
700     if (it == pluginMap_.end()) {
701         HiviewEventReport::ReportPluginUnload(name, PluginEventSpace::UNLOAD_NOT_FOUND);
702         return;
703     }
704 
705     auto target = it->second;
706     if (target == nullptr) {
707         return;
708     }
709 
710     auto count = target.use_count();
711     // two counts for 1.current ref 2.map holder ref
712     if (count > 2) {
713         HIVIEW_LOGW("Plugin %{public}s has more refs(%{public}ld), may caused by unfinished task. unload failed.",
714             name.c_str(), count);
715         HiviewEventReport::ReportPluginUnload(name, PluginEventSpace::UNLOAD_IN_USE);
716         return;
717     }
718 
719     pluginMap_.erase(name);
720     target->OnUnload();
721     HiviewEventReport::ReportPluginUnload(name, PluginEventSpace::UNLOAD_SUCCESS);
722     auto looper = target->GetWorkLoop();
723     if (looper == nullptr) {
724         return;
725     }
726 
727     auto looperName = looper->GetName();
728     // three counts for 1.current ref 2.plugin ref 3.map holder ref
729     if (looper.use_count() <= 3) {
730         HIVIEW_LOGI("%s has refs(%ld).", looperName.c_str(), looper.use_count());
731         looper->StopLoop();
732         privateWorkLoopMap_.erase(looperName);
733         HIVIEW_LOGI("Stop %s done.", looperName.c_str());
734     }
735 
736     if (target->GetType() == Plugin::PluginType::DYNAMIC) {
737         // remove static register before closing the dynamic library handle
738         PluginFactory::UnregisterPlugin(target->GetName());
739     }
740 }
741 
GetHiViewDirectory(HiviewContext::DirectoryType type)742 std::string HiviewPlatform::GetHiViewDirectory(HiviewContext::DirectoryType type)
743 {
744     switch (type) {
745         case HiviewContext::DirectoryType::CONFIG_DIRECTORY:
746             return defaultConfigDir_;
747         case HiviewContext::DirectoryType::WORK_DIRECTORY:
748             return defaultWorkDir_;
749         case HiviewContext::DirectoryType::PERSIST_DIR:
750             return defaultPersistDir_;
751         default:
752             break;
753     }
754     return "";
755 }
756 
ValidateAndCreateDirectory(std::string & defaultPath,const std::string & realPath)757 void HiviewPlatform::ValidateAndCreateDirectory(std::string& defaultPath, const std::string& realPath)
758 {
759     if (defaultPath != realPath) {
760         defaultPath = realPath;
761     }
762     if (FileUtil::IsDirectory(defaultPath)) {
763         return;
764     }
765     FileUtil::CreateDirWithDefaultPerm(defaultPath, AID_SYSTEM, AID_SYSTEM);
766 }
767 
ValidateAndCreateDirectories(const std::string & localPath,const std::string & workPath,const std::string & persistPath)768 void HiviewPlatform::ValidateAndCreateDirectories(const std::string& localPath, const std::string& workPath,
769     const std::string& persistPath)
770 {
771     ValidateAndCreateDirectory(defaultConfigDir_, localPath);
772     ValidateAndCreateDirectory(defaultWorkDir_, workPath);
773     ValidateAndCreateDirectory(defaultPersistDir_, persistPath);
774 }
775 
776 #ifndef _WIN32
ExitHiviewIfNeed()777 void HiviewPlatform::ExitHiviewIfNeed()
778 {
779     int selfPid = getpid();
780     std::string selfProcName = CommonUtils::GetProcNameByPid(selfPid);
781     if (selfProcName != "hiview") {
782         return;
783     }
784 
785     std::string pidFile = defaultWorkDir_ + "/" + std::string(HIVIEW_PID_FILE_NAME);
786     if (!FileUtil::FileExists(pidFile)) {
787         return;
788     }
789 
790     std::string content;
791     FileUtil::LoadStringFromFile(pidFile, content);
792     int32_t pid = -1;
793     if (!StringUtil::StrToInt(content, pid)) {
794         return;
795     }
796 
797     std::string procName = CommonUtils::GetProcNameByPid(pid);
798     if (procName == "hiview") {
799         printf("Hiview is already started, exit! \n");
800         exit(1);
801     }
802     FileUtil::SaveStringToFile(pidFile, std::to_string(selfPid));
803 }
804 #else
ExitHiviewIfNeed()805 void HiviewPlatform::ExitHiviewIfNeed()
806 {
807 }
808 #endif
809 
GetPluginConfigPath()810 std::string HiviewPlatform::GetPluginConfigPath()
811 {
812     return defaultConfigDir_ + defaultConfigName_;
813 }
814 
AppendPluginToPipeline(const std::string & pluginName,const std::string & pipelineName)815 void HiviewPlatform::AppendPluginToPipeline(const std::string& pluginName, const std::string& pipelineName)
816 {
817     auto it = pipelines_.find(pipelineName);
818     if (it == pipelines_.end()) {
819         HIVIEW_LOGW("Fail to find pipeline with name :%{public}s", pipelineName.c_str());
820         return;
821     }
822     auto ptr = GetPluginByName(pluginName);
823     if (ptr == nullptr) {
824         HIVIEW_LOGW("Fail to find plugin with name :%{public}s", pluginName.c_str());
825         return;
826     }
827     it->second->AppendProcessor(ptr);
828     HIVIEW_LOGI("plugin %{public}s add to pipeline %{public}s succeed.", pluginName.c_str(), pipelineName.c_str());
829 }
830 
RequestLoadBundle(const std::string & bundleName)831 void HiviewPlatform::RequestLoadBundle(const std::string& bundleName)
832 {
833     if (pluginBundleInfos_.find(bundleName) != pluginBundleInfos_.end()) {
834         HIVIEW_LOGW("Bundle already loaded.");
835         return;
836     }
837 
838     std::string configPath = defaultConfigDir_ + bundleName + "_plugin_config";
839     LoadPluginBundle(bundleName, configPath);
840 }
841 
RequestUnloadBundle(const std::string & bundleName,uint64_t delay)842 void HiviewPlatform::RequestUnloadBundle(const std::string& bundleName, uint64_t delay)
843 {
844     auto task = [this, bundleName]() {
845         HIVIEW_LOGI("start to unload the bundle %{public}s.", bundleName.c_str());
846         if (pluginBundleInfos_.find(bundleName) != pluginBundleInfos_.end()) {
847             pluginBundleInfos_.erase(bundleName);
848         }
849     };
850     sharedWorkLoop_->AddTimerEvent(nullptr, nullptr, task, delay, false);
851 }
852 
InstancePluginByProxy(std::shared_ptr<Plugin> proxy)853 std::shared_ptr<Plugin> HiviewPlatform::InstancePluginByProxy(std::shared_ptr<Plugin> proxy)
854 {
855     if (proxy == nullptr) {
856         return nullptr;
857     }
858 
859     auto proxyPtr = std::static_pointer_cast<PluginProxy>(proxy);
860     std::shared_ptr<PluginRegistInfo> registInfo = PluginFactory::GetGlobalPluginInfo(proxyPtr->GetName());
861     if (registInfo == nullptr) {
862         HIVIEW_LOGE("Failed to find registInfo:%{public}s", proxyPtr->GetName().c_str());
863         return nullptr;
864     }
865 
866     auto plugin = registInfo->getPluginObject();
867     plugin->SetName(proxyPtr->GetName());
868     plugin->SetHiviewContext(this);
869     plugin->BindWorkLoop(proxyPtr->GetWorkLoop());
870     plugin->OnLoad();
871     auto config = proxyPtr->GetPluginConfig();
872     if (config.isEventSource) {
873         auto sharedSource = std::static_pointer_cast<EventSource>(plugin);
874         for (auto& pipelineName : config.pipelineNameList) {
875             sharedSource->AddPipeline(pipelines_[pipelineName]);
876         }
877         eventSourceList_.push_back(plugin);
878     }
879     return plugin;
880 }
881 
GetPluginByName(const std::string & name)882 std::shared_ptr<Plugin> HiviewPlatform::GetPluginByName(const std::string& name)
883 {
884     auto it = pluginMap_.find(name);
885     if (it == pluginMap_.end()) {
886         return nullptr;
887     }
888     return it->second;
889 }
890 
GetHiviewProperty(const std::string & key,const std::string & defaultValue)891 std::string HiviewPlatform::GetHiviewProperty(const std::string& key, const std::string& defaultValue)
892 {
893     auto propPair = hiviewProperty_.find(key);
894     if (propPair != hiviewProperty_.end()) {
895         return propPair->second;
896     }
897     return Parameter::GetString(key, defaultValue);
898 }
899 
SetHiviewProperty(const std::string & key,const std::string & value,bool forceUpdate)900 bool HiviewPlatform::SetHiviewProperty(const std::string& key, const std::string& value, bool forceUpdate)
901 {
902     auto propPair = hiviewProperty_.find(key);
903     if (forceUpdate || (propPair == hiviewProperty_.end())) {
904         hiviewProperty_[key] = value;
905         return true;
906     }
907     return Parameter::SetProperty(key, value);
908 }
909 
CheckUnloadablePlugins()910 void HiviewPlatform::CheckUnloadablePlugins()
911 {
912     for (auto const &pluginKv : pluginMap_) {
913         if (pluginKv.second->GetType() != Plugin::PluginType::PROXY) {
914             continue;
915         }
916         auto ptr = std::static_pointer_cast<PluginProxy>(pluginKv.second);
917         if (ptr == nullptr) {
918             continue;
919         }
920         std::shared_ptr<EventLoop> eventloop = ptr->GetWorkLoop();
921         if (eventloop != nullptr) {
922             auto task = std::bind(&PluginProxy::DestroyInstanceIfNeed, ptr.get(), maxIdleTime_);
923             if (eventloop->AddEvent(nullptr, nullptr, task) != 0) {
924                 continue;
925             }
926             HIVIEW_LOGW("AddEvent failed");
927         }
928         ptr->DestroyInstanceIfNeed(maxIdleTime_);
929     }
930 }
931 
ScheduleCheckUnloadablePlugins()932 void HiviewPlatform::ScheduleCheckUnloadablePlugins()
933 {
934     auto task = std::bind(&HiviewPlatform::CheckUnloadablePlugins, this);
935     sharedWorkLoop_->AddTimerEvent(nullptr, nullptr, task, checkIdlePeriod_, true);
936 }
937 
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)938 void HiviewPlatform::AddDispatchInfo(std::weak_ptr<Plugin> plugin, const std::unordered_set<uint8_t>& types,
939     const std::unordered_set<std::string>& eventNames, const std::unordered_set<std::string>& tags,
940     const std::unordered_map<std::string, DomainRule>& domainRulesMap)
941 {
942     auto ptr = plugin.lock();
943     if (ptr == nullptr) {
944         return;
945     }
946     auto name = ptr->GetName();
947     auto itDispatchInfo = dispatchers_.find(name);
948     std::shared_ptr<DispatchInfo> data = nullptr;
949     if (itDispatchInfo == dispatchers_.end()) {
950         auto tmp = std::make_shared<DispatchInfo>();
951         tmp->plugin_ = plugin;
952         dispatchers_[name] = tmp;
953         data = dispatchers_[name];
954     } else {
955         data = itDispatchInfo->second;
956     }
957     if (!types.empty()) {
958         data->typesInfo_.insert(types.begin(), types.end());
959     }
960     if (!tags.empty()) {
961         data->tagsInfo_.insert(tags.begin(), tags.end());
962     }
963     if (!eventNames.empty()) {
964         data->eventsInfo_.insert(eventNames.begin(), eventNames.end());
965     }
966     if (!domainRulesMap.empty()) {
967         data->domainsInfo_.insert(domainRulesMap.begin(), domainRulesMap.end());
968     }
969 }
970 
AddListenerInfo(uint32_t type,const std::string & name,const std::set<std::string> & eventNames,const std::map<std::string,DomainRule> & domainRulesMap)971 void HiviewPlatform::AddListenerInfo(uint32_t type, const std::string& name, const std::set<std::string>& eventNames,
972     const std::map<std::string, DomainRule>& domainRulesMap)
973 {
974     auto itListenerInfo = listeners_.find(name);
975     std::shared_ptr<ListenerInfo> data = nullptr;
976     if (itListenerInfo == listeners_.end()) {
977         auto tmp = std::make_shared<ListenerInfo>();
978         listeners_[name] = tmp;
979         data = listeners_[name];
980     } else {
981         data = itListenerInfo->second;
982     }
983     if (!eventNames.empty()) {
984         auto it = data->eventsInfo_.find(type);
985         if (it != data->eventsInfo_.end()) {
986             it->second.insert(eventNames.begin(), eventNames.end());
987         } else {
988             data->eventsInfo_[type] = eventNames;
989         }
990     }
991     if (!domainRulesMap.empty()) {
992         auto it = data->domainsInfo_.find(type);
993         if (it != data->domainsInfo_.end()) {
994             it->second.insert(domainRulesMap.begin(), domainRulesMap.end());
995         } else {
996             data->domainsInfo_[type] = domainRulesMap;
997         }
998     }
999 }
1000 
AddListenerInfo(uint32_t type,const std::string & name)1001 void HiviewPlatform::AddListenerInfo(uint32_t type, const std::string& name)
1002 {
1003     auto itListenerInfo = listeners_.find(name);
1004     std::shared_ptr<ListenerInfo> data = nullptr;
1005     if (itListenerInfo == listeners_.end()) {
1006         auto tmp = std::make_shared<ListenerInfo>();
1007         listeners_[name] = tmp;
1008         data = listeners_[name];
1009     } else {
1010         data = itListenerInfo->second;
1011     }
1012     data->messageTypes_.push_back(type);
1013 }
1014 
GetListenerInfo(uint32_t type,const std::string & eventName,const std::string & domain)1015 std::vector<std::weak_ptr<EventListener>> HiviewPlatform::GetListenerInfo(uint32_t type,
1016     const std::string& eventName, const std::string& domain)
1017 {
1018     std::vector<std::weak_ptr<EventListener>> ret;
1019     for (auto& pairListener : listeners_) {
1020         auto listenerInfo = pairListener.second;
1021         if (listenerInfo->Match(type, eventName, domain)) {
1022             ret.push_back(listenerInfo->listener_);
1023         }
1024     }
1025     return ret;
1026 }
1027 
GetDisPatcherInfo(uint32_t type,const std::string & eventName,const std::string & tag,const std::string & domain)1028 std::vector<std::weak_ptr<Plugin>> HiviewPlatform::GetDisPatcherInfo(uint32_t type,
1029     const std::string& eventName, const std::string& tag, const std::string& domain)
1030 {
1031     std::vector<std::weak_ptr<Plugin>> ret;
1032     for (auto& pairDispatcher : dispatchers_) {
1033         auto dispatcherInfo = pairDispatcher.second;
1034         if (dispatcherInfo->Match(type, eventName, tag, domain)) {
1035             ret.push_back(dispatcherInfo->plugin_);
1036         }
1037     }
1038     return ret;
1039 }
1040 } // namespace HiviewDFX
1041 } // namespace OHOS
1042