1 /*
2 * Copyright (c) 2021-2022 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 <dlfcn.h>
19 #include <mutex>
20 #include <regex>
21 #include <sstream>
22 #include <string>
23
24 #include "application_context.h"
25 #include "context.h"
26 #include "file_util.h"
27 #include "hiappevent_base.h"
28 #include "hiappevent_read.h"
29 #include "hilog/log.h"
30
31 namespace OHOS {
32 namespace HiviewDFX {
33 namespace {
34 const HiLogLabel LABEL = { LOG_CORE, HIAPPEVENT_DOMAIN, "HiAppEvent_config" };
35 const std::string DISABLE = "disable";
36 const std::string MAX_STORAGE = "max_storage";
37 const std::string DEFAULT_STORAGE_DIR = "";
38 const std::string APP_EVENT_DIR = "/hiappevent/";
39 constexpr uint64_t STORAGE_UNIT_KB = 1024;
40 constexpr uint64_t STORAGE_UNIT_MB = STORAGE_UNIT_KB * 1024;
41 constexpr uint64_t STORAGE_UNIT_GB = STORAGE_UNIT_MB * 1024;
42 constexpr uint64_t STORAGE_UNIT_TB = STORAGE_UNIT_GB * 1024;
43 constexpr int DECIMAL_UNIT = 10;
44
45 std::mutex g_mutex;
46
TransUpperToUnderscoreAndLower(const std::string & str)47 std::string TransUpperToUnderscoreAndLower(const std::string& str)
48 {
49 if (str.empty()) {
50 return "";
51 }
52
53 std::stringstream ss;
54 for (size_t i = 0; i < str.size(); i++) {
55 char tmp = str[i];
56 if (tmp < 'A' || tmp > 'Z') {
57 ss << tmp;
58 continue;
59 }
60 if (i != 0) { // prevent string from starting with an underscore
61 ss << "_";
62 }
63 tmp += 32; // 32 means upper case to lower case
64 ss << tmp;
65 }
66
67 return ss.str();
68 }
69
LoadAnalyticsModule(const std::string & moduleName)70 void LoadAnalyticsModule(const std::string& moduleName)
71 {
72 const std::string searchDirs[] = {
73 "/system/lib/", "/system/lib64/", "/system/lib/ndk/", "/system/lib64/ndk/"
74 };
75 std::string modulePath;
76 for (auto& searchDir : searchDirs) {
77 if (FileUtil::IsFileExists(searchDir + moduleName)) {
78 modulePath = searchDir + moduleName;
79 break;
80 }
81 }
82 if (modulePath.empty()) {
83 HiLog::Info(LABEL, "the module=%{public}s does not exist.", moduleName.c_str());
84 return;
85 }
86
87 if (dlopen(modulePath.c_str(), RTLD_GLOBAL) == nullptr) {
88 HiLog::Info(LABEL, "failed to load module=%{public}s, error=%{public}s.", modulePath.c_str(), dlerror());
89 } else {
90 HiLog::Info(LABEL, "success to load module=%{public}s.", modulePath.c_str());
91 }
92 }
93 }
94
GetInstance()95 HiAppEventConfig& HiAppEventConfig::GetInstance()
96 {
97 static HiAppEventConfig instance;
98 return instance;
99 }
100
SetConfigurationItem(std::string name,std::string value)101 bool HiAppEventConfig::SetConfigurationItem(std::string name, std::string value)
102 {
103 // trans uppercase to underscore and lowercase
104 name = TransUpperToUnderscoreAndLower(name);
105 HiLog::Debug(LABEL, "start to configure, name=%{public}s, value=%{public}s.", name.c_str(), value.c_str());
106
107 if (name == "") {
108 HiLog::Error(LABEL, "item name can not be empty.");
109 return false;
110 }
111 std::transform(name.begin(), name.end(), name.begin(), ::tolower);
112
113 if (value == "") {
114 HiLog::Error(LABEL, "item value can not be empty.");
115 return false;
116 }
117 std::transform(value.begin(), value.end(), value.begin(), ::tolower);
118
119 // temporay loading scheme
120 LoadAnalyticsModule("libanalyticskit_native.z.so");
121
122 if (name == DISABLE) {
123 return SetDisableItem(value);
124 } else if (name == MAX_STORAGE) {
125 return SetMaxStorageSizeItem(value);
126 } else {
127 HiLog::Error(LABEL, "unrecognized configuration item name.");
128 return false;
129 }
130 }
131
SetDisableItem(const std::string & value)132 bool HiAppEventConfig::SetDisableItem(const std::string& value)
133 {
134 if (value == "true") {
135 SetDisable(true);
136 } else if (value == "false") {
137 SetDisable(false);
138 } else {
139 HiLog::Error(LABEL, "invalid bool value=%{public}s of the application dotting switch.", value.c_str());
140 return false;
141 }
142 return true;
143 }
144
SetMaxStorageSizeItem(const std::string & value)145 bool HiAppEventConfig::SetMaxStorageSizeItem(const std::string& value)
146 {
147 if (!std::regex_match(value, std::regex("[0-9]+[k|m|g|t]?[b]?"))) {
148 HiLog::Error(LABEL, "invalid value=%{public}s of the event file dir storage quota size.", value.c_str());
149 return false;
150 }
151
152 auto len = value.length();
153 std::string::size_type numEndIndex = 0;
154 uint64_t numValue = std::stoull(value, &numEndIndex, DECIMAL_UNIT);
155 if (numEndIndex == len) {
156 SetMaxStorageSize(numValue);
157 return true;
158 }
159
160 uint32_t unitLen = (numEndIndex == (len - 1)) ? 1 : 2; // 1 2, means the length of the storage unit
161 char unitChr = value[len - unitLen];
162 uint64_t maxStoSize = 0;
163 switch (unitChr) {
164 case 'b':
165 maxStoSize = numValue;
166 break;
167 case 'k':
168 maxStoSize = numValue * STORAGE_UNIT_KB;
169 break;
170 case 'm':
171 maxStoSize = numValue * STORAGE_UNIT_MB;
172 break;
173 case 'g':
174 maxStoSize = numValue * STORAGE_UNIT_GB;
175 break;
176 case 't':
177 maxStoSize = numValue * STORAGE_UNIT_TB;
178 break;
179 default:
180 HiLog::Error(LABEL, "invalid storage unit value=%{public}c.", unitChr);
181 return false;
182 }
183
184 SetMaxStorageSize(maxStoSize);
185 return true;
186 }
187
SetDisable(bool disable)188 void HiAppEventConfig::SetDisable(bool disable)
189 {
190 {
191 std::lock_guard<std::mutex> lockGuard(g_mutex);
192 this->disable = disable;
193 }
194 }
195
SetMaxStorageSize(uint64_t size)196 void HiAppEventConfig::SetMaxStorageSize(uint64_t size)
197 {
198 {
199 std::lock_guard<std::mutex> lockGuard(g_mutex);
200 this->maxStorageSize = size;
201 }
202 }
203
SetStorageDir(const std::string & dir)204 void HiAppEventConfig::SetStorageDir(const std::string& dir)
205 {
206 {
207 std::lock_guard<std::mutex> lockGuard(g_mutex);
208 this->storageDir = dir;
209 LogAssistant::Instance().UpdateHiAppEventLogDir(dir);
210 }
211 }
212
GetDisable()213 bool HiAppEventConfig::GetDisable()
214 {
215 return this->disable;
216 }
217
GetMaxStorageSize()218 uint64_t HiAppEventConfig::GetMaxStorageSize()
219 {
220 return this->maxStorageSize;
221 }
222
GetStorageDir()223 std::string HiAppEventConfig::GetStorageDir()
224 {
225 if (!this->storageDir.empty()) {
226 return this->storageDir;
227 }
228 std::shared_ptr<OHOS::AbilityRuntime::ApplicationContext> context =
229 OHOS::AbilityRuntime::Context::GetApplicationContext();
230 if (context == nullptr) {
231 HiLog::Error(LABEL, "Context is null.");
232 return DEFAULT_STORAGE_DIR;
233 }
234 if (context->GetFilesDir().empty()) {
235 HiLog::Error(LABEL, "The files dir obtained from context is empty.");
236 return DEFAULT_STORAGE_DIR;
237 }
238 std::string dir = context->GetFilesDir() + APP_EVENT_DIR;
239 SetStorageDir(dir);
240 return this->storageDir;
241 }
242 } // namespace HiviewDFX
243 } // namespace OHOS
244