1 /*
2  * Copyright (c) 2022-2023 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 #ifndef RESSCHED_SERVICES_RESSCHEDMGR_RESSCHEDFWK_INCLUDE_PLUGIN_MGR_H
17 #define RESSCHED_SERVICES_RESSCHEDMGR_RESSCHEDFWK_INCLUDE_PLUGIN_MGR_H
18 
19 #include <atomic>
20 #include <functional>
21 #include <list>
22 #include <string>
23 #include <memory>
24 #include <map>
25 #include <vector>
26 #include <unordered_set>
27 #include "datetime_ex.h"
28 #include "event_handler.h"
29 #include "config_reader.h"
30 #include "plugin_switch.h"
31 #include "plugin.h"
32 #include "nocopyable.h"
33 #include "res_data.h"
34 #include "single_instance.h"
35 #include "config_info.h"
36 #include "ffrt.h"
37 #ifdef RESOURCE_SCHEDULE_SERVICE_WITH_EXT_RES_ENABLE
38 #include "res_type.h"
39 #endif
40 
41 namespace OHOS {
42 namespace ResourceSchedule {
43 using Clock = std::chrono::high_resolution_clock;
44 using TimePoint = std::chrono::time_point<Clock>;
45 using OnPluginInitFunc = bool (*)(std::string&);
46 using OnDispatchResourceFunc = void (*)(const std::shared_ptr<ResData>&);
47 using OnDeliverResourceFunc = int32_t (*)(const std::shared_ptr<ResData>&);
48 using OnDumpFunc = void (*)(const std::vector<std::string>&, std::string&);
49 using OnPluginDisableFunc = void (*)();
50 using OnIsAllowedAppPreloadFunc = bool (*)(const std::string&, int32_t preloadMode);
51 using GetExtMultiConfigFunc = int32_t (*)(int32_t, std::vector<std::string>&);
52 
53 constexpr int32_t DISPATCH_TIME_OUT = 50; // ms
54 constexpr int32_t DISPATCH_TIME_OUT_US = DISPATCH_TIME_OUT * 1000; // us
55 constexpr int32_t PLUGIN_STAT_MAX_USE_COUNT = 1000;
56 
57 struct PluginStat {
58     uint64_t totalTime;
59     uint64_t useCount;
60     std::list<TimePoint> timeOutTime;
61 
UpdateOHOS::ResourceSchedule::PluginStat62     inline void Update(int32_t costTime)
63     {
64         if (costTime > 0 && costTime < DISPATCH_TIME_OUT_US) {
65             if (totalTime + (uint32_t)costTime < totalTime) {
66                 totalTime = (uint32_t)costTime;
67                 useCount = 1;
68             } else {
69                 totalTime += (uint32_t)costTime;
70                 useCount += 1;
71             }
72         }
73     }
74 
AverageTimeOHOS::ResourceSchedule::PluginStat75     inline uint64_t AverageTime()
76     {
77         return (useCount > 0) ? (totalTime / useCount) : 0;
78     }
79 };
80 
81 struct PluginLib {
82     std::shared_ptr<void> handle = nullptr;
83     OnPluginInitFunc onPluginInitFunc_;
84     OnDispatchResourceFunc onDispatchResourceFunc_;
85     OnDeliverResourceFunc onDeliverResourceFunc_;
86     OnDumpFunc onDumpFunc_;
87     OnPluginDisableFunc onPluginDisableFunc_;
88 };
89 
90 class PluginMgr {
91     DECLARE_SINGLE_INSTANCE_BASE(PluginMgr);
92 
93 public:
94     ~PluginMgr();
95 
96     /**
97      * Init pluginmanager, load xml config file, construct plugin instances.
98      *
99      * @param isRssExe Calling service is resource schedule executor.
100      */
101     void Init(bool isRssExe = false);
102 
103     /**
104      * Disable all plugins, maybe service exception happens or stopped.
105      */
106     void Stop();
107 
108     /**
109      * receive all reported resource data, then dispatch all plugins.
110      *
111      * @param resData Reported resource data.
112      */
113     void DispatchResource(const std::shared_ptr<ResData>& resData);
114 
115     /**
116      * receive all reported sync resource data, then deliver to plugins.
117      *
118      * @param resData Reported resource data.
119      */
120     int32_t DeliverResource(const std::shared_ptr<ResData>& resData);
121 
122     /**
123      * Subscribe resource type from plugin.
124      *
125      * @param pluginLib The lib name of plugin.
126      * @param resType interested in resource type.
127      */
128     void SubscribeResource(const std::string& pluginLib, uint32_t resType);
129 
130     /**
131      * Unsubscribe resource type from plugin.
132      *
133      * @param pluginLib The lib name of plugin.
134      * @param resType interested in resource type.
135      */
136     void UnSubscribeResource(const std::string& pluginLib, uint32_t resType);
137 
138     /**
139      * Subscribe sync resource type from plugin.
140      *
141      * @param pluginLib The lib name of plugin.
142      * @param resType interested in resource type.
143      */
144     void SubscribeSyncResource(const std::string& pluginLib, uint32_t resType);
145 
146     /**
147      * Unsubscribe sync resource type from plugin.
148      *
149      * @param pluginLib The lib name of plugin.
150      * @param resType interested in resource type.
151      */
152     void UnSubscribeSyncResource(const std::string& pluginLib, uint32_t resType);
153 
154     /**
155      * Kill process by pid.
156      *
157      * @param payload process message.
158      */
159     void KillProcessByPid(const nlohmann::json& payload, std::string killClientInitiator);
160 
161     void DumpAllPlugin(std::string &result);
162 
163     void DumpAllPluginConfig(std::string &result);
164 
165     void DumpOnePlugin(std::string &result, std::string pluginName, std::vector<std::string>& args);
166 
167     std::string DumpInfoFromPlugin(std::string& result, std::string libPath, std::vector<std::string>& args);
168 
169     void DumpHelpFromPlugin(std::string& result);
170 
171     PluginConfig GetConfig(const std::string& pluginName, const std::string& configName);
172 
173     void SetResTypeStrMap(const std::map<uint32_t, std::string>& resTypeStr);
174 
175     std::shared_ptr<PluginLib> GetPluginLib(const std::string& libPath);
176 
177     void GetConfigContent(int32_t configIdx, const std::string& configPath, std::vector<std::string>& contents);
178 
179     /**
180      * Get config reader xml file.
181      *
182      * @return config reader xml file string.
183      */
184     std::vector<std::string> GetConfigReaderStr();
185 
186     /**
187      * Get plugin switch xml file.
188      *
189      * @return plugin switch xml file string.
190      */
191     std::vector<std::string> GetPluginSwitchStr();
192 
193     /**
194      * Parse config reader xml file.
195      *
196      * @param configStr The string of config reader xml file.
197      */
198     void ParseConfigReader(const std::vector<std::string>& configStrs);
199 
200     /**
201      * Parse plugin switch xml file.
202      *
203      * @param switchStr The string of plugin switch xml file.
204      * @param isRssExe is calling service resource_schedule_executor.
205      */
206     void ParsePluginSwitch(const std::vector<std::string>& switchStrs, bool isRssExe = false);
207 
208     /**
209      * set plugin blocked time.
210      *
211      * @param time over time will be judge blocked
212      */
213     void SetBlockedTime(const int64_t time);
214 
215 private:
216     PluginMgr() = default;
217     void OnDestroy();
218     void LoadPlugin();
219     void LoadGetExtConfigFunc();
220     std::shared_ptr<PluginLib> LoadOnePlugin(const PluginInfo& info);
221     void UnLoadPlugin();
222     void ClearResource();
223     void DispatchResourceToPluginSync(const std::list<std::string>& pluginList,
224         const std::shared_ptr<ResData>& resData);
225 #ifdef RESOURCE_SCHEDULE_SERVICE_WITH_FFRT_ENABLE
226     void DispatchResourceToPluginAsync(const std::list<std::string>& pluginList,
227         const std::shared_ptr<ResData>& resData);
228     void HandlePluginTimeout(const std::string& pluginLib);
229     void EnablePluginIfResume(const std::string& pluginLib);
230     void RecordRinningStat(std::string pluginLib, bool isRunning);
231     bool IsPluginRunning(const std::string& pluginLib);
232 #endif
233     void RepairPlugin(TimePoint endTime, const std::string& pluginLib, PluginLib libInfo);
234     void RemoveDisablePluginHandler();
235     void DumpPluginInfoAppend(std::string &result, PluginInfo info);
236     bool GetPluginListByResType(uint32_t resType, std::list<std::string>& pluginList);
237     bool CheckRealPath(const std::string& partialPath, std::string& fullPath);
238     std::vector<std::string> GetAllRealConfigPath(const std::string& configName);
239     std::string BuildDispatchTrace(const std::shared_ptr<ResData>& resData, std::string& libNameAll,
240         const std::string& funcName, std::list<std::string>& pluginList);
241 #ifdef RESOURCE_SCHEDULE_SERVICE_WITH_EXT_RES_ENABLE
242     int32_t GetExtTypeByResPayload(const std::shared_ptr<ResData>& resData);
243 #endif
244     std::list<std::string> SortPluginList(const std::list<std::string>& pluginList);
245     std::string GetStrFromResTypeStrMap(uint32_t resType);
246     class InnerTimeUtil {
247     public:
248         InnerTimeUtil(const std::string& func, const std::string& plugin);
249         ~InnerTimeUtil();
250     private:
251         TimePoint beginTime_;
252         std::string functionName_;
253         std::string pluginName_;
254     };
255 
256     // plugin crash 3 times in 60s, will be disable forever
257     const int32_t MAX_PLUGIN_TIMEOUT_TIMES = 3;
258     const int32_t DISABLE_PLUGIN_TIME = 60000;
259     const int32_t DUMP_ONE_STRING_SIZE = 32;
260     int64_t pluginBlockTime = 10 * 60 * 1000 * 1000;
261     std::unique_ptr<ConfigReader> configReader_ = nullptr;
262     std::unique_ptr<PluginSwitch> pluginSwitch_ = nullptr;
263 
264     std::map<std::string, PluginLib> pluginLibMap_;
265 
266     // mutex for resTypeMap_
267     std::mutex resTypeMutex_;
268     // mutex for resTypeLibSyncMap_
269     std::mutex resTypeSyncMutex_;
270     // mutex for resTypeStrMap_
271     std::mutex resTypeStrMutex_;
272     std::mutex pluginMutex_;
273     ffrt::mutex dispatcherHandlerMutex_;
274     std::mutex libPathMutex_;
275     std::map<uint32_t, std::list<std::string>> resTypeLibMap_;
276     std::map<uint32_t, std::string> resTypeLibSyncMap_;
277     std::map<uint32_t, std::string> resTypeStrMap_;
278 
279 #ifdef RESOURCE_SCHEDULE_SERVICE_WITH_FFRT_ENABLE
280     std::map<std::string, std::shared_ptr<ffrt::queue>> dispatchers_;
281     ffrt::mutex runningStatsMutex_;
282     std::map<std::string, bool> runningStats_;
283     std::unordered_set<std::string> disablePlugins_;
284 #else
285     std::shared_ptr<AppExecFwk::EventHandler> dispatcher_ = nullptr;
286 #endif
287     std::atomic<bool> isInit = {false};
288 
289     std::map<std::string, PluginStat> pluginStat_;
290     GetExtMultiConfigFunc getExtMultiConfigFunc_ = nullptr;
291 };
292 } // namespace ResourceSchedule
293 } // namespace OHOS
294 
295 #endif // RESSCHED_SERVICES_RESSCHEDMGR_RESSCHEDFWK_INCLUDE_PLUGIN_MGR_H
296