• 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 
16 #include <sys/stat.h>
17 #include "dfx_database_utils.h"
18 
19 #include "dfx_utils.h"
20 #include "dfx_reporter.h"
21 #include "medialibrary_rdbstore.h"
22 #include "medialibrary_tracer.h"
23 #include "medialibrary_unistore_manager.h"
24 #include "media_log.h"
25 #include "media_column.h"
26 #include "media_file_utils.h"
27 #include "medialibrary_errno.h"
28 #include "moving_photo_file_utils.h"
29 #include "result_set_utils.h"
30 #include "photo_album_column.h"
31 #include "photo_file_utils.h"
32 #include "preferences.h"
33 #include "preferences_helper.h"
34 #include "power_efficiency_manager.h"
35 #include "userfile_manager_types.h"
36 
37 namespace OHOS {
38 namespace Media {
39 const std::string RECORD_COUNT = "recordCount";
40 const std::string ABNORMAL_VALUE = "-1";
41 const std::string DFX_OPT_TYPE = "opt_type";
42 const std::string OPT_ADD_VALUE = "1";
43 const std::string OPT_DEL_VALUE = "2";
44 const std::string OPT_UPDATE_VALUE = "3";
45 const int32_t BATCH_QUERY_PHOTO_NUMBER = 2000;
46 const int32_t FILE_HEIGHT_AND_WIDTH_240 = 240;
47 const int32_t FILE_HEIGHT_AND_WIDTH_360 = 360;
48 const int32_t FILE_HEIGHT_AND_WIDTH_480 = 480;
49 const int32_t FILE_HEIGHT_AND_WIDTH_720 = 720;
50 const int32_t FILE_HEIGHT_AND_WIDTH_1080 = 1080;
51 const int32_t FILE_HEIGHT_AND_WIDTH_1440 = 1440;
52 const int32_t FILE_HEIGHT_AND_WIDTH_2000 = 2000;
53 const int32_t FILE_HEIGHT_AND_WIDTH_4000 = 4000;
54 const int64_t PHOTO_FILE_SIZE = 1024;
55 static const std::vector<std::pair<int64_t, std::string>> sizeRanges = {
56     {100, "size100K"},
57     {250, "size250K"},
58     {500, "size500K"},
59     {1 * 1024, "size1M"},
60     {2 * 1024, "size2M"},
61     {3 * 1024, "size3M"},
62     {4 * 1024, "size4M"},
63     {5 * 1024, "size5M"},
64     {7 * 1024, "size7M"},
65     {10 * 1024, "size10M"},
66     {15 * 1024, "size15M"},
67     {20 * 1024, "size20M"},
68     {30 * 1024, "size30M"},
69     {50 * 1024, "size50M"},
70     {100 * 1024, "size100M"},
71     {500 * 1024, "size500M"},
72     {1 * 1024 * 1024, "size1G"},
73     {2 * 1024 * 1024, "size2G"},
74     {5 * 1024 * 1024, "size5G"}
75 };
76 
77 static const std::unordered_map<std::string, int32_t> DEFAULT_PHOTO_SIZE_MAP = {
78     {"size100K", 0},
79     {"size250K", 0},
80     {"size500K", 0},
81     {"size1M", 0},
82     {"size2M", 0},
83     {"size3M", 0},
84     {"size4M", 0},
85     {"size5M", 0},
86     {"size7M", 0},
87     {"size10M", 0},
88     {"size15M", 0},
89     {"size20M", 0},
90     {"size30M", 0},
91     {"size50M", 0},
92     {"size100M", 0},
93     {"size500M", 0},
94     {"size1G", 0},
95     {"size2G", 0},
96     {"size5G", 0},
97     {"sizeOther", 0}
98 };
99 
100 static const std::unordered_map<std::string, int32_t> DEFAULT_PHOTO_RESOLUTION_MAP = {
101     {"resolutionLess240P", 0},
102     {"resolution240P", 0},
103     {"resolution360P", 0},
104     {"resolution480P", 0},
105     {"resolution720P", 0},
106     {"resolution1080P", 0},
107     {"resolution2K", 0},
108     {"resolution4K", 0}
109 };
110 
111 static const std::unordered_map<std::string, int32_t> DEFAULT_VIDEO_RESOLUTION_MAP = {
112     {"resolutionLess720P", 0},
113     {"resolution720P", 0},
114     {"resolution1080P", 0},
115     {"resolution2K", 0},
116     {"resolution4K", 0}
117 };
118 
119 struct SizeAndResolutionInfoMap {
120     unordered_map<std::string, int32_t> localImageSizeMap = DEFAULT_PHOTO_SIZE_MAP;
121     unordered_map<std::string, int32_t> localVideoSizeMap = DEFAULT_PHOTO_SIZE_MAP;
122     unordered_map<std::string, int32_t> cloudImageSizeMap = DEFAULT_PHOTO_SIZE_MAP;
123     unordered_map<std::string, int32_t> cloudVideoSizeMap = DEFAULT_PHOTO_SIZE_MAP;
124     unordered_map<std::string, int32_t> localImageResolutionMap = DEFAULT_PHOTO_RESOLUTION_MAP;
125     unordered_map<std::string, int32_t> localVideoResolutionMap = DEFAULT_VIDEO_RESOLUTION_MAP;
126     unordered_map<std::string, int32_t> cloudImageResolutionMap = DEFAULT_PHOTO_RESOLUTION_MAP;
127     unordered_map<std::string, int32_t> cloudVideoResolutionMap = DEFAULT_VIDEO_RESOLUTION_MAP;
128 };
129 
QueryFromPhotos(int32_t mediaType,int32_t position)130 int32_t DfxDatabaseUtils::QueryFromPhotos(int32_t mediaType, int32_t position)
131 {
132     NativeRdb::RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
133     predicates.EqualTo(MediaColumn::MEDIA_TYPE, mediaType);
134     predicates.EqualTo(PhotoColumn::PHOTO_POSITION, position);
135 
136     std::vector<std::string> columns = { "count(1) AS count" };
137     std::string queryColumn = "count";
138 
139     int32_t count;
140     int32_t errCode = QueryInt(predicates, columns, queryColumn, count);
141     if (errCode != E_OK) {
142         MEDIA_ERR_LOG("query photos fail: %{public}d mediaType: %{public}d position: %{public}d",
143             errCode, mediaType, position);
144     }
145 
146     return count;
147 }
148 
QueryAlbumInfoBySubtype(int32_t albumSubtype)149 AlbumInfo DfxDatabaseUtils::QueryAlbumInfoBySubtype(int32_t albumSubtype)
150 {
151     AlbumInfo albumInfo;
152     NativeRdb::RdbPredicates predicates(PhotoAlbumColumns::TABLE);
153     predicates.EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, albumSubtype);
154     std::vector<std::string> columns = { PhotoAlbumColumns::ALBUM_COUNT, PhotoAlbumColumns::ALBUM_IMAGE_COUNT,
155         PhotoAlbumColumns::ALBUM_VIDEO_COUNT, PhotoAlbumColumns::ALBUM_CLOUD_ID };
156     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
157     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
158         MEDIA_ERR_LOG("query album fail");
159         return albumInfo;
160     }
161     albumInfo.count = GetInt32Val(PhotoAlbumColumns::ALBUM_COUNT, resultSet);
162     albumInfo.imageCount = GetInt32Val(PhotoAlbumColumns::ALBUM_IMAGE_COUNT, resultSet);
163     albumInfo.videoCount = GetInt32Val(PhotoAlbumColumns::ALBUM_VIDEO_COUNT, resultSet);
164     albumInfo.isLocal = GetStringVal(PhotoAlbumColumns::ALBUM_CLOUD_ID, resultSet) == "" ? true : false;
165     return albumInfo;
166 }
167 
QueryDirtyCloudPhoto()168 std::vector<PhotoInfo> DfxDatabaseUtils::QueryDirtyCloudPhoto()
169 {
170     vector<PhotoInfo> photoInfoList;
171     NativeRdb::RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
172     predicates.NotEqualTo(PhotoColumn::PHOTO_POSITION, 1);
173     predicates.NotEqualTo(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t> (DirtyType::TYPE_SYNCED));
174     predicates.Limit(DIRTY_PHOTO_COUNT);
175     std::vector<std::string> columns = { MediaColumn::MEDIA_FILE_PATH, PhotoColumn::PHOTO_DIRTY,
176         PhotoColumn::PHOTO_CLOUD_ID };
177     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
178     if (resultSet == nullptr) {
179         MEDIA_ERR_LOG("resultSet is null");
180         return photoInfoList;
181     }
182     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
183         PhotoInfo photoInfo;
184         photoInfo.data = DfxUtils::GetSafePath(GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet));
185         photoInfo.dirty = GetInt32Val(PhotoColumn::PHOTO_DIRTY, resultSet);
186         photoInfo.cloudVersion = GetInt32Val(PhotoColumn::PHOTO_CLOUD_ID, resultSet);
187         photoInfoList.push_back(photoInfo);
188     }
189     return photoInfoList;
190 }
191 
ParseResultSet(const string & querySql,int32_t mediaTypePara,int32_t & photoInfoCount)192 static bool ParseResultSet(const string &querySql, int32_t mediaTypePara, int32_t &photoInfoCount)
193 {
194     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
195     if (rdbStore == nullptr) {
196         MEDIA_ERR_LOG("rdbStore is nullptr!");
197         return false;
198     }
199     auto resultSet = rdbStore->QuerySql(querySql);
200     if (resultSet == nullptr) {
201         MEDIA_ERR_LOG("resultSet is null");
202         return false;
203     }
204     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
205         if (mediaTypePara > 0) {
206             int32_t mediaType = GetInt32Val(MediaColumn::MEDIA_TYPE, resultSet);
207             if (mediaType == mediaTypePara) {
208                 photoInfoCount = GetInt32Val(RECORD_COUNT, resultSet);
209             }
210         } else {
211             photoInfoCount = GetInt32Val(RECORD_COUNT, resultSet);
212         }
213     }
214     return true;
215 }
216 
QueryOperationResultSet(const string & querySql,int32_t & operationQueryInfoCount)217 static bool QueryOperationResultSet(const string &querySql, int32_t &operationQueryInfoCount)
218 {
219     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
220     if (rdbStore == nullptr) {
221         MEDIA_ERR_LOG("rdbStore is nullptr");
222         return E_HAS_DB_ERROR;
223     }
224     int32_t rowCount = 0;
225     auto resultSet = rdbStore->QuerySql(querySql);
226     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
227         MEDIA_ERR_LOG("query not match data failed");
228         return E_DB_FAIL;
229     }
230     if (resultSet->GetInt(0, rowCount) != NativeRdb::E_OK) {
231         MEDIA_ERR_LOG("rdb failed");
232         return E_DB_FAIL;
233     }
234     operationQueryInfoCount = rowCount;
235     return true;
236 }
237 
GetDuplicateLpathCountQuerrySql()238 static string GetDuplicateLpathCountQuerrySql()
239 {
240     return "SELECT COUNT(*) AS " + RECORD_COUNT + " FROM " +
241         PhotoAlbumColumns::TABLE + " WHERE COALESCE(lpath, '') IN (SELECT lpath FROM " +
242         PhotoAlbumColumns::TABLE + " WHERE " + PhotoAlbumColumns::ALBUM_TYPE + " IN (0, 2048) AND " +
243         "COALESCE(lpath, '') <> '' AND " + PhotoAlbumColumns::ALBUM_DIRTY +
244         " <> 4 GROUP BY lpath HAVING COUNT(1) > 1) AND COALESCE(PhotoAlbum.dirty, 1) <> 4";
245 }
246 
GetAbnormalLpathCountQuerySql()247 static string GetAbnormalLpathCountQuerySql()
248 {
249     return "SELECT COUNT(*) AS " + RECORD_COUNT + " FROM " +
250         PhotoAlbumColumns::TABLE + " WHERE COALESCE(lpath, '') = '' AND " +
251         PhotoAlbumColumns::ALBUM_TYPE + " != " + std::to_string(PhotoAlbumType::SYSTEM) + " AND " +
252         PhotoAlbumColumns::ALBUM_DIRTY + " != 4";
253 }
254 
BuildDbInfo(PhotoRecordInfo & photoRecordInfo)255 static void BuildDbInfo(PhotoRecordInfo &photoRecordInfo)
256 {
257     string databaseDir = MEDIA_DB_DIR + "/rdb";
258     if (access(databaseDir.c_str(), E_OK) != 0) {
259         MEDIA_WARN_LOG("can not get rdb through sandbox");
260         return;
261     }
262     string dbPath = databaseDir.append("/").append(MEDIA_DATA_ABILITY_DB_NAME);
263 
264     struct stat statInfo {};
265     if (stat(dbPath.c_str(), &statInfo) != 0) {
266         MEDIA_ERR_LOG("stat syscall err");
267         return;
268     }
269     photoRecordInfo.dbFileSize = statInfo.st_size;
270 
271     struct stat slaveStatInfo {};
272     if (stat(MEDIA_DB_FILE_SLAVE.c_str(), &slaveStatInfo) == 0) {
273         photoRecordInfo.slaveDbFileSize = slaveStatInfo.st_size;
274     }
275 }
276 
QueryPhotoRecordInfo(PhotoRecordInfo & photoRecordInfo)277 int32_t DfxDatabaseUtils::QueryPhotoRecordInfo(PhotoRecordInfo &photoRecordInfo)
278 {
279     const string filterCondition = MediaColumn::MEDIA_TIME_PENDING + " = 0 AND " +
280         PhotoColumn::PHOTO_SYNC_STATUS + " = " +
281         to_string(static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE)) + " AND " +
282         PhotoColumn::PHOTO_CLEAN_FLAG + " = " +
283         to_string(static_cast<int32_t>(CleanType::TYPE_NOT_CLEAN));
284 
285     const string imageAndVideoCountQuerySql = "SELECT " + MediaColumn::MEDIA_TYPE + ", COUNT(*) AS " + RECORD_COUNT +
286         " FROM " + PhotoColumn::PHOTOS_TABLE + " WHERE " + filterCondition + " GROUP BY " + MediaColumn::MEDIA_TYPE;
287 
288     const string abnormalSizeCountQuerySql = "SELECT COUNT(*) AS " + RECORD_COUNT + " FROM " +
289         PhotoColumn::PHOTOS_TABLE + " WHERE " + MediaColumn::MEDIA_SIZE + " = " + ABNORMAL_VALUE +
290         " AND " + filterCondition;
291 
292     const string abnormalWidthHeightQuerySql = "SELECT COUNT(*) AS " + RECORD_COUNT + " FROM " +
293         PhotoColumn::PHOTOS_TABLE + " WHERE (" + PhotoColumn::PHOTO_WIDTH + " = " + ABNORMAL_VALUE +
294         " OR " + PhotoColumn::PHOTO_HEIGHT + " = " + ABNORMAL_VALUE + ") AND " + filterCondition;
295 
296     const string abnormalVideoDurationQuerySql = "SELECT COUNT(*) AS " + RECORD_COUNT + " FROM " +
297         PhotoColumn::PHOTOS_TABLE + " WHERE " + MediaColumn::MEDIA_DURATION + " = " + ABNORMAL_VALUE +
298         " AND " + MediaColumn::MEDIA_TYPE + " = " + std::to_string(MEDIA_TYPE_VIDEO) + " AND " + filterCondition;
299 
300     const string totalAbnormalRecordSql = "SELECT COUNT(*) AS " + RECORD_COUNT + " FROM " +
301         PhotoColumn::PHOTOS_TABLE + " WHERE (" + MediaColumn::MEDIA_SIZE + " = 0 OR " +
302         MediaColumn::MEDIA_SIZE + " IS NULL OR " + MediaColumn::MEDIA_MIME_TYPE + " IS NULL OR " +
303         MediaColumn::MEDIA_MIME_TYPE + " = '' OR " + PhotoColumn::PHOTO_HEIGHT + " = 0 OR " +
304         PhotoColumn::PHOTO_HEIGHT + " IS NULL OR " + PhotoColumn::PHOTO_WIDTH + " = 0 OR " +
305         PhotoColumn::PHOTO_WIDTH + " IS NULL OR ((" + MediaColumn::MEDIA_DURATION + " IS NULL OR " +
306         MediaColumn::MEDIA_DURATION + " = 0 ) AND " + MediaColumn::MEDIA_TYPE + " = " +
307         std::to_string(MEDIA_TYPE_VIDEO) + " )) AND " + filterCondition;
308 
309     const string duplicateLpathCountQuerySql = GetDuplicateLpathCountQuerrySql();
310     const string abnormalLpathCountQuerySql = GetAbnormalLpathCountQuerySql();
311 
312     int32_t ret = ParseResultSet(imageAndVideoCountQuerySql, MEDIA_TYPE_VIDEO, photoRecordInfo.videoCount);
313     ret = ParseResultSet(imageAndVideoCountQuerySql, MEDIA_TYPE_IMAGE, photoRecordInfo.imageCount) && ret;
314     ret = ParseResultSet(abnormalSizeCountQuerySql, 0, photoRecordInfo.abnormalSizeCount) && ret;
315     ret = ParseResultSet(abnormalWidthHeightQuerySql, 0, photoRecordInfo.abnormalWidthOrHeightCount) && ret;
316     ret = ParseResultSet(abnormalVideoDurationQuerySql, 0, photoRecordInfo.abnormalVideoDurationCount) && ret;
317     ret = ParseResultSet(totalAbnormalRecordSql, 0, photoRecordInfo.toBeUpdatedRecordCount) && ret;
318     ret = ParseResultSet(duplicateLpathCountQuerySql, 0, photoRecordInfo.duplicateLpathCount) && ret;
319     ret = ParseResultSet(abnormalLpathCountQuerySql, 0, photoRecordInfo.abnormalLpathCount) && ret;
320 
321     BuildDbInfo(photoRecordInfo);
322     return ret;
323 }
324 
QueryOperationRecordInfo(OperationRecordInfo & operationRecordInfo)325 int32_t DfxDatabaseUtils::QueryOperationRecordInfo(OperationRecordInfo &operationRecordInfo)
326 {
327     const string addTotalCountQuerySql = "SELECT COUNT(*) FROM " + PhotoColumn::TAB_ASSET_AND_ALBUM_OPERATION_TABLE +
328         " WHERE " + DFX_OPT_TYPE + " = " + OPT_ADD_VALUE;
329     const string delTotalCountQuerySql = "SELECT COUNT(*) FROM " + PhotoColumn::TAB_ASSET_AND_ALBUM_OPERATION_TABLE +
330         " WHERE " + DFX_OPT_TYPE + " = " + OPT_DEL_VALUE;
331     const string updateTotalCountQuerySql = "SELECT COUNT(*) FROM " + PhotoColumn::TAB_ASSET_AND_ALBUM_OPERATION_TABLE +
332         " WHERE " + DFX_OPT_TYPE + " = " + OPT_UPDATE_VALUE;
333 
334     bool ret = QueryOperationResultSet(addTotalCountQuerySql, operationRecordInfo.addTotalCount);
335     ret = QueryOperationResultSet(delTotalCountQuerySql, operationRecordInfo.delTotalCount) && ret;
336     ret = QueryOperationResultSet(updateTotalCountQuerySql, operationRecordInfo.updateTotalCount) && ret;
337     operationRecordInfo.totalCount = operationRecordInfo.addTotalCount + operationRecordInfo.delTotalCount +
338         operationRecordInfo.updateTotalCount;
339     return ret ? E_OK : E_FAIL;
340 }
341 
QueryAnalysisVersion(const std::string & table,const std::string & column)342 int32_t DfxDatabaseUtils::QueryAnalysisVersion(const std::string &table, const std::string &column)
343 {
344     NativeRdb::RdbPredicates predicates(table);
345     string whereClause = "max(" + column + ") AS version";
346     std::vector<std::string> columns = { whereClause };
347     string version = "version";
348     double count;
349     int32_t errCode = QueryDouble(predicates, columns, version, count);
350     if (errCode != E_OK) {
351         MEDIA_ERR_LOG("query analysis version fail: %{public}d", errCode);
352     }
353     return static_cast<int32_t> (count);
354 }
355 
QueryDbVersion()356 int32_t DfxDatabaseUtils::QueryDbVersion()
357 {
358     int64_t dbVersion = 0;
359     MediaLibraryRdbStore::QueryPragma("user_version", dbVersion);
360     return static_cast<int32_t> (dbVersion);
361 }
362 
QueryInt(const NativeRdb::AbsRdbPredicates & predicates,const std::vector<std::string> & columns,const std::string & queryColumn,int32_t & value)363 int32_t DfxDatabaseUtils::QueryInt(const NativeRdb::AbsRdbPredicates &predicates,
364     const std::vector<std::string> &columns, const std::string &queryColumn, int32_t &value)
365 {
366     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
367     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
368         return E_DB_FAIL;
369     }
370     value = GetInt32Val(queryColumn, resultSet);
371     return E_OK;
372 }
373 
QueryDouble(const NativeRdb::AbsRdbPredicates & predicates,const std::vector<std::string> & columns,const std::string & queryColumn,double & value)374 int32_t DfxDatabaseUtils::QueryDouble(const NativeRdb::AbsRdbPredicates &predicates,
375     const std::vector<std::string> &columns, const std::string &queryColumn, double &value)
376 {
377     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
378     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
379         return E_DB_FAIL;
380     }
381     value = GetDoubleVal(queryColumn, resultSet);
382     return E_OK;
383 }
384 
QueryDownloadedAndGeneratedThumb(int32_t & downloadedThumb,int32_t & generatedThumb)385 int32_t DfxDatabaseUtils::QueryDownloadedAndGeneratedThumb(int32_t& downloadedThumb, int32_t& generatedThumb)
386 {
387     // cloud image that are all generated
388     NativeRdb::RdbPredicates generatePredicates(PhotoColumn::PHOTOS_TABLE);
389     std::vector<std::string> columns = { "count(1) AS count" };
390     std::string queryColumn = "count";
391     int32_t cloudImage = 2;
392     int32_t thumbGeneratedFinished = 2;
393     generatePredicates.GreaterThanOrEqualTo(PhotoColumn::PHOTO_POSITION, cloudImage)->And()
394         ->GreaterThanOrEqualTo(PhotoColumn::PHOTO_THUMBNAIL_READY, thumbGeneratedFinished);
395     int32_t errCode = QueryInt(generatePredicates, columns, queryColumn, generatedThumb);
396     if (errCode != E_OK) {
397         MEDIA_ERR_LOG("query generated image fail: %{public}d", errCode);
398         return errCode;
399     }
400 
401     // cloud image that are downloaded
402     NativeRdb::RdbPredicates downloadPredicates(PhotoColumn::PHOTOS_TABLE);
403     downloadPredicates.GreaterThanOrEqualTo(PhotoColumn::PHOTO_POSITION, cloudImage)->And()
404         ->EqualTo(PhotoColumn::PHOTO_THUMB_STATUS, 0);
405     errCode = QueryInt(downloadPredicates, columns, queryColumn, downloadedThumb);
406     if (errCode != E_OK) {
407         MEDIA_ERR_LOG("query downloaded image fail: %{public}d", errCode);
408         return errCode;
409     }
410     return E_OK;
411 }
412 
QueryASTCThumb(bool isLocal)413 int32_t DfxDatabaseUtils::QueryASTCThumb(bool isLocal)
414 {
415     NativeRdb::RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
416 
417     int32_t localImage = 1;
418     int32_t cloudImage = 2;
419     int32_t localAndCloudImage = 3;
420     int32_t thumbnail_ready = 3;
421     if (isLocal) {
422         predicates.BeginWrap();
423         predicates.EqualTo(PhotoColumn::PHOTO_POSITION, localImage);
424         predicates.Or()->EqualTo(PhotoColumn::PHOTO_POSITION, localAndCloudImage);
425         predicates.EndWrap();
426     } else {
427         predicates.EqualTo(PhotoColumn::PHOTO_POSITION, cloudImage);
428     }
429 
430     predicates.And()
431         ->GreaterThanOrEqualTo(PhotoColumn::PHOTO_THUMBNAIL_READY, thumbnail_ready);
432 
433     std::vector<std::string> columns = { "count(1) AS count" };
434     std::string queryColumn = "count";
435     int32_t count = 0;
436     int32_t errCode = QueryInt(predicates, columns, queryColumn, count);
437     if (errCode != E_OK) {
438         MEDIA_ERR_LOG("query astc thumb fail: %{public}d", errCode);
439     }
440 
441     return count;
442 }
443 
QueryLCDThumb(bool isLocal)444 int32_t DfxDatabaseUtils::QueryLCDThumb(bool isLocal)
445 {
446     NativeRdb::RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
447 
448     int32_t lcd_visit_time = 2;
449     int32_t localImage = 1;
450     int32_t cloudImage = 2;
451     int32_t localAndCloudImage = 3;
452     int32_t localThumb = 0;
453     int32_t cloudThumb = 2;
454     if (isLocal) {
455         predicates.BeginWrap();
456         predicates.EqualTo(PhotoColumn::PHOTO_POSITION, localImage);
457         predicates.And()->EqualTo(PhotoColumn::PHOTO_LCD_VISIT_TIME, lcd_visit_time);
458         predicates.EndWrap();
459         predicates.Or()->BeginWrap();
460         predicates.BeginWrap();
461         predicates.EqualTo(PhotoColumn::PHOTO_LCD_VISIT_TIME, lcd_visit_time);
462         predicates.Or()->EqualTo(PhotoColumn::PHOTO_THUMB_STATUS, localThumb);
463         predicates.Or()->EqualTo(PhotoColumn::PHOTO_THUMB_STATUS, cloudThumb);
464         predicates.EndWrap();
465         predicates.And()->EqualTo(PhotoColumn::PHOTO_POSITION, localAndCloudImage);
466         predicates.EndWrap();
467     } else {
468         predicates.BeginWrap();
469         predicates.EqualTo(PhotoColumn::PHOTO_THUMB_STATUS, localThumb);
470         predicates.Or()->EqualTo(PhotoColumn::PHOTO_THUMB_STATUS, cloudThumb);
471         predicates.EndWrap();
472         predicates.And()->EqualTo(PhotoColumn::PHOTO_POSITION, cloudImage);
473     }
474 
475     std::vector<std::string> columns = { "count(1) AS count" };
476     std::string queryColumn = "count";
477 
478     int32_t count = 0;
479     int32_t errCode = QueryInt(predicates, columns, queryColumn, count);
480     if (errCode != E_OK) {
481         MEDIA_ERR_LOG("query lcd thumb fail: %{public}d", errCode);
482     }
483 
484     return count;
485 }
486 
QueryPhotoFilePath(const shared_ptr<MediaLibraryRdbStore> rdbStore,int offset)487 static shared_ptr<NativeRdb::ResultSet> QueryPhotoFilePath(
488     const shared_ptr<MediaLibraryRdbStore> rdbStore, int offset)
489 {
490     string querySql = "SELECT " + MediaColumn::MEDIA_FILE_PATH + " FROM " + PhotoColumn::PHOTOS_TABLE +
491         " WHERE " + PhotoColumn::PHOTO_POSITION + " = 1" +
492         " LIMIT " + std::to_string(offset) + ", " + std::to_string(BATCH_QUERY_PHOTO_NUMBER);
493     return rdbStore->QuerySql(querySql);
494 }
495 
CheckChargingAndScreenOff(bool isReported)496 bool DfxDatabaseUtils::CheckChargingAndScreenOff(bool isReported)
497 {
498     bool bFlag = PowerEfficiencyManager::IsChargingAndScreenOff();
499     if (bFlag) {
500         return bFlag;
501     }
502     int32_t errCode;
503     shared_ptr<NativePreferences::Preferences> prefs =
504         NativePreferences::PreferencesHelper::GetPreferences(DFX_COMMON_XML, errCode);
505     if (!prefs) {
506         MEDIA_ERR_LOG("get preferences error: %{public}d", errCode);
507         return bFlag;
508     }
509     if (isReported) {
510         int64_t time = MediaFileUtils::UTCTimeSeconds() - TWO_DAY;
511         MEDIA_INFO_LOG("change to last two day time");
512         prefs->PutLong(LAST_TWO_DAY_REPORT_TIME, time);
513     } else {
514         int64_t time = MediaFileUtils::UTCTimeSeconds() - ONE_WEEK;
515         MEDIA_INFO_LOG("change to last week day time");
516         prefs->PutLong(LAST_WEEK_REPORT_TIME, time);
517     }
518     prefs->FlushSync();
519     return bFlag;
520 }
521 
QueryPhotoErrorCount()522 int32_t DfxDatabaseUtils::QueryPhotoErrorCount()
523 {
524     MEDIA_DEBUG_LOG("QueryPhotoErrorCount start");
525     MediaLibraryTracer tracer;
526     tracer.Start("QueryPhotoErrorCount");
527     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
528     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_OK, "rdbStore is nullptr");
529     std::string querySql = "SELECT count(1) as count FROM " + PhotoColumn::PHOTOS_TABLE + " WHERE " +
530         PhotoColumn::PHOTO_POSITION + " = 1";
531     shared_ptr<NativeRdb::ResultSet> resultCount = rdbStore->QuerySql(querySql);
532     CHECK_AND_RETURN_RET_LOG(resultCount != nullptr, E_OK, "Failed to query resultCount");
533     int32_t count = 0;
534     if (resultCount->GoToNextRow() == NativeRdb::E_OK) {
535         count = GetInt32Val("count", resultCount);
536         MEDIA_INFO_LOG("position == one ,count: %{public}d", count);
537     }
538     resultCount->Close();
539     CHECK_AND_RETURN_RET_LOG(count > 0, E_OK, "Failed to get count");
540     int32_t photoCount = 0;
541     for (int32_t offset = 0; offset < count; offset += BATCH_QUERY_PHOTO_NUMBER) {
542         if (!CheckChargingAndScreenOff(true)) {
543             MEDIA_ERR_LOG("Charging and screen off");
544             return E_OK;
545         }
546         auto resultSet = QueryPhotoFilePath(rdbStore, offset);
547         CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_OK, "Failed to query resultSet");
548         while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
549             string filePath = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
550             if (!PhotoFileUtils::IsThumbnailExists(filePath)) {
551                 MEDIA_ERR_LOG("Invali date thumbnail, file path: %{private}s", filePath.c_str());
552                 continue;
553             }
554             if (!MediaFileUtils::IsFileExists(filePath)) {
555                 MEDIA_ERR_LOG("File not exists, file path: %{private}s", filePath.c_str());
556                 photoCount++;
557             }
558         }
559         resultSet->Close();
560     }
561     return photoCount;
562 }
563 
QueryTotalCloudThumb(int32_t & totalDownload)564 int32_t DfxDatabaseUtils::QueryTotalCloudThumb(int32_t& totalDownload)
565 {
566     int32_t cloudImage = 2;
567     NativeRdb::RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
568     predicates.GreaterThanOrEqualTo(PhotoColumn::PHOTO_POSITION, cloudImage);
569     std::vector<std::string> columns = { "count(1) AS count" };
570     std::string queryColumn = "count";
571     int32_t errCode = QueryInt(predicates, columns, queryColumn, totalDownload);
572     if (errCode != E_OK) {
573         MEDIA_ERR_LOG("query total download image fail: %{public}d", errCode);
574         return errCode;
575     }
576     return E_OK;
577 }
578 
UpdatePhotoSizeMap(const int64_t size,std::unordered_map<std::string,int32_t> & photoSizeMap)579 static void UpdatePhotoSizeMap(const int64_t size, std::unordered_map<std::string, int32_t> &photoSizeMap)
580 {
581     if (size <= 0) {
582         MEDIA_ERR_LOG("is wrong size");
583         return;
584     }
585     int64_t fileSize = size / PHOTO_FILE_SIZE;
586     for (const auto &range : sizeRanges) {
587         if (fileSize <= range.first) {
588             photoSizeMap[range.second]++;
589             return;
590         }
591     }
592     photoSizeMap["sizeOther"]++;
593 }
594 
UpdatePhotoResolutionMap(const int32_t height,const int32_t width,std::unordered_map<std::string,int32_t> & resolutionMap)595 static void UpdatePhotoResolutionMap(const int32_t height, const int32_t width,
596     std::unordered_map<std::string, int32_t> &resolutionMap)
597 {
598     int32_t min = std::min(height, width);
599     int32_t max = std::max(height, width);
600     if (max < FILE_HEIGHT_AND_WIDTH_2000) {
601         if (min < FILE_HEIGHT_AND_WIDTH_240) {
602             resolutionMap["resolutionLess240P"]++;
603         } else if (min >= FILE_HEIGHT_AND_WIDTH_240 && min < FILE_HEIGHT_AND_WIDTH_360) {
604             resolutionMap["resolution240P"]++;
605         } else if (min >= FILE_HEIGHT_AND_WIDTH_360 && min < FILE_HEIGHT_AND_WIDTH_480) {
606             resolutionMap["resolution360P"]++;
607         } else if (min >= FILE_HEIGHT_AND_WIDTH_480 && min < FILE_HEIGHT_AND_WIDTH_720) {
608             resolutionMap["resolution480P"]++;
609         } else if (min >= FILE_HEIGHT_AND_WIDTH_720 && min < FILE_HEIGHT_AND_WIDTH_1080) {
610             resolutionMap["resolution720P"]++;
611         } else if (min >= FILE_HEIGHT_AND_WIDTH_1080 && min < FILE_HEIGHT_AND_WIDTH_1440) {
612             resolutionMap["resolution1080P"]++;
613         } else {
614             MEDIA_ERR_LOG("is wrong resolution");
615         }
616     } else {
617         if (min >= FILE_HEIGHT_AND_WIDTH_1440 && max < FILE_HEIGHT_AND_WIDTH_4000) {
618             resolutionMap["resolution2K"]++;
619         } else if (min >= FILE_HEIGHT_AND_WIDTH_1440 && max >= FILE_HEIGHT_AND_WIDTH_4000) {
620             resolutionMap["resolution4K"]++;
621         } else {
622             MEDIA_ERR_LOG("is wrong resolution");
623         }
624     }
625 }
626 
UpdateVideoResolutionMap(const int32_t height,const int32_t width,std::unordered_map<std::string,int32_t> & resolutionMap)627 static void UpdateVideoResolutionMap(const int32_t height, const int32_t width,
628     std::unordered_map<std::string, int32_t> &resolutionMap)
629 {
630     int32_t min = std::min(height, width);
631     int32_t max = std::max(height, width);
632     if (min < FILE_HEIGHT_AND_WIDTH_720 && max < FILE_HEIGHT_AND_WIDTH_2000) {
633         resolutionMap["resolutionLess720P"]++;
634     } else if (min >= FILE_HEIGHT_AND_WIDTH_720 && min < FILE_HEIGHT_AND_WIDTH_1080 &&
635         max < FILE_HEIGHT_AND_WIDTH_2000) {
636         resolutionMap["resolution720P"]++;
637     } else if (min >= FILE_HEIGHT_AND_WIDTH_1080 && min < FILE_HEIGHT_AND_WIDTH_1440 &&
638         max < FILE_HEIGHT_AND_WIDTH_2000) {
639         resolutionMap["resolution1080P"]++;
640     } else if (min >= FILE_HEIGHT_AND_WIDTH_1440 && max < FILE_HEIGHT_AND_WIDTH_4000 &&
641         max >= FILE_HEIGHT_AND_WIDTH_2000) {
642         resolutionMap["resolution2K"]++;
643     } else if (min >= FILE_HEIGHT_AND_WIDTH_1440 && max >= FILE_HEIGHT_AND_WIDTH_4000) {
644         resolutionMap["resolution4K"]++;
645     } else {
646         MEDIA_ERR_LOG("is wrong resolution");
647     }
648 }
649 
GetPhotoMimeType(std::string & photoMimeType)650 void DfxDatabaseUtils::GetPhotoMimeType(std::string &photoMimeType)
651 {
652     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
653     CHECK_AND_RETURN_LOG(rdbStore != nullptr, "rdbStore is nullptr");
654     std::string querySql = "SELECT " + MediaColumn::MEDIA_MIME_TYPE + ", COUNT(*) AS count FROM " +
655         PhotoColumn::PHOTOS_TABLE + " WHERE " + PhotoColumn::PHOTO_IS_TEMP + " = 0 AND " +
656         PhotoColumn::MEDIA_DATE_TRASHED + " = 0 AND " + PhotoColumn::PHOTO_BURST_COVER_LEVEL +
657         " = 1 GROUP BY " + MediaColumn::MEDIA_MIME_TYPE;
658     shared_ptr<NativeRdb::ResultSet> resultSet = rdbStore->QuerySql(querySql);
659     CHECK_AND_RETURN_LOG(resultSet != nullptr, "Failed to query resultCount");
660     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
661         string mediaType = GetStringVal(MediaColumn::MEDIA_MIME_TYPE, resultSet);
662         int32_t count = GetInt32Val("count", resultSet);
663         photoMimeType += mediaType + ":" + std::to_string(count) + ", ";
664     }
665     resultSet->Close();
666 }
667 
StatisticsSizeAndResolution(shared_ptr<NativeRdb::ResultSet> & resultSet,SizeAndResolutionInfoMap & infoMap)668 static void StatisticsSizeAndResolution(shared_ptr<NativeRdb::ResultSet> &resultSet,
669     SizeAndResolutionInfoMap &infoMap)
670 {
671     CHECK_AND_RETURN_LOG(resultSet != nullptr, "Failed to statistics");
672     int32_t position = GetInt64Val(PhotoColumn::PHOTO_POSITION, resultSet);
673     int32_t mediaType = GetInt64Val(MediaColumn::MEDIA_TYPE, resultSet);
674     int32_t height = GetInt64Val(PhotoColumn::PHOTO_HEIGHT, resultSet);
675     int32_t width = GetInt64Val(PhotoColumn::PHOTO_WIDTH, resultSet);
676     int64_t size = GetInt64Val(MediaColumn::MEDIA_SIZE, resultSet);
677     if (mediaType == MEDIA_TYPE_IMAGE) {
678         if (position == static_cast<int32_t>(PhotoPositionType::LOCAL)) {
679             UpdatePhotoSizeMap(size, infoMap.localImageSizeMap);
680             UpdatePhotoResolutionMap(height, width, infoMap.localImageResolutionMap);
681         } else  {
682             UpdatePhotoSizeMap(size, infoMap.cloudImageSizeMap);
683             UpdatePhotoResolutionMap(height, width, infoMap.cloudImageResolutionMap);
684         }
685     } else if (mediaType == MEDIA_TYPE_VIDEO) {
686         if (position == static_cast<int32_t>(PhotoPositionType::LOCAL)) {
687             UpdatePhotoSizeMap(size, infoMap.localVideoSizeMap);
688             UpdateVideoResolutionMap(height, width, infoMap.localVideoResolutionMap);
689         } else {
690             UpdatePhotoSizeMap(size, infoMap.cloudVideoSizeMap);
691             UpdateVideoResolutionMap(height, width, infoMap.cloudVideoResolutionMap);
692         }
693     } else {
694         MEDIA_ERR_LOG("is wrong mediaType");
695     }
696 }
697 
GetInfoToString(const unordered_map<string,int32_t> & defaultMap)698 static string GetInfoToString(const unordered_map<string, int32_t>& defaultMap)
699 {
700     std::string result;
701     for (const auto& pair : defaultMap) {
702         if (pair.second > 0) {
703             result += pair.first + ":" + std::to_string(pair.second) + "; ";
704         }
705     }
706     return result;
707 }
708 
GetSizeAndResolutionInfo(QuerySizeAndResolution & queryInfo)709 bool DfxDatabaseUtils::GetSizeAndResolutionInfo(QuerySizeAndResolution &queryInfo)
710 {
711     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
712     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, false, "rdbStore is nullptr");
713     std::string querySql = "SELECT count(1) as count FROM " + PhotoColumn::PHOTOS_TABLE + " WHERE " +
714         PhotoColumn::PHOTO_IS_TEMP + " = 0 AND " + PhotoColumn::MEDIA_DATE_TRASHED + " = 0 AND " +
715         PhotoColumn::PHOTO_BURST_COVER_LEVEL + " = 1 ";
716     shared_ptr<NativeRdb::ResultSet> resultCount = rdbStore->QuerySql(querySql);
717     CHECK_AND_RETURN_RET_LOG(resultCount != nullptr, false, "Failed to query resultCount");
718     int32_t count = 0;
719     if (resultCount->GoToNextRow() == NativeRdb::E_OK) {
720         count = GetInt32Val("count", resultCount);
721     }
722     resultCount->Close();
723     CHECK_AND_RETURN_RET_LOG(count > 0, false, "Failed to get count");
724     SizeAndResolutionInfoMap infoMap;
725     for (int32_t offset = 0; offset < count; offset += BATCH_QUERY_PHOTO_NUMBER) {
726         if (!CheckChargingAndScreenOff(false)) {
727             MEDIA_ERR_LOG("Charging and screen off");
728             return false;
729         }
730         std::string querySql = "SELECT " + PhotoColumn::PHOTO_POSITION + ", " + MediaColumn::MEDIA_TYPE +
731             " , " + MediaColumn::MEDIA_SIZE + ", " + PhotoColumn::PHOTO_HEIGHT + ", " + PhotoColumn::PHOTO_WIDTH +
732             " FROM " + PhotoColumn::PHOTOS_TABLE + " WHERE " +
733             PhotoColumn::PHOTO_IS_TEMP + " = 0 AND " + PhotoColumn::MEDIA_DATE_TRASHED + " = 0 AND " +
734             PhotoColumn::PHOTO_BURST_COVER_LEVEL + " = 1 " +
735             " LIMIT " + std::to_string(offset) + ", " + std::to_string(BATCH_QUERY_PHOTO_NUMBER);
736 
737         shared_ptr<NativeRdb::ResultSet> resultSet = rdbStore->QuerySql(querySql);
738         CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, false, "Failed to query resultCount");
739         while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
740             StatisticsSizeAndResolution(resultSet, infoMap);
741         }
742         resultSet->Close();
743     }
744     queryInfo.localImageSize = GetInfoToString(infoMap.localImageSizeMap);
745     queryInfo.localVideoSize = GetInfoToString(infoMap.localVideoSizeMap);
746     queryInfo.cloudImageSize = GetInfoToString(infoMap.cloudImageSizeMap);
747     queryInfo.cloudVideoSize = GetInfoToString(infoMap.cloudVideoSizeMap);
748     queryInfo.localImageResolution = GetInfoToString(infoMap.localImageResolutionMap);
749     queryInfo.localVideoResolution = GetInfoToString(infoMap.localVideoResolutionMap);
750     queryInfo.cloudImageResolution = GetInfoToString(infoMap.cloudImageResolutionMap);
751     queryInfo.cloudVideoResolution = GetInfoToString(infoMap.cloudVideoResolutionMap);
752     return true;
753 }
754 } // namespace Media
755 } // namespace OHOS