• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <sys/statfs.h>
23 
24 #include "common_utils.h"
25 #include "continuous_task_log.h"
26 #include "config_policy_utils.h"
27 #include "directory_ex.h"
28 #include "hisysevent.h"
29 #include <file_ex.h>
30 
31 namespace OHOS {
32 namespace BackgroundTaskMgr {
33 namespace {
34 static constexpr char TASK_RECORD_FILE_PATH[] = "/data/service/el1/public/background_task_mgr/running_task";
35 static const std::string RESOURCE_RECORD_FILE_PATH = "/data/service/el1/public/background_task_mgr/resource_record";
36 static const std::string APP_RESOURCE_RECORD = "appResourceRecord";
37 static const std::string PROCESS_RESOURCE_RECORD = "processResourceRecord";
38 const std::string PARAM = "param";
39 const std::string FAST_FROZEN = "fast_frozen";
40 const std::string ENABLE = "enable";
41 const std::string DOZE_TIME = "doze_time";
42 }
43 
DataStorageHelper()44 DataStorageHelper::DataStorageHelper() {}
45 
~DataStorageHelper()46 DataStorageHelper::~DataStorageHelper() {}
47 
RefreshTaskRecord(const std::unordered_map<std::string,std::shared_ptr<ContinuousTaskRecord>> & allRecord)48 ErrCode DataStorageHelper::RefreshTaskRecord(const std::unordered_map<std::string,
49     std::shared_ptr<ContinuousTaskRecord>> &allRecord)
50 {
51     nlohmann::json root;
52     for (const auto &iter : allRecord) {
53         auto record = iter.second;
54         std::string data = record->ParseToJsonStr();
55         nlohmann::json recordJson = nlohmann::json::parse(data, nullptr, false);;
56         if (!recordJson.is_discarded()) {
57             root[iter.first] = recordJson;
58         }
59     }
60     if (access(TASK_RECORD_FILE_PATH, F_OK) == ERR_OK) {
61         BGTASK_LOGD("the file: %{private}s already exists.", TASK_RECORD_FILE_PATH);
62     } else {
63         FILE *file = fopen(TASK_RECORD_FILE_PATH, "w+");
64         if (file == nullptr) {
65             BGTASK_LOGE("Fail to open file: %{private}s, errno: %{public}s", TASK_RECORD_FILE_PATH, strerror(errno));
66             return ERR_BGTASK_CREATE_FILE_ERR;
67         }
68         int closeResult = fclose(file);
69         if (closeResult < 0) {
70             BGTASK_LOGE("Fail to close file: %{private}s, errno: %{public}s", TASK_RECORD_FILE_PATH, strerror(errno));
71             return ERR_BGTASK_CREATE_FILE_ERR;
72         }
73     }
74     return SaveJsonValueToFile(root.dump(CommonUtils::jsonFormat_), TASK_RECORD_FILE_PATH);
75 }
76 
RestoreTaskRecord(std::unordered_map<std::string,std::shared_ptr<ContinuousTaskRecord>> & allRecord)77 ErrCode DataStorageHelper::RestoreTaskRecord(std::unordered_map<std::string,
78     std::shared_ptr<ContinuousTaskRecord>> &allRecord)
79 {
80     nlohmann::json root;
81     if (ParseJsonValueFromFile(root, TASK_RECORD_FILE_PATH) != ERR_OK) {
82         return ERR_BGTASK_DATA_STORAGE_ERR;
83     }
84     for (auto iter = root.begin(); iter != root.end(); iter++) {
85         nlohmann::json recordJson = iter.value();
86         std::shared_ptr<ContinuousTaskRecord> record = std::make_shared<ContinuousTaskRecord>();
87         if (record->ParseFromJson(recordJson)) {
88             allRecord.emplace(iter.key(), record);
89         }
90     }
91     return ERR_OK;
92 }
93 
RefreshResourceRecord(const ResourceRecordMap & appRecord,const ResourceRecordMap & processRecord)94 ErrCode DataStorageHelper::RefreshResourceRecord(const ResourceRecordMap &appRecord,
95     const ResourceRecordMap &processRecord)
96 {
97     std::string record {""};
98     ConvertMapToString(appRecord, processRecord, record);
99     if (access(RESOURCE_RECORD_FILE_PATH.c_str(), F_OK) == ERR_OK) {
100         BGTASK_LOGD("the file: %{private}s already exists.", RESOURCE_RECORD_FILE_PATH.c_str());
101     } else {
102         FILE *file = fopen(RESOURCE_RECORD_FILE_PATH.c_str(), "w+");
103         if (file == nullptr) {
104             BGTASK_LOGE("Fail to open file: %{private}s, errno: %{public}s",
105                 RESOURCE_RECORD_FILE_PATH.c_str(), strerror(errno));
106             return ERR_BGTASK_CREATE_FILE_ERR;
107         }
108         int closeResult = fclose(file);
109         if (closeResult < 0) {
110             BGTASK_LOGE("Fail to close file: %{private}s, errno: %{public}s",
111                 RESOURCE_RECORD_FILE_PATH.c_str(), strerror(errno));
112             return ERR_BGTASK_CREATE_FILE_ERR;
113         }
114     }
115     return SaveJsonValueToFile(record, RESOURCE_RECORD_FILE_PATH);
116 }
117 
RestoreResourceRecord(ResourceRecordMap & appRecord,ResourceRecordMap & processRecord)118 ErrCode DataStorageHelper::RestoreResourceRecord(ResourceRecordMap &appRecord,
119     ResourceRecordMap &processRecord)
120 {
121     nlohmann::json root;
122     if (ParseJsonValueFromFile(root, RESOURCE_RECORD_FILE_PATH) != ERR_OK) {
123         BGTASK_LOGD("can not read string form file: %{private}s", RESOURCE_RECORD_FILE_PATH.c_str());
124         return ERR_BGTASK_DATA_STORAGE_ERR;
125     }
126     DivideJsonToMap(root, appRecord, processRecord);
127     return ERR_OK;
128 }
129 
SaveJsonValueToFile(const std::string & value,const std::string & filePath)130 int32_t DataStorageHelper::SaveJsonValueToFile(const std::string &value, const std::string &filePath)
131 {
132     std::ofstream fout;
133     std::string realPath;
134     if (!ConvertFullPath(filePath, realPath)) {
135         BGTASK_LOGE("SaveJsonValueToFile Get real file path: %{private}s failed", filePath.c_str());
136         return ERR_BGTASK_GET_ACTUAL_FILE_ERR;
137     }
138     fout.open(realPath, std::ios::out);
139     if (!fout.is_open()) {
140         BGTASK_LOGE("Open file: %{private}s failed.", filePath.c_str());
141         return ERR_BGTASK_OPEN_FILE_ERR;
142     }
143     fout << value.c_str() << std::endl;
144     fout.close();
145     if (filePath == TASK_RECORD_FILE_PATH) {
146         ReportUserDataSizeEvent();
147     }
148     return ERR_OK;
149 }
150 
ParseFastSuspendDozeTime(const std::string & FilePath,int & time)151 bool DataStorageHelper::ParseFastSuspendDozeTime(const std::string &FilePath, int &time)
152 {
153     nlohmann::json jsonObj;
154     std::string absolutePath = GetConfigFileAbsolutePath(FilePath);
155     if (ParseJsonValueFromFile(jsonObj, absolutePath) != ERR_OK) {
156         return false;
157     }
158     if (jsonObj.is_null() || !jsonObj.is_object() || !CommonUtils::CheckJsonValue(jsonObj, {PARAM})) {
159         BGTASK_LOGW("check jsonObj value failed.");
160         return false;
161     }
162     nlohmann::json param = jsonObj[PARAM];
163     if (param.is_null() || !param.is_object() || !CommonUtils::CheckJsonValue(param, {FAST_FROZEN})) {
164         BGTASK_LOGW("check param value failed.");
165         return false;
166     }
167     nlohmann::json fastFrozen = param[FAST_FROZEN];
168     if (fastFrozen.is_null() || !fastFrozen.is_object() ||
169         !CommonUtils::CheckJsonValue(fastFrozen, {ENABLE, DOZE_TIME})) {
170         BGTASK_LOGW("check fastFrozen value failed.");
171         return false;
172     }
173     if (!fastFrozen[ENABLE].is_boolean() || !fastFrozen.at(ENABLE).get<bool>()) {
174         BGTASK_LOGW("fast suspend switch is Disable");
175         return false;
176     }
177     if (!fastFrozen[DOZE_TIME].is_number_integer()) {
178         BGTASK_LOGW("fast suspend num is invalid");
179         return false;
180     }
181     time = fastFrozen.at(DOZE_TIME).get<int>();
182     return true;
183 }
184 
ParseJsonValueFromFile(nlohmann::json & value,const std::string & filePath)185 int32_t DataStorageHelper::ParseJsonValueFromFile(nlohmann::json &value, const std::string &filePath)
186 {
187     std::string realPath;
188     if (!ConvertFullPath(filePath, realPath)) {
189         BGTASK_LOGE("Get real path failed");
190         return ERR_BGTASK_DATA_STORAGE_ERR;
191     }
192     std::string data;
193     LoadStringFromFile(realPath.c_str(), data);
194     value = nlohmann::json::parse(data, nullptr, false);
195     if (value.is_discarded()) {
196         BGTASK_LOGE("failed due to data is discarded");
197         return ERR_BGTASK_DATA_STORAGE_ERR;
198     }
199     return ERR_OK;
200 }
201 
GetConfigFileAbsolutePath(const std::string & relativePath)202 std::string DataStorageHelper::GetConfigFileAbsolutePath(const std::string &relativePath)
203 {
204     if (relativePath.empty()) {
205         BGTASK_LOGE("relativePath is empty");
206         return "";
207     }
208     char buf[PATH_MAX];
209     char *tmpPath = GetOneCfgFile(relativePath.c_str(), buf, PATH_MAX);
210     char absolutePath[PATH_MAX] = {0};
211     if (!tmpPath || strlen(tmpPath) > PATH_MAX || !realpath(tmpPath, absolutePath)) {
212         BGTASK_LOGE("get file fail.");
213         return "";
214     }
215     return std::string(absolutePath);
216 }
217 
ConvertFullPath(const std::string & partialPath,std::string & fullPath)218 bool DataStorageHelper::ConvertFullPath(const std::string& partialPath, std::string& fullPath)
219 {
220     if (partialPath.empty() || partialPath.length() >= PATH_MAX) {
221         return false;
222     }
223     char tmpPath[PATH_MAX] = {0};
224     if (realpath(partialPath.c_str(), tmpPath) == nullptr) {
225         return false;
226     }
227     fullPath = tmpPath;
228     return true;
229 }
230 
ConvertMapToString(const ResourceRecordMap & appRecord,const ResourceRecordMap & processRecord,std::string & recordString)231 void DataStorageHelper::ConvertMapToString(const ResourceRecordMap &appRecord,
232     const ResourceRecordMap &processRecord, std::string &recordString)
233 {
234     nlohmann::json root;
235     nlohmann::json appValue;
236     ConvertMapToJson(appRecord, appValue);
237     root[APP_RESOURCE_RECORD] = appValue;
238     nlohmann::json processValue;
239     ConvertMapToJson(processRecord, processValue);
240     root[PROCESS_RESOURCE_RECORD] = processValue;
241     recordString = root.dump(CommonUtils::jsonFormat_);
242 }
243 
ConvertMapToJson(const ResourceRecordMap & appRecord,nlohmann::json & root)244 void DataStorageHelper::ConvertMapToJson(const ResourceRecordMap &appRecord, nlohmann::json &root)
245 {
246     for (const auto &iter : appRecord) {
247         nlohmann::json value;
248         iter.second->ParseToJson(value);
249         root[std::to_string(iter.first)] = value;
250     }
251 }
252 
DivideJsonToMap(nlohmann::json & root,ResourceRecordMap & appRecord,ResourceRecordMap & processRecord)253 void DataStorageHelper::DivideJsonToMap(nlohmann::json &root,
254     ResourceRecordMap &appRecord, ResourceRecordMap &processRecord)
255 {
256     if (root.contains(APP_RESOURCE_RECORD) && root.at(APP_RESOURCE_RECORD).is_object()) {
257         nlohmann::json appRecordJson = root.at(APP_RESOURCE_RECORD);
258         ConvertJsonToMap(appRecordJson, appRecord);
259     } else {
260         BGTASK_LOGE("can not read appRecord, json init fail");
261     }
262     if (root.contains(PROCESS_RESOURCE_RECORD) && root.at(PROCESS_RESOURCE_RECORD).is_object()) {
263         nlohmann::json processrecordJson = root.at(PROCESS_RESOURCE_RECORD);
264         ConvertJsonToMap(processrecordJson, processRecord);
265     } else {
266         BGTASK_LOGE("can not read processRecord, json init fail");
267     }
268 }
269 
ConvertJsonToMap(const nlohmann::json & value,ResourceRecordMap & recordMap)270 void DataStorageHelper::ConvertJsonToMap(const nlohmann::json &value, ResourceRecordMap &recordMap)
271 {
272     for (auto iter = value.begin(); iter != value.end(); iter++) {
273         std::shared_ptr<ResourceApplicationRecord> recordPtr = std::make_shared<ResourceApplicationRecord>();
274         recordPtr->ParseFromJson(iter.value());
275         recordMap.emplace(static_cast<uint32_t>(std::atoi(iter.key().c_str())), recordPtr);
276     }
277 }
278 
GetRemainPartitionSize(const std::string & partitionName)279 uint64_t GetRemainPartitionSize(const std::string& partitionName)
280 {
281     struct statfs stat;
282     if (statfs(partitionName.c_str(), &stat) != 0) {
283         return -1;
284     }
285     uint64_t blockSize = stat.f_bsize;
286     uint64_t freeSize = stat.f_bfree * blockSize;
287     constexpr double units = 1024.0;
288     return freeSize / (units * units);
289 }
290 
GetFileOrFolderSize(const std::vector<std::string> & paths)291 std::vector<uint64_t> GetFileOrFolderSize(const std::vector<std::string>& paths)
292 {
293     std::vector<uint64_t> folderSize;
294     for (auto path : paths) {
295         folderSize.emplace_back(OHOS::GetFolderSize(path));
296     }
297     return folderSize;
298 }
299 
ReportUserDataSizeEvent()300 void DataStorageHelper::ReportUserDataSizeEvent()
301 {
302     std::vector<std::string> paths = {
303         "/data/service/el1/public/background_task_mgr/"
304     };
305     uint64_t remainPartitionSize = GetRemainPartitionSize("/data");
306     std::vector<uint64_t> folderSize = GetFileOrFolderSize(paths);
307     HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::FILEMANAGEMENT, "USER_DATA_SIZE",
308         HiviewDFX::HiSysEvent::EventType::STATISTIC,
309         "COMPONENT_NAME", "background_task_mgr",
310         "PARTITION_NAME", "/data",
311         "REMAIN_PARTITION_SIZE", remainPartitionSize,
312         "FILE_OR_FOLDER_PATH", paths,
313         "FILE_OR_FOLDER_SIZE", folderSize);
314 }
315 }  // namespace BackgroundTaskMgr
316 }  // namespace OHOS
317 
318