• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-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 
16 #include "bundle_active_config_reader.h"
17 #include "config_policy_utils.h"
18 #include "bundle_active_constant.h"
19 #include "bundle_active_log.h"
20 #include "file_ex.h"
21 
22 using namespace std;
23 namespace OHOS {
24 namespace DeviceUsageStats {
25 const static char* CONFIG_PATH = "etc/device_usage_statistics/device_usage_statistics_config.json";
26 const static char* APPLICATION_USE_PERIODICALLY_KEY = "application_use_periodically";
27 const static char* MIN_USE_TIMES = "MinUseTimes";
28 const static char* MAX_USE_TIMES = "MaxUseTimes";
29 const static char* MIN_USE_DAYS = "MinUseDays";
30 const static char* MAX_DATA_SIZE = "MaxDataSize";
31 const static char* APPLICATION_USE_HIGH_FREQUENCY_JUDGE_THRESHOLD =
32     "application_use_high_frequency_judge_threshold";
33 const static char* MIN_TOTAL_USE_DAYS = "MinTotalUseDays";
34 const static char* MIN_TOP_USE_HOURS_LIMIT = "MinTopUseHoursLimit";
35 const static char* MIN_HOUR_USE_DAYS = "MinHourUseDays";
36 const static char* MAX_HIGH_FREQUENCY_HOUR_NUM = "MaxHighFrequencyHourNum";
37 const int32_t DEFAULT_MIN_USE_TIMES = 1;
38 const int32_t DEFAULT_MAX_USE_TIMES = 10;
39 const int32_t DEFAULT_MIN_USE_DAYS = 3;
40 const int32_t DEFAULT_MIN_TOTAL_USE_DAYS = 4;
41 const int32_t DEFAULT_TOP_USE_HOURS_LIMIT = 6;
42 const int32_t DEFAULT_MIN_HOUR_USE_DAYS = 4;
43 const int32_t DEFAULT_MAX_HIGH_FREQUENCY_HOUR_NUM = 3;
44 const int32_t MAX_BUFFER = 2048;
45 const uint64_t DEFAULT_MAX_DATA_SIZE = 5 * 1024 * 1024;
46 
47 
LoadConfig()48 void BundleActiveConfigReader::LoadConfig()
49 {
50     appUsePeriodicallyConfig_ = {DEFAULT_MIN_USE_TIMES, DEFAULT_MAX_USE_TIMES, DEFAULT_MIN_USE_DAYS};
51     appHighFreqPeriodThresholdConfig_ = {DEFAULT_MIN_TOTAL_USE_DAYS,
52         DEFAULT_TOP_USE_HOURS_LIMIT,
53         DEFAULT_MIN_HOUR_USE_DAYS,
54         DEFAULT_MAX_HIGH_FREQUENCY_HOUR_NUM};
55     auto cfgFiles = GetCfgFiles(CONFIG_PATH);
56 // LCOV_EXCL_START
57     if (!cfgFiles) {
58         BUNDLE_ACTIVE_LOGE("GetCfgFiles failed");
59         return;
60     }
61 // LCOV_EXCL_STOP
62     for (const auto& filePath : cfgFiles->paths) {
63         LoadConfigFile(filePath);
64     }
65     BUNDLE_ACTIVE_LOGI("appUsePeriodicallyConfig minUseTimes:%{public}d, maxUseTimes:%{public}d,"
66         "minUseDays:%{public}d maxDataSize:%{public}lu", appUsePeriodicallyConfig_.minUseTimes,
67         appUsePeriodicallyConfig_.maxUseTimes, appUsePeriodicallyConfig_.minUseDays,
68         static_cast<unsigned long>(maxDataSize_));
69     BUNDLE_ACTIVE_LOGI("appHighFreqPeriodThresholdConfig minTotalUseDays:%{public}d, minTopUseHoursLimit:%{public}d,"
70         "minHourUseDays:%{public}d,"
71         "maxHighFreqHourNum:%{public}d",
72         appHighFreqPeriodThresholdConfig_.minTotalUseDays,
73         appHighFreqPeriodThresholdConfig_.minTopUseHoursLimit,
74         appHighFreqPeriodThresholdConfig_.minHourUseDays,
75         appHighFreqPeriodThresholdConfig_.maxHighFreqHourNum);
76     FreeCfgFiles(cfgFiles);
77 }
78 
LoadConfigFile(const char * filePath)79 void BundleActiveConfigReader::LoadConfigFile(const char *filePath)
80 {
81     if (!filePath) {
82         BUNDLE_ACTIVE_LOGE("file does no exit");
83         return;
84     }
85     cJSON *root = nullptr;
86     if (!GetJsonFromFile(filePath, root) || !root) {
87         BUNDLE_ACTIVE_LOGE("file is empty %{private}s", filePath);
88         return;
89     }
90 // LCOV_EXCL_START
91     LoadApplicationUsePeriodically(root);
92     LoadAppHighFreqPeriodThresholdConfig(root);
93     LoadMaxDataSize(root);
94     cJSON_Delete(root);
95 // LCOV_EXCL_STOP
96 }
97 
98 // LCOV_EXCL_START
LoadApplicationUsePeriodically(cJSON * root)99 void BundleActiveConfigReader::LoadApplicationUsePeriodically(cJSON* root)
100 {
101     cJSON *appUsePeriodicallyRoot = cJSON_GetObjectItem(root, APPLICATION_USE_PERIODICALLY_KEY);
102     if (!IsValidObject(appUsePeriodicallyRoot)) {
103         BUNDLE_ACTIVE_LOGE("application_use_periodically content is empty");
104         return;
105     }
106 
107     int32_t minUseTimes =
108         GetIntValue(appUsePeriodicallyRoot, MIN_USE_TIMES, MINIMUM_LIMIT, INT32_MAX, DEFAULT_MIN_USE_TIMES);
109     int32_t maxUseTimes =
110         GetIntValue(appUsePeriodicallyRoot, MAX_USE_TIMES, MINIMUM_LIMIT, INT32_MAX, DEFAULT_MAX_USE_TIMES);
111     int32_t minUseDays =
112         GetIntValue(appUsePeriodicallyRoot, MIN_USE_DAYS, MINIMUM_LIMIT, INT32_MAX, DEFAULT_MIN_USE_DAYS);
113 
114     appUsePeriodicallyConfig_ = {minUseTimes, maxUseTimes, minUseDays};
115 }
116 
LoadAppHighFreqPeriodThresholdConfig(cJSON * root)117 void BundleActiveConfigReader::LoadAppHighFreqPeriodThresholdConfig(cJSON* root)
118 {
119     cJSON* appHighFreqPeriodThresholdConfigRoot =
120         cJSON_GetObjectItem(root, APPLICATION_USE_HIGH_FREQUENCY_JUDGE_THRESHOLD);
121     if (!IsValidObject(appHighFreqPeriodThresholdConfigRoot)) {
122         BUNDLE_ACTIVE_LOGE("application_use_high_frequency_judge_threshold content is empty");
123         return;
124     }
125     int32_t minTotalUseDays = GetIntValue(appHighFreqPeriodThresholdConfigRoot,
126         MIN_TOTAL_USE_DAYS,
127         MINIMUM_LIMIT,
128         NUM_DAY_ONE_WEEK,
129         DEFAULT_MIN_TOTAL_USE_DAYS);
130 
131     int32_t minTopUseHoursLimit = GetIntValue(appHighFreqPeriodThresholdConfigRoot,
132         MIN_TOP_USE_HOURS_LIMIT,
133         MINIMUM_LIMIT,
134         NUM_HOUR_ONE_DAY,
135         DEFAULT_TOP_USE_HOURS_LIMIT);
136     int32_t minHourUseDays = GetIntValue(appHighFreqPeriodThresholdConfigRoot,
137         MIN_HOUR_USE_DAYS,
138         MINIMUM_LIMIT,
139         NUM_DAY_ONE_WEEK,
140         DEFAULT_MIN_HOUR_USE_DAYS);
141     int32_t maxHighFreqHourNum = GetIntValue(appHighFreqPeriodThresholdConfigRoot,
142         MAX_HIGH_FREQUENCY_HOUR_NUM,
143         MINIMUM_LIMIT,
144         NUM_HOUR_ONE_DAY,
145         DEFAULT_MAX_HIGH_FREQUENCY_HOUR_NUM);
146 
147     appHighFreqPeriodThresholdConfig_ = {minTotalUseDays, minTopUseHoursLimit, minHourUseDays, maxHighFreqHourNum};
148 }
149 
LoadMaxDataSize(cJSON * root)150 void BundleActiveConfigReader::LoadMaxDataSize(cJSON* root)
151 {
152     cJSON *maxDataSizeItem = cJSON_GetObjectItem(root, MAX_DATA_SIZE);
153     if (!IsValidNumber(maxDataSizeItem)) {
154         BUNDLE_ACTIVE_LOGE("not have max data size key");
155         return;
156     }
157     maxDataSize_ = static_cast<uint64_t>(maxDataSizeItem->valueint);
158 }
159 // LCOV_EXCL_STOP
160 
GetJsonFromFile(const char * filePath,cJSON * & root)161 bool BundleActiveConfigReader::GetJsonFromFile(const char *filePath, cJSON *&root)
162 {
163     std::string realPath;
164     if (!BundleActiveConfigReader::ConvertFullPath(filePath, realPath)) {
165         BUNDLE_ACTIVE_LOGE("Get real path failed %{private}s", filePath);
166         return false;
167     }
168     BUNDLE_ACTIVE_LOGD("Read from %{private}s", realPath.c_str());
169     std::string data;
170     if (!LoadStringFromFile(realPath.c_str(), data)) {
171         BUNDLE_ACTIVE_LOGE("load string from %{private}s failed", realPath.c_str());
172         return false;
173     }
174 // LCOV_EXCL_START
175     if (data.empty()) {
176         return false;
177     }
178     root = cJSON_Parse(data.c_str());
179     if (!root) {
180         BUNDLE_ACTIVE_LOGE("parse %{private}s json error", realPath.c_str());
181         return false;
182     }
183     return true;
184 // LCOV_EXCL_STOP
185 }
186 
ConvertFullPath(const std::string & partialPath,std::string & fullPath)187 bool BundleActiveConfigReader::ConvertFullPath(const std::string& partialPath, std::string& fullPath)
188 {
189 // LCOV_EXCL_START
190     if (partialPath.empty() || partialPath.length() >= PATH_MAX) {
191         return false;
192     }
193 // LCOV_EXCL_STOP
194     char tmpPath[PATH_MAX] = {0};
195     if (realpath(partialPath.c_str(), tmpPath) == nullptr) {
196         return false;
197     }
198     fullPath = tmpPath;
199     return true;
200 }
201 
GetApplicationUsePeriodicallyConfig()202 AppUsePeriodicallyConfig BundleActiveConfigReader::GetApplicationUsePeriodicallyConfig()
203 {
204     return appUsePeriodicallyConfig_;
205 }
206 
GetAppHighFrequencyPeriodThresholdConfig()207 AppHighFrequencyPeriodThresholdConfig BundleActiveConfigReader::GetAppHighFrequencyPeriodThresholdConfig()
208 {
209     return appHighFreqPeriodThresholdConfig_;
210 }
211 // LCOV_EXCL_START
GetMaxDataSize()212 uint64_t BundleActiveConfigReader::GetMaxDataSize()
213 {
214     if (maxDataSize_ == 0) {
215         return DEFAULT_MAX_DATA_SIZE;
216     }
217     return maxDataSize_;
218 }
219 
GetIntValue(cJSON * root,const char * parameterName,int32_t minLimit,int32_t maxLimit,int32_t defaultValue)220 int32_t BundleActiveConfigReader::GetIntValue(
221     cJSON* root, const char* parameterName, int32_t minLimit, int32_t maxLimit, int32_t defaultValue)
222 {
223     cJSON* item = cJSON_GetObjectItem(root, parameterName);
224     if (!IsValidNumber(item)) {
225         BUNDLE_ACTIVE_LOGE("Configuration parameter %{private}s error", parameterName);
226         return defaultValue;
227     }
228     int32_t value = static_cast<int32_t>(item->valueint);
229     if (value < minLimit || value > maxLimit) {
230         BUNDLE_ACTIVE_LOGE("Configuration parameter %{private}s is invalid value", parameterName);
231         return defaultValue;
232     }
233     return value;
234 }
235 
IsValidObject(cJSON * item)236 bool BundleActiveConfigReader::IsValidObject(cJSON* item)
237 {
238     return item != nullptr && cJSON_IsObject(item);
239 }
240 
IsValidNumber(cJSON * item)241 bool BundleActiveConfigReader::IsValidNumber(cJSON* item)
242 {
243     return item != nullptr && cJSON_IsNumber(item);
244 }
245 // LCOV_EXCL_STOP
246 }  // namespace DeviceUsageStats
247 }  // namespace OHOS