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