• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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