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