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