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