• 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 "hidebug_ffi.h"
17 
18 #include <numeric>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <fcntl.h>
22 #include <memory>
23 #include <unistd.h>
24 #include <malloc.h>
25 #include <codecvt>
26 #include <string>
27 #include <vector>
28 #include <parameters.h>
29 
30 #include "cpu_collector.h"
31 #include "dump_usage.h"
32 #include "file_ex.h"
33 #include "directory_ex.h"
34 #include "storage_acl.h"
35 #include "hidebug_native_interface.h"
36 #include "memory_collector.h"
37 #include "hilog/log.h"
38 #include "system_ability_definition.h"
39 #include "iservice_registry.h"
40 
41 namespace OHOS::HiviewDFX {
42 
43 #undef LOG_DOMAIN
44 #define LOG_DOMAIN 0xD002D0A
45 #undef LOG_TAG
46 #define LOG_TAG "CJ_HiDebug"
47 
48 const std::string KEY_HIVIEW_USER_TYPE = "const.logsystem.versiontype";
49 const std::string KEY_HIVIEW_DEVELOP_TYPE = "persist.hiview.leak_detector";
50 
51 enum ErrorCode {
52     MEM_ERROR = 1,
53     PERMISSION_ERROR = 201,
54     PARAMETER_ERROR = 401,
55     VERSION_ERROR = 801,
56     SYSTEM_ABILITY_NOT_FOUND = 11400101,
57     HAVA_ALREADY_TRACE = 11400102,
58     WITHOUT_WRITE_PERMISSON = 11400103,
59     SYSTEM_STATUS_ABNORMAL = 11400104,
60     NO_CAPTURE_TRACE_RUNNING = 11400105,
61 };
62 
CheckVersionType(const std::string & type,const std::string & key)63 static bool CheckVersionType(const std::string& type, const std::string& key)
64 {
65     auto versionType = OHOS::system::GetParameter(key, "unknown");
66     return (versionType.find(type) != std::string::npos);
67 }
68 
CreateSanBoxDir()69 static bool CreateSanBoxDir()
70 {
71     constexpr mode_t defaultLogDirMode = 0x0770;
72     const std::string reourceLimitDir = "/data/storage/el2/log/resourcelimit/";
73     if (!OHOS::FileExists(reourceLimitDir)) {
74         OHOS::ForceCreateDirectory(reourceLimitDir);
75         OHOS::ChangeModeDirectory(reourceLimitDir, defaultLogDirMode);
76     }
77     if (OHOS::StorageDaemon::AclSetAccess(reourceLimitDir, "g:1201:rwx") != 0) {
78         HILOG_ERROR(LOG_CORE, "CreateSanBoxDir Failed to AclSetAccess");
79         return false;
80     }
81     return true;
82 }
83 
84 extern "C" {
FfiHidebugGetPss()85     uint64_t FfiHidebugGetPss()
86     {
87         std::shared_ptr<UCollectUtil::MemoryCollector> collector = UCollectUtil::MemoryCollector::Create();
88         if (collector != nullptr) {
89             int pid = getprocpid();
90             auto collectResult = collector->CollectProcessMemory(pid);
91             int32_t pssInfo = collectResult.data.pss + collectResult.data.swapPss;
92             return static_cast<uint64_t>(pssInfo);
93         } else {
94             return 0;
95         }
96     }
97 
FfiHidebugGetVss()98     uint64_t FfiHidebugGetVss()
99     {
100         std::shared_ptr<UCollectUtil::MemoryCollector> collector = UCollectUtil::MemoryCollector::Create();
101         if (collector != nullptr) {
102             pid_t pid = getprocpid();
103             auto collectResult = collector->CollectProcessVss(pid);
104             uint64_t vssInfo = collectResult.data;
105             return vssInfo;
106         } else {
107             return 0;
108         }
109     }
110 
FfiHidebugGetNativeHeapSize()111     uint64_t FfiHidebugGetNativeHeapSize()
112     {
113         struct mallinfo mi = mallinfo();
114         return static_cast<uint64_t>(mi.uordblks + mi.fordblks);
115     }
116 
FfiHidebugGetNativeHeapAllocatedSize()117     uint64_t FfiHidebugGetNativeHeapAllocatedSize()
118     {
119         struct mallinfo mi = mallinfo();
120         return static_cast<uint64_t>(mi.uordblks);
121     }
122 
FfiHidebugGetNativeHeapFreeSize()123     uint64_t FfiHidebugGetNativeHeapFreeSize()
124     {
125         struct mallinfo mi = mallinfo();
126         return static_cast<uint64_t>(mi.fordblks);
127     }
128 
FfiHidebugGetSharedDirty()129     uint64_t FfiHidebugGetSharedDirty()
130     {
131         std::shared_ptr<UCollectUtil::MemoryCollector> collector = UCollectUtil::MemoryCollector::Create();
132         if (collector != nullptr) {
133             int pid = getprocpid();
134             auto collectResult = collector->CollectProcessMemory(pid);
135             int32_t sharedDirtyInfo = collectResult.data.sharedDirty;
136             return static_cast<uint64_t>(sharedDirtyInfo);
137         } else {
138             return 0;
139         }
140     }
141 
FfiHidebugGetPrivateDirty()142     uint64_t FfiHidebugGetPrivateDirty()
143     {
144         std::shared_ptr<UCollectUtil::MemoryCollector> collector = UCollectUtil::MemoryCollector::Create();
145         if (collector != nullptr) {
146             pid_t pid = getprocpid();
147             auto collectResult = collector->CollectProcessMemory(pid);
148             int32_t privateDirty = collectResult.data.privateDirty;
149             return static_cast<uint64_t>(privateDirty);
150         } else {
151             return 0;
152         }
153     }
154 
FfiHidebugGetCpuUsage()155     double FfiHidebugGetCpuUsage()
156     {
157         std::unique_ptr<DumpUsage> dumpUsage = std::make_unique<DumpUsage>();
158         pid_t pid = getprocpid();
159         return dumpUsage->GetCpuUsage(pid);
160     }
161 
FfiHidebugGetSystemCpuUsage(int32_t & code)162     double FfiHidebugGetSystemCpuUsage(int32_t &code)
163     {
164         auto cpuUsageOptional = HidebugNativeInterface::GetInstance().GetSystemCpuUsage();
165         if (cpuUsageOptional.has_value()) {
166             return cpuUsageOptional.value();
167         }
168         code = ErrorCode::SYSTEM_STATUS_ABNORMAL;
169         return 0;
170     }
171 
FfiHidebugGetAppThreadCpuUsage(int32_t & code)172     ThreadCpuUsageArr FfiHidebugGetAppThreadCpuUsage(int32_t &code)
173     {
174         ThreadCpuUsageArr arr{ .head = nullptr, .size = 0};
175         std::map<uint32_t, double> threadMap = HidebugNativeInterface::GetInstance().GetAppThreadCpuUsage();
176         auto size = threadMap.size();
177         if (size <= 0) {
178             return arr;
179         }
180         arr.head = static_cast<CThreadCpuUsage *>(malloc(sizeof(CThreadCpuUsage) * size));
181         if (arr.head == nullptr) {
182             code = ErrorCode::MEM_ERROR;
183             return arr;
184         }
185         size_t idx = 0;
186         for (const auto[id, usage] : threadMap) {
187             arr.head[idx] = CThreadCpuUsage{ .threadId = id, .cpuUsage = usage };
188             idx++;
189         }
190         return arr;
191     }
192 
FfiHidebugGetSystemMemInfo(int32_t & code)193     CSystemMemInfo FfiHidebugGetSystemMemInfo(int32_t &code)
194     {
195         CSystemMemInfo info{.totalMem = 0, .freeMem = 0, .availableMem = 0};
196         auto systemMemInfo = HidebugNativeInterface::GetInstance().GetSystemMemInfo();
197         if (!systemMemInfo) {
198             code = ErrorCode::MEM_ERROR;
199             return info;
200         }
201 
202         info.totalMem = static_cast<uint64_t>(systemMemInfo->memTotal);
203         info.freeMem = static_cast<uint64_t>(systemMemInfo->memFree);
204         info.availableMem = static_cast<uint64_t>(systemMemInfo->memAvailable);
205         return info;
206     }
207 
FfiHidebugGetAppNativeMemInfo(int32_t & code)208     CNativeMemInfo FfiHidebugGetAppNativeMemInfo(int32_t &code)
209     {
210         CNativeMemInfo info{};
211         auto nativeMemInfo = HidebugNativeInterface::GetInstance().GetAppNativeMemInfo();
212         if (!nativeMemInfo) {
213             code = ErrorCode::MEM_ERROR;
214             return info;
215         }
216         info.pss = nativeMemInfo->pss;
217         info.vss = nativeMemInfo->vss;
218         info.rss = nativeMemInfo->rss;
219         info.sharedDirty = nativeMemInfo->sharedDirty;
220         info.privateDirty = nativeMemInfo->privateDirty;
221         info.sharedClean = nativeMemInfo->sharedClean;
222         info.privateClean = nativeMemInfo->privateClean;
223         return info;
224     }
225 
FfiHidebugGetAppMemoryLimit(int32_t & code)226     CMemoryLimit FfiHidebugGetAppMemoryLimit(int32_t &code)
227     {
228         CMemoryLimit limit{.rssLimit = 0, .vssLimit = 0};
229         auto memoryLimit = HidebugNativeInterface::GetInstance().GetAppMemoryLimit();
230         if (!memoryLimit) {
231             code = ErrorCode::MEM_ERROR;
232             return limit;
233         }
234         limit.rssLimit = memoryLimit->rssLimit;
235         limit.vssLimit = memoryLimit->vssLimit;
236 
237         return limit;
238     }
239 
FfiHidebugGetServiceDump(int32_t serviceId,int32_t fd,CArrString args)240     int32_t FfiHidebugGetServiceDump(int32_t serviceId, int32_t fd, CArrString args)
241     {
242         sptr<ISystemAbilityManager> sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
243         if (!sam) {
244             return ErrorCode::MEM_ERROR;
245         }
246         sptr<IRemoteObject> sa = sam->CheckSystemAbility(serviceId);
247         if (sa == nullptr) {
248             return ErrorCode::SYSTEM_ABILITY_NOT_FOUND;
249         }
250         std::vector<std::u16string> cargs;
251         std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> strCnv;
252         for (int64_t i = 0; i < args.size; i++) {
253             cargs.push_back(strCnv.from_bytes(args.head[i]));
254         }
255         int dumpResult = sa->Dump(fd, cargs);
256         HILOG_INFO(LOG_CORE, "Dump result: %{public}d", dumpResult);
257         return 0;
258     }
259 
FfiHidebugStartAppTraceCapture(CArrUnit tags,int32_t flag,uint32_t limitSize,int32_t & code)260     char *FfiHidebugStartAppTraceCapture(CArrUnit tags, int32_t flag, uint32_t limitSize, int32_t &code)
261     {
262         std::vector<uint64_t> taglist;
263         uint64_t *tagPtr = static_cast<uint64_t *>(tags.head);
264         for (int64_t i = 0; i < tags.size; i++) {
265             taglist.push_back(tagPtr[i]);
266         }
267         uint64_t tag = std::accumulate(taglist.begin(), taglist.end(), 0ull,
268             [](uint64_t a, uint64_t b) { return a | b; });
269         std::string file;
270         code = HidebugNativeInterface::GetInstance().StartAppTraceCapture(tag, flag, limitSize, file);
271         if (code != HIDEBUG_SUCCESS || file.empty()) {
272             return nullptr;
273         }
274         auto len = file.length() + 1;
275         char *res = static_cast<char *>(malloc(sizeof(char) * len));
276         if (res == nullptr) {
277             return nullptr;
278         }
279         return std::char_traits<char>::copy(res, file.c_str(), len);
280     }
281 
FfiHidebugStopAppTraceCapture()282     int32_t FfiHidebugStopAppTraceCapture()
283     {
284         return HidebugNativeInterface::GetInstance().StopAppTraceCapture();
285     }
286 
FfiHidebugSetAppResourceLimit(const char * type,int32_t value,bool enableDebugLog)287     int32_t FfiHidebugSetAppResourceLimit(const char *type, int32_t value, bool enableDebugLog)
288     {
289         if (!CheckVersionType("beta", KEY_HIVIEW_USER_TYPE) &&
290             !CheckVersionType("enable", KEY_HIVIEW_DEVELOP_TYPE)) {
291             HILOG_ERROR(LOG_CORE, "SetAppResourceLimit failed. Not developer options or beta versions");
292             return ErrorCode::VERSION_ERROR;
293         }
294         auto abilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
295         if (!abilityManager) {
296             return ErrorCode::MEM_ERROR;
297         }
298         sptr<IRemoteObject> remoteObject = abilityManager->CheckSystemAbility(DFX_SYS_HIVIEW_ABILITY_ID);
299         if (remoteObject == nullptr) {
300             HILOG_ERROR(LOG_CORE, "SetAppResourceLimit failed. No this system ability.");
301             return ErrorCode::SYSTEM_STATUS_ABNORMAL;
302         }
303         auto result =
304             HidebugNativeInterface::GetInstance().GetMemoryLeakResource(std::string(type), value, enableDebugLog);
305         if (result == MemoryState::MEMORY_FAILED) {
306             return 0;
307         }
308         CreateSanBoxDir();
309         return 0;
310     }
311 
FfiHidebugIsDebugState()312     bool FfiHidebugIsDebugState()
313     {
314         return HidebugNativeInterface::GetInstance().IsDebuggerConnected();
315     }
316 }
317 }
318