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