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