• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "plugin_mgr.h"
17 #include <cinttypes>
18 #include <algorithm>
19 #include <cstdint>
20 #include <dlfcn.h>
21 #include <iostream>
22 #include <string>
23 #include <string_ex.h>
24 #include <fstream>
25 #include "config_policy_utils.h"
26 #include "file_ex.h"
27 #ifdef RESOURCE_SCHEDULE_SERVICE_WITH_FFRT_ENABLE
28 #include "ffrt_inner.h"
29 #else
30 #include "event_runner.h"
31 #endif
32 #include "hisysevent.h"
33 #include "refbase.h"
34 #include "res_sched_log.h"
35 #include "hitrace_meter.h"
36 #include "batch_log_printer.h"
37 #include "res_sched_file_util.h"
38 
39 using namespace std;
40 
41 namespace OHOS {
42 namespace ResourceSchedule {
43 using namespace AppExecFwk;
44 using namespace HiviewDFX;
45 
46 namespace {
47     static const int32_t DISPATCH_WARNING_TIME = 10; // ms
48     static const int32_t PLUGIN_SWITCH_FILE_IDX = 0;
49     static const int32_t CONFIG_FILE_IDX = 1;
50     static const int32_t SIMPLIFY_LIB_INDEX = 3;
51     static const int32_t SIMPLIFY_LIB_LENGTH = 2;
52     static const int32_t MAX_FILE_LENGTH = 32 * 1024 * 1024;
53     static const int32_t PLUGIN_REQUEST_ERROR = -1;
54     static const char* RUNNER_NAME = "rssDispatcher";
55     static const char* PLUGIN_SWITCH_FILE_NAME = "etc/ressched/res_sched_plugin_switch.xml";
56     static const char* CONFIG_FILE_NAME = "etc/ressched/res_sched_config.xml";
57     static const char* EXT_CONFIG_LIB = "libsuspend_manager_service.z.so";
58 #ifdef RESOURCE_SCHEDULE_SERVICE_WITH_EXT_RES_ENABLE
59     static const int32_t DEFAULT_VALUE = -1;
60     static const char* EXT_RES_KEY = "extType";
61 #endif
62 }
63 
64 IMPLEMENT_SINGLE_INSTANCE(PluginMgr);
65 
~PluginMgr()66 PluginMgr::~PluginMgr()
67 {
68     OnDestroy();
69 }
70 
Init(bool isRssExe)71 void PluginMgr::Init(bool isRssExe)
72 {
73     if (pluginSwitch_) {
74         RESSCHED_LOGW("%{public}s, PluginMgr has Initialized!", __func__);
75         return;
76     }
77 
78     if (!pluginSwitch_) {
79         pluginSwitch_ = make_unique<PluginSwitch>();
80     }
81     if (!configReader_) {
82         configReader_ = make_unique<ConfigReader>();
83     }
84 
85     if (!isRssExe) {
86         LoadGetExtConfigFunc();
87     }
88     RESSCHED_LOGI("PluginMgr::Init success!");
89 }
90 
GetConfigReaderStr()91 std::vector<std::string> PluginMgr::GetConfigReaderStr()
92 {
93     std::vector<std::string> configStrs;
94     GetConfigContent(CONFIG_FILE_IDX, CONFIG_FILE_NAME, configStrs);
95     return configStrs;
96 }
97 
GetPluginSwitchStr()98 std::vector<std::string> PluginMgr::GetPluginSwitchStr()
99 {
100     std::vector<std::string> switchStrs;
101     GetConfigContent(PLUGIN_SWITCH_FILE_IDX, PLUGIN_SWITCH_FILE_NAME, switchStrs);
102     return switchStrs;
103 }
104 
ParseConfigReader(const std::vector<std::string> & configStrs)105 void PluginMgr::ParseConfigReader(const std::vector<std::string>& configStrs)
106 {
107     if (!configReader_) {
108         RESSCHED_LOGW("%{public}s, configReader null!", __func__);
109         return;
110     }
111 
112     int32_t configStrsSize = static_cast<int32_t>(configStrs.size());
113     RESSCHED_LOGI("plugin configStrs size %{public}d", configStrsSize);
114     for (int index = 0; index < configStrsSize; index++) {
115         if (configStrs[index].empty()) {
116             continue;
117         }
118         if (!configReader_->LoadFromConfigContent(configStrs[index])) {
119             RESSCHED_LOGW("%{public}s, PluginMgr load config file index:%{public}d failed!", __func__, index);
120             HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::RSS, "INIT_FAULT",
121                 HiviewDFX::HiSysEvent::EventType::FAULT,
122                 "COMPONENT_NAME", "MAIN", "ERR_TYPE", "configure error",
123                 "ERR_MSG", "PluginMgr load parameter config file failed");
124             continue;
125         }
126         RESSCHED_LOGI("PluginMgr load config file index:%{public}d success!", index);
127     }
128 }
129 
ParsePluginSwitch(const std::vector<std::string> & switchStrs,bool isRssExe)130 void PluginMgr::ParsePluginSwitch(const std::vector<std::string>& switchStrs, bool isRssExe)
131 {
132     if (!pluginSwitch_) {
133         RESSCHED_LOGW("%{public}s, pluginSwitch null!", __func__);
134         return;
135     }
136 
137     int32_t switchStrsSize = static_cast<int32_t>(switchStrs.size());
138     RESSCHED_LOGI("plugin switchStrs size %{public}d", switchStrsSize);
139     for (int32_t index = 0; index < switchStrsSize; index++) {
140         if (switchStrs[index].empty()) {
141             continue;
142         }
143         if (!pluginSwitch_->LoadFromConfigContent(switchStrs[index], isRssExe)) {
144             RESSCHED_LOGW("%{public}s, PluginMgr load switch config file index:%{public}d failed!", __func__, index);
145             HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::RSS, "INIT_FAULT",
146                 HiviewDFX::HiSysEvent::EventType::FAULT,
147                 "COMPONENT_NAME", "MAIN", "ERR_TYPE", "configure error",
148                 "ERR_MSG", "PluginMgr load switch config file failed!");
149             continue;
150         }
151         RESSCHED_LOGI("PluginMgr load switch config file index:%{public}d success!", index);
152     }
153     LoadPlugin();
154     std::lock_guard<ffrt::mutex> autoLock(dispatcherHandlerMutex_);
155 #ifdef RESOURCE_SCHEDULE_SERVICE_WITH_FFRT_ENABLE
156     dispatchers_.clear();
157     for (const auto& [libPath, libInfo] : pluginLibMap_) {
158         auto callback = [pluginName = libPath, time = pluginBlockTime]() {
159             PluginMgr::GetInstance().HandlePluginTimeout(pluginName);
160             ffrt::submit([pluginName]() {
161                 PluginMgr::GetInstance().EnablePluginIfResume(pluginName);
162                 }, {}, {}, ffrt::task_attr().delay(time));
163         };
164         dispatchers_.emplace(libPath, std::make_shared<ffrt::queue>(libPath.c_str(),
165             ffrt::queue_attr().qos(ffrt::qos_user_interactive)));
166     }
167 #else
168     if (!dispatcher_) {
169         dispatcher_ = std::make_shared<EventHandler>(EventRunner::Create(RUNNER_NAME));
170     }
171     if (!dispatcher_) {
172         RESSCHED_LOGI("create dispatcher failed");
173     }
174 #endif
175     isInit = true;
176     RESSCHED_LOGI("PluginMgr load plugin success!");
177 }
178 
LoadGetExtConfigFunc()179 void PluginMgr::LoadGetExtConfigFunc()
180 {
181     auto handle = dlopen(EXT_CONFIG_LIB, RTLD_NOW);
182     if (!handle) {
183         RESSCHED_LOGE("not find lib,errno: %{public}d", errno);
184         return;
185     }
186     getExtMultiConfigFunc_ = reinterpret_cast<GetExtMultiConfigFunc>(dlsym(handle, "GetExtMultiConfig"));
187     if (!getExtMultiConfigFunc_) {
188         RESSCHED_LOGE("dlsym getExtConfig func failed!");
189         dlclose(handle);
190     }
191 }
192 
GetConfigContent(int32_t configIdx,const std::string & configPath,std::vector<std::string> & contents)193 void PluginMgr::GetConfigContent(int32_t configIdx, const std::string& configPath, std::vector<std::string>& contents)
194 {
195     if (configIdx != -1 && getExtMultiConfigFunc_) {
196         getExtMultiConfigFunc_(configIdx, contents);
197         return;
198     }
199     auto configFilePaths = GetAllRealConfigPath(configPath);
200     if (configFilePaths.size() <= 0) {
201         return;
202     }
203     for (auto configFilePath : configFilePaths) {
204         if (configFilePath.empty()) {
205             continue;
206         }
207         std::string content;
208         LoadStringFromFile(configFilePath, content);
209         contents.emplace_back(content);
210     }
211 }
212 
GetAllRealConfigPath(const std::string & configName)213 std::vector<std::string> PluginMgr::GetAllRealConfigPath(const std::string& configName)
214 {
215     std::vector<std::string> configFilePaths;
216     auto cfgDirList = GetCfgDirList();
217     if (cfgDirList == nullptr) {
218         return configFilePaths;
219     }
220     std::string baseRealPath;
221     for (const auto& cfgDir : cfgDirList->paths) {
222         if (cfgDir == nullptr) {
223             continue;
224         }
225         if (!CheckRealPath(std::string(cfgDir) + "/" + configName, baseRealPath)) {
226             continue;
227         }
228         configFilePaths.emplace_back(baseRealPath);
229     }
230     FreeCfgDirList(cfgDirList);
231     return configFilePaths;
232 }
233 
CheckRealPath(const std::string & partialPath,std::string & fullPath)234 bool PluginMgr::CheckRealPath(const std::string& partialPath, std::string& fullPath)
235 {
236     char tmpPath[PATH_MAX] = {0};
237     if (partialPath.size() > PATH_MAX || !realpath(partialPath.c_str(), tmpPath)) {
238         return false;
239     }
240     fullPath = tmpPath;
241     return true;
242 }
243 
LoadPlugin()244 void PluginMgr::LoadPlugin()
245 {
246     if (!pluginSwitch_) {
247         RESSCHED_LOGW("%{public}s, pluginSwitch null!", __func__);
248         return;
249     }
250 
251     std::list<PluginInfo> pluginInfoList = pluginSwitch_->GetPluginSwitch();
252     for (const auto& info : pluginInfoList) {
253         if (!info.switchOn) {
254             continue;
255         }
256         if (pluginLibMap_.find(info.libPath) != pluginLibMap_.end()) {
257             continue;
258         }
259         shared_ptr<PluginLib> libInfoPtr = LoadOnePlugin(info);
260         if (libInfoPtr == nullptr) {
261             continue;
262         }
263         std::lock_guard<std::mutex> autoLock(pluginMutex_);
264         pluginLibMap_.emplace(info.libPath, *libInfoPtr);
265 
266         RESSCHED_LOGD("%{public}s, init %{private}s success!", __func__, info.libPath.c_str());
267     }
268 }
269 
LoadOnePlugin(const PluginInfo & info)270 shared_ptr<PluginLib> PluginMgr::LoadOnePlugin(const PluginInfo& info)
271 {
272     if (!ResCommonUtil::IsValidPath(info.libPath)) {
273         RESSCHED_LOGE("%{public}s, libPath error!", __func__);
274         HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::RSS, "INIT_FAULT", HiviewDFX::HiSysEvent::EventType::FAULT,
275             "COMPONENT_NAME", info.libPath, "ERR_TYPE", "plugin failure",
276             "ERR_MSG", info.libPath + "is error path!");
277         return nullptr;
278     }
279     void* pluginHandle = dlopen(info.libPath.c_str(), RTLD_NOW);
280     if (!pluginHandle) {
281         RESSCHED_LOGE("%{public}s, not find plugin lib !", __func__);
282         HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::RSS, "INIT_FAULT", HiviewDFX::HiSysEvent::EventType::FAULT,
283             "COMPONENT_NAME", info.libPath, "ERR_TYPE", "plugin failure",
284             "ERR_MSG", "PluginMgr dlopen " + info.libPath + " failed!");
285         return nullptr;
286     }
287     std::string errorMsg = "";
288     OnPluginInitFunc onPluginInitFunc;
289     OnPluginDisableFunc onPluginDisableFunc;
290     if (!CheckValidPlugin(info, pluginHandle, errorMsg, onPluginInitFunc, onPluginDisableFunc)) {
291         HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::RSS, "INIT_FAULT", HiviewDFX::HiSysEvent::EventType::FAULT,
292             "COMPONENT_NAME", info.libPath, "ERR_TYPE", "plugin failure",
293             "ERR_MSG", errorMsg);
294         dlclose(pluginHandle);
295         return nullptr;
296     }
297     // OnDispatchResource is not necessary for plugin
298     auto onDispatchResourceFunc = reinterpret_cast<OnDispatchResourceFunc>(dlsym(pluginHandle,
299         "OnDispatchResource"));
300 
301     // OnDeliverResource is not necessary for plugin
302     auto onDeliverResourceFunc = reinterpret_cast<OnDeliverResourceFunc>(dlsym(pluginHandle,
303         "OnDeliverResource"));
304 
305     // OnDispatchResource is not necessary for plugin
306     auto onDumpFunc = reinterpret_cast<OnDumpFunc>(dlsym(pluginHandle, "OnDump"));
307 
308     PluginLib libInfo;
309     libInfo.handle = std::shared_ptr<void>(pluginHandle, dlclose);
310     libInfo.onPluginInitFunc_ = onPluginInitFunc;
311     libInfo.onDispatchResourceFunc_ = onDispatchResourceFunc;
312     libInfo.onDeliverResourceFunc_ = onDeliverResourceFunc;
313     libInfo.onDumpFunc_ = onDumpFunc;
314     libInfo.onPluginDisableFunc_ = onPluginDisableFunc;
315     return make_shared<PluginLib>(libInfo);
316 }
317 
CheckValidPlugin(const PluginInfo & info,void * pluginHandle,std::string & errorMsg,OnPluginInitFunc & onPluginInitFunc,OnPluginDisableFunc & onPluginDisableFunc)318 bool PluginMgr::CheckValidPlugin(const PluginInfo& info, void* pluginHandle, std::string& errorMsg,
319     OnPluginInitFunc& onPluginInitFunc, OnPluginDisableFunc& onPluginDisableFunc)
320 {
321     onPluginInitFunc = reinterpret_cast<OnPluginInitFunc>(dlsym(pluginHandle, "OnPluginInit"));
322     if (!onPluginInitFunc) {
323         RESSCHED_LOGE("%{public}s, dlsym OnPluginInit failed!", __func__);
324         errorMsg = "PluginMgr dlsym OnPluginInit " + info.libPath + "failed!";
325         return false;
326     }
327 
328     onPluginDisableFunc = reinterpret_cast<OnPluginDisableFunc>(dlsym(pluginHandle, "OnPluginDisable"));
329     if (!onPluginDisableFunc) {
330         RESSCHED_LOGE("%{public}s, dlsym OnPluginDisable failed!", __func__);
331         errorMsg = "PluginMgr don't found dlsym " + info.libPath + "!";
332         return false;
333     }
334 
335     if (!onPluginInitFunc(const_cast<std::string&>(info.libPath))) {
336         RESSCHED_LOGE("%{public}s, %{private}s init failed!", __func__, info.libPath.c_str());
337         errorMsg = "Plugin " + info.libPath + " init failed!";
338         return false;
339     }
340     return true;
341 }
342 
GetConfig(const std::string & pluginName,const std::string & configName)343 PluginConfig PluginMgr::GetConfig(const std::string& pluginName, const std::string& configName)
344 {
345     PluginConfig config;
346     if (!configReader_) {
347         return config;
348     }
349     return configReader_->GetConfig(pluginName, configName);
350 }
351 
RemoveConfig(const std::string & pluginName,const std::string & configName)352 void PluginMgr::RemoveConfig(const std::string& pluginName, const std::string& configName)
353 {
354     PluginConfig config;
355     if (!configReader_) {
356         return;
357     }
358     configReader_->RemoveConfig(pluginName, configName);
359 }
360 
Stop()361 void PluginMgr::Stop()
362 {
363     OnDestroy();
364 }
365 
366 #ifdef RESOURCE_SCHEDULE_SERVICE_WITH_EXT_RES_ENABLE
GetExtTypeByResPayload(const std::shared_ptr<ResData> & resData)367 int32_t PluginMgr::GetExtTypeByResPayload(const std::shared_ptr<ResData>& resData)
368 {
369     if (!resData || resData->resType != ResType::RES_TYPE_KEY_PERF_SCENE) {
370         return DEFAULT_VALUE;
371     }
372     auto payload = resData->payload;
373     if (!payload.contains(EXT_RES_KEY) || !payload[EXT_RES_KEY].is_string()) {
374         return DEFAULT_VALUE;
375     }
376     int type = DEFAULT_VALUE;
377     if (StrToInt(payload[EXT_RES_KEY], type)) {
378         return type;
379     } else {
380         return DEFAULT_VALUE;
381     }
382 }
383 #endif
384 
GetPluginListByResType(uint32_t resType,std::list<std::string> & pluginList)385 bool PluginMgr::GetPluginListByResType(uint32_t resType, std::list<std::string>& pluginList)
386 {
387     std::lock_guard<std::mutex> autoLock(resTypeMutex_);
388     auto iter = resTypeLibMap_.find(resType);
389     if (iter == resTypeLibMap_.end()) {
390         RESSCHED_LOGD("%{public}s, PluginMgr resType no lib register!", __func__);
391         return false;
392     }
393     pluginList = iter->second;
394     return true;
395 }
396 
BuildSimplifyLibAll(const std::list<std::string> & pluginList,std::string & simplifyLibAll)397 inline void BuildSimplifyLibAll(const std::list<std::string>& pluginList, std::string& simplifyLibAll)
398 {
399     for (const auto& libName : pluginList) {
400         simplifyLibAll.append(libName.substr(SIMPLIFY_LIB_INDEX, SIMPLIFY_LIB_LENGTH));
401     }
402 }
403 
GetResTypeList(std::set<uint32_t> & resTypeList)404 void PluginMgr::GetResTypeList(std::set<uint32_t>& resTypeList)
405 {
406     std::lock_guard<std::mutex> autoLock(resTypeMutex_);
407     for (auto& [type, pluginList] : resTypeLibMap_) {
408         resTypeList.insert(type);
409     }
410 }
411 
GetPluginLib(const std::string & libPath)412 std::shared_ptr<PluginLib> PluginMgr::GetPluginLib(const std::string& libPath)
413 {
414     std::lock_guard<std::mutex> autoLock(libPathMutex_);
415     auto iter = pluginLibMap_.find(libPath);
416     if (iter == pluginLibMap_.end()) {
417         RESSCHED_LOGE("%{public}s, PluginMgr libPath no lib register!", __func__);
418         return nullptr;
419     }
420     return make_shared<PluginLib>(iter->second);
421 }
422 
BuildDispatchTrace(const std::shared_ptr<ResData> & resData,std::string & libNameAll,const std::string & funcName,std::list<std::string> & pluginList)423 std::string PluginMgr::BuildDispatchTrace(const std::shared_ptr<ResData>& resData, std::string& libNameAll,
424     const std::string& funcName, std::list<std::string>& pluginList)
425 {
426     libNameAll.append("[");
427     for (const auto& libName : pluginList) {
428 #ifdef RESOURCE_SCHEDULE_SERVICE_WITH_FFRT_ENABLE
429         if (disablePlugins_.find(libName) != disablePlugins_.end()) {
430             continue;
431         }
432 #endif
433         libNameAll.append(libName);
434         libNameAll.append(",");
435     }
436     libNameAll.append("]");
437     string trace_str(funcName);
438     string resTypeString = GetStrFromResTypeStrMap(resData->resType);
439     trace_str.append(" PluginMgr ,resType[").append(std::to_string(resData->resType)).append("]");
440     trace_str.append(",resTypeStr[").append(resTypeString).append("]");
441     trace_str.append(",value[").append(std::to_string(resData->value)).append("]");
442     trace_str.append(",pluginlist:").append(libNameAll);
443     return trace_str;
444 }
445 
DispatchResource(const std::shared_ptr<ResData> & resData)446 void PluginMgr::DispatchResource(const std::shared_ptr<ResData>& resData)
447 {
448     if (!isInit.load()) {
449         RESSCHED_LOGE("%{public}s, not init.", __func__);
450         return;
451     }
452     if (!resData) {
453         RESSCHED_LOGE("%{public}s, failed, null res data.", __func__);
454         return;
455     }
456     std::list<std::string> pluginList;
457 #ifdef RESOURCE_SCHEDULE_SERVICE_WITH_EXT_RES_ENABLE
458     int32_t extType = GetExtTypeByResPayload(resData);
459     if (extType != DEFAULT_VALUE) {
460         resData->resType = (uint32_t)extType;
461     }
462 #endif
463     if (!GetPluginListByResType(resData->resType, pluginList)) {
464         return;
465     }
466     std::string libNameAll = "";
467     string trace_str = BuildDispatchTrace(resData, libNameAll, __func__, pluginList);
468     StartTrace(HITRACE_TAG_APP, trace_str, -1);
469     RESSCHED_LOGD("%{public}s, PluginMgr, resType = %{public}d, value = %{public}lld, pluginlist is %{public}s.",
470         __func__, resData->resType, (long long)resData->value, libNameAll.c_str());
471     FinishTrace(HITRACE_TAG_APP);
472     std::string simplifyLibAll = "";
473     BuildSimplifyLibAll(pluginList, simplifyLibAll);
474     BatchLogPrinter::GetInstance().SubmitLog(std::to_string(resData->resType).
475         append(",").append(std::to_string(resData->value)).append(",").append(simplifyLibAll));
476 #ifdef RESOURCE_SCHEDULE_SERVICE_WITH_FFRT_ENABLE
477     DispatchResourceToPluginAsync(pluginList, resData);
478 #else
479     std::lock_guard<ffrt::mutex> autoLock(dispatcherHandlerMutex_);
480     if (dispatcher_) {
481         dispatcher_->PostTask(
482             [pluginList, resData, this] {
483                 DispatchResourceToPluginSync(pluginList, resData);
484             });
485     }
486 #endif
487 }
488 
DeliverResource(const std::shared_ptr<ResData> & resData)489 int32_t PluginMgr::DeliverResource(const std::shared_ptr<ResData>& resData)
490 {
491     if (!isInit.load()) {
492         RESSCHED_LOGE("%{public}s, not init.", __func__);
493         return PLUGIN_REQUEST_ERROR;
494     }
495 
496     if (!resData) {
497         RESSCHED_LOGE("%{public}s, failed, null res data.", __func__);
498         return PLUGIN_REQUEST_ERROR;
499     }
500 
501     std::string pluginLib;
502     {
503         std::lock_guard<std::mutex> autoLock(resTypeSyncMutex_);
504         auto iter = resTypeLibSyncMap_.find(resData->resType);
505         if (iter == resTypeLibSyncMap_.end()) {
506             RESSCHED_LOGE("%{public}s, PluginMgr resType %{public}d no lib register!", __func__, resData->resType);
507             return PLUGIN_REQUEST_ERROR;
508         }
509         pluginLib = iter->second;
510     }
511 
512     PluginLib libInfo;
513     {
514         std::lock_guard<std::mutex> autoLock(pluginMutex_);
515         auto itMap = pluginLibMap_.find(pluginLib);
516         if (itMap == pluginLibMap_.end()) {
517             RESSCHED_LOGE("%{public}s, no plugin %{public}s!", __func__, pluginLib.c_str());
518             return PLUGIN_REQUEST_ERROR;
519         }
520         libInfo = itMap->second;
521     }
522 
523     OnDeliverResourceFunc pluginDeliverFunc = libInfo.onDeliverResourceFunc_;
524     if (!pluginDeliverFunc) {
525         RESSCHED_LOGE("%{public}s, %{public}s no DeliverResourceFunc!", __func__, pluginLib.c_str());
526         return PLUGIN_REQUEST_ERROR;
527     }
528     RESSCHED_LOGD("%{public}s, PluginMgr, resType = %{public}d, value = %{public}lld, plugin is %{public}s.",
529         __func__, resData->resType, (long long)resData->value, pluginLib.c_str());
530 
531     int32_t ret;
532     {
533         std::string libName = "";
534         std::list<std::string> pluginList = { pluginLib };
535         std::string traceStr = BuildDispatchTrace(resData, libName, __func__, pluginList);
536         HitraceScoped hitrace(HITRACE_TAG_OHOS, traceStr);
537         InnerTimeUtil timeUtil(__func__, pluginLib);
538         ret = pluginDeliverFunc(resData);
539     }
540     return ret;
541 }
542 
SubscribeResource(const std::string & pluginLib,uint32_t resType)543 void PluginMgr::SubscribeResource(const std::string& pluginLib, uint32_t resType)
544 {
545     if (pluginLib.size() == 0) {
546         RESSCHED_LOGE("%{public}s, PluginMgr failed, pluginLib is null.", __func__);
547         return;
548     }
549     std::lock_guard<std::mutex> autoLock(resTypeMutex_);
550     resTypeLibMap_[resType].emplace_back(pluginLib);
551 }
552 
UnSubscribeResource(const std::string & pluginLib,uint32_t resType)553 void PluginMgr::UnSubscribeResource(const std::string& pluginLib, uint32_t resType)
554 {
555     if (pluginLib.size() == 0) {
556         RESSCHED_LOGE("%{public}s, PluginMgr failed, pluginLib is null.", __func__);
557         return;
558     }
559     std::lock_guard<std::mutex> autoLock(resTypeMutex_);
560     auto iter = resTypeLibMap_.find(resType);
561     if (iter == resTypeLibMap_.end()) {
562         RESSCHED_LOGE("%{public}s, PluginMgr failed, res type has no plugin subscribe.", __func__);
563         return;
564     }
565 
566     iter->second.remove(pluginLib);
567     if (iter->second.empty()) {
568         resTypeLibMap_.erase(iter);
569     }
570 }
571 
UnSubscribeAllResources(const std::string & pluginLib)572 void PluginMgr::UnSubscribeAllResources(const std::string& pluginLib)
573 {
574     if (pluginLib.size() == 0) {
575         RESSCHED_LOGE("%{public}s, PluginMgr failed, pluginLib is null.", __func__);
576         return;
577     }
578     std::lock_guard<std::mutex> autoLock(resTypeMutex_);
579     std::unordered_set<uint32_t> keysToDelete;
580     for (auto iter : resTypeLibMap_) {
581         auto it = std::find(iter.second.begin(), iter.second.end(), pluginLib);
582         if (it != iter.second.end()) {
583             iter.second.erase(it);
584         }
585         if (iter.second.empty()) {
586             keysToDelete.insert(iter.first);
587         }
588     }
589     for (auto key : keysToDelete) {
590         resTypeLibMap_.erase(key);
591     }
592 }
593 
SubscribeSyncResource(const std::string & pluginLib,uint32_t resType)594 void PluginMgr::SubscribeSyncResource(const std::string& pluginLib, uint32_t resType)
595 {
596     if (pluginLib.empty()) {
597         RESSCHED_LOGE("%{public}s, PluginMgr failed, pluginLib is null.", __func__);
598         return;
599     }
600     std::lock_guard<std::mutex> autoLock(resTypeSyncMutex_);
601     auto iter = resTypeLibSyncMap_.find(resType);
602     if (iter != resTypeLibSyncMap_.end()) {
603         RESSCHED_LOGW("%{public}s, resType[%{public}d] subcribed by [%{public}s], replace by [%{public}s].",
604             __func__, resType, iter->second.c_str(), pluginLib.c_str());
605     }
606     resTypeLibSyncMap_[resType] = pluginLib;
607 }
608 
UnSubscribeSyncResource(const std::string & pluginLib,uint32_t resType)609 void PluginMgr::UnSubscribeSyncResource(const std::string& pluginLib, uint32_t resType)
610 {
611     if (pluginLib.empty()) {
612         RESSCHED_LOGE("%{public}s, PluginMgr failed, pluginLib is null.", __func__);
613         return;
614     }
615     std::lock_guard<std::mutex> autoLock(resTypeSyncMutex_);
616     auto iter = resTypeLibSyncMap_.find(resType);
617     if (iter == resTypeLibSyncMap_.end()) {
618         RESSCHED_LOGE("%{public}s, PluginMgr failed, res type has no plugin subscribe.", __func__);
619         return;
620     }
621     resTypeLibSyncMap_.erase(iter);
622 }
623 
DumpAllPlugin(std::string & result)624 void PluginMgr::DumpAllPlugin(std::string &result)
625 {
626     std::list<PluginInfo> pluginInfoList = pluginSwitch_->GetPluginSwitch();
627     for (const auto& info : pluginInfoList) {
628         result.append(info.libPath).append(" ");
629         DumpPluginInfoAppend(result, info);
630     }
631 }
632 
DumpAllPluginConfig(std::string & result)633 void PluginMgr::DumpAllPluginConfig(std::string &result)
634 {
635     std::list<PluginInfo> pluginInfoList = pluginSwitch_->GetPluginSwitch();
636     result.append("================Resource Schedule Plugin Switch================\n");
637     for (const auto& info : pluginInfoList) {
638         result.append(info.libPath).append(" ").append(std::to_string(info.switchOn)).append("\n");
639     }
640     configReader_->Dump(result);
641 }
642 
DumpOnePlugin(std::string & result,std::string pluginName,std::vector<std::string> & args)643 void PluginMgr::DumpOnePlugin(std::string &result, std::string pluginName, std::vector<std::string>& args)
644 {
645     std::list<PluginInfo> pluginInfoList = pluginSwitch_->GetPluginSwitch();
646     auto pos = std::find_if(pluginInfoList.begin(),
647         pluginInfoList.end(), [&pluginName](PluginInfo &info) { return pluginName == info.libPath; });
648     if (pos == pluginInfoList.end()) {
649         result.append(" Error params.\n");
650         return;
651     }
652     if (args.size() == 0) {
653         result.append(pluginName).append(" ");
654         DumpPluginInfoAppend(result, *pos);
655     } else {
656         result.append("\n");
657         std::string errMsg = DumpInfoFromPlugin(result, pos->libPath, args);
658         if (errMsg != "") {
659             result.append(errMsg);
660         }
661     }
662 }
663 
DumpInfoFromPlugin(std::string & result,std::string libPath,std::vector<std::string> & args)664 std::string PluginMgr::DumpInfoFromPlugin(std::string& result, std::string libPath, std::vector<std::string>& args)
665 {
666     std::lock_guard<std::mutex> autoLock(pluginMutex_);
667     auto pluginLib = pluginLibMap_.find(libPath);
668     if (pluginLib == pluginLibMap_.end()) {
669         return "Error params.";
670     }
671 
672     if (pluginLib->second.onDumpFunc_) {
673         pluginLib->second.onDumpFunc_(args, result);
674         result.append("\n");
675     }
676     return "";
677 }
678 
DumpHelpFromPlugin(std::string & result)679 void PluginMgr::DumpHelpFromPlugin(std::string& result)
680 {
681     std::vector<std::string> args;
682     args.emplace_back("-h");
683     std::string pluginHelpMsg = "";
684     std::list<PluginInfo> pluginInfoList = pluginSwitch_->GetPluginSwitch();
685     for (auto &pluginInfo : pluginInfoList) {
686         DumpInfoFromPlugin(pluginHelpMsg, pluginInfo.libPath, args);
687     }
688     result.append(pluginHelpMsg);
689 }
690 
DumpPluginInfoAppend(std::string & result,PluginInfo info)691 void PluginMgr::DumpPluginInfoAppend(std::string &result, PluginInfo info)
692 {
693     if (info.switchOn) {
694         result.append(" | switch on\t");
695     } else {
696         result.append(" | switch off\t");
697     }
698     std::lock_guard<std::mutex> autoLock(pluginMutex_);
699     if (pluginLibMap_.find(info.libPath) != pluginLibMap_.end()) {
700         result.append(" | running now\n");
701     } else {
702         result.append(" | disabled\n");
703     }
704 }
705 
ClearResource()706 void PluginMgr::ClearResource()
707 {
708     {
709         std::lock_guard<std::mutex> autoLock(resTypeMutex_);
710         resTypeLibMap_.clear();
711     }
712     {
713         std::lock_guard<std::mutex> autoLock(resTypeSyncMutex_);
714         resTypeLibSyncMap_.clear();
715     }
716     {
717         std::lock_guard<std::mutex> autoLock(resTypeStrMutex_);
718         resTypeStrMap_.clear();
719     }
720     {
721         std::lock_guard<std::mutex> autoLock(linkJumpOptMutex_);
722         linkJumpOptSet_.clear();
723     }
724 }
725 
RepairPlugin(TimePoint endTime,const std::string & pluginLib,PluginLib libInfo)726 void PluginMgr::RepairPlugin(TimePoint endTime, const std::string& pluginLib, PluginLib libInfo)
727 {
728     auto& timeOutTime = pluginStat_[pluginLib].timeOutTime;
729     int32_t crash_time = (int32_t)((endTime - timeOutTime.front()) / std::chrono::milliseconds(1));
730     timeOutTime.emplace_back(endTime);
731     RESSCHED_LOGW("%{public}s %{public}s crash %{public}d times in %{public}d ms!", __func__,
732         pluginLib.c_str(), (int32_t)timeOutTime.size(), crash_time);
733     if ((int32_t)timeOutTime.size() >= MAX_PLUGIN_TIMEOUT_TIMES) {
734         if (crash_time < DISABLE_PLUGIN_TIME) {
735             // disable plugin forever
736             RESSCHED_LOGE("%{public}s, %{public}s disable it forever.", __func__, pluginLib.c_str());
737             if (libInfo.onPluginDisableFunc_) {
738                 libInfo.onPluginDisableFunc_();
739             }
740             HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::RSS, "PLUGIN_DISABLE",
741                 HiSysEvent::EventType::FAULT, "plugin_name", pluginLib);
742             timeOutTime.clear();
743             pluginMutex_.lock();
744             pluginLibMap_.erase(pluginLib);
745             pluginMutex_.unlock();
746             return;
747         }
748 
749         timeOutTime.pop_front();
750     }
751 
752     if (libInfo.onPluginDisableFunc_ && libInfo.onPluginInitFunc_) {
753         RESSCHED_LOGW("%{public}s, %{public}s disable and enable it.", __func__, pluginLib.c_str());
754         libInfo.onPluginDisableFunc_();
755         libInfo.onPluginInitFunc_(const_cast<std::string&>(pluginLib));
756     }
757 }
758 
DispatchResourceToPluginSync(const std::list<std::string> & pluginList,const std::shared_ptr<ResData> & resData)759 void PluginMgr::DispatchResourceToPluginSync(const std::list<std::string>& pluginList,
760     const std::shared_ptr<ResData>& resData)
761 {
762     auto sortPluginList = SortPluginList(pluginList);
763     for (auto& pluginLib : sortPluginList) {
764         PluginLib libInfo;
765         {
766             std::lock_guard<std::mutex> autoLock(pluginMutex_);
767             auto itMap = pluginLibMap_.find(pluginLib);
768             if (itMap == pluginLibMap_.end()) {
769                 RESSCHED_LOGE("%{public}s, no plugin %{public}s !", __func__, pluginLib.c_str());
770                 continue;
771             }
772             libInfo = itMap->second;
773         }
774         OnDispatchResourceFunc pluginDispatchFunc = libInfo.onDispatchResourceFunc_;
775         if (!pluginDispatchFunc) {
776             RESSCHED_LOGE("%{public}s, no DispatchResourceFun !", __func__);
777             continue;
778         }
779 
780         StartTrace(HITRACE_TAG_APP, pluginLib);
781         auto beginTime = Clock::now();
782         pluginDispatchFunc(std::make_shared<ResData>(resData->resType, resData->value, resData->payload));
783         auto endTime = Clock::now();
784         FinishTrace(HITRACE_TAG_APP);
785         int32_t costTimeUs = (endTime - beginTime) / std::chrono::microseconds(1);
786         int32_t costTime = costTimeUs / 1000;
787         pluginStat_[pluginLib].Update(costTimeUs);
788 
789         if (costTime > DISPATCH_TIME_OUT) {
790             // dispatch resource use too long time, unload it
791             RESSCHED_LOGE("%{public}s, ERROR :%{public}s cost time(%{public}dms) over %{public}d ms! disable it.",
792                 __func__, pluginLib.c_str(), costTime, DISPATCH_TIME_OUT);
793             RepairPlugin(endTime, pluginLib, libInfo);
794         } else if (costTime > DISPATCH_WARNING_TIME) {
795             RESSCHED_LOGW("%{public}s, WARNING :%{public}s plugin cost time(%{public}dms) over %{public}d ms!",
796                 __func__, pluginLib.c_str(), costTime, DISPATCH_WARNING_TIME);
797         }
798     }
799 }
800 
801 #ifdef RESOURCE_SCHEDULE_SERVICE_WITH_FFRT_ENABLE
DispatchResourceToPluginAsync(const std::list<std::string> & pluginList,const std::shared_ptr<ResData> & resData)802 void PluginMgr::DispatchResourceToPluginAsync(const std::list<std::string>& pluginList,
803     const std::shared_ptr<ResData>& resData)
804 {
805     for (auto& pluginLib : pluginList) {
806         if (disablePlugins_.find(pluginLib) != disablePlugins_.end()) {
807             continue;
808         }
809         PluginLib libInfo;
810         {
811             std::lock_guard<std::mutex> autoLock(pluginMutex_);
812             auto itMap = pluginLibMap_.find(pluginLib);
813             if (itMap == pluginLibMap_.end()) {
814                 RESSCHED_LOGE("%{public}s, no plugin %{public}s !", __func__, pluginLib.c_str());
815                 continue;
816             }
817             libInfo = itMap->second;
818         }
819         OnDispatchResourceFunc pluginDispatchFunc = libInfo.onDispatchResourceFunc_;
820         if (!pluginDispatchFunc) {
821             RESSCHED_LOGE("%{public}s, no DispatchResourceFun !", __func__);
822             continue;
823         }
824         std::lock_guard<ffrt::mutex> autoLock(dispatcherHandlerMutex_);
825         dispatchers_[pluginLib]->submit(
826             [pluginLib, resData, pluginDispatchFunc] {
827                 StartTrace(HITRACE_TAG_APP, pluginLib);
828                 pluginDispatchFunc(std::make_shared<ResData>(resData->resType, resData->value, resData->payload));
829                 FinishTrace(HITRACE_TAG_APP);
830             });
831     }
832 }
833 
EnablePluginIfResume(const std::string & pluginLib)834 void PluginMgr::EnablePluginIfResume(const std::string& pluginLib)
835 {
836     std::lock_guard<ffrt::mutex> autoLock(dispatcherHandlerMutex_);
837     ffrt_queue_cancel_all(*reinterpret_cast<ffrt_queue_t*>(dispatchers_[pluginLib].get()));
838     if (!IsPluginRunning(pluginLib)) {
839         disablePlugins_.erase(pluginLib);
840     } else {
841         StartTrace(HITRACE_TAG_APP, "Blocked plugin:" + pluginLib, -1);
842         RESSCHED_LOGI("plugin:%{public}s been locked!", pluginLib.c_str());
843         FinishTrace(HITRACE_TAG_APP);
844         ffrt::submit([lib = pluginLib]() {
845             PluginMgr::GetInstance().EnablePluginIfResume(lib);
846             }, {}, {}, ffrt::task_attr().delay(pluginBlockTime));
847     }
848 }
849 
HandlePluginTimeout(const std::string & pluginLib)850 void PluginMgr::HandlePluginTimeout(const std::string& pluginLib)
851 {
852     std::lock_guard<ffrt::mutex> autoLock(dispatcherHandlerMutex_);
853     ffrt_queue_cancel_all(*reinterpret_cast<ffrt_queue_t*>(dispatchers_[pluginLib].get()));
854     if (IsPluginRunning(pluginLib)) {
855         RESSCHED_LOGI("%{public}s, %{public}s has blocked task, stop dispatch resource to it!",
856             __func__, pluginLib.c_str());
857             disablePlugins_.insert(pluginLib);
858     } else {
859         RESSCHED_LOGI("%{public}s, %{public}s all tasks cancled!", __func__, pluginLib.c_str());
860     }
861 }
862 
RecordRinningStat(std::string pluginLib,bool isRunning)863 void PluginMgr::RecordRinningStat(std::string pluginLib, bool isRunning)
864 {
865     std::lock_guard<ffrt::mutex> autoLock(runningStatsMutex_);
866     runningStats_[pluginLib] = isRunning;
867 }
868 
IsPluginRunning(const std::string & pluginLib)869 bool PluginMgr::IsPluginRunning(const std::string& pluginLib)
870 {
871     std::lock_guard<ffrt::mutex> autoLock(runningStatsMutex_);
872     auto stateItem = runningStats_.find(pluginLib);
873     if (stateItem == runningStats_.end()) {
874         return false;
875     }
876     return stateItem->second;
877 }
878 #endif
879 
UnLoadPlugin()880 void PluginMgr::UnLoadPlugin()
881 {
882     std::lock_guard<std::mutex> autoLock(pluginMutex_);
883     // unload all plugin
884     for (const auto& [libPath, libInfo] : pluginLibMap_) {
885         if (!libInfo.onPluginDisableFunc_) {
886             continue;
887         }
888         libInfo.onPluginDisableFunc_();
889     }
890     // close all plugin handle
891     pluginLibMap_.clear();
892 }
893 
OnDestroy()894 void PluginMgr::OnDestroy()
895 {
896     UnLoadPlugin();
897     configReader_ = nullptr;
898     pluginSwitch_ = nullptr;
899     ClearResource();
900     std::lock_guard<ffrt::mutex> autoLock(dispatcherHandlerMutex_);
901 #ifdef RESOURCE_SCHEDULE_SERVICE_WITH_FFRT_ENABLE
902     dispatchers_.clear();
903 #else
904     if (dispatcher_) {
905         dispatcher_->RemoveAllEvents();
906         dispatcher_ = nullptr;
907     }
908 #endif
909 }
910 
SetResTypeStrMap(const std::map<uint32_t,std::string> & resTypeStr)911 void PluginMgr::SetResTypeStrMap(const std::map<uint32_t, std::string>& resTypeStr)
912 {
913     std::lock_guard<std::mutex> autoLock(resTypeStrMutex_);
914     resTypeStrMap_ = resTypeStr;
915 }
916 
SetBlockedTime(const int64_t time)917 void PluginMgr::SetBlockedTime(const int64_t time)
918 {
919     pluginBlockTime = time;
920 }
921 
SetLinkJumpOptSet(const std::unordered_set<std::string> linkJumpOptSet)922 void PluginMgr::SetLinkJumpOptSet(const std::unordered_set<std::string> linkJumpOptSet)
923 {
924     std::lock_guard<std::mutex> autoLock(linkJumpOptMutex_);
925     linkJumpOptSet_ = linkJumpOptSet;
926 }
927 
GetLinkJumpOptConfig(const std::string & bundleName,bool & isAllowedLinkJump)928 bool PluginMgr::GetLinkJumpOptConfig(const std::string& bundleName, bool& isAllowedLinkJump)
929 {
930     std::lock_guard<std::mutex> autoLock(linkJumpOptMutex_);
931     auto iter = linkJumpOptSet_.find(bundleName);
932     if (iter != linkJumpOptSet_.end()) {
933         isAllowedLinkJump = true;
934         return true;
935     }
936     return false;
937 }
938 
GetStrFromResTypeStrMap(uint32_t resType)939 std::string PluginMgr::GetStrFromResTypeStrMap(uint32_t resType)
940 {
941     std::lock_guard<std::mutex> autoLock(resTypeStrMutex_);
942     return resTypeStrMap_.count(resType) ? resTypeStrMap_.at(resType) : "UNKNOWN";
943 }
944 
SortPluginList(const std::list<std::string> & pluginList)945 std::list<std::string> PluginMgr::SortPluginList(const std::list<std::string>& pluginList)
946 {
947     auto sortPluginList = pluginList;
948     sortPluginList.sort([&](const std::string& a, const std::string& b) -> bool {
949         if (pluginStat_.find(a) == pluginStat_.end() || pluginStat_.find(b) == pluginStat_.end()) {
950             return false;
951         }
952         return pluginStat_[a].AverageTime() < pluginStat_[b].AverageTime();
953     });
954     return sortPluginList;
955 }
956 
InnerTimeUtil(const std::string & func,const std::string & plugin)957 PluginMgr::InnerTimeUtil::InnerTimeUtil(const std::string& func, const std::string& plugin)
958 {
959     beginTime_ = Clock::now();
960     functionName_ = func;
961     pluginName_ = plugin;
962 }
963 
~InnerTimeUtil()964 PluginMgr::InnerTimeUtil::~InnerTimeUtil()
965 {
966     auto endTime = Clock::now();
967     int32_t costTime = (endTime - beginTime_) / std::chrono::milliseconds(1);
968     RESSCHED_LOGD("%{public}s, %{public}s plugin cost time(%{public}d ms).",
969         functionName_.c_str(), pluginName_.c_str(), costTime);
970     if (costTime > DISPATCH_WARNING_TIME) {
971         RESSCHED_LOGW("%{public}s, WARNING :%{public}s plugin cost time(%{public}d ms) over %{public}d ms!",
972             functionName_.c_str(), pluginName_.c_str(), costTime, DISPATCH_WARNING_TIME);
973     }
974 }
975 extern "C" {
SetBlockedTime(const int64_t time)976     void SetBlockedTime(const int64_t time)
977     {
978         PluginMgr::GetInstance().SetBlockedTime(time);
979     }
980 }
981 } // namespace ResourceSchedule
982 } // namespace OHOS