• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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 #include "hiappevent_config.h"
16 
17 #include <algorithm>
18 #include <cinttypes>
19 #include <cstdlib>
20 #include <mutex>
21 #include <regex>
22 #include <sstream>
23 #include <string>
24 
25 #include "app_event_observer_mgr.h"
26 #include "resource_overlimit_mgr.h"
27 #include "application_context.h"
28 #include "context.h"
29 #include "hiappevent_base.h"
30 #include "hilog/log.h"
31 #include "iservice_registry.h"
32 #include "storage_manager_proxy.h"
33 #include "system_ability_definition.h"
34 #include "xcollie/watchdog.h"
35 
36 #undef LOG_DOMAIN
37 #define LOG_DOMAIN 0xD002D07
38 
39 #undef LOG_TAG
40 #define LOG_TAG "Config"
41 
42 namespace OHOS {
43 namespace HiviewDFX {
44 namespace {
45 constexpr const char* const DISABLE = "disable";
46 constexpr const char* const MAX_STORAGE = "max_storage";
47 constexpr const char* const APP_EVENT_DIR = "/hiappevent/";
48 constexpr const char* const APP_CRASH = "APP_CRASH";
49 constexpr const char* const MAIN_THREAD_JANK = "MAIN_THREAD_JANK";
50 constexpr uint64_t STORAGE_UNIT_KB = 1024;
51 constexpr uint64_t STORAGE_UNIT_MB = STORAGE_UNIT_KB * 1024;
52 constexpr uint64_t STORAGE_UNIT_GB = STORAGE_UNIT_MB * 1024;
53 constexpr uint64_t STORAGE_UNIT_TB = STORAGE_UNIT_GB * 1024;
54 constexpr int DECIMAL_UNIT = 10;
55 constexpr int64_t FREE_SIZE_LIMIT = STORAGE_UNIT_MB * 300;
56 
57 std::mutex g_mutex;
58 
59 extern "C" int DFX_SetCrashLogConfig(uint8_t type, uint32_t value) __attribute__((weak));
60 
TransUpperToUnderscoreAndLower(const std::string & str)61 std::string TransUpperToUnderscoreAndLower(const std::string& str)
62 {
63     if (str.empty()) {
64         return "";
65     }
66 
67     std::stringstream ss;
68     for (size_t i = 0; i < str.size(); i++) {
69         char tmp = str[i];
70         if (tmp < 'A' || tmp > 'Z') {
71             ss << tmp;
72             continue;
73         }
74         if (i != 0) { // prevent string from starting with an underscore
75             ss << "_";
76         }
77         tmp += 32; // 32 means upper case to lower case
78         ss << tmp;
79     }
80 
81     return ss.str();
82 }
83 
GetStorageMgr()84 sptr<OHOS::StorageManager::IStorageManager> GetStorageMgr()
85 {
86     auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
87     if (systemAbilityManager == nullptr) {
88         HILOG_WARN(LOG_CORE, "systemAbilityManager is null.");
89         return nullptr;
90     }
91     sptr<IRemoteObject> storageMgrSa = systemAbilityManager->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID);
92     if (storageMgrSa == nullptr) {
93         HILOG_WARN(LOG_CORE, "storageMgrSa is null.");
94         return nullptr;
95     }
96     return iface_cast<OHOS::StorageManager::IStorageManager>(storageMgrSa);
97 }
98 }
99 
GetInstance()100 HiAppEventConfig& HiAppEventConfig::GetInstance()
101 {
102     static HiAppEventConfig instance;
103     return instance;
104 }
105 
SetConfigurationItem(std::string name,std::string value)106 bool HiAppEventConfig::SetConfigurationItem(std::string name, std::string value)
107 {
108     // trans uppercase to underscore and lowercase
109     name = TransUpperToUnderscoreAndLower(name);
110     HILOG_DEBUG(LOG_CORE, "start to configure.");
111 
112     if (name == "") {
113         HILOG_ERROR(LOG_CORE, "item name can not be empty.");
114         return false;
115     }
116     std::transform(name.begin(), name.end(), name.begin(), ::tolower);
117 
118     if (value == "") {
119         HILOG_ERROR(LOG_CORE, "item value can not be empty.");
120         return false;
121     }
122     std::transform(value.begin(), value.end(), value.begin(), ::tolower);
123 
124     if (name == DISABLE) {
125         return SetDisableItem(value);
126     } else if (name == MAX_STORAGE) {
127         return SetMaxStorageSizeItem(value);
128     } else {
129         HILOG_ERROR(LOG_CORE, "unrecognized configuration item name.");
130         return false;
131     }
132 }
133 
SetDisableItem(const std::string & value)134 bool HiAppEventConfig::SetDisableItem(const std::string& value)
135 {
136     if (value == "true") {
137         SetDisable(true);
138     } else if (value == "false") {
139         SetDisable(false);
140     } else {
141         HILOG_ERROR(LOG_CORE, "invalid bool value=%{public}s of the application dotting switch.", value.c_str());
142         return false;
143     }
144     return true;
145 }
146 
SetMaxStorageSizeItem(const std::string & value)147 bool HiAppEventConfig::SetMaxStorageSizeItem(const std::string& value)
148 {
149     if (!std::regex_match(value, std::regex("[0-9]+[k|m|g|t]?[b]?"))) {
150         HILOG_ERROR(LOG_CORE, "invalid value=%{public}s of the event file dir storage quota size.", value.c_str());
151         return false;
152     }
153 
154     char* numEndIndex = nullptr;
155     uint64_t numValue = std::strtoull(value.c_str(), &numEndIndex, DECIMAL_UNIT);
156     if (*numEndIndex == '\0') {
157         SetMaxStorageSize(numValue);
158         return true;
159     }
160 
161     uint32_t unitLen = std::strlen(numEndIndex);
162     auto len = value.length();
163     char unitChr = value[len - unitLen];
164     uint64_t maxStoSize = 0;
165     switch (unitChr) {
166         case 'b':
167             maxStoSize = numValue;
168             break;
169         case 'k':
170             maxStoSize = numValue * STORAGE_UNIT_KB;
171             break;
172         case 'm':
173             maxStoSize = numValue * STORAGE_UNIT_MB;
174             break;
175         case 'g':
176             maxStoSize = numValue * STORAGE_UNIT_GB;
177             break;
178         case 't':
179             maxStoSize = numValue * STORAGE_UNIT_TB;
180             break;
181         default:
182             HILOG_ERROR(LOG_CORE, "invalid storage unit value=%{public}c.", unitChr);
183             return false;
184     }
185 
186     SetMaxStorageSize(maxStoSize);
187     return true;
188 }
189 
SetDisable(bool disable)190 void HiAppEventConfig::SetDisable(bool disable)
191 {
192     std::lock_guard<std::mutex> lockGuard(g_mutex);
193     disable_ = disable;
194 }
195 
SetMaxStorageSize(uint64_t size)196 void HiAppEventConfig::SetMaxStorageSize(uint64_t size)
197 {
198     std::lock_guard<std::mutex> lockGuard(g_mutex);
199     maxStorageSize_ = size;
200 }
201 
SetStorageDir(const std::string & dir)202 void HiAppEventConfig::SetStorageDir(const std::string& dir)
203 {
204     storageDir_ = dir;
205 }
206 
GetDisable()207 bool HiAppEventConfig::GetDisable()
208 {
209     std::lock_guard<std::mutex> lockGuard(g_mutex);
210     return disable_;
211 }
212 
GetMaxStorageSize()213 uint64_t HiAppEventConfig::GetMaxStorageSize()
214 {
215     std::lock_guard<std::mutex> lockGuard(g_mutex);
216     return maxStorageSize_;
217 }
218 
GetStorageDir()219 std::string HiAppEventConfig::GetStorageDir()
220 {
221     std::lock_guard<std::mutex> lockGuard(g_mutex);
222     if (!storageDir_.empty()) {
223         return storageDir_;
224     }
225     std::shared_ptr<OHOS::AbilityRuntime::ApplicationContext> context =
226         OHOS::AbilityRuntime::Context::GetApplicationContext();
227     if (context == nullptr) {
228         HILOG_ERROR(LOG_CORE, "Context is null.");
229         return "";
230     }
231     if (context->GetFilesDir().empty()) {
232         HILOG_ERROR(LOG_CORE, "The files dir obtained from context is empty.");
233         return "";
234     }
235     std::string dir = context->GetFilesDir() + APP_EVENT_DIR;
236     SetStorageDir(dir);
237     return storageDir_;
238 }
239 
GetRunningId()240 std::string HiAppEventConfig::GetRunningId()
241 {
242     std::lock_guard<std::mutex> lockGuard(g_mutex);
243     if (!runningId_.empty()) {
244         return runningId_;
245     }
246     std::shared_ptr<OHOS::AbilityRuntime::ApplicationContext> context =
247         OHOS::AbilityRuntime::Context::GetApplicationContext();
248     if (context == nullptr) {
249         HILOG_ERROR(LOG_CORE, "Context is null.");
250         return "";
251     }
252     runningId_ = context->GetAppRunningUniqueId();
253     if (runningId_.empty()) {
254         HILOG_ERROR(LOG_CORE, "The running id from context is empty.");
255     }
256     return runningId_;
257 }
258 
IsFreeSizeOverLimit()259 bool HiAppEventConfig::IsFreeSizeOverLimit()
260 {
261     std::lock_guard<std::mutex> lockGuard(g_mutex);
262     if (!isInitFreeSize_) {
263         isInitFreeSize_ = true;
264         auto storageMgr = GetStorageMgr();
265         int64_t freeSize = -1;
266         if (storageMgr == nullptr || storageMgr->GetFreeSize(freeSize) != 0) {
267             HILOG_WARN(LOG_CORE, "Failed to get free size.");
268             return false;
269         }
270         HILOG_INFO(LOG_CORE, "get free size=%{public}" PRId64, freeSize);
271         freeSize_ = freeSize;
272     }
273     return freeSize_ >= 0 && freeSize_ < FREE_SIZE_LIMIT;
274 }
275 
RefreshFreeSize()276 void HiAppEventConfig::RefreshFreeSize()
277 {
278     auto storageMgr = GetStorageMgr();
279     int64_t freeSize = -1;
280     if (storageMgr == nullptr || storageMgr->GetFreeSize(freeSize) != 0) {
281         HILOG_WARN(LOG_CORE, "Failed to refresh free size.");
282         return;
283     }
284     HILOG_INFO(LOG_CORE, "refresh free size=%{public}" PRId64, freeSize);
285     std::lock_guard<std::mutex> lockGuard(g_mutex);
286     freeSize_ = freeSize;
287 }
288 
SetEventConfig(const std::string & name,const std::map<std::string,std::string> & configMap)289 int HiAppEventConfig::SetEventConfig(const std::string& name, const std::map<std::string, std::string> &configMap)
290 {
291     if (name == MAIN_THREAD_JANK) {
292         return Watchdog::GetInstance().SetEventConfig(configMap);
293     }
294     if (name == RESOURCE_OVERLIMIT) {
295         ResourceOverlimitMgr::GetInstance().SetRunningId(GetRunningId());
296         return ResourceOverlimitMgr::GetInstance().SetEventConfig(configMap);
297     }
298 
299     HILOG_ERROR(LOG_CORE, "Failed to set event config, name is invalid. name=%{public}s", name.c_str());
300     return ErrorCode::ERROR_INVALID_PARAM_VALUE;
301 }
302 
SetCrashConfig(const std::map<uint8_t,uint32_t> & configMap)303 int HiAppEventConfig::SetCrashConfig(const std::map<uint8_t, uint32_t> &configMap)
304 {
305     if (DFX_SetCrashLogConfig == nullptr) {
306         HILOG_ERROR(LOG_CORE, "set crash log config func was not found.");
307         return ErrorCode::ERROR_UNKNOWN;
308     }
309 
310     for (const auto& [key, value] : configMap) {
311         (void)DFX_SetCrashLogConfig(key, value);
312     }
313     return ErrorCode::HIAPPEVENT_VERIFY_SUCCESSFUL;
314 }
315 } // namespace HiviewDFX
316 } // namespace OHOS
317