• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "gallery_download_file_stat.h"
16 
17 #include <fcntl.h>
18 #include <fstream>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 
22 #include "dfs_error.h"
23 #include "hisysevent.h"
24 #include "utils_log.h"
25 
26 namespace OHOS {
27 namespace FileManagement {
28 namespace CloudFile {
29 #define TYPE_DOWNLOAD_FILE_IMAGE 1
30 #define TYPE_DOWNLOAD_FILE_VIDEO 2
31 #define DOWNLOAD_FILE_BYTE_SIZE 1e6
32 #define DIR_MODE 0770
33 #define FILE_MODE 0660
34 #define CLOUD_SYNC_SYS_EVENT(eventName, type, ...)    \
35     HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::FILEMANAGEMENT, eventName,    \
36                     type, ##__VA_ARGS__)    \
37 
38 const std::string DOWNLOAD_FILE_STAT_LOCAL_PATH = "/data/service/el1/public/cloudfile/cloud_data_statistic/";
39 const std::string DOWNLOAD_FILE_STAT_NAME = "cloud_sync_download_file_stat";
40 const std::vector<uint64_t> DOWNLOAD_IMAGE_SIZE_RANGE_VECTOR = { 2, 4, 6, 8, 15 };
41 const std::vector<uint64_t> DOWNLOAD_VIDEO_SIZE_RANGE_VECTOR = { 20, 40, 80, 200, 400, 800 };
42 
43 enum DownloadFileStatIndex {
44     DOWNLOAD_BUNDLE_NAME = 0,
45     DOWNLOAD_FILE_ERROR,
46     DOWNLOAD_IMAGE_SIZE,
47     DOWNLOAD_IMAGE_SPEED,
48     DOWNLOAD_VIDEO_SIZE,
49     DOWNLOAD_VIDEO_SPEED,
50 };
51 
CreateDataStatisticFolder()52 static int32_t CreateDataStatisticFolder()
53 {
54     std::string path = DOWNLOAD_FILE_STAT_LOCAL_PATH;
55     if (access(path.c_str(), F_OK) == 0) {
56         LOGI("cloud data statistic folder already exists");
57         return E_OK;
58     }
59     int32_t ret = mkdir(path.c_str(), DIR_MODE);
60     if (ret != E_OK) {
61         LOGE("Create cloud data statistic folder fail errno = %{public}d", errno);
62         return E_PATH;
63     }
64     return E_OK;
65 }
66 
CreateDownloadFileStatData()67 static int32_t CreateDownloadFileStatData()
68 {
69     const std::string path = DOWNLOAD_FILE_STAT_LOCAL_PATH + DOWNLOAD_FILE_STAT_NAME;
70     if (access(path.c_str(), F_OK) == 0) {
71         LOGI("download file statistics data file already exists");
72         return E_OK;
73     }
74     std::FILE *file = fopen(path.c_str(), "w");
75     if (file == nullptr) {
76         LOGE("create file downloadstatistic report fail, ret = %{public}d", errno);
77         return errno;
78     }
79     if (fclose(file)) {
80         LOGE("close file downloadstatistic report fail, ret = %{public}d", errno);
81     }
82     return E_OK;
83 }
84 
GalleryDownloadFileStat()85 GalleryDownloadFileStat::GalleryDownloadFileStat()
86 {
87     auto ret = CreateDataStatisticFolder();
88     if (ret !=E_OK) {
89         LOGE("create data statistic failed with error %{public}d", ret);
90         return;
91     }
92     ret = CreateDownloadFileStatData();
93     if (ret != E_OK) {
94         LOGE("create download file stat failed with error %{public}d", ret);
95         return;
96     }
97 }
98 
GetRangeIndex(uint64_t value,const std::vector<uint64_t> rangeVector)99 static uint32_t GetRangeIndex(uint64_t value, const std::vector<uint64_t> rangeVector)
100 {
101     uint32_t index = 0;
102     for (; index < rangeVector.size(); index++) {
103         if (value <= rangeVector[index] * DOWNLOAD_FILE_BYTE_SIZE) {
104             break;
105         }
106     }
107     return index;
108 }
109 
UpdateDownloadSpeedStat(uint32_t mediaType,uint64_t size,uint64_t duration)110 void GalleryDownloadFileStat::UpdateDownloadSpeedStat(uint32_t mediaType, uint64_t size, uint64_t duration)
111 {
112     double sizeMb = static_cast<double>(size) / DOWNLOAD_FILE_BYTE_SIZE;
113     double time = static_cast<double>(duration) / DOWNLOAD_FILE_BYTE_SIZE;
114 
115     double precision = 1e-10;
116     uint32_t indexSpeed = 15;
117     if (abs(time) > precision) {
118         double speed = sizeMb / time;
119         indexSpeed = static_cast<uint32_t>(floor(speed));
120     }
121     if (mediaType == TYPE_DOWNLOAD_FILE_IMAGE && indexSpeed < stat_.imageDownloadSpeed.size()) {
122         stat_.imageDownloadSpeed[indexSpeed]++;
123     }
124     if (mediaType == TYPE_DOWNLOAD_FILE_VIDEO && indexSpeed < stat_.videoDownloadSpeed.size()) {
125         stat_.videoDownloadSpeed[indexSpeed]++;
126     }
127 }
128 
UpdateDownloadSizeStat(uint32_t mediaType,uint64_t size,uint64_t duration)129 void GalleryDownloadFileStat::UpdateDownloadSizeStat(uint32_t mediaType, uint64_t size, uint64_t duration)
130 {
131     std::vector<uint64_t> rangeVector;
132     if (mediaType == TYPE_DOWNLOAD_FILE_IMAGE) {
133         rangeVector = DOWNLOAD_IMAGE_SIZE_RANGE_VECTOR;
134         uint32_t index = GetRangeIndex(size, rangeVector);
135         if (index >= stat_.imageSize.size()) {
136             return;
137         }
138         stat_.imageSize[index]++;
139     } else {
140         rangeVector = DOWNLOAD_VIDEO_SIZE_RANGE_VECTOR;
141         uint32_t index = GetRangeIndex(size, rangeVector);
142         if (index >= stat_.videoSize.size()) {
143             return;
144         }
145         stat_.videoSize[index]++;
146     }
147 }
148 
UpdateDownloadStat(uint32_t mediaType,uint64_t size,uint64_t duration)149 void GalleryDownloadFileStat::UpdateDownloadStat(uint32_t mediaType, uint64_t size, uint64_t duration)
150 {
151     UpdateDownloadSizeStat(mediaType, size, duration);
152     UpdateDownloadSpeedStat(mediaType, size, duration);
153 }
154 
UpdateDownloadBundleName(const std::string & bundleName)155 void GalleryDownloadFileStat::UpdateDownloadBundleName(const std::string &bundleName)
156 {
157     stat_.bundleName = bundleName;
158 }
159 
VectorToString(const std::vector<uint64_t> & vec)160 static std::string VectorToString(const std::vector<uint64_t> &vec)
161 {
162     std::ostringstream oss;
163     for (size_t i = 0; i < vec.size(); ++i) {
164         oss << vec[i];
165         if (i <= vec.size() -1) {
166             oss << " ";
167         }
168     }
169     return oss.str();
170 }
171 
StringToVector(std::string line)172 static std::vector<uint64_t> StringToVector(std::string line)
173 {
174     std::vector<uint64_t> vec;
175     std::istringstream iss(line);
176     uint64_t num;
177     while (iss >> num) {
178         vec.push_back(num);
179     }
180     return vec;
181 }
182 
SumTwoVector(std::vector<uint64_t> & dataOne,std::vector<uint64_t> dataTwo)183 static inline void SumTwoVector(std::vector<uint64_t> &dataOne, std::vector<uint64_t> dataTwo)
184 {
185     if (dataOne.size() != dataTwo.size()) {
186         return;
187     }
188     for (size_t i = 0; i < dataOne.size(); i++) {
189         dataOne[i] += dataTwo[i];
190     }
191     return;
192 }
193 
SumTwoDownloadFileStat(DownloadFileStatInfo dataOne,DownloadFileStatInfo dataTwo)194 static inline DownloadFileStatInfo SumTwoDownloadFileStat(DownloadFileStatInfo dataOne, DownloadFileStatInfo dataTwo)
195 {
196     SumTwoVector(dataOne.downloadFileError, dataTwo.downloadFileError);
197     SumTwoVector(dataOne.imageSize, dataTwo.imageSize);
198     SumTwoVector(dataOne.imageDownloadSpeed, dataTwo.imageDownloadSpeed);
199     SumTwoVector(dataOne.videoSize, dataTwo.videoSize);
200     SumTwoVector(dataOne.videoDownloadSpeed, dataTwo.videoDownloadSpeed);
201     if (dataOne.bundleName.empty()) {
202         dataOne.bundleName = dataTwo.bundleName;
203     }
204     return dataOne;
205 }
206 
HandleBundleName(const DownloadFileStatInfo & info)207 void GalleryDownloadFileStat::HandleBundleName(const DownloadFileStatInfo &info)
208 {
209     if (!info.bundleName.empty() && info.bundleName != stat_.bundleName &&
210         !stat_.bundleName.empty()) {
211         auto ret = ReportDownloadFileStat(info);
212         if (ret != E_OK) {
213             LOGE("report CLOUD_SYNC_DOWNLOAD_FILE_STAT error %{public}d", ret);
214         }
215     } else {
216         stat_ = SumTwoDownloadFileStat(stat_, info);
217     }
218 }
219 
OutputToFile()220 void GalleryDownloadFileStat::OutputToFile()
221 {
222     DownloadFileStatInfo tmpInfo = ReadVecFromLocal();
223     HandleBundleName(tmpInfo);
224 
225     std::vector<std::string> lines;
226     /*  Keep code order below */
227     lines.emplace_back(stat_.bundleName);
228     lines.emplace_back(VectorToString(stat_.downloadFileError));
229     lines.emplace_back(VectorToString(stat_.imageSize));
230     lines.emplace_back(VectorToString(stat_.imageDownloadSpeed));
231     lines.emplace_back(VectorToString(stat_.videoSize));
232     lines.emplace_back(VectorToString(stat_.videoDownloadSpeed));
233 
234     std::ofstream localData(DOWNLOAD_FILE_STAT_LOCAL_PATH + DOWNLOAD_FILE_STAT_NAME, std::ios::trunc);
235     if (!localData.is_open()) {
236         LOGE("Open cloud data statistic local data fail %{public}d", errno);
237         return;
238     }
239     for (std::string line : lines) {
240         localData << line << std::endl;
241     }
242     localData.close();
243     ClearDownloadFileStat();
244     return;
245 }
246 
ReadVecFromLocal()247 DownloadFileStatInfo GalleryDownloadFileStat::ReadVecFromLocal()
248 {
249     std::vector<uint64_t> vec;
250     DownloadFileStatInfo tmpStat;
251     std::ifstream localData(DOWNLOAD_FILE_STAT_LOCAL_PATH + DOWNLOAD_FILE_STAT_NAME);
252     if (localData) {
253         uint32_t rowCount = 0;
254         std::string line;
255         while (std::getline(localData, line)) {
256             if (rowCount != 0) {
257                 vec = StringToVector(line);
258             }
259             if (rowCount == DOWNLOAD_BUNDLE_NAME) {
260                 tmpStat.bundleName = line;
261             }
262             if (rowCount == DOWNLOAD_FILE_ERROR) {
263                 tmpStat.downloadFileError = vec;
264             }
265             if (rowCount == DOWNLOAD_IMAGE_SIZE) {
266                 tmpStat.imageSize = vec;
267             }
268             if (rowCount == DOWNLOAD_IMAGE_SPEED) {
269                 tmpStat.imageDownloadSpeed = vec;
270             }
271             if (rowCount == DOWNLOAD_VIDEO_SIZE) {
272                 tmpStat.videoSize = vec;
273             }
274             if (rowCount == DOWNLOAD_VIDEO_SPEED) {
275                 tmpStat.videoDownloadSpeed = vec;
276             }
277             rowCount += 1;
278         }
279         localData.close();
280     } else {
281         LOGE("Open cloud data statistic local data fail %{public}d", errno);
282     }
283     return tmpStat;
284 }
285 
ClearDownloadFileStat()286 void GalleryDownloadFileStat::ClearDownloadFileStat()
287 {
288     std::fill(stat_.downloadFileError.begin(), stat_.downloadFileError.end(), 0);
289     std::fill(stat_.imageSize.begin(), stat_.imageSize.end(), 0);
290     std::fill(stat_.imageDownloadSpeed.begin(), stat_.imageDownloadSpeed.end(), 0);
291     std::fill(stat_.videoSize.begin(), stat_.videoSize.end(), 0);
292     std::fill(stat_.videoDownloadSpeed.begin(), stat_.videoDownloadSpeed.end(), 0);
293 }
294 
ReportDownloadFileStat(const DownloadFileStatInfo & info)295 int32_t GalleryDownloadFileStat::ReportDownloadFileStat(const DownloadFileStatInfo &info)
296 {
297     int32_t ret = CLOUD_SYNC_SYS_EVENT("CLOUD_SYNC_DOWNLOAD_FILE_STAT",
298         HiviewDFX::HiSysEvent::EventType::STATISTIC,
299         "bundle_name", info.bundleName,
300         "download_file", info.downloadFileError,
301         "image_size", info.imageSize,
302         "image_download_speed", info.imageDownloadSpeed,
303         "video_size", info.videoSize,
304         "video_download_speed", info.videoDownloadSpeed);
305     return ret;
306 }
307 
Report()308 void GalleryDownloadFileStat::Report()
309 {
310     const std::string path = DOWNLOAD_FILE_STAT_LOCAL_PATH + DOWNLOAD_FILE_STAT_NAME;
311     if (access(path.c_str(), F_OK) == -1) {
312         LOGE("download file statistics data file not exists");
313         return;
314     }
315 
316     /* read stat from dist */
317     stat_ = ReadVecFromLocal();
318 
319     int32_t ret = ReportDownloadFileStat(stat_);
320     if (ret != E_OK) {
321         LOGE("report CLOUD_SYNC_DOWNLOAD_FILE_STAT error %{public}d", ret);
322     }
323     ret = unlink(path.c_str());
324     if (ret != 0) {
325         LOGE("fail to delete local statistic data, errno %{public}d", errno);
326     }
327 }
328 
GetInstance()329 GalleryDownloadFileStat &GalleryDownloadFileStat::GetInstance()
330 {
331     static GalleryDownloadFileStat downloadStat_;
332     return downloadStat_;
333 }
334 } // CloudFile
335 } // FileManagement
336 } // OHOS