• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
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 "native_memory_profiler_sa_service.h"
17 #include "native_memory_profiler_sa_death_recipient.h"
18 #include "iservice_registry.h"
19 #include "ipc_skeleton.h"
20 #include "trace_file_writer.h"
21 #include "socket_context.h"
22 #include "hook_common.h"
23 #include "init_param.h"
24 #include "token_setproc.h"
25 #include "accesstoken_kit.h"
26 #include "common.h"
27 #include "logging.h"
28 
29 namespace OHOS::Developtools::NativeDaemon {
30 namespace {
31 constexpr int32_t TIME_BASE = 1000;
32 constexpr int32_t MAX_TASK_NUM = 4;
33 const std::string FILE_PATH_HEAD = "/data/local/tmp/native_memory_";
34 const std::string FILE_PATH_TAIL = ".htrace";
35 constexpr int32_t DELAYED_SHUTDOWN_TIME = 20;
36 constexpr int FILE_MODE = 0644;
37 constexpr int32_t SIMP_NMD = 3;
38 constexpr int32_t NMD_WAIT_MS = 100;
39 constexpr int32_t NMD_WAIT_TIMES = 50;
40 }
41 
NativeMemoryProfilerSaService()42 NativeMemoryProfilerSaService::NativeMemoryProfilerSaService() : SystemAbility(NATIVE_DAEMON_SYSTEM_ABILITY_ID, true)
43 {
44     serviceName_ = "HookService";
45     serviceEntry_ = std::make_shared<ServiceEntry>();
46     if (!serviceEntry_->StartServer(DEFAULT_UNIX_SOCKET_HOOK_PATH)) {
47         serviceEntry_ = nullptr;
48         PROFILER_LOG_ERROR(LOG_CORE, "Start IPC Service FAIL");
49         return;
50     }
51     serviceEntry_->RegisterService(*this);
52     DelayedShutdown(false);
53 }
54 
~NativeMemoryProfilerSaService()55 NativeMemoryProfilerSaService::~NativeMemoryProfilerSaService()
56 {
57     serviceEntry_ = nullptr;
58 }
59 
StartServiceAbility()60 bool NativeMemoryProfilerSaService::StartServiceAbility()
61 {
62     sptr<ISystemAbilityManager> serviceManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
63     CHECK_NOTNULL(serviceManager, false, "serviceManager is nullptr");
64 
65     static sptr<NativeMemoryProfilerSaService> native(new NativeMemoryProfilerSaService());
66     CHECK_NOTNULL(native, false, "native is nullptr");
67     int32_t result = serviceManager->AddSystemAbility(NATIVE_DAEMON_SYSTEM_ABILITY_ID, native);
68     if (result != 0) {
69         PROFILER_LOG_ERROR(LOG_CORE, "Service native memory failed to start");
70         return false;
71     }
72 
73     auto abilityObject = serviceManager->AsObject();
74     CHECK_NOTNULL(abilityObject, false, "abilityObject is nullptr");
75 
76     bool ret = abilityObject->AddDeathRecipient(new NativeMemoryProfilerSaDeathRecipient());
77     if (ret == false) {
78         PROFILER_LOG_ERROR(LOG_CORE, "AddDeathRecipient failed");
79         return false;
80     }
81     PROFILER_LOG_INFO(LOG_CORE, "Service native memory started successfully");
82     return true;
83 }
84 
HasProfilingPermission()85 bool NativeMemoryProfilerSaService::HasProfilingPermission()
86 {
87     uint32_t callingTokenID = IPCSkeleton::GetCallingTokenID();
88     int res = Security::AccessToken::AccessTokenKit::VerifyAccessToken(callingTokenID,
89                                                                        "ohos.permission.ENABLE_PROFILER");
90     if (res != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
91         PROFILER_LOG_ERROR(LOG_CORE, "No profiling permission, please check!");
92         return false;
93     }
94     return true;
95 }
96 
Start(std::shared_ptr<NativeMemoryProfilerSaConfig> & config)97 int32_t NativeMemoryProfilerSaService::Start(std::shared_ptr<NativeMemoryProfilerSaConfig>& config)
98 {
99     if (config->printNmd_) {
100         std::lock_guard<std::mutex> guard(nmdMtx_);
101         nmdPidType_[config->nmdPid_] = std::make_pair(0, config->nmdType_);
102         if (!config->printNmdOnly_) {
103             return RET_OK;
104         }
105     }
106     return StartHook(config);
107 }
108 
Start(std::shared_ptr<NativeMemoryProfilerSaConfig> & config,MessageParcel & reply)109 int32_t NativeMemoryProfilerSaService::Start(std::shared_ptr<NativeMemoryProfilerSaConfig>& config,
110                                              MessageParcel &reply)
111 {
112     if (config->printNmd_) {
113         std::lock_guard<std::mutex> guard(nmdMtx_);
114         nmdPidType_[config->nmdPid_] = std::make_pair(0, config->nmdType_);
115         if (!config->printNmdOnly_) {
116             return RET_OK;
117         }
118     }
119     return StartHook(config, 0, reply);
120 }
121 
Stop(uint32_t pid)122 int32_t NativeMemoryProfilerSaService::Stop(uint32_t pid)
123 {
124     StopHook(pid);
125     return RET_OK;
126 }
127 
Stop(const std::string & name)128 int32_t NativeMemoryProfilerSaService::Stop(const std::string& name)
129 {
130     StopHook(0, name);
131     return RET_OK;
132 }
133 
DumpData(uint32_t fd,std::shared_ptr<NativeMemoryProfilerSaConfig> & config)134 int32_t NativeMemoryProfilerSaService::DumpData(uint32_t fd, std::shared_ptr<NativeMemoryProfilerSaConfig>& config)
135 {
136     if (config->printNmd_) {
137         std::lock_guard<std::mutex> guard(nmdMtx_);
138         nmdPidType_[config->nmdPid_] = std::make_pair(fd, config->nmdType_);
139         if (!config->printNmdOnly_) {
140             return RET_OK;
141         }
142     }
143     if (StartHook(config, fd) == RET_ERR) {
144         close(fd);
145         return RET_ERR;
146     }
147     return RET_OK;
148 }
149 
StopHook(uint32_t pid,std::string name)150 void NativeMemoryProfilerSaService::StopHook(uint32_t pid, std::string name)
151 {
152     if (!HasProfilingPermission()) {
153         PROFILER_LOG_ERROR(LOG_CORE, "StopHook failed, no profiling permission!");
154         return;
155     }
156     std::lock_guard<std::mutex> guard(mtx_);
157     std::shared_ptr<TaskConfig> config = nullptr;
158     if (pid > 0) {
159         if (auto taskIter = pidCtx_.find(pid); taskIter != pidCtx_.end()) {
160             config = taskIter->second;
161         }
162     } else if (auto taskIter = nameAndFilePathCtx_.find(name); taskIter != nameAndFilePathCtx_.end()) {
163         config = taskIter->second;
164     }
165     if (config == nullptr) {
166         PROFILER_LOG_INFO(LOG_CORE, "NativeMemoryProfilerSaService: hook has stop, pid: %d, process name: %s",
167             pid, name.c_str());
168         return;
169     }
170 
171     config->hookMgr->StopPluginSession({});
172     config->hookMgr->DestroyPluginSession({});
173     nameAndFilePathCtx_.erase(config->processName);
174     nameAndFilePathCtx_.erase(config->filePath);
175     pidCtx_.erase(config->pid);
176     if (nmdPidType_.find(config->pid) != nmdPidType_.end()) {
177         nmdPidType_.erase(config->pid);
178     }
179     if (config->isStartupMode) {
180         hasStartupMode_ = false;
181     }
182     if (config->fd > 0) {
183         close(config->fd);
184     }
185     if (--taskNum_ == 0) {
186         PROFILER_LOG_INFO(LOG_CORE, "StringViewMemoryHold clear");
187         StringViewMemoryHold::GetInstance().Clear();
188         DelayedShutdown(false);
189     }
190 }
191 
GetCmdArgs(std::shared_ptr<NativeMemoryProfilerSaConfig> & config)192 std::string NativeMemoryProfilerSaService::GetCmdArgs(std::shared_ptr<NativeMemoryProfilerSaConfig>& config)
193 {
194     std::stringstream args;
195     args << "pid: " << COMMON::GetProcessNameByPid(config->pid_) << ", ";
196     args << "filter_size: " << config->filterSize_ << ", ";
197     args << "max_stack_depth: " << std::to_string(config->maxStackDepth_) << ", ";
198     args << "process_name: " << config->processName_ << ", ";
199     args << "malloc_disable: " << (config->mallocDisable_ ? "true" : "false") << ", ";
200     args << "mmap_disable: " << (config->mmapDisable_ ? "true" : "false") << ", ";
201     args << "free_stack_report: " << (config->freeStackData_ ? "true" : "false") << ", ";
202     args << "munmap_stack_report: " << (config->munmapStackData_ ? "true" : "false") << ", ";
203     args << "malloc_free_matching_interval: " << std::to_string(config->mallocFreeMatchingInterval_) << ", ";
204     args << "malloc_free_matching_cnt: " << std::to_string(config->mallocFreeMatchingCnt_) << ", ";
205     args << "string_compressed: " << (config->stringCompressed_ ? "true" : "false") << ", ";
206     args << "fp_unwind: " << (config->fpUnwind_ ? "true" : "false") << ", ";
207     args << "blocked: " << (config->blocked_ ? "true" : "false") << ", ";
208     args << "record_accurately: " << (config->recordAccurately_ ? "true" : "false") << ", ";
209     args << "startup_mode: " << (config->startupMode_ ? "true" : "false") << ", ";
210     args << "memtrace_enable: " << (config->memtraceEnable_ ? "true" : "false") << ", ";
211     args << "offline_symbolization: " << (config->offlineSymbolization_ ? "true" : "false") << ", ";
212     args << "callframe_compress: " << (config->callframeCompress_ ? "true" : "false") << ", ";
213     args << "statistics_interval: " << std::to_string(config->statisticsInterval_) << ", ";
214     args << "clock: " << std::to_string(config->clockId_) << ", ";
215     args << "sample_interval: " << std::to_string(config->sampleInterval_) << ", ";
216     args << "response_library_mode: " << (config->responseLibraryMode_ ? "true" : "false") << ", ";
217     args << "js_stack_report: " << std::to_string(config->jsStackReport_) << ", ";
218     args << "max_js_stack_depth: " << std::to_string(config->maxJsStackDepth_) << ", ";
219     args << "filter_napi_name: " << config->filterNapiName_ << ", ";
220     args << "nmd_pid: " << std::to_string(config->nmdPid_) << ", ";
221     args << "nmd_type: " << std::to_string(config->nmdType_) << ", ";
222     return args.str();
223 }
224 
StartHookLock(std::shared_ptr<NativeMemoryProfilerSaConfig> & config,uint32_t fd,std::shared_ptr<HookManager> & hook,std::string & args)225 int32_t NativeMemoryProfilerSaService::StartHookLock(std::shared_ptr<NativeMemoryProfilerSaConfig>& config,
226                                                      uint32_t fd, std::shared_ptr<HookManager>& hook,
227                                                      std::string& args)
228 {
229     std::lock_guard<std::mutex> guard(mtx_);
230     if (config->filePath_.empty() && fd == 0) {
231         std::string filePathStr = (config->pid_ > 0) ? std::to_string(config->pid_) : config->processName_;
232         config->filePath_ = FILE_PATH_HEAD + filePathStr + FILE_PATH_TAIL;
233     }
234     PROFILER_LOG_INFO(LOG_CORE, "file path: %s", config->filePath_.c_str());
235 
236     if (!CheckConfig(config, fd)) {
237         COMMON::PluginWriteToHisysevent("native_hook_plugin", "hiview", args, COMMON::ErrorType::RET_MSG_EMPTY,
238             "check config failed");
239         return RET_ERR;
240     }
241 
242     if (fd == 0) {
243         auto retFile = COMMON::CheckNotExistsFilePath(config->filePath_);
244         if (!retFile.first) {
245             PROFILER_LOG_INFO(LOG_CORE, "%s:check file path %s fail", __func__, config->filePath_.c_str());
246             COMMON::PluginWriteToHisysevent("native_hook_plugin", "hiview", args, COMMON::ErrorType::RET_INVALID_PATH,
247                 "check file path failed");
248             return RET_ERR;
249         }
250         int fdTemp = open(retFile.second.c_str(), O_RDWR | O_CREAT, FILE_MODE);
251         CHECK_TRUE(fdTemp >= 0, RET_ERR, "Failed to open file(%s)", config->filePath_.c_str());
252         fd = static_cast<uint32_t>(fdTemp);
253     }
254     std::shared_ptr<TraceFileWriter> writeFile = nullptr;
255     if (config->printNmdOnly_) {
256         writeFile = std::make_shared<TraceFileWriter>(0);
257     } else {
258         writeFile = std::make_shared<TraceFileWriter>(fd);
259     }
260     CHECK_NOTNULL(writeFile, RET_ERR, "Failed to create TraceFileWriter");
261     writeFile->SetTimeSource();
262 
263     hook->RegisterWriter(writeFile);
264     hook->SetSaMode(true);
265     hook->SetHookConfig(config);
266     hook->SetSaServiceConfig(true, false);
267     if (config->pid_ > 0) {
268         std::lock_guard<std::mutex> nmdGuard(nmdMtx_);
269         if (nmdPidType_.find(config->pid_) != nmdPidType_.end()) {
270             hook->SetNmdInfo(nmdPidType_[config->pid_]);
271         }
272     }
273     if (hook->CreatePluginSession() != RET_OK) {
274         COMMON::PluginWriteToHisysevent("native_hook_plugin", "hiview", args, COMMON::ErrorType::RET_FAIL,
275             "create pluginsession failed");
276         return RET_ERR;
277     }
278     if (!config->printNmdOnly_) {
279         hook->WriteHookConfig();
280     }
281     hook->StartPluginSession();
282 
283     int32_t timerFd = scheduleTaskManager_.ScheduleTask(
284         [this, config] { this->StopHook(config->pid_, config->processName_); },
285         config->duration_ * TIME_BASE,
286         true);
287     if (timerFd == -1) {
288         PROFILER_LOG_ERROR(LOG_CORE, "NativeMemoryProfilerSaService Start Schedule Task failed");
289         COMMON::PluginWriteToHisysevent("native_hook_plugin", "hiview", args, COMMON::ErrorType::RET_FAIL,
290             "start schedule task failed");
291         return RET_ERR;
292     }
293 
294     std::shared_ptr<TaskConfig> configCtx =
295         std::make_shared<TaskConfig>(hook, config->pid_, config->processName_, config->filePath_, timerFd,
296                                      config->startupMode_, fd);
297     CHECK_NOTNULL(hook, RET_ERR, "Failed to create TaskConfig");
298     if (!hasStartupMode_ && config->startupMode_) {
299         hasStartupMode_ = true;
300         startupModeProcessName_ = config->processName_;
301     }
302 
303     if (configCtx->pid > 0) {
304         pidCtx_[configCtx->pid] = configCtx;
305     } else if (!configCtx->processName.empty()) {
306         nameAndFilePathCtx_[configCtx->processName] = configCtx;
307     }
308 
309     if (fd == 0) {
310         nameAndFilePathCtx_[configCtx->filePath] = configCtx;
311     }
312     ++taskNum_;
313     DelayedShutdown(true);
314     COMMON::PluginWriteToHisysevent("native_hook_plugin", "hiview", args, COMMON::ErrorType::RET_SUCC, "success");
315     return RET_OK;
316 }
317 
StartHook(std::shared_ptr<NativeMemoryProfilerSaConfig> & config,uint32_t fd)318 int32_t NativeMemoryProfilerSaService::StartHook(std::shared_ptr<NativeMemoryProfilerSaConfig>& config, uint32_t fd)
319 {
320     auto args = GetCmdArgs(config);
321     if (!HasProfilingPermission()) {
322         COMMON::PluginWriteToHisysevent("native_hook_plugin", "hiview", args, COMMON::ErrorType::RET_NO_PERMISSION,
323             "no profiling permission");
324         PROFILER_LOG_ERROR(LOG_CORE, "StartHook failed, no profiling permission!");
325         return RET_ERR;
326     }
327     if (config == nullptr) {
328         return RET_ERR;
329     }
330     std::shared_ptr<HookManager> hook = std::make_shared<HookManager>();
331     CHECK_NOTNULL(hook, RET_ERR, "Failed to create HookManager");
332 
333     return StartHookLock(config, fd, hook, args);
334 }
335 
WaitSimplifiedNmdTimeout(uint32_t times,std::shared_ptr<HookManager> & hook,MessageParcel & reply)336 static int32_t WaitSimplifiedNmdTimeout(uint32_t times, std::shared_ptr<HookManager>& hook, MessageParcel &reply)
337 {
338     uint32_t cnt = 0;
339     while ((!hook->nmdComplete_) && (cnt < times)) {
340         std::this_thread::sleep_for(std::chrono::milliseconds(NMD_WAIT_MS));
341         cnt++;
342     }
343     if (!hook->nmdComplete_) {
344         PROFILER_LOG_ERROR(LOG_CORE, "WaitSimplifiedNmdTimeout, %d ms", times * NMD_WAIT_MS);
345         return RET_ERR;
346     }
347     WRITESTRING(reply, hook->simplifiedNmd_, RET_ERR);
348     return RET_OK;
349 }
350 
StartHook(std::shared_ptr<NativeMemoryProfilerSaConfig> & config,uint32_t fd,MessageParcel & reply)351 int32_t NativeMemoryProfilerSaService::StartHook(std::shared_ptr<NativeMemoryProfilerSaConfig>& config,
352                                                  uint32_t fd, MessageParcel &reply)
353 {
354     auto args = GetCmdArgs(config);
355     if (!HasProfilingPermission()) {
356         COMMON::PluginWriteToHisysevent("native_hook_plugin", "hiview", args, COMMON::ErrorType::RET_NO_PERMISSION,
357             "no profiling permission");
358         PROFILER_LOG_ERROR(LOG_CORE, "StartHook failed, no profiling permission!");
359         return RET_ERR;
360     }
361     if (config == nullptr) {
362         return RET_ERR;
363     }
364     std::shared_ptr<HookManager> hook = std::make_shared<HookManager>();
365     CHECK_NOTNULL(hook, RET_ERR, "Failed to create HookManager");
366 
367     int32_t ret = StartHookLock(config, fd, hook, args);
368     if (ret != RET_OK) {
369         return ret;
370     }
371 
372     if (config->nmdType_ == SIMP_NMD) {
373         return WaitSimplifiedNmdTimeout(NMD_WAIT_TIMES, hook, reply);
374     }
375     return RET_OK;
376 }
377 
CheckConfig(std::shared_ptr<NativeMemoryProfilerSaConfig> & config,uint32_t fd)378 bool NativeMemoryProfilerSaService::CheckConfig(std::shared_ptr<NativeMemoryProfilerSaConfig>& config, uint32_t fd)
379 {
380     if (taskNum_ + 1 > MAX_TASK_NUM) {
381         PROFILER_LOG_INFO(LOG_CORE, "NativeMemoryProfilerSaService: Support up to 4 tasks at the same time");
382         return false;
383     }
384 
385     if (hasStartupMode_ && config->startupMode_) {
386         PROFILER_LOG_INFO(LOG_CORE, "NativeMemoryProfilerSaService: tasks with an existing startup mode, name: %s",
387             startupModeProcessName_.c_str());
388         return false;
389     }
390 
391     if (config->pid_ > 0) {
392         config->processName_.clear();
393         if (pidCtx_.find(config->pid_) != pidCtx_.end()) {
394             PROFILER_LOG_INFO(LOG_CORE, "NativeMemoryProfilerSaService: hook has started, pid: %d", config->pid_);
395             return false;
396         }
397     } else if (!config->processName_.empty()) {
398         if (nameAndFilePathCtx_.find(config->processName_) != nameAndFilePathCtx_.end()) {
399             PROFILER_LOG_INFO(LOG_CORE, "NativeMemoryProfilerSaService: hook has started, process name: %s",
400                               config->processName_.c_str());
401             return false;
402         }
403     } else {
404         PROFILER_LOG_ERROR(LOG_CORE, "The PID and process name are not configured");
405         return false;
406     }
407 
408     if (fd > 0) {
409         return true;
410     }
411 
412     if (!config->filePath_.empty()) {
413         if (nameAndFilePathCtx_.find(config->filePath_) != nameAndFilePathCtx_.end()) {
414             PROFILER_LOG_ERROR(LOG_CORE,
415                                "NativeMemoryProfilerSaService: File %s is being used.", config->filePath_.c_str());
416             return false;
417         }
418     } else {
419         PROFILER_LOG_ERROR(LOG_CORE, "The file path are not configured");
420         return false;
421     }
422     return true;
423 }
424 
FillTaskConfigContext(int32_t pid,const std::string & name)425 void NativeMemoryProfilerSaService::FillTaskConfigContext(int32_t pid, const std::string& name)
426 {
427     std::lock_guard<std::mutex> guard(mtx_);
428     if (auto iter = pidCtx_.find(pid); iter != pidCtx_.end()) {
429         iter->second->processName = name;
430         nameAndFilePathCtx_[name] = iter->second;
431         if (iter->second->isStartupMode) {
432             hasStartupMode_ = false;
433         }
434     } else if (auto it = nameAndFilePathCtx_.find(name); it != nameAndFilePathCtx_.end()) {
435         it->second->pid = pid;
436         pidCtx_[pid] = it->second;
437         if (it->second->isStartupMode) {
438             hasStartupMode_ = false;
439         }
440     } else {
441         PROFILER_LOG_ERROR(LOG_CORE, "NativeMemoryProfilerSaService: fill TaskConfig context failed");
442     }
443 }
444 
ProtocolProc(SocketContext & context,uint32_t pnum,const int8_t * buf,const uint32_t size)445 bool NativeMemoryProfilerSaService::ProtocolProc(SocketContext &context, uint32_t pnum, const int8_t *buf,
446     const uint32_t size)
447 {
448     if (size != sizeof(int)) {
449         return false;
450     }
451     int peerConfig = *const_cast<int *>(reinterpret_cast<const int *>(buf));
452     if (peerConfig == -1) {
453         return false;
454     }
455 
456     std::string filePath = "/proc/" + std::to_string(peerConfig) + "/cmdline";
457     std::string bundleName;
458     if (!LoadStringFromFile(filePath, bundleName)) {
459         PROFILER_LOG_ERROR(LOG_CORE, "Get process name by pid failed!, pid: %d", peerConfig);
460         return false;
461     }
462     bundleName.resize(strlen(bundleName.c_str()));
463 
464     if (bundleName.substr(0, 2) == "./") { // 2: size, Command line programs will be prefixed with "./"
465         bundleName = bundleName.substr(2); // 2: point
466     }
467     FillTaskConfigContext(peerConfig, bundleName); // Save the relevant context for subsequent inspection
468 
469     std::lock_guard<std::mutex> guard(mtx_);
470     if (auto iter = pidCtx_.find(peerConfig); iter != pidCtx_.end()) {
471         auto [eventFd, smbFd] = iter->second->hookMgr->GetFds(peerConfig, bundleName);
472         iter->second->hookMgr->SetPid(peerConfig);
473         if (eventFd == smbFd) {
474             PROFILER_LOG_ERROR(LOG_CORE,
475                                "Get eventFd and smbFd failed!, name: %s, pid: %d", bundleName.c_str(), peerConfig);
476             return false;
477         }
478         PROFILER_LOG_INFO(LOG_CORE,
479             "ProtocolProc, receive message from hook client, and send hook config to process %d, name: %s",
480             peerConfig, bundleName.c_str());
481         ClientConfig clientConfig;
482         iter->second->hookMgr->GetClientConfig(clientConfig);
483         if (iter->second->hookMgr->GetNoDataQueueFlag()) {
484             clientConfig.freeEventOnlyAddrEnable = true;
485         }
486         clientConfig.isSaMode = true;
487         context.SendHookConfig(reinterpret_cast<uint8_t *>(&clientConfig), sizeof(clientConfig));
488         context.SendFileDescriptor(smbFd);
489         context.SendFileDescriptor(eventFd);
490         iter->second->hookMgr->ResetStartupParam();
491     } else {
492         PROFILER_LOG_ERROR(LOG_CORE, "ProtocolProc: send config failed");
493         return false;
494     }
495     return true;
496 }
497 
DelayedShutdown(bool cancel)498 void NativeMemoryProfilerSaService::DelayedShutdown(bool cancel)
499 {
500     if (cancel) {
501         scheduleTaskManager_.UnscheduleTask(delayedShutdownTimerFd_);
502         delayedShutdownTimerFd_ = -1;
503     } else {
504         int32_t timerFd = scheduleTaskManager_.ScheduleTask(
505             []() {
506                 int ret = SystemSetParameter("hiviewdfx.hiprofiler.native_memoryd.start", "0");
507                 if (ret < 0) {
508                     PROFILER_LOG_ERROR(LOG_CORE, "DelayedShutdown close sa failed");
509                 } else {
510                     PROFILER_LOG_INFO(LOG_CORE, "DelayedShutdown close sa success");
511                 }
512             },
513             DELAYED_SHUTDOWN_TIME * TIME_BASE, true);
514         if (timerFd == -1) {
515             PROFILER_LOG_ERROR(LOG_CORE, "NativeMemoryProfilerSaService:DelayedShutdown Schedule Task failed");
516             return;
517         }
518         delayedShutdownTimerFd_ = timerFd;
519     }
520 }
521 } // namespace OHOS::Developtools::NativeDaemon