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 "bundle_active_config_reader.h"
17 #include "config_policy_utils.h"
18 #include "bundle_active_log.h"
19 #include <fstream>
20 #include <iostream>
21
22 using namespace std;
23 namespace OHOS {
24 namespace DeviceUsageStats {
25 const char* CONFIG_PATH = "etc/device_usage_statistics/device_usage_statistics_config.json";
26 const std::string APPLICATION_USE_PERIODICALLY_KEY = "application_use_periodically";
27 const std::string MIN_USE_TIMES = "MinUseTimes";
28 const std::string MAX_USE_TIMES = "MaxUseTimes";
29 const std::string MIN_USE_DAYS = "MinUseDays";
30 const int32_t DEFAULT_MIN_USE_TIMES = 1;
31 const int32_t DEFAULT_MAX_USE_TIMES = 10;
32 const int32_t DEFAULT_MIN_USE_DAYS = 3;
33 const int32_t MAX_BUFFER = 2048;
34
35
LoadConfig()36 void BundleActiveConfigReader::LoadConfig()
37 {
38 appUsePeriodicallyConfig_ = { DEFAULT_MIN_USE_TIMES, DEFAULT_MAX_USE_TIMES, DEFAULT_MIN_USE_DAYS};
39 auto cfgFiles = GetCfgFiles(CONFIG_PATH);
40 if (!cfgFiles) {
41 BUNDLE_ACTIVE_LOGE("GetCfgFiles failed");
42 return;
43 }
44 for (const auto& filePath : cfgFiles->paths) {
45 LoadApplicationUsePeriodically(filePath);
46 }
47 BUNDLE_ACTIVE_LOGI("appUsePeriodicallyConfig minUseTimes:%{public}d, maxUseTimes:%{public}d,"
48 "minUseDays:%{public}d", appUsePeriodicallyConfig_.minUseTimes,
49 appUsePeriodicallyConfig_.maxUseTimes, appUsePeriodicallyConfig_.minUseDays);
50 FreeCfgFiles(cfgFiles);
51 };
52
LoadApplicationUsePeriodically(const char * filePath)53 void BundleActiveConfigReader::LoadApplicationUsePeriodically(const char *filePath)
54 {
55 if (!filePath) {
56 return;
57 }
58 Json::Value root;
59 if (!GetJsonFromFile(filePath, root) || root.empty()) {
60 BUNDLE_ACTIVE_LOGE("file is empty %{private}s", filePath);
61 return;
62 }
63 if (!root.isMember(APPLICATION_USE_PERIODICALLY_KEY)) {
64 BUNDLE_ACTIVE_LOGE("not have application_use_periodically key");
65 return;
66 }
67 Json::Value appUsePeriodicallyRoot = root[APPLICATION_USE_PERIODICALLY_KEY];
68 if (appUsePeriodicallyRoot.empty() || !appUsePeriodicallyRoot.isObject()) {
69 BUNDLE_ACTIVE_LOGE("application_use_periodically content is empty");
70 return;
71 }
72 if (appUsePeriodicallyRoot[MIN_USE_TIMES].empty() || !appUsePeriodicallyRoot[MIN_USE_TIMES].isInt()) {
73 BUNDLE_ACTIVE_LOGE("not have MinUseTimes key");
74 return;
75 }
76 int32_t minUseTimes = appUsePeriodicallyRoot[MIN_USE_TIMES].asInt();
77 if (appUsePeriodicallyRoot[MAX_USE_TIMES].empty() || !appUsePeriodicallyRoot[MAX_USE_TIMES].isInt()) {
78 BUNDLE_ACTIVE_LOGE("not have MaxUseTimes key");
79 return;
80 }
81 int32_t maxUseTimes = appUsePeriodicallyRoot[MAX_USE_TIMES].asInt();
82 if (appUsePeriodicallyRoot[MIN_USE_DAYS].empty() || !appUsePeriodicallyRoot[MIN_USE_DAYS].isInt()) {
83 BUNDLE_ACTIVE_LOGE("not have MinUseDays key");
84 return;
85 }
86 int32_t minUseDays = appUsePeriodicallyRoot[MIN_USE_DAYS].asInt();
87 appUsePeriodicallyConfig_ = { minUseTimes, maxUseTimes, minUseDays};
88 };
89
GetJsonFromFile(const char * filePath,Json::Value & root)90 bool BundleActiveConfigReader::GetJsonFromFile(const char *filePath, Json::Value &root)
91 {
92 ifstream fin;
93 std::string realPath;
94 if (!BundleActiveConfigReader::ConvertFullPath(filePath, realPath)) {
95 BUNDLE_ACTIVE_LOGE("Get real path failed %{private}s", filePath);
96 return false;
97 }
98 BUNDLE_ACTIVE_LOGD("Read from %{private}s", realPath.c_str());
99 fin.open(realPath, ios::in);
100 if (!fin.is_open()) {
101 BUNDLE_ACTIVE_LOGE("cannot open file %{private}s", realPath.c_str());
102 return false;
103 }
104 char buffer[MAX_BUFFER];
105 ostringstream os;
106 while (fin.getline(buffer, MAX_BUFFER)) {
107 os << buffer;
108 }
109 string data = os.str();
110 JSONCPP_STRING errs;
111 Json::CharReaderBuilder readerBuilder;
112 const unique_ptr<Json::CharReader> jsonReader(readerBuilder.newCharReader());
113 bool res = jsonReader->parse(data.c_str(), data.c_str() + data.length(), &root, &errs);
114 fin.close();
115 if (!res || !errs.empty()) {
116 BUNDLE_ACTIVE_LOGE("parse %{private}s json error", realPath.c_str());
117 return false;
118 }
119 return true;
120 }
121
ConvertFullPath(const std::string & partialPath,std::string & fullPath)122 bool BundleActiveConfigReader::ConvertFullPath(const std::string& partialPath, std::string& fullPath)
123 {
124 if (partialPath.empty() || partialPath.length() >= PATH_MAX) {
125 return false;
126 }
127 char tmpPath[PATH_MAX] = {0};
128 if (realpath(partialPath.c_str(), tmpPath) == nullptr) {
129 return false;
130 }
131 fullPath = tmpPath;
132 return true;
133 }
134
GetApplicationUsePeriodicallyConfig()135 AppUsePeriodicallyConfig BundleActiveConfigReader::GetApplicationUsePeriodicallyConfig()
136 {
137 return appUsePeriodicallyConfig_;
138 };
139
140 } // namespace DeviceUsageStats
141 } // namespace OHOS
142
143