1 /*
2 * Copyright (c) 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 "data_storage_helper.h"
16
17 #include <fcntl.h>
18 #include <fstream>
19 #include <unistd.h>
20 #include <sstream>
21 #include <sys/stat.h>
22
23 #include "common_utils.h"
24 #include "continuous_task_log.h"
25 #include "config_policy_utils.h"
26
27 namespace OHOS {
28 namespace BackgroundTaskMgr {
29 namespace {
30 static constexpr int32_t MAX_BUFFER = 2048;
31 static constexpr char TASK_RECORD_FILE_PATH[] = "/data/service/el1/public/background_task_mgr/running_task";
32 static const std::string RESOURCE_RECORD_FILE_PATH = "/data/service/el1/public/background_task_mgr/resource_record";
33 static const std::string APP_RESOURCE_RECORD = "appResourceRecord";
34 static const std::string PROCESS_RESOURCE_RECORD = "processResourceRecord";
35 const std::string PARAM = "param";
36 const std::string FAST_FROZEN = "fast_frozen";
37 const std::string ENABLE = "enable";
38 const std::string DOZE_TIME = "doze_time";
39 }
40
DataStorageHelper()41 DataStorageHelper::DataStorageHelper() {}
42
~DataStorageHelper()43 DataStorageHelper::~DataStorageHelper() {}
44
RefreshTaskRecord(const std::unordered_map<std::string,std::shared_ptr<ContinuousTaskRecord>> & allRecord)45 ErrCode DataStorageHelper::RefreshTaskRecord(const std::unordered_map<std::string,
46 std::shared_ptr<ContinuousTaskRecord>> &allRecord)
47 {
48 nlohmann::json root;
49 for (const auto &iter : allRecord) {
50 auto record = iter.second;
51 std::string data = record->ParseToJsonStr();
52 nlohmann::json recordJson = nlohmann::json::parse(data, nullptr, false);;
53 if (!recordJson.is_discarded()) {
54 root[iter.first] = recordJson;
55 }
56 }
57 return SaveJsonValueToFile(root.dump(CommonUtils::jsonFormat_), TASK_RECORD_FILE_PATH);
58 }
59
RestoreTaskRecord(std::unordered_map<std::string,std::shared_ptr<ContinuousTaskRecord>> & allRecord)60 ErrCode DataStorageHelper::RestoreTaskRecord(std::unordered_map<std::string,
61 std::shared_ptr<ContinuousTaskRecord>> &allRecord)
62 {
63 nlohmann::json root;
64 if (ParseJsonValueFromFile(root, TASK_RECORD_FILE_PATH) != ERR_OK) {
65 return ERR_BGTASK_DATA_STORAGE_ERR;
66 }
67 for (auto iter = root.begin(); iter != root.end(); iter++) {
68 nlohmann::json recordJson = iter.value();
69 std::shared_ptr<ContinuousTaskRecord> record = std::make_shared<ContinuousTaskRecord>();
70 if (record->ParseFromJson(recordJson)) {
71 allRecord.emplace(iter.key(), record);
72 }
73 }
74 return ERR_OK;
75 }
76
RefreshResourceRecord(const ResourceRecordMap & appRecord,const ResourceRecordMap & processRecord)77 ErrCode DataStorageHelper::RefreshResourceRecord(const ResourceRecordMap &appRecord,
78 const ResourceRecordMap &processRecord)
79 {
80 std::string record {""};
81 ConvertMapToString(appRecord, processRecord, record);
82 return SaveJsonValueToFile(record, RESOURCE_RECORD_FILE_PATH);
83 }
84
RestoreResourceRecord(ResourceRecordMap & appRecord,ResourceRecordMap & processRecord)85 ErrCode DataStorageHelper::RestoreResourceRecord(ResourceRecordMap &appRecord,
86 ResourceRecordMap &processRecord)
87 {
88 nlohmann::json root;
89 if (ParseJsonValueFromFile(root, RESOURCE_RECORD_FILE_PATH) != ERR_OK) {
90 BGTASK_LOGD("can not read string form file: %{private}s", RESOURCE_RECORD_FILE_PATH.c_str());
91 return ERR_BGTASK_DATA_STORAGE_ERR;
92 }
93 DivideJsonToMap(root, appRecord, processRecord);
94 return ERR_OK;
95 }
96
SaveJsonValueToFile(const std::string & value,const std::string & filePath)97 int32_t DataStorageHelper::SaveJsonValueToFile(const std::string &value, const std::string &filePath)
98 {
99 if (!CreateNodeFile(filePath)) {
100 BGTASK_LOGE("Create file failed.");
101 return ERR_BGTASK_CREATE_FILE_ERR;
102 }
103 std::ofstream fout;
104 std::string realPath;
105 if (!ConvertFullPath(filePath, realPath)) {
106 BGTASK_LOGE("SaveJsonValueToFile Get real file path: %{private}s failed", filePath.c_str());
107 return ERR_BGTASK_GET_ACTUAL_FILE_ERR;
108 }
109 fout.open(realPath, std::ios::out);
110 if (!fout.is_open()) {
111 BGTASK_LOGE("Open file: %{private}s failed.", filePath.c_str());
112 return ERR_BGTASK_OPEN_FILE_ERR;
113 }
114 fout << value.c_str() << std::endl;
115 fout.close();
116 return ERR_OK;
117 }
118
ParseFastSuspendDozeTime(const std::string & FilePath,int & time)119 bool DataStorageHelper::ParseFastSuspendDozeTime(const std::string &FilePath, int &time)
120 {
121 nlohmann::json jsonObj;
122 std::string absolutePath = GetConfigFileAbsolutePath(FilePath);
123 if (ParseJsonValueFromFile(jsonObj, absolutePath) != ERR_OK) {
124 return false;
125 }
126 if (jsonObj.is_null() || !jsonObj.is_object() || !CommonUtils::CheckJsonValue(jsonObj, {PARAM})) {
127 BGTASK_LOGW("check jsonObj value failed.");
128 return false;
129 }
130 nlohmann::json param = jsonObj[PARAM];
131 if (param.is_null() || !param.is_object() || !CommonUtils::CheckJsonValue(param, {FAST_FROZEN})) {
132 BGTASK_LOGW("check param value failed.");
133 return false;
134 }
135 nlohmann::json fastFrozen = param[FAST_FROZEN];
136 if (fastFrozen.is_null() || !fastFrozen.is_object() ||
137 !CommonUtils::CheckJsonValue(fastFrozen, {ENABLE, DOZE_TIME})) {
138 BGTASK_LOGW("check fastFrozen value failed.");
139 return false;
140 }
141 if (!fastFrozen[ENABLE].is_boolean() || !fastFrozen.at(ENABLE).get<bool>()) {
142 BGTASK_LOGW("fast suspend switch is Disable");
143 return false;
144 }
145 if (!fastFrozen[DOZE_TIME].is_number_integer()) {
146 BGTASK_LOGW("fast suspend num is invalid");
147 return false;
148 }
149 time = fastFrozen.at(DOZE_TIME).get<int>();
150 return true;
151 }
152
ParseJsonValueFromFile(nlohmann::json & value,const std::string & filePath)153 int32_t DataStorageHelper::ParseJsonValueFromFile(nlohmann::json &value, const std::string &filePath)
154 {
155 std::ifstream fin;
156 std::string realPath;
157 if (!ConvertFullPath(filePath, realPath)) {
158 BGTASK_LOGE("Get real path failed");
159 return ERR_BGTASK_DATA_STORAGE_ERR;
160 }
161 fin.open(realPath, std::ios::in);
162 if (!fin.is_open()) {
163 BGTASK_LOGE("cannot open file %{private}s", realPath.c_str());
164 return ERR_BGTASK_DATA_STORAGE_ERR;
165 }
166 char buffer[MAX_BUFFER];
167 std::ostringstream os;
168 while (fin.getline(buffer, MAX_BUFFER)) {
169 os << buffer;
170 }
171 std::string data = os.str();
172 value = nlohmann::json::parse(data, nullptr, false);
173 if (value.is_discarded()) {
174 BGTASK_LOGE("failed due to data is discarded");
175 return ERR_BGTASK_DATA_STORAGE_ERR;
176 }
177 return ERR_OK;
178 }
179
CreateNodeFile(const std::string & filePath)180 bool DataStorageHelper::CreateNodeFile(const std::string &filePath)
181 {
182 if (access(filePath.c_str(), F_OK) == ERR_OK) {
183 BGTASK_LOGD("the file: %{private}s already exists.", filePath.c_str());
184 return true;
185 }
186 int32_t fd = open(filePath.c_str(), O_CREAT|O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
187 if (fd < ERR_OK) {
188 BGTASK_LOGE("Fail to open file: %{private}s", filePath.c_str());
189 return false;
190 }
191 close(fd);
192 return true;
193 }
194
GetConfigFileAbsolutePath(const std::string & relativePath)195 std::string DataStorageHelper::GetConfigFileAbsolutePath(const std::string &relativePath)
196 {
197 if (relativePath.empty()) {
198 BGTASK_LOGE("relativePath is empty");
199 return "";
200 }
201 char buf[PATH_MAX];
202 char *tmpPath = GetOneCfgFile(relativePath.c_str(), buf, PATH_MAX);
203 char absolutePath[PATH_MAX] = {0};
204 if (!tmpPath || strlen(tmpPath) > PATH_MAX || !realpath(tmpPath, absolutePath)) {
205 BGTASK_LOGE("get file fail.");
206 return "";
207 }
208 return std::string(absolutePath);
209 }
210
ConvertFullPath(const std::string & partialPath,std::string & fullPath)211 bool DataStorageHelper::ConvertFullPath(const std::string& partialPath, std::string& fullPath)
212 {
213 if (partialPath.empty() || partialPath.length() >= PATH_MAX) {
214 return false;
215 }
216 char tmpPath[PATH_MAX] = {0};
217 if (realpath(partialPath.c_str(), tmpPath) == nullptr) {
218 return false;
219 }
220 fullPath = tmpPath;
221 return true;
222 }
223
ConvertMapToString(const ResourceRecordMap & appRecord,const ResourceRecordMap & processRecord,std::string & recordString)224 void DataStorageHelper::ConvertMapToString(const ResourceRecordMap &appRecord,
225 const ResourceRecordMap &processRecord, std::string &recordString)
226 {
227 nlohmann::json root;
228 nlohmann::json appValue;
229 ConvertMapToJson(appRecord, appValue);
230 root[APP_RESOURCE_RECORD] = appValue;
231 nlohmann::json processValue;
232 ConvertMapToJson(processRecord, processValue);
233 root[PROCESS_RESOURCE_RECORD] = processValue;
234 recordString = root.dump(CommonUtils::jsonFormat_);
235 }
236
ConvertMapToJson(const ResourceRecordMap & appRecord,nlohmann::json & root)237 void DataStorageHelper::ConvertMapToJson(const ResourceRecordMap &appRecord, nlohmann::json &root)
238 {
239 for (const auto &iter : appRecord) {
240 nlohmann::json value;
241 iter.second->ParseToJson(value);
242 root[std::to_string(iter.first)] = value;
243 }
244 }
245
DivideJsonToMap(nlohmann::json & root,ResourceRecordMap & appRecord,ResourceRecordMap & processRecord)246 void DataStorageHelper::DivideJsonToMap(nlohmann::json &root,
247 ResourceRecordMap &appRecord, ResourceRecordMap &processRecord)
248 {
249 if (root.contains(APP_RESOURCE_RECORD) && root.at(APP_RESOURCE_RECORD).is_object()) {
250 nlohmann::json appRecordJson = root.at(APP_RESOURCE_RECORD);
251 ConvertJsonToMap(appRecordJson, appRecord);
252 } else {
253 BGTASK_LOGE("can not read appRecord, json init fail");
254 }
255 if (root.contains(PROCESS_RESOURCE_RECORD) && root.at(PROCESS_RESOURCE_RECORD).is_object()) {
256 nlohmann::json processrecordJson = root.at(PROCESS_RESOURCE_RECORD);
257 ConvertJsonToMap(processrecordJson, processRecord);
258 } else {
259 BGTASK_LOGE("can not read processRecord, json init fail");
260 }
261 }
262
ConvertJsonToMap(const nlohmann::json & value,ResourceRecordMap & recordMap)263 void DataStorageHelper::ConvertJsonToMap(const nlohmann::json &value, ResourceRecordMap &recordMap)
264 {
265 for (auto iter = value.begin(); iter != value.end(); iter++) {
266 std::shared_ptr<ResourceApplicationRecord> recordPtr = std::make_shared<ResourceApplicationRecord>();
267 recordPtr->ParseFromJson(iter.value());
268 recordMap.emplace(static_cast<uint32_t>(std::atoi(iter.key().c_str())), recordPtr);
269 }
270 }
271 } // namespace BackgroundTaskMgr
272 } // namespace OHOS
273
274