• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "ark_idle_monitor.h"
17 
18 
19 #include "utils/log.h"
20 #if defined(ENABLE_FFRT)
21 #include "ffrt.h"
22 #include "c/executor_task.h"
23 #endif
24 #ifdef ENABLE_UCOLLECTION
25 #include "cpu_collector_client.h"
26 #endif
27 #ifdef ENABLE_HITRACE
28 #include "hitrace/trace.h"
29 #include "hitrace_meter.h"
30 #include "parameter.h"
31 #include "musl_preinit_common.h"
32 #include "memory_trace.h"
33 #endif
34 #include "ark_native_engine.h"
35 
36 namespace panda::ecmascript {
37 
NotifyLooperIdleStart(int64_t timestamp,int idleTime)38 void ArkIdleMonitor::NotifyLooperIdleStart(int64_t timestamp, [[maybe_unused]] int idleTime)
39 {
40     SetIdleState(true);
41     AddIdleNotifyCount();
42     recordedRunningNotifyInterval_.Push(timestamp - idleEndTimestamp_);
43 #ifndef DISABLE_SHORT_IDLE_CHECK
44     CheckShortIdleTask(timestamp, idleTime);
45 #endif
46     SetNotifyTimestamp(timestamp);
47 }
48 
CheckShortIdleTask(int64_t timestamp,int idleTime)49 void ArkIdleMonitor::CheckShortIdleTask(int64_t timestamp, int idleTime)
50 {
51 #if defined(ENABLE_FFRT)
52     while (handlerWaitToStopCount_ > 0) {
53         if (timerHandlerQueue_.size() <= 0) {
54             handlerWaitToStopCount_ = 0;
55             break;
56         }
57         int handler = timerHandlerQueue_.front();
58         timerHandlerQueue_.pop();
59         int ret = ffrt_timer_stop(ffrt_qos_user_initiated, handler);
60         if (ret != 0) {
61             HILOG_ERROR("ArkIdleMonitor: ffrt_timer_stop error handler: timerHandler='%{public}d', ret='%{public}d'",
62                 handler, ret);
63         }
64         handlerWaitToStopCount_--;
65     }
66 #endif
67     if (triggeredGC_ && mainVM_ != nullptr) {
68 #ifdef ENABLE_HITRACE
69         StartTrace(HITRACE_TAG_ACE, "NotifyLooperIdleStart::TriggeredGC");
70 #endif
71         triggeredGC_ = JSNApi::NotifyLooperIdleStart(mainVM_, timestamp, idleTime);
72 #ifdef ENABLE_HITRACE
73         FinishTrace(HITRACE_TAG_ACE);
74 #endif
75          return;
76      }
77     if (ShouldTryTriggerGC(timestamp - GetNotifyTimestamp()) &&
78         idleTime > MIN_TRIGGER_GC_IDLE_INTERVAL &&
79         needCheckIntervalIdle_) {
80         PostIdleCheckTask();
81     }
82     if (!needCheckIntervalIdle_) {
83         needCheckIntervalIdle_ = true;
84     }
85 }
86 
ShouldTryTriggerGC(int64_t interval)87 bool ArkIdleMonitor::ShouldTryTriggerGC(int64_t interval)
88 {
89     if (interval < MIN_TRIGGER_GC_IDLE_INTERVAL ||
90         recordedIdleNotifyInterval_.Count() != IDLE_CHECK_INTERVAL_LENGTH) {
91         return false;
92     }
93     int64_t sumIdleInterval = recordedIdleNotifyInterval_.Sum([](int64_t a, int64_t b) {return a + b;}, 0);
94     int64_t averageIdleInterval = sumIdleInterval / recordedIdleNotifyInterval_.Count();
95     int64_t sumRunningInterval = recordedRunningNotifyInterval_.Sum([](int64_t a, int64_t b) {return a + b;}, 0);
96     int64_t averageRunningInterval = sumRunningInterval / recordedRunningNotifyInterval_.Count();
97     if (averageIdleInterval > MIN_TRIGGER_GC_IDLE_INTERVAL &&
98             averageRunningInterval <= MAX_TRIGGER_GC_RUNNING_INTERVAL) {
99         return true;
100     }
101     return false;
102 }
103 
NotifyLooperIdleEnd(int64_t timestamp)104 void ArkIdleMonitor::NotifyLooperIdleEnd(int64_t timestamp)
105 {
106     idleEndTimestamp_ = timestamp;
107     SetIdleState(false);
108     int64_t duration = timestamp - GetNotifyTimestamp();
109     recordedIdleNotifyInterval_.Push(duration);
110     AddIdleDuration(duration);
111     if (mainVM_ != nullptr) {
112         JSNApi::NotifyLooperIdleEnd(mainVM_, timestamp);
113     }
114 }
115 
CheckLowNotifyState() const116 bool ArkIdleMonitor::CheckLowNotifyState() const
117 {
118     uint32_t checkCounts = IsInBackground() ? IDLE_INBACKGROUND_CHECK_LENGTH : IDLE_CHECK_LENGTH;
119     HILOG_DEBUG("ArkIdleMonitor: low Notify checkCounts '%{public}d', result '%{public}d' ",
120         checkCounts, static_cast<int>(numberOfLowIdleNotifyCycles_));
121     return numberOfLowIdleNotifyCycles_ >= checkCounts;
122 }
123 
CheckLowRunningDurationState() const124 bool ArkIdleMonitor::CheckLowRunningDurationState() const
125 {
126     uint32_t checkCounts = IsInBackground() ? IDLE_INBACKGROUND_CHECK_LENGTH : IDLE_CHECK_LENGTH;
127     HILOG_DEBUG("ArkIdleMonitor: low Duration checkCounts '%{public}d', result '%{public}d' ",
128         checkCounts, static_cast<int>(numberOfHighIdleTimeRatio_));
129     return numberOfHighIdleTimeRatio_ >= checkCounts;
130 }
131 
IntervalMonitor()132 void ArkIdleMonitor::IntervalMonitor()
133 {
134     if (!timerMutex_.try_lock()) {
135         HILOG_INFO("ArkIdleMonitor: IntervalMonitor stop by timerMutex_");
136         return;
137     }
138     auto nowTimestamp = std::chrono::time_point_cast<std::chrono::milliseconds>(
139         std::chrono::high_resolution_clock::now()).time_since_epoch().count();
140     int64_t idleDuration = GetTotalIdleDuration() - lastTotalIdleDuration_;
141     if (IsIdleState()) {
142         idleDuration += (nowTimestamp - GetNotifyTimestamp());
143     }
144     lastTotalIdleDuration_ = GetTotalIdleDuration();
145     if (GetIdleNotifyCount() <= LOW_IDLE_NOTIFY_THRESHOLD) {
146         numberOfLowIdleNotifyCycles_++;
147     } else {
148         numberOfLowIdleNotifyCycles_ = 0U;
149     }
150     ResetIdleNotifyCount();
151     int64_t recordTotalDuration = nowTimestamp - startRecordTimestamp_;
152     if (recordTotalDuration <= 0) {
153         numberOfHighIdleTimeRatio_ = 0U;
154         HILOG_ERROR("ArkIdleMonitor: recordTotalDuration <= 0");
155     } else {
156         double idleTimeRatio = static_cast<double>(idleDuration) / recordTotalDuration;
157         HILOG_DEBUG("ArkIdleMonitor: idleTimeRatio '%{public}.2f'", idleTimeRatio);
158         idleTimeRatio >= IDLE_RATIO ? numberOfHighIdleTimeRatio_++ : (numberOfHighIdleTimeRatio_ = 0U);
159     }
160     startRecordTimestamp_ = nowTimestamp;
161     CheckWorkerEnvQueue();
162     uint32_t checkCounts = IsInBackground() ? IDLE_INBACKGROUND_CHECK_LENGTH : IDLE_CHECK_LENGTH;
163     uint32_t workThreadCheckCounts = checkCounts - IDLE_WORKER_TRIGGER_COUNT;
164     if (numberOfLowIdleNotifyCycles_ >= checkCounts &&
165             numberOfHighIdleTimeRatio_ >= checkCounts) {
166         NotifyMainThreadTryCompressGC();
167         PostMonitorTask(SLEEP_MONITORING_INTERVAL);
168         ClearIdleStats();
169     } else if (numberOfLowIdleNotifyCycles_ >= workThreadCheckCounts &&
170                     numberOfHighIdleTimeRatio_ >= workThreadCheckCounts) {
171         NotifyOneWorkerThreadTryCompressGC();
172         PostMonitorTask(IDLE_MONITORING_INTERVAL);
173     } else {
174         PostMonitorTask(IDLE_MONITORING_INTERVAL);
175     }
176     timerMutex_.unlock();
177 }
178 
PostMonitorTask(uint64_t delayMs)179 void ArkIdleMonitor::PostMonitorTask(uint64_t delayMs)
180 {
181 #if defined(ENABLE_FFRT)
182     auto task = [](void* idleMonitorPtr) {
183         if (idleMonitorPtr != nullptr) {
184             ArkIdleMonitor* arkIdleMonitor = reinterpret_cast<ArkIdleMonitor *>(idleMonitorPtr);
185             arkIdleMonitor->IntervalMonitor();
186         }
187     };
188     if (waitForStopTimerHandler_ != -1) {
189         int ret = ffrt_timer_stop(ffrt_qos_user_initiated, waitForStopTimerHandler_);
190         if (ret != 0) {
191             HILOG_ERROR("ArkIdleMonitor: ffrt_timer_stop error handler: timerHandler='%{public}d', ret='%{public}d'",
192                 waitForStopTimerHandler_, ret);
193         }
194     }
195     waitForStopTimerHandler_ = currentTimerHandler_;
196     currentTimerHandler_ = ffrt_timer_start(ffrt_qos_user_initiated, delayMs, this, task, false);
197 #endif
198 }
199 
~ArkIdleMonitor()200 ArkIdleMonitor::~ArkIdleMonitor()
201 {
202 #if defined(ENABLE_FFRT)
203     StopIdleMonitorTimerTask();
204     while (timerHandlerQueue_.size() > 0) {
205         ffrt_timer_stop(ffrt_qos_user_initiated, timerHandlerQueue_.front());
206         timerHandlerQueue_.pop();
207     }
208 #endif
209 }
210 
ClearIdleStats()211 void ArkIdleMonitor::ClearIdleStats()
212 {
213     ResetIdleNotifyCount();
214     numberOfLowIdleNotifyCycles_ = 0U;
215     numberOfHighIdleTimeRatio_ = 0U;
216 }
217 
NotifyMainThreadTryCompressGC()218 void ArkIdleMonitor::NotifyMainThreadTryCompressGC()
219 {
220 #if defined(ENABLE_EVENT_HANDLER)
221     double cpuUsage = GetCpuUsage();
222     if (cpuUsage >= IDLE_CPU_USAGE) {
223         HILOG_INFO("ArkIdleMonitor: Sending a quiet notification is canceled due to high CPU usage: %{public}.2f",
224             cpuUsage);
225         return;
226     }
227     if (mainThreadHandler_ == nullptr) {
228         mainThreadHandler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(
229             OHOS::AppExecFwk::EventRunner::GetMainEventRunner());
230     };
231     if (mainVM_ == nullptr) {
232         return;
233     }
234     auto task = [this]() {
235         JSNApi::TriggerIdleGC(mainVM_, TRIGGER_IDLE_GC_TYPE::FULL_GC);
236         if (CheckWorkerEnvQueueAllInIdle()) {
237             JSNApi::TriggerIdleGC(mainVM_, TRIGGER_IDLE_GC_TYPE::SHARED_FULL_GC);
238         }
239     };
240     mainThreadHandler_->PostTask(task, "ARKTS_IDLE_COMPRESS", 0, OHOS::AppExecFwk::EventQueue::Priority::IMMEDIATE);
241 #endif
242 }
243 
NotifyMainThreadTryCompressGCByBackground()244 void ArkIdleMonitor::NotifyMainThreadTryCompressGCByBackground()
245 {
246 #if defined(ENABLE_EVENT_HANDLER)
247     if (mainVM_ == nullptr) {
248         return;
249     }
250     if (mainThreadHandler_ == nullptr) {
251         mainThreadHandler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(
252             OHOS::AppExecFwk::EventRunner::GetMainEventRunner());
253     };
254     auto task = [this]() {
255         JSNApi::TriggerIdleGC(mainVM_, TRIGGER_IDLE_GC_TYPE::FULL_GC);
256         JSNApi::TriggerIdleGC(mainVM_, TRIGGER_IDLE_GC_TYPE::SHARED_FULL_GC);
257     };
258     if (IsIdleState()) {
259         mainThreadHandler_->PostTask(task, "ARKTS_BACKGROUND_COMPRESS", 0,
260             OHOS::AppExecFwk::EventQueue::Priority::IMMEDIATE);
261     }
262 #endif
263 }
264 
SetStartTimerCallback()265 void ArkIdleMonitor::SetStartTimerCallback()
266 {
267     JSNApi::SetStartIdleMonitorCallback([this]() {
268         this->IntervalMonitor();
269         started_ = true;
270     });
271 }
272 
NotifyChangeBackgroundState(bool inBackground)273 void ArkIdleMonitor::NotifyChangeBackgroundState(bool inBackground)
274 {
275     inBackground_.store(inBackground, std::memory_order_relaxed);
276     ClearIdleStats();
277     if (!started_ && inBackground) {
278         HILOG_DEBUG("ArkIdleMonitor change to background but not started idle check");
279         return;
280     }
281 #if defined(ENABLE_FFRT)
282     if (started_ && inBackground) {
283         HILOG_DEBUG("ArkIdleMonitor post check switch background gc task");
284         StopIdleMonitorTimerTask();
285         PostSwitchBackgroundGCTask();
286     }
287 #endif
288 }
289 
GetCpuUsage() const290 double ArkIdleMonitor::GetCpuUsage() const
291 {
292 #ifdef ENABLE_UCOLLECTION
293     auto collector = OHOS::HiviewDFX::UCollectClient::CpuCollector::Create();
294     auto collectResult = collector->GetSysCpuUsage();
295     if (collectResult.retCode == OHOS::HiviewDFX::UCollect::UcError::SUCCESS) {
296         HILOG_DEBUG("ArkIdleMonitor cpu usage: %{public}.2f", collectResult.data);
297         return collectResult.data;
298     }
299     HILOG_ERROR("ArkIdleMonitor get cpu usage failed, error code:%{public}d", collectResult.retCode);
300 #endif
301     return 0.0f;
302 }
303 
CheckIntervalIdle(int64_t timestamp,int64_t idleDuration)304 bool ArkIdleMonitor::CheckIntervalIdle(int64_t timestamp, int64_t idleDuration)
305 {
306     if (!IsIdleState()) {
307         return false;
308     }
309     int64_t nowTimestamp = std::chrono::time_point_cast<std::chrono::milliseconds>(
310         std::chrono::high_resolution_clock::now()).time_since_epoch().count();
311     int64_t sumDuration = nowTimestamp - timestamp;
312     int64_t sumIdleDuration = (GetTotalIdleDuration() - idleDuration) + (nowTimestamp - GetNotifyTimestamp());
313     [[maybe_unused]] double idlePercentage = static_cast<double>(sumIdleDuration) / static_cast<double>(sumDuration);
314 #ifdef ENABLE_HITRACE
315     StartTrace(HITRACE_TAG_ACE, "CheckIntervalIdle::sumDuration:" + std::to_string(sumDuration)
316         + "sumIdleDuration:" + std::to_string(sumIdleDuration)
317         + "idlePercentage" + std::to_string(idlePercentage));
318 #endif
319 #if defined(ENABLE_EVENT_HANDLER)
320     if (idlePercentage > SHORT_IDLE_RATIO && mainVM_!= nullptr) {
321         if (mainThreadHandler_ == nullptr) {
322             mainThreadHandler_ = std::make_shared<OHOS::AppExecFwk::EventHandler>(
323                 OHOS::AppExecFwk::EventRunner::GetMainEventRunner());
324         };
325         auto task = [this]() {
326             triggeredGC_ = JSNApi::NotifyLooperIdleStart(mainVM_, 0, 0);
327             needCheckIntervalIdle_ = false;
328             handlerWaitToStopCount_++;
329             // If GC is triggered, reset the statistics to avoid triggering monitoring tasks continuously.
330             if (!triggeredGC_) {
331                 recordedIdleNotifyInterval_.Reset();
332             }
333         };
334         mainThreadHandler_->PostTask(task, "ARKTS_IDLE_NOTIFY", 0, OHOS::AppExecFwk::EventQueue::Priority::IMMEDIATE);
335     }
336 #endif
337 #ifdef ENABLE_HITRACE
338     FinishTrace(HITRACE_TAG_ACE);
339 #endif
340     return true;
341 }
342 
PostIdleCheckTask()343 void ArkIdleMonitor::PostIdleCheckTask()
344 {
345 #ifdef ENABLE_HITRACE
346         StartTrace(HITRACE_TAG_ACE, "NotifyLooperIdleStart::PostIdleCheckTask");
347 #endif
348 #if defined(ENABLE_FFRT)
349     auto nowTimestamp = std::chrono::time_point_cast<std::chrono::milliseconds>(
350         std::chrono::high_resolution_clock::now()).time_since_epoch().count();
351     std::tuple<ArkIdleMonitor*, int64_t, int64_t> myTuple = std::make_tuple(this, nowTimestamp, GetTotalIdleDuration());
352     std::tuple<ArkIdleMonitor*, int64_t, int64_t> *data = new std::tuple<ArkIdleMonitor*, int64_t, int64_t>(myTuple);
353     auto task = [](void* data) {
354         std::tuple<ArkIdleMonitor*, int64_t, int64_t>* tuple =
355             reinterpret_cast<std::tuple<ArkIdleMonitor*, int64_t, int64_t>*>(data);
356         if (tuple == nullptr || std::get<0>(*tuple) == nullptr) {
357             return;
358         }
359         std::get<0>(*tuple)->CheckIntervalIdle(std::get<1>(*tuple), std::get<2>(*tuple));
360         delete tuple;
361     };
362     int timerHandler = ffrt_timer_start(ffrt_qos_user_initiated, SHORT_IDLE_DELAY_INTERVAL,
363         reinterpret_cast<void*>(data), task, false);
364     timerHandlerQueue_.push(timerHandler);
365 #endif
366 #ifdef ENABLE_HITRACE
367     FinishTrace(HITRACE_TAG_ACE);
368 #endif
369 }
370 
SwitchBackgroundCheckGCTask(int64_t timestamp,int64_t idleDuration)371 void ArkIdleMonitor::SwitchBackgroundCheckGCTask(int64_t timestamp, int64_t idleDuration)
372 {
373     int64_t nowTimestamp = std::chrono::time_point_cast<std::chrono::milliseconds>(
374         std::chrono::high_resolution_clock::now()).time_since_epoch().count();
375     int64_t sumDuration = nowTimestamp - timestamp;
376     int64_t sumIdleDuration = (GetTotalIdleDuration() - idleDuration) + (nowTimestamp - GetNotifyTimestamp());
377     double idlePercentage = static_cast<double>(sumIdleDuration) / static_cast<double>(sumDuration);
378     double cpuUsage = GetCpuUsage();
379     if (idlePercentage > BACKGROUND_IDLE_RATIO && cpuUsage <= IDLE_BACKGROUND_CPU_USAGE) {
380         NotifyMainThreadTryCompressGCByBackground();
381     } else {
382         HILOG_INFO("ArkIdleMonitor canceled background GC task, idlePercentage:%{public}.2f, cpuUsage:%{public}.2f",
383             idlePercentage, cpuUsage);
384     }
385     PostMonitorTask(SLEEP_MONITORING_INTERVAL);
386     ClearIdleStats();
387 }
388 
PostSwitchBackgroundGCTask()389 void ArkIdleMonitor::PostSwitchBackgroundGCTask()
390 {
391 #if defined(ENABLE_FFRT)
392     if (switchBackgroundTimerHandler_ != -1) {
393         ffrt_timer_stop(ffrt_qos_user_initiated, switchBackgroundTimerHandler_);
394     }
395     auto nowTimestamp = std::chrono::time_point_cast<std::chrono::milliseconds>(
396         std::chrono::high_resolution_clock::now()).time_since_epoch().count();
397     std::tuple<ArkIdleMonitor*, int64_t, int64_t> myTuple = std::make_tuple(this, nowTimestamp, GetTotalIdleDuration());
398     std::tuple<ArkIdleMonitor*, int64_t, int64_t> *data = new std::tuple<ArkIdleMonitor*, int64_t, int64_t>(myTuple);
399     auto task = [](void* data) {
400         std::tuple<ArkIdleMonitor*, int64_t, int64_t>* tuple =
401             reinterpret_cast<std::tuple<ArkIdleMonitor*, int64_t, int64_t>*>(data);
402         if (tuple == nullptr || std::get<0>(*tuple) == nullptr) {
403             return;
404         }
405         std::get<0>(*tuple)->SwitchBackgroundCheckGCTask(std::get<1>(*tuple), std::get<2>(*tuple));
406         delete tuple;
407     };
408     switchBackgroundTimerHandler_ = ffrt_timer_start(ffrt_qos_user_initiated, IDLE_MONITORING_INTERVAL,
409         reinterpret_cast<void*>(data), task, false);
410 #endif
411 }
412 
CheckWorkerEnvQueue()413 void ArkIdleMonitor::CheckWorkerEnvQueue()
414 {
415     std::lock_guard<std::mutex> lock(queueMutex_);
416     for (size_t i = 0; i < workerEnvQueue_.size(); i++) {
417         napi_env env = workerEnvQueue_.front();
418         auto arkNativeEngine = reinterpret_cast<ArkNativeEngine*>(env);
419         workerEnvQueue_.pop();
420         workerEnvQueue_.push(env);
421         arkNativeEngine->GetWorkerThreadState()->CheckIdleState();
422         HILOG_DEBUG("ArkIdleMonitor::CheckWorkerEnvQueue,tid=%{public}d, workerCount=%{public}d",
423             arkNativeEngine->GetSysTid(), arkNativeEngine->GetWorkerThreadState()->GetCheckCount());
424     }
425 }
426 
CheckWorkerEnvQueueAllInIdle()427 bool ArkIdleMonitor::CheckWorkerEnvQueueAllInIdle()
428 {
429     std::lock_guard<std::mutex> lock(queueMutex_);
430     for (size_t i = 0; i < workerEnvQueue_.size(); i++) {
431         napi_env env = workerEnvQueue_.front();
432         auto arkNativeEngine = reinterpret_cast<ArkNativeEngine*>(env);
433         if (arkNativeEngine->GetWorkerThreadState()->GetCheckCount() < IDLE_INBACKGROUND_CHECK_LENGTH) {
434             return false;
435         }
436         workerEnvQueue_.pop();
437         workerEnvQueue_.push(env);
438     }
439     return true;
440 }
441 
NotifyOneWorkerThreadTryCompressGC()442 void ArkIdleMonitor::NotifyOneWorkerThreadTryCompressGC()
443 {
444     std::lock_guard<std::mutex> lock(queueMutex_);
445     for (size_t i = 0; i < workerEnvQueue_.size(); i++) {
446         napi_env env = workerEnvQueue_.front();
447         workerEnvQueue_.pop();
448         workerEnvQueue_.push(env);
449         auto arkNativeEngine = reinterpret_cast<ArkNativeEngine*>(env);
450         if (arkNativeEngine->GetWorkerThreadState()->GetCheckCount() >= IDLE_INBACKGROUND_CHECK_LENGTH) {
451             std::pair<void*, uint8_t> data(reinterpret_cast<void*>(const_cast<EcmaVM*>(arkNativeEngine->GetEcmaVm())),
452                 static_cast<uint8_t>(TRIGGER_IDLE_GC_TYPE::FULL_GC));
453             arkNativeEngine->PostTriggerGCTask(data);
454             return;
455         }
456     }
457 }
458 
StopIdleMonitorTimerTask()459 void ArkIdleMonitor::StopIdleMonitorTimerTask()
460 {
461 #if defined(ENABLE_FFRT)
462     std::lock_guard<std::mutex> lock(timerMutex_);
463     HILOG_INFO("StopIdleMonitorTimerTask get timerMutex_");
464     if (currentTimerHandler_ != -1) {
465         ffrt_timer_stop(ffrt_qos_user_initiated, currentTimerHandler_);
466         currentTimerHandler_ = -1;
467     }
468     if (waitForStopTimerHandler_ != -1) {
469         ffrt_timer_stop(ffrt_qos_user_initiated, waitForStopTimerHandler_);
470         waitForStopTimerHandler_ = -1;
471     }
472 #endif
473 }
474 
475 
476 std::shared_ptr<ArkIdleMonitor> ArkIdleMonitor::instance_ = std::make_shared<ArkIdleMonitor>();
477 
GetInstance()478 std::shared_ptr<ArkIdleMonitor> ArkIdleMonitor::GetInstance()
479 {
480     return instance_;
481 }
482 }
483 
484