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