• 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 
16 #ifndef RELIABILITY_WATCHDOG_INNER_H
17 #define RELIABILITY_WATCHDOG_INNER_H
18 
19 #include <atomic>
20 #include <condition_variable>
21 #include <csignal>
22 #include <memory>
23 #include <mutex>
24 #include <queue>
25 #include <set>
26 #include <string>
27 #include <thread>
28 
29 #include "watchdog_task.h"
30 #include "c/ffrt_dump.h"
31 #include "singleton.h"
32 #include "client/trace_collector_client.h"
33 
34 namespace OHOS {
35 namespace HiviewDFX {
36 constexpr const char* const KEY_SAMPLE_INTERVAL = "sample_interval";
37 constexpr const char* const KEY_SAMPLE_COUNT = "sample_count";
38 constexpr const char* const KEY_SAMPLE_REPORT_TIMES = "report_times_per_app";
39 constexpr const char* const KEY_LOG_TYPE = "log_type";
40 constexpr const char* const KEY_SET_TIMES_FLAG = "set_report_times_flag";
41 constexpr const char* const KEY_IGNORE_STARTUP_TIME = "ignore_startup_time";
42 const int SAMPLE_DEFULE_INTERVAL = 150;
43 const int SAMPLE_DEFULE_COUNT = 10;
44 const int SAMPLE_DEFULE_REPORT_TIMES = 1;
45 const int SET_TIMES_FLAG = 1;
46 const int DEFAULT_IGNORE_STARTUP_TIME = 10; // 10s
47 
48 using TimePoint = AppExecFwk::InnerEvent::TimePoint;
49 struct TimeContent {
50     int64_t curBegin;
51     int64_t curEnd;
52 };
53 
54 struct StackContent {
55     bool isStartSampleEnabled {true};
56     int detectorCount {0};
57     int collectCount {0};
58     int reportTimes {SAMPLE_DEFULE_REPORT_TIMES};
59     int scrollTimes {SAMPLE_DEFULE_REPORT_TIMES};
60     int64_t reportBegin {0};
61     int64_t reportEnd {0};
62     TimePoint lastEndTime;
63 };
64 
65 struct TraceContent {
66     int traceState {0};
67     int traceCount {0};
68     int dumpCount {0};
69     int64_t reportBegin {0};
70     int64_t reportEnd {0};
71     TimePoint lastEndTime;
72 };
73 
74 typedef void (*WatchdogInnerBeginFunc)(const char* eventName);
75 typedef void (*WatchdogInnerEndFunc)(const char* eventName);
76 
77 typedef int (*ThreadSamplerInitFunc)(int);
78 typedef int32_t (*ThreadSamplerSampleFunc)();
79 typedef int (*ThreadSamplerCollectFunc)(char*, char*, size_t, size_t, int);
80 typedef int (*ThreadSamplerDeinitFunc)();
81 typedef void (*SigActionType)(int, siginfo_t*, void*);
82 
83 class WatchdogInner : public Singleton<WatchdogInner> {
84     DECLARE_SINGLETON(WatchdogInner);
85 public:
86     static const int XCOLLIE_CALLBACK_HISTORY_MAX = 5;
87     static const int XCOLLIE_CALLBACK_TIMEWIN_MAX = 60;
88     std::map<int64_t, int> taskIdCnt;
89     int AddThread(const std::string &name, std::shared_ptr<AppExecFwk::EventHandler> handler, uint64_t interval);
90     int AddThread(const std::string &name, std::shared_ptr<AppExecFwk::EventHandler> handler,
91         TimeOutCallback timeOutCallback, uint64_t interval);
92     void RunOneShotTask(const std::string& name, Task&& task, uint64_t delay);
93     void RunPeriodicalTask(const std::string& name, Task&& task, uint64_t interval, uint64_t delay);
94     int64_t RunXCollieTask(const std::string& name, uint64_t timeout, XCollieCallback func, void *arg,
95         unsigned int flag);
96     void RemoveXCollieTask(int64_t id);
97     int64_t SetTimerCountTask(const std::string &name, uint64_t timeLimit, int countLimit);
98     void TriggerTimerCountTask(const std::string &name, bool bTrigger, const std::string &message);
99     void StopWatchdog();
100     bool IsCallbackLimit(unsigned int flag);
101     void IpcCheck();
102     void InitFfrtWatchdog();
103     static bool WriteStringToFile(uint32_t pid, const char *str);
104     static void FfrtCallback(uint64_t taskId, const char *taskInfo, uint32_t delayedTaskCount);
105     static void SendFfrtEvent(const std::string &msg, const std::string &eventName, const char *taskInfo);
106     static void LeftTimeExitProcess(const std::string &description);
107     static void KillPeerBinderProcess(const std::string &description);
108     bool StartScrollProfile(const TimePoint& endTime, int64_t durationTime, int sampleInterval);
109     void StartProfileMainThread(const TimePoint& endTime, int64_t durationTime, int sampleInterval);
110     bool CollectStack(std::string& stack, std::string& heaviestStack);
111     bool Deinit();
112     void SetBundleInfo(const std::string& bundleName, const std::string& bundleVersion);
113     void SetForeground(const bool& isForeground);
114     void RemoveInnerTask(const std::string& name);
115     void InitMainLooperWatcher(WatchdogInnerBeginFunc* beginFunc, WatchdogInnerEndFunc* endFunc);
116     void SetAppDebug(bool isAppDebug);
117     bool GetAppDebug();
118     int SetEventConfig(std::map<std::string, std::string> paramsMap);
119     bool SampleStackDetect(const TimePoint& endTime, int& reportTimes, int updateTimes,
120         int ignoreTime = DEFAULT_IGNORE_STARTUP_TIME);
121     void CollectTraceDetect(const TimePoint& endTime, int64_t durationTime);
122     void SetSpecifiedProcessName(const std::string& name);
123     std::string GetSpecifiedProcessName();
124     void SetScrollState(bool isScroll);
125 
126 public:
127     std::string currentScene_;
128     TimePoint bussinessBeginTime_;
129     TimeContent timeContent_ {0};
130     StackContent stackContent_;
131     TraceContent traceContent_;
132     std::map<std::string, int> jankParamsMap = {
133         {KEY_SAMPLE_INTERVAL, SAMPLE_DEFULE_INTERVAL}, {KEY_IGNORE_STARTUP_TIME, DEFAULT_IGNORE_STARTUP_TIME},
134         {KEY_SAMPLE_COUNT, SAMPLE_DEFULE_COUNT}, {KEY_SAMPLE_REPORT_TIMES, SAMPLE_DEFULE_REPORT_TIMES},
135         {KEY_LOG_TYPE, 0}, {KEY_SET_TIMES_FLAG, SET_TIMES_FLAG}
136     };
137     bool isScroll_ {false};
138 
139 private:
140     bool Start();
141     bool Stop();
142     bool SendMsgToHungtask(const std::string& msg);
143     bool KickWatchdog();
144     bool IsTaskExistLocked(const std::string& name);
145     bool IsExceedMaxTaskLocked();
146     int64_t InsertWatchdogTaskLocked(const std::string& name, WatchdogTask&& task);
147     bool IsInSleep(const WatchdogTask& queuedTaskCheck);
148     void CheckKickWatchdog(uint64_t now, const WatchdogTask& queuedTask);
149     bool CheckCurrentTaskLocked(const WatchdogTask& queuedTaskCheck);
150     uint64_t FetchNextTask(uint64_t now, WatchdogTask& task);
151     void ReInsertTaskIfNeed(WatchdogTask& task);
152     void CreateWatchdogThreadIfNeed();
153     bool ReportMainThreadEvent(int64_t tid, bool isScroll = false);
154     bool CheckEventTimer(int64_t currentTime, int64_t reportBegin, int64_t reportEnd, int interval);
155     void DumpTraceProfile(int32_t interval);
156     int32_t StartTraceProfile();
157     void UpdateTime(int64_t& reportBegin, int64_t& reportEnd, TimePoint& lastEndTime, const TimePoint& endTime);
158     bool CheckThreadSampler();
159     bool InitThreadSamplerFuncs();
160     void ResetThreadSamplerFuncs();
161     static void GetFfrtTaskTid(int32_t& tid, const std::string& msg);
162     void UpdateJankParam(int sampleInterval, int startUpTime, int sampleCount, int logType, int reportTimes);
163     int ConvertStrToNum(std::map<std::string, std::string> paramsMap, const std::string& key);
164     bool CheckSampleParam(std::map<std::string, std::string> paramsMap);
165 
166     static void ThreadSamplerSigHandler(int sig, siginfo_t* si, void* context);
167     bool InstallThreadSamplerSignal();
168     void UninstallThreadSamplerSignal();
169 
170     static SigActionType threadSamplerSigHandler_;
171 
172     static const unsigned int MAX_WATCH_NUM = 128; // 128: max handler thread
173     std::priority_queue<WatchdogTask> checkerQueue_; // protected by lock_
174     std::unique_ptr<std::thread> threadLoop_;
175     std::mutex lock_;
176     static std::mutex lockFfrt_;
177     std::condition_variable condition_;
178     std::atomic_bool isNeedStop_ = false;
179     std::once_flag flag_;
180     std::set<std::string> taskNameSet_;
181     std::set<int64_t> buissnessThreadInfo_;
182     std::shared_ptr<AppExecFwk::EventRunner> mainRunner_;
183     std::shared_ptr<AppExecFwk::EventHandler> binderCheckHander_;
184     int cntCallback_;
185     time_t timeCallback_;
186     bool isHmos = false;
187     void* threadSamplerFuncHandler_  {nullptr};
188     ThreadSamplerInitFunc threadSamplerInitFunc_ {nullptr};
189     ThreadSamplerSampleFunc threadSamplerSampleFunc_ {nullptr};
190     ThreadSamplerCollectFunc threadSamplerCollectFunc_ {nullptr};
191     ThreadSamplerDeinitFunc threadSamplerDeinitFunc_ {nullptr};
192     uint64_t watchdogStartTime_ {0};
193     static std::mutex threadSamplerSignalMutex_;
194 
195     bool isMainThreadStackEnabled_ {false};
196     bool isMainThreadTraceEnabled_ {false};
197     std::string bundleName_;
198     std::string bundleVersion_;
199     bool isForeground_ {false};
200     bool isAppDebug_ {false};
201     std::shared_ptr<UCollectClient::TraceCollector> traceCollector_;
202     UCollectClient::AppCaller appCaller_ {
203         .actionId = 0,
204         .foreground = 0,
205         .uid = 0,
206         .pid = 0,
207         .happenTime = 0,
208         .beginTime = 0,
209         .endTime = 0,
210         .isBusinessJank = false,
211     };
212     std::string specifiedProcessName_;
213 };
214 } // end of namespace HiviewDFX
215 } // end of namespace OHOS
216 #endif
217