• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 #define MLOG_TAG "Scanner"
16 
17 #include "media_scanner_db.h"
18 
19 #include "abs_rdb_predicates.h"
20 #include "ipc_skeleton.h"
21 #include "medialibrary_asset_operations.h"
22 #include "media_column.h"
23 #include "media_error_column.h"
24 #include "media_file_utils.h"
25 #include "media_log.h"
26 #include "medialibrary_command.h"
27 #include "medialibrary_data_manager.h"
28 #include "medialibrary_db_const.h"
29 #include "medialibrary_errno.h"
30 #include "medialibrary_rdb_transaction.h"
31 #include "medialibrary_rdb_utils.h"
32 #include "medialibrary_smartalbum_map_operations.h"
33 #include "medialibrary_type_const.h"
34 #include "medialibrary_unistore_manager.h"
35 #include "rdb_errno.h"
36 #include "rdb_utils.h"
37 #include "result_set.h"
38 #include "result_set_utils.h"
39 #include "userfile_manager_types.h"
40 #include "userfilemgr_uri.h"
41 #include "values_bucket.h"
42 #include "post_event_utils.h"
43 #include "photo_file_utils.h"
44 
45 namespace OHOS {
46 namespace Media {
47 using namespace std;
48 using namespace OHOS::NativeRdb;
49 using namespace OHOS::DataShare;
50 
51 constexpr double DOUBLE_EPSILON = 1e-15;
52 
MediaScannerDb()53 MediaScannerDb::MediaScannerDb() {}
54 
GetDatabaseInstance()55 unique_ptr<MediaScannerDb> MediaScannerDb::GetDatabaseInstance()
56 {
57     unique_ptr<MediaScannerDb> database = make_unique<MediaScannerDb>();
58     return database;
59 }
60 
SetRdbHelper(void)61 void MediaScannerDb::SetRdbHelper(void)
62 {
63 }
64 
65 #ifdef MEDIALIBRARY_COMPATIBILITY
SetVirtualPath(const Metadata & metadata,ValuesBucket & values)66 static inline void SetVirtualPath(const Metadata &metadata, ValuesBucket &values)
67 {
68     string relativePath = metadata.GetRelativePath();
69     string displayName = metadata.GetFileName();
70     string virtualPath = (relativePath.back() == '/' ? relativePath : relativePath + "/") + displayName;
71     values.PutString(MediaColumn::MEDIA_VIRTURL_PATH, virtualPath);
72 }
73 #endif
74 
SetRemainFileMetadataApi9(const Metadata & metadata,ValuesBucket & values)75 static inline void SetRemainFileMetadataApi9(const Metadata &metadata, ValuesBucket &values)
76 {
77     values.PutString(MEDIA_DATA_DB_AUDIO_ALBUM, metadata.GetAlbum());
78     values.PutString(MEDIA_DATA_DB_ARTIST, metadata.GetFileArtist());
79     values.PutInt(MEDIA_DATA_DB_HEIGHT, metadata.GetFileHeight());
80     values.PutInt(MEDIA_DATA_DB_WIDTH, metadata.GetFileWidth());
81     values.PutInt(MEDIA_DATA_DB_ORIENTATION, metadata.GetOrientation());
82     values.PutString(MEDIA_DATA_DB_BUCKET_NAME, metadata.GetAlbumName());
83     values.PutInt(MEDIA_DATA_DB_PARENT_ID, metadata.GetParentId());
84     values.PutInt(MEDIA_DATA_DB_BUCKET_ID, metadata.GetParentId());
85     values.PutDouble(MEDIA_DATA_DB_LATITUDE, metadata.GetLatitude());
86     values.PutDouble(MEDIA_DATA_DB_LONGITUDE, metadata.GetLongitude());
87 }
88 
SetValuesFromMetaDataAndType(const Metadata & metadata,ValuesBucket & values,MediaType mediaType,const string & tableName)89 static void SetValuesFromMetaDataAndType(const Metadata &metadata, ValuesBucket &values, MediaType mediaType,
90     const string &tableName)
91 {
92 #ifdef MEDIALIBRARY_COMPATIBILITY
93     if (mediaType == MediaType::MEDIA_TYPE_IMAGE || mediaType == MEDIA_TYPE_VIDEO) {
94         if (tableName == MEDIALIBRARY_TABLE) {
95             SetRemainFileMetadataApi9(metadata, values);
96         } else {
97             values.PutInt(MEDIA_DATA_DB_HEIGHT, metadata.GetFileHeight());
98             values.PutInt(MEDIA_DATA_DB_WIDTH, metadata.GetFileWidth());
99             values.PutInt(MEDIA_DATA_DB_ORIENTATION, metadata.GetOrientation());
100             values.PutDouble(MEDIA_DATA_DB_LATITUDE, metadata.GetLatitude());
101             values.PutDouble(MEDIA_DATA_DB_LONGITUDE, metadata.GetLongitude());
102             SetVirtualPath(metadata, values);
103             if (metadata.GetPhotoSubType() != 0) {
104                 values.PutInt(PhotoColumn::PHOTO_SUBTYPE, metadata.GetPhotoSubType());
105             }
106         }
107     } else if (mediaType == MediaType::MEDIA_TYPE_AUDIO) {
108         if (tableName == MEDIALIBRARY_TABLE) {
109             SetRemainFileMetadataApi9(metadata, values);
110         } else {
111             values.PutString(MEDIA_DATA_DB_AUDIO_ALBUM, metadata.GetAlbum());
112             values.PutString(MEDIA_DATA_DB_ARTIST, metadata.GetFileArtist());
113             SetVirtualPath(metadata, values);
114         }
115     } else {
116         SetRemainFileMetadataApi9(metadata, values);
117     }
118 #else
119     SetRemainFileMetadataApi9(metadata, values);
120 #endif
121 }
122 
InsertDateAdded(const Metadata & metadata,ValuesBucket & outValues)123 static void InsertDateAdded(const Metadata &metadata, ValuesBucket &outValues)
124 {
125     int64_t dateAdded = metadata.GetFileDateAdded();
126     if (dateAdded == 0) {
127         int64_t dateTaken = metadata.GetDateTaken();
128         if (dateTaken == 0) {
129             int64_t dateModified = metadata.GetFileDateModified();
130             if (dateModified == 0) {
131                 dateAdded = MediaFileUtils::UTCTimeMilliSeconds();
132                 MEDIA_WARN_LOG("Invalid dateAdded time, use current time instead: %{public}lld",
133                     static_cast<long long>(dateAdded));
134             } else {
135                 dateAdded = dateModified;
136                 MEDIA_WARN_LOG("Invalid dateAdded time, use dateModified instead: %{public}lld",
137                     static_cast<long long>(dateAdded));
138             }
139         } else {
140             dateAdded = dateTaken;
141             MEDIA_WARN_LOG("Invalid dateAdded time, use dateTaken instead: %{public}lld",
142                 static_cast<long long>(dateAdded));
143         }
144     }
145     outValues.PutLong(MediaColumn::MEDIA_DATE_ADDED, dateAdded);
146 }
147 
HandleDateAdded(const Metadata & metadata,const bool isInsert,ValuesBucket & outValues)148 static inline void HandleDateAdded(const Metadata &metadata, const bool isInsert, ValuesBucket &outValues)
149 {
150     if (isInsert) {
151         InsertDateAdded(metadata, outValues);
152     }
153 }
154 
HandleDetailTimeAndYearMonthDay(const Metadata & metadata,ValuesBucket & outValues)155 static void HandleDetailTimeAndYearMonthDay(const Metadata &metadata, ValuesBucket &outValues)
156 {
157     MediaType type = metadata.GetFileMediaType();
158     if ((type != MEDIA_TYPE_PHOTO) && (type != MEDIA_TYPE_IMAGE) && (type != MEDIA_TYPE_VIDEO)) {
159         return;
160     }
161     string detailTime = metadata.GetDetailTime();
162     if (detailTime.empty()) {
163         int64_t dateTaken = metadata.GetDateTaken() / MSEC_TO_SEC;
164         detailTime = MediaFileUtils::StrCreateTime(PhotoColumn::PHOTO_DETAIL_TIME_FORMAT, dateTaken);
165     }
166     outValues.Put(PhotoColumn::PHOTO_DETAIL_TIME, detailTime);
167 
168     auto const [dateYear, dateMonth, dateDay] = PhotoFileUtils::ExtractYearMonthDay(detailTime);
169     outValues.Put(PhotoColumn::PHOTO_DATE_YEAR, dateYear);
170     outValues.Put(PhotoColumn::PHOTO_DATE_MONTH, dateMonth);
171     outValues.Put(PhotoColumn::PHOTO_DATE_DAY, dateDay);
172 }
173 
SetValuesFromMetaDataApi9(const Metadata & metadata,ValuesBucket & values,bool isInsert,const string & table)174 static void SetValuesFromMetaDataApi9(const Metadata &metadata, ValuesBucket &values, bool isInsert,
175     const string &table)
176 {
177     MediaType mediaType = metadata.GetFileMediaType();
178     values.PutString(MEDIA_DATA_DB_FILE_PATH, metadata.GetFilePath());
179     values.PutString(MEDIA_DATA_DB_RELATIVE_PATH, metadata.GetRelativePath());
180     values.PutString(MEDIA_DATA_DB_MIME_TYPE, metadata.GetFileMimeType());
181     values.PutInt(MEDIA_DATA_DB_MEDIA_TYPE, mediaType);
182     values.PutString(MEDIA_DATA_DB_NAME, metadata.GetFileName());
183     values.PutString(MEDIA_DATA_DB_TITLE, metadata.GetFileTitle());
184     values.PutLong(MEDIA_DATA_DB_SIZE, metadata.GetFileSize());
185     values.PutLong(MEDIA_DATA_DB_DATE_MODIFIED, metadata.GetFileDateModified());
186     values.PutInt(MEDIA_DATA_DB_DURATION, metadata.GetFileDuration());
187     values.PutLong(MEDIA_DATA_DB_DATE_TAKEN, metadata.GetDateTaken());
188     values.PutLong(MEDIA_DATA_DB_TIME_PENDING, 0);
189 
190     SetValuesFromMetaDataAndType(metadata, values, mediaType, table);
191     HandleDateAdded(metadata, isInsert, values);
192     HandleDetailTimeAndYearMonthDay(metadata, values);
193 }
194 
HandleMovingPhotoDirty(const Metadata & metadata,ValuesBucket & values)195 static void HandleMovingPhotoDirty(const Metadata &metadata, ValuesBucket &values)
196 {
197     if (metadata.GetPhotoSubType() != static_cast<int32_t>(PhotoSubType::MOVING_PHOTO) ||
198         metadata.GetDirty() != -1) {
199         return;
200     }
201 
202     if (metadata.GetPhotoQuality() != static_cast<int32_t>(MultiStagesPhotoQuality::FULL)) {
203         MEDIA_DEBUG_LOG("moving photo is not high-quality");
204         return;
205     }
206 
207     if (metadata.GetIsTemp() != 0) {
208         MEDIA_DEBUG_LOG("moving photo is temp, not saved");
209         return;
210     }
211 
212     string videoPath = MediaFileUtils::GetMovingPhotoVideoPath(metadata.GetFilePath());
213     size_t videoSize = 0;
214     if (!MediaFileUtils::GetFileSize(videoPath, videoSize) || videoSize == 0) {
215         MEDIA_DEBUG_LOG("video of moving photo cannot upload");
216         return;
217     }
218     values.PutInt(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyTypes::TYPE_NEW));
219 }
220 
HandleMovingPhoto(const Metadata & metadata,ValuesBucket & values)221 static void HandleMovingPhoto(const Metadata &metadata, ValuesBucket &values)
222 {
223     if (metadata.GetPhotoSubType() == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
224         values.PutInt(PhotoColumn::PHOTO_IS_RECTIFICATION_COVER, 1);
225     }
226     HandleMovingPhotoDirty(metadata, values);
227 }
228 
SetImageVideoValuesFromMetaDataApi10(const Metadata & metadata,ValuesBucket & values,bool isInsert,bool skipPhoto)229 static void SetImageVideoValuesFromMetaDataApi10(const Metadata &metadata, ValuesBucket &values, bool isInsert,
230     bool skipPhoto)
231 {
232     values.PutString(PhotoColumn::PHOTO_MEDIA_SUFFIX, ScannerUtils::GetFileExtension(metadata.GetFileName()));
233     values.PutInt(PhotoColumn::PHOTO_HEIGHT, metadata.GetFileHeight());
234     values.PutInt(PhotoColumn::PHOTO_WIDTH, metadata.GetFileWidth());
235     values.PutInt(PhotoColumn::PHOTO_ORIENTATION, metadata.GetOrientation());
236     values.PutInt(PhotoColumn::PHOTO_EXIF_ROTATE, metadata.GetExifRotate());
237     if (fabs(metadata.GetLongitude()) > DOUBLE_EPSILON || fabs(metadata.GetLatitude()) > DOUBLE_EPSILON) {
238         values.PutDouble(PhotoColumn::PHOTO_LONGITUDE, metadata.GetLongitude());
239         values.PutDouble(PhotoColumn::PHOTO_LATITUDE, metadata.GetLatitude());
240     } else {
241         values.PutNull(PhotoColumn::PHOTO_LONGITUDE);
242         values.PutNull(PhotoColumn::PHOTO_LATITUDE);
243     }
244     if (skipPhoto && !metadata.GetUserComment().empty()) {
245         values.PutString(PhotoColumn::PHOTO_USER_COMMENT, metadata.GetUserComment());
246     }
247     values.PutString(PhotoColumn::PHOTO_ALL_EXIF, metadata.GetAllExif());
248     values.PutString(PhotoColumn::PHOTO_SHOOTING_MODE, metadata.GetShootingMode());
249     values.PutString(PhotoColumn::PHOTO_SHOOTING_MODE_TAG, metadata.GetShootingModeTag());
250     values.PutLong(PhotoColumn::PHOTO_LAST_VISIT_TIME, metadata.GetLastVisitTime());
251     values.PutInt(PhotoColumn::PHOTO_DYNAMIC_RANGE_TYPE, metadata.GetDynamicRangeType());
252     values.PutLong(PhotoColumn::PHOTO_COVER_POSITION, metadata.GetCoverPosition());
253     values.PutString(PhotoColumn::PHOTO_FRONT_CAMERA, metadata.GetFrontCamera());
254     values.PutString(PhotoColumn::PHOTO_DETAIL_TIME, metadata.GetDetailTime());
255     values.PutLong(PhotoColumn::PHOTO_META_DATE_MODIFIED, MediaFileUtils::UTCTimeMilliSeconds());
256     values.PutString(PhotoColumn::MEDIA_MIME_TYPE, metadata.GetFileMimeType());
257 
258     if (metadata.GetPhotoSubType() != 0) {
259         values.PutInt(PhotoColumn::PHOTO_SUBTYPE, metadata.GetPhotoSubType());
260         HandleMovingPhoto(metadata, values);
261     }
262     MEDIA_INFO_LOG("MediaScannerDb height: %{public}d, width: %{public}d.",
263         metadata.GetFileHeight(), metadata.GetFileWidth());
264 }
265 
SetValuesFromMetaDataApi10(const Metadata & metadata,ValuesBucket & values,bool isInsert,bool skipPhoto=true)266 static void SetValuesFromMetaDataApi10(const Metadata &metadata, ValuesBucket &values, bool isInsert,
267     bool skipPhoto = true)
268 {
269     MediaType mediaType = metadata.GetFileMediaType();
270 
271     values.PutString(MediaColumn::MEDIA_FILE_PATH, metadata.GetFilePath());
272     values.PutInt(MediaColumn::MEDIA_TYPE, mediaType);
273     if (skipPhoto) {
274         values.PutString(MediaColumn::MEDIA_NAME, metadata.GetFileName());
275     }
276     values.PutString(MediaColumn::MEDIA_TITLE, metadata.GetFileTitle());
277 
278     values.PutLong(MediaColumn::MEDIA_SIZE, metadata.GetFileSize());
279     values.PutLong(MediaColumn::MEDIA_DATE_MODIFIED, metadata.GetFileDateModified());
280     values.PutInt(MediaColumn::MEDIA_DURATION, metadata.GetFileDuration());
281     values.PutLong(MediaColumn::MEDIA_DATE_TAKEN, metadata.GetDateTaken());
282     values.PutLong(MediaColumn::MEDIA_TIME_PENDING, 0);
283 
284     if (mediaType == MediaType::MEDIA_TYPE_IMAGE || mediaType == MEDIA_TYPE_VIDEO) {
285         SetImageVideoValuesFromMetaDataApi10(metadata, values, isInsert, skipPhoto);
286     } else if (mediaType == MediaType::MEDIA_TYPE_AUDIO) {
287         values.PutString(AudioColumn::AUDIO_ALBUM, metadata.GetAlbum());
288         values.PutString(AudioColumn::AUDIO_ARTIST, metadata.GetFileArtist());
289     }
290 
291     HandleDateAdded(metadata, isInsert, values);
292     HandleDetailTimeAndYearMonthDay(metadata, values);
293 }
294 
GetTableNameByPath(int32_t mediaType,string & tableName,const string & path="")295 static void GetTableNameByPath(int32_t mediaType, string &tableName, const string &path = "")
296 {
297     if (!path.empty() && MediaFileUtils::IsFileTablePath(path)) {
298         tableName = MEDIALIBRARY_TABLE;
299         return;
300     }
301     switch (mediaType) {
302         case MediaType::MEDIA_TYPE_IMAGE:
303         case MediaType::MEDIA_TYPE_VIDEO: {
304             tableName = PhotoColumn::PHOTOS_TABLE;
305             break;
306         }
307         case MediaType::MEDIA_TYPE_AUDIO: {
308             tableName = AudioColumn::AUDIOS_TABLE;
309             break;
310         }
311         default: {
312             tableName = MEDIALIBRARY_TABLE;
313             break;
314         }
315     }
316 }
317 
InsertData(ValuesBucket values,const string & tableName,int64_t & rowNum,shared_ptr<AccurateRefresh::AssetAccurateRefresh> refresh)318 bool MediaScannerDb::InsertData(ValuesBucket values, const string &tableName, int64_t &rowNum,
319     shared_ptr<AccurateRefresh::AssetAccurateRefresh> refresh)
320 {
321     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
322     if (rdbStore == nullptr) {
323         MEDIA_ERR_LOG("MediaDataAbility Insert functionality rdbStore is null");
324         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
325             {KEY_OPT_TYPE, OptType::SCAN}};
326         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
327         return false;
328     }
329 
330     int32_t result = -1;
331     if (refresh != nullptr) {
332         refresh->Init();
333         result = refresh->Insert(rowNum, tableName, values);
334     } else {
335         result = rdbStore->Insert(rowNum, tableName, values);
336     }
337     if (rowNum <= 0) {
338         MEDIA_ERR_LOG("MediaDataAbility Insert functionality is failed, rowNum %{public}ld", (long)rowNum);
339         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__},
340             {KEY_ERR_CODE, static_cast<int32_t>(rowNum)}, {KEY_OPT_TYPE, OptType::SCAN}};
341         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
342         return false;
343     }
344 
345     if (result != NativeRdb::E_OK) {
346         MEDIA_ERR_LOG("MediaDataAbility Insert functionality is failed, return %{public}d", result);
347         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, result},
348             {KEY_OPT_TYPE, OptType::SCAN}};
349         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
350         return false;
351     }
352 
353     return true;
354 }
355 
InsertMetadata(const Metadata & metadata,string & tableName,MediaLibraryApi api,shared_ptr<AccurateRefresh::AssetAccurateRefresh> refresh)356 string MediaScannerDb::InsertMetadata(const Metadata &metadata, string &tableName, MediaLibraryApi api,
357     shared_ptr<AccurateRefresh::AssetAccurateRefresh> refresh)
358 {
359     MediaType mediaType = metadata.GetFileMediaType();
360     string mediaTypeUri;
361     ValuesBucket values;
362     if (api == MediaLibraryApi::API_10) {
363         mediaTypeUri = MediaFileUtils::GetMediaTypeUriV10(mediaType);
364     } else {
365         mediaTypeUri = MediaFileUtils::GetMediaTypeUri(mediaType);
366 #ifdef MEDIALIBRARY_COMPATIBILITY
367         if ((mediaType != MediaType::MEDIA_TYPE_IMAGE) && (mediaType != MediaType::MEDIA_TYPE_VIDEO) &&
368             (mediaType != MediaType::MEDIA_TYPE_AUDIO)) {
369             values.PutString(MEDIA_DATA_DB_URI, mediaTypeUri);
370         }
371 #else
372         values.PutString(MEDIA_DATA_DB_URI, mediaTypeUri);
373 #endif
374     }
375 
376     tableName = MEDIALIBRARY_TABLE;
377     if (api == MediaLibraryApi::API_10) {
378         SetValuesFromMetaDataApi10(metadata, values, true);
379         GetTableNameByPath(mediaType, tableName);
380     } else {
381 #ifdef MEDIALIBRARY_COMPATIBILITY
382         GetTableNameByPath(mediaType, tableName, metadata.GetFilePath());
383 #endif
384         SetValuesFromMetaDataApi9(metadata, values, true, tableName);
385     }
386 
387     int64_t rowNum = 0;
388     if (!InsertData(values, tableName, rowNum, refresh)) {
389         return "";
390     }
391 
392     if (mediaTypeUri.empty()) {
393         return "";
394     }
395     if (api == MediaLibraryApi::API_10) {
396         return MediaFileUtils::GetUriByExtrConditions(mediaTypeUri + "/", to_string(rowNum),
397             MediaFileUtils::GetExtraUri(metadata.GetFileName(), metadata.GetFilePath())) + "?api_version=10";
398     }
399     return MediaFileUtils::GetUriByExtrConditions(mediaTypeUri + "/", to_string(rowNum));
400 }
401 
GetUriStringInUpdate(MediaType mediaType,MediaLibraryApi api,string & mediaTypeUri,ValuesBucket & values)402 static inline void GetUriStringInUpdate(MediaType mediaType, MediaLibraryApi api, string &mediaTypeUri,
403     ValuesBucket &values)
404 {
405     if (api == MediaLibraryApi::API_10) {
406         mediaTypeUri = MediaFileUtils::GetMediaTypeUriV10(mediaType);
407     } else {
408         mediaTypeUri = MediaFileUtils::GetMediaTypeUri(mediaType);
409 #ifdef MEDIALIBRARY_COMPATIBILITY
410         if ((mediaType != MediaType::MEDIA_TYPE_IMAGE) && (mediaType != MediaType::MEDIA_TYPE_VIDEO) &&
411             (mediaType != MediaType::MEDIA_TYPE_AUDIO)) {
412             values.PutString(MEDIA_DATA_DB_URI, mediaTypeUri);
413         }
414 #else
415         values.PutString(MEDIA_DATA_DB_URI, mediaTypeUri);
416 #endif
417     }
418 }
419 
420 /**
421  * @brief Update single metadata in the media database
422  *
423  * @param metadata The metadata object which has the information about the file
424  * @return string The mediatypeUri corresponding to the given metadata
425  */
UpdateMetadata(const Metadata & metadata,string & tableName,MediaLibraryApi api,bool skipPhoto,shared_ptr<AccurateRefresh::AssetAccurateRefresh> refresh)426 string MediaScannerDb::UpdateMetadata(const Metadata &metadata, string &tableName, MediaLibraryApi api, bool skipPhoto,
427     shared_ptr<AccurateRefresh::AssetAccurateRefresh> refresh)
428 {
429     int32_t updateCount(0);
430     ValuesBucket values;
431     string whereClause = MEDIA_DATA_DB_ID + " = ?";
432     vector<string> whereArgs = { to_string(metadata.GetFileId()) };
433     MediaType mediaType = metadata.GetFileMediaType();
434     string mediaTypeUri;
435     GetUriStringInUpdate(mediaType, api, mediaTypeUri, values);
436 
437     tableName = MEDIALIBRARY_TABLE;
438     if (api == MediaLibraryApi::API_10) {
439         SetValuesFromMetaDataApi10(metadata, values, false, skipPhoto);
440         GetTableNameByPath(mediaType, tableName);
441     } else {
442 #ifdef MEDIALIBRARY_COMPATIBILITY
443         GetTableNameByPath(mediaType, tableName, metadata.GetFilePath());
444 #endif
445         SetValuesFromMetaDataApi9(metadata, values, false, tableName);
446     }
447 
448     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
449     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, "", "rdbStore is nullptr");
450 
451     int32_t result = -1;
452     if (refresh != nullptr && tableName == PhotoColumn::PHOTOS_TABLE) {
453         result = refresh->Update(updateCount, tableName, values, whereClause, whereArgs);
454     } else {
455         result = rdbStore->Update(updateCount, tableName, values, whereClause, whereArgs);
456     }
457     if (result != NativeRdb::E_OK || updateCount <= 0) {
458         MEDIA_ERR_LOG("Update operation failed. Result %{public}d. Updated %{public}d", result, updateCount);
459         if (result != NativeRdb::E_OK) {
460             VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, result},
461                 {KEY_OPT_TYPE, OptType::SCAN}};
462             PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
463         }
464         if (updateCount <= 0) {
465             VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, updateCount},
466                 {KEY_OPT_TYPE, OptType::SCAN}};
467             PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
468         }
469         return "";
470     }
471 
472     CHECK_AND_RETURN_RET(!mediaTypeUri.empty(), "");
473     CHECK_AND_RETURN_RET(api != MediaLibraryApi::API_10, MakeFileUri(mediaTypeUri, metadata));
474     return MediaFileUtils::GetUriByExtrConditions(mediaTypeUri + "/", to_string(metadata.GetFileId()));
475 }
476 
477 /**
478  * @brief Deletes particular entry in database based on row id
479  *
480  * @param idList The list of IDs to be deleted from the media db
481  * @return bool Status of the delete operation
482  */
DeleteMetadata(const vector<string> & idList,const string & tableName)483 bool MediaScannerDb::DeleteMetadata(const vector<string> &idList, const string &tableName)
484 {
485     if (idList.size() == 0) {
486         MEDIA_ERR_LOG("to-deleted idList size equals to 0");
487         return false;
488     }
489 
490     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
491     if (rdbStore == nullptr) {
492         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
493             {KEY_OPT_TYPE, OptType::SCAN}};
494         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
495         MEDIA_ERR_LOG("rdbStore is nullptr");
496         return false;
497     }
498 
499     NativeRdb::RdbPredicates rdbPredicate(tableName);
500     rdbPredicate.In(MEDIA_DATA_DB_ID, idList);
501     int32_t ret = rdbStore->Delete(rdbPredicate);
502     return ret == static_cast<int32_t>(idList.size());
503 }
504 
GetOprnObjectFromPath(const string & path)505 static OperationObject GetOprnObjectFromPath(const string &path)
506 {
507     const map<string, OperationObject> oprnMap = {
508         { ROOT_MEDIA_DIR + PHOTO_BUCKET, OperationObject::FILESYSTEM_PHOTO },
509         { ROOT_MEDIA_DIR + AUDIO_BUCKET, OperationObject::FILESYSTEM_AUDIO },
510 #ifdef MEDIALIBRARY_COMPATIBILITY
511         { ROOT_MEDIA_DIR + PIC_DIR_VALUES, OperationObject::FILESYSTEM_PHOTO },
512         { ROOT_MEDIA_DIR + AUDIO_DIR_VALUES, OperationObject::FILESYSTEM_AUDIO },
513         { ROOT_MEDIA_DIR + VIDEO_DIR_VALUES, OperationObject::FILESYSTEM_PHOTO },
514         { ROOT_MEDIA_DIR + CAMERA_DIR_VALUES, OperationObject::FILESYSTEM_PHOTO }
515 #endif
516     };
517 
518     for (const auto &iter : oprnMap) {
519         if (path.find(iter.first) != string::npos) {
520             return iter.second;
521         }
522     }
523     return OperationObject::FILESYSTEM_ASSET;
524 }
525 
GetQueryParamsByPath(const string & path,MediaLibraryApi api,vector<string> & columns,OperationObject & oprnObject,string & whereClause)526 static void GetQueryParamsByPath(const string &path, MediaLibraryApi api, vector<string> &columns,
527     OperationObject &oprnObject, string &whereClause)
528 {
529     oprnObject = GetOprnObjectFromPath(path);
530     if (api == MediaLibraryApi::API_10) {
531         whereClause = MediaColumn::MEDIA_FILE_PATH + " = ?";
532         if (oprnObject == OperationObject::FILESYSTEM_PHOTO) {
533             columns = {
534                 MediaColumn::MEDIA_ID, MediaColumn::MEDIA_SIZE, MediaColumn::MEDIA_DATE_MODIFIED,
535                 MediaColumn::MEDIA_NAME, PhotoColumn::PHOTO_ORIENTATION, MediaColumn::MEDIA_TIME_PENDING,
536                 MediaColumn::MEDIA_DATE_ADDED, PhotoColumn::PHOTO_DATE_DAY, MediaColumn::MEDIA_OWNER_PACKAGE,
537                 PhotoColumn::PHOTO_SUBTYPE, PhotoColumn::PHOTO_IS_TEMP, PhotoColumn::MOVING_PHOTO_EFFECT_MODE,
538                 PhotoColumn::PHOTO_DIRTY, PhotoColumn::PHOTO_QUALITY, MediaColumn::MEDIA_DATE_TAKEN,
539                 PhotoColumn::PHOTO_BURST_COVER_LEVEL, PhotoColumn::PHOTO_OWNER_ALBUM_ID
540             };
541         } else if (oprnObject == OperationObject::FILESYSTEM_AUDIO) {
542             columns = {
543                 MediaColumn::MEDIA_ID, MediaColumn::MEDIA_SIZE, MediaColumn::MEDIA_DATE_MODIFIED,
544                 MediaColumn::MEDIA_NAME, MediaColumn::MEDIA_TIME_PENDING
545             };
546         }
547     } else {
548         if (oprnObject == OperationObject::FILESYSTEM_PHOTO) {
549             whereClause = MediaColumn::MEDIA_FILE_PATH + " = ?";
550             columns = {
551                 MediaColumn::MEDIA_ID, MediaColumn::MEDIA_SIZE, MediaColumn::MEDIA_DATE_MODIFIED,
552                 MediaColumn::MEDIA_NAME, PhotoColumn::PHOTO_ORIENTATION, MediaColumn::MEDIA_TIME_PENDING,
553                 MediaColumn::MEDIA_DATE_ADDED, PhotoColumn::PHOTO_DATE_DAY, MediaColumn::MEDIA_OWNER_PACKAGE
554             };
555         } else if (oprnObject == OperationObject::FILESYSTEM_AUDIO) {
556             whereClause = MediaColumn::MEDIA_FILE_PATH + " = ?";
557             columns = {
558                 MediaColumn::MEDIA_ID, MediaColumn::MEDIA_SIZE, MediaColumn::MEDIA_DATE_MODIFIED,
559                 MediaColumn::MEDIA_NAME, MediaColumn::MEDIA_TIME_PENDING
560             };
561         } else {
562             whereClause = MEDIA_DATA_DB_FILE_PATH + " = ? And " + MEDIA_DATA_DB_IS_TRASH + " = ? ";
563             columns = {
564                 MEDIA_DATA_DB_ID, MEDIA_DATA_DB_SIZE, MEDIA_DATA_DB_DATE_MODIFIED,
565                 MEDIA_DATA_DB_NAME, MEDIA_DATA_DB_ORIENTATION, MEDIA_DATA_DB_RECYCLE_PATH
566             };
567         }
568     }
569 }
570 
GetFileSet(MediaLibraryCommand & cmd,const vector<string> & columns,shared_ptr<NativeRdb::ResultSet> & resultSet)571 int32_t MediaScannerDb::GetFileSet(MediaLibraryCommand &cmd, const vector<string> &columns,
572     shared_ptr<NativeRdb::ResultSet> &resultSet)
573 {
574     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
575     if (rdbStore == nullptr) {
576         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_RDB},
577             {KEY_OPT_TYPE, OptType::SCAN}};
578         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
579         return E_RDB;
580     }
581     resultSet = rdbStore->Query(cmd, columns);
582     if (resultSet == nullptr) {
583         MEDIA_ERR_LOG("return nullptr when query rdb");
584         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_RDB},
585             {KEY_OPT_TYPE, OptType::SCAN}};
586         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
587         return E_RDB;
588     }
589 
590     int32_t rowCount = 0;
591     int32_t ret = resultSet->GetRowCount(rowCount);
592     if (ret != NativeRdb::E_OK) {
593         MEDIA_ERR_LOG("failed to get row count");
594         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
595             {KEY_OPT_TYPE, OptType::SCAN}};
596         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
597         return E_RDB;
598     }
599 
600     if (rowCount == 0) {
601         return E_OK;
602     }
603 
604     ret = resultSet->GoToFirstRow();
605     if (ret != NativeRdb::E_OK) {
606         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
607             {KEY_OPT_TYPE, OptType::SCAN}};
608         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
609         MEDIA_ERR_LOG("failed to go to first row");
610         return E_RDB;
611     }
612     return E_OK;
613 }
614 
615 /**
616  * @brief Get date modified, id, size and name info for a file
617  *
618  * @param path The file path for which to obtain the latest modification info from the db
619  * @return unique_ptr<Metadata> The metadata object representing the latest info for the given filepath
620  */
GetFileBasicInfo(const string & path,unique_ptr<Metadata> & ptr,MediaLibraryApi api,int32_t fileId)621 int32_t MediaScannerDb::GetFileBasicInfo(const string &path, unique_ptr<Metadata> &ptr, MediaLibraryApi api,
622     int32_t fileId)
623 {
624     vector<string> columns;
625     string whereClause;
626     OperationObject oprnObject = OperationObject::FILESYSTEM_ASSET;
627     GetQueryParamsByPath(path, api, columns, oprnObject, whereClause);
628 
629     vector<string> args;
630     if (oprnObject == OperationObject::FILESYSTEM_PHOTO || oprnObject == OperationObject::FILESYSTEM_AUDIO) {
631         if (fileId > 0) {
632             whereClause = MediaColumn::MEDIA_ID + " = ? ";
633             args = { to_string(fileId) };
634         } else {
635             args = { path };
636         }
637     } else {
638         args = { path, to_string(NOT_TRASHED) };
639     }
640 
641     MediaLibraryCommand cmd(oprnObject, OperationType::QUERY, api);
642     cmd.GetAbsRdbPredicates()->SetWhereClause(whereClause);
643     cmd.GetAbsRdbPredicates()->SetWhereArgs(args);
644 
645     shared_ptr<NativeRdb::ResultSet> resultSet;
646     int32_t ret = GetFileSet(cmd, columns, resultSet);
647     if (ret != E_OK) {
648         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
649             {KEY_OPT_TYPE, OptType::SCAN}};
650         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
651         return ret;
652     }
653     ptr->SetTableName(cmd.GetTableName());
654 
655     return FillMetadata(resultSet, ptr);
656 }
657 
PreparePredicatesAndColumns(const string & path,const string & tableName,const string & whitePath,AbsRdbPredicates & predicates,vector<string> & columns)658 static void PreparePredicatesAndColumns(const string &path, const string &tableName, const string &whitePath,
659     AbsRdbPredicates &predicates, vector<string> &columns)
660 {
661     string querySql;
662     vector<string> args;
663     if (whitePath.empty()) {
664         if (tableName == MEDIALIBRARY_TABLE) {
665             querySql = MEDIA_DATA_DB_FILE_PATH + " LIKE ? AND " + MEDIA_DATA_DB_IS_TRASH + " = ? ";
666             args = { path.back() != '/' ? path + "/%" : path + "%", to_string(NOT_TRASHED) };
667             columns = { MEDIA_DATA_DB_ID, MEDIA_DATA_DB_MEDIA_TYPE, MEDIA_DATA_DB_RECYCLE_PATH };
668         } else {
669             querySql = MEDIA_DATA_DB_FILE_PATH + " LIKE ? AND " + MediaColumn::MEDIA_TIME_PENDING + " <> ? ";
670             args= { path.back() != '/' ? path + "/%" : path + "%", to_string(UNCREATE_FILE_TIMEPENDING) };
671             columns = { MEDIA_DATA_DB_ID, MEDIA_DATA_DB_MEDIA_TYPE };
672         }
673     } else {
674         if (tableName == MEDIALIBRARY_TABLE) {
675             querySql = MEDIA_DATA_DB_FILE_PATH + " LIKE ? AND " + MEDIA_DATA_DB_FILE_PATH + " NOT LIKE ? AND " +
676                 MEDIA_DATA_DB_IS_TRASH + " = ? ";
677             args = { path.back() != '/' ? path + "/%" : path + "%",
678             whitePath.back() != '/' ? whitePath + "/%" : whitePath + "%", to_string(NOT_TRASHED) };
679             columns = { MEDIA_DATA_DB_ID, MEDIA_DATA_DB_MEDIA_TYPE, MEDIA_DATA_DB_RECYCLE_PATH };
680         } else {
681             querySql = MEDIA_DATA_DB_FILE_PATH + " LIKE ? AND " + MEDIA_DATA_DB_FILE_PATH + " NOT LIKE ? AND " +
682                 MediaColumn::MEDIA_TIME_PENDING + " <> ? ";
683             args= { path.back() != '/' ? path + "/%" : path + "%",
684                 whitePath.back() != '/' ? whitePath + "/%" : whitePath + "%", to_string(UNCREATE_FILE_TIMEPENDING) };
685             columns = { MEDIA_DATA_DB_ID, MEDIA_DATA_DB_MEDIA_TYPE };
686         }
687     }
688 
689     predicates.SetWhereClause(querySql);
690     predicates.SetWhereArgs(args);
691 }
692 
693 /**
694  * @brief Get the list of all IDs corresponding to given path
695  *
696  * @param path The path from which to obtain the list of child IDs
697  * @return unordered_map<int32_t, MediaType> The list of IDS along with mediaType information
698  */
GetIdsFromFilePath(const string & path,const string & tableName,const string & whitePath)699 unordered_map<int32_t, MediaType> MediaScannerDb::GetIdsFromFilePath(const string &path, const string &tableName,
700     const string &whitePath)
701 {
702     unordered_map<int32_t, MediaType> idMap = {};
703     AbsRdbPredicates predicates(tableName);
704     vector<string> columns;
705     PreparePredicatesAndColumns(path, tableName, whitePath, predicates, columns);
706 
707     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
708     if (rdbStore == nullptr) {
709         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
710             {KEY_OPT_TYPE, OptType::SCAN}};
711         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
712         return idMap;
713     }
714     auto resultSet = rdbStore->Query(predicates, columns);
715     if (resultSet == nullptr) {
716         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
717             {KEY_OPT_TYPE, OptType::SCAN}};
718         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
719         return idMap;
720     }
721 
722     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
723         if (tableName == MEDIALIBRARY_TABLE) {
724             string recyclePath = GetStringVal(MEDIA_DATA_DB_RECYCLE_PATH, resultSet);
725             if (!recyclePath.empty()) {
726                 continue;
727             }
728         }
729         int32_t id = GetInt32Val(MEDIA_DATA_DB_ID, resultSet);
730         int32_t mediaType = GetInt32Val(MEDIA_DATA_DB_MEDIA_TYPE, resultSet);
731         idMap.emplace(make_pair(id, static_cast<MediaType>(mediaType)));
732     }
733     return idMap;
734 }
735 
GetFileDBUriFromPath(const string & path)736 string MediaScannerDb::GetFileDBUriFromPath(const string &path)
737 {
738     string uri;
739 
740     vector<string> columns = {};
741     columns.push_back(MEDIA_DATA_DB_URI);
742 
743     DataShare::DataSharePredicates predicates;
744     predicates.SetWhereClause(MEDIA_DATA_DB_FILE_PATH + " = ? AND " + MEDIA_DATA_DB_IS_TRASH + " = ?");
745     vector<string> args = { path, to_string(NOT_TRASHED) };
746     predicates.SetWhereArgs(args);
747 
748     Uri queryUri(MEDIALIBRARY_DATA_URI);
749     MediaLibraryCommand cmd(queryUri, OperationType::QUERY);
750     int errCode = 0;
751     auto resultSet = MediaLibraryDataManager::GetInstance()->QueryRdb(cmd, columns, predicates, errCode);
752     if (resultSet == nullptr) {
753         MEDIA_ERR_LOG("No result found for this path");
754         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
755             {KEY_OPT_TYPE, OptType::SCAN}};
756         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
757         return uri;
758     }
759     auto ret = resultSet->GoToFirstRow();
760     if (ret != NativeRdb::E_OK) {
761         MEDIA_ERR_LOG("Get data error for this path");
762         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
763             {KEY_OPT_TYPE, OptType::SCAN}};
764         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
765         return uri;
766     }
767 
768     int32_t intValue(0);
769     int32_t columnIndex(0);
770     resultSet->GetColumnIndex(MEDIA_DATA_DB_ID, columnIndex);
771     resultSet->GetInt(columnIndex, intValue);
772     uri = MEDIALIBRARY_DATA_URI + "/" + to_string(intValue);
773     return uri;
774 }
775 
GetIdFromPath(const string & path)776 int32_t MediaScannerDb::GetIdFromPath(const string &path)
777 {
778     int32_t id = UNKNOWN_ID;
779     int32_t columnIndex = -1;
780 
781     DataShare::DataSharePredicates predicates;
782     predicates.SetWhereClause(MEDIA_DATA_DB_FILE_PATH + " = ? AND " + MEDIA_DATA_DB_IS_TRASH + " = ?");
783     vector<string> args = { path, to_string(NOT_TRASHED) };
784     predicates.SetWhereArgs(args);
785 
786     Uri uri(MEDIALIBRARY_DATA_URI);
787     MediaLibraryCommand cmd(uri, OperationType::QUERY);
788     vector<string> columns = {MEDIA_DATA_DB_ID};
789     int errCode = 0;
790     auto resultSet = MediaLibraryDataManager::GetInstance()->QueryRdb(cmd, columns, predicates, errCode);
791     if (resultSet == nullptr) {
792         MEDIA_ERR_LOG("No data found for the given path %{private}s", path.c_str());
793         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
794             {KEY_OPT_TYPE, OptType::SCAN}};
795         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
796         return id;
797     }
798     auto ret = resultSet->GoToFirstRow();
799     if (ret != NativeRdb::E_OK) {
800         MEDIA_ERR_LOG("Get data for the given path %{private}s error", path.c_str());
801         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
802             {KEY_OPT_TYPE, OptType::SCAN}};
803         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
804         return id;
805     }
806 
807     resultSet->GetColumnIndex(MEDIA_DATA_DB_ID, columnIndex);
808     resultSet->GetInt(columnIndex, id);
809 
810     return id;
811 }
812 
ReadAlbums(const string & path,unordered_map<string,Metadata> & albumMap)813 int32_t MediaScannerDb::ReadAlbums(const string &path, unordered_map<string, Metadata> &albumMap)
814 {
815     if ((path + "/").find(ROOT_MEDIA_DIR) != 0) {
816         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_INVALID_ARGUMENTS},
817             {KEY_OPT_TYPE, OptType::SCAN}};
818         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
819         return E_INVALID_ARGUMENTS;
820     }
821 
822     AbsRdbPredicates predicates(MEDIALIBRARY_TABLE);
823     string queryCmd = MEDIA_DATA_DB_MEDIA_TYPE + " = ? AND " + MEDIA_DATA_DB_FILE_PATH + " like ? AND " +
824         MEDIA_DATA_DB_IS_TRASH + " = ?";
825     string queryPath = path.back() != '/' ? path + "/%" : path + "%";
826     vector<string> args = { to_string(MediaType::MEDIA_TYPE_ALBUM), queryPath, to_string(NOT_TRASHED) };
827     predicates.SetWhereClause(queryCmd);
828     predicates.SetWhereArgs(args);
829     vector<string> columns = {MEDIA_DATA_DB_ID, MEDIA_DATA_DB_FILE_PATH, MEDIA_DATA_DB_DATE_MODIFIED};
830 
831     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
832     if (rdbStore == nullptr) {
833         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
834             {KEY_OPT_TYPE, OptType::SCAN}};
835         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
836         return E_HAS_DB_ERROR;
837     }
838     auto resultSet = rdbStore->Query(predicates, columns);
839     if (resultSet == nullptr) {
840         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
841             {KEY_OPT_TYPE, OptType::SCAN}};
842         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
843         return E_HAS_DB_ERROR;
844     }
845 
846     albumMap.clear();
847     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
848         Metadata metadata;
849         int32_t intValue = GetInt32Val(MEDIA_DATA_DB_ID, resultSet);
850         metadata.SetFileId(intValue);
851         string strValue = GetStringVal(MEDIA_DATA_DB_FILE_PATH, resultSet);
852         metadata.SetFilePath(strValue);
853         int64_t dateModified = GetInt64Val(MEDIA_DATA_DB_DATE_MODIFIED, resultSet);
854         metadata.SetFileDateModified(dateModified);
855         albumMap.insert(make_pair(strValue, metadata));
856     }
857 
858     return E_OK;
859 }
860 
InsertAlbum(const Metadata & metadata)861 int32_t MediaScannerDb::InsertAlbum(const Metadata &metadata)
862 {
863     int32_t id = 0;
864 
865     string tableName;
866     string uri = InsertMetadata(metadata, tableName);
867     id = stoi(MediaFileUtils::GetIdFromUri(uri));
868 
869     return id;
870 }
871 
UpdateAlbum(const Metadata & metadata)872 int32_t MediaScannerDb::UpdateAlbum(const Metadata &metadata)
873 {
874     int32_t id = 0;
875 
876     string tableName;
877     string uri = UpdateMetadata(metadata, tableName);
878     id = stoi(MediaFileUtils::GetIdFromUri(uri));
879 
880     return id;
881 }
882 
NotifyDatabaseChange(const MediaType mediaType)883 void MediaScannerDb::NotifyDatabaseChange(const MediaType mediaType)
884 {
885     string notifyUri = MediaFileUtils::GetMediaTypeUri(mediaType);
886     Uri uri(notifyUri);
887 
888     MediaLibraryDataManager::GetInstance()->NotifyChange(uri);
889 }
890 
ExtractMetaFromColumn(const shared_ptr<NativeRdb::ResultSet> & resultSet,unique_ptr<Metadata> & metadata,const std::string & col)891 void MediaScannerDb::ExtractMetaFromColumn(const shared_ptr<NativeRdb::ResultSet> &resultSet,
892                                            unique_ptr<Metadata> &metadata, const std::string &col)
893 {
894     ResultSetDataType dataType = ResultSetDataType::TYPE_NULL;
895     Metadata::MetadataFnPtr requestFunc = nullptr;
896     auto itr = metadata->memberFuncMap_.find(col);
897     if (itr != metadata->memberFuncMap_.end()) {
898         dataType = itr->second.first;
899         requestFunc = itr->second.second;
900     } else {
901         MEDIA_ERR_LOG("invalid column name %{private}s", col.c_str());
902         return;
903     }
904 
905     std::variant<int32_t, std::string, int64_t, double> data =
906         ResultSetUtils::GetValFromColumn<const shared_ptr<NativeRdb::ResultSet>>(col, resultSet, dataType);
907 
908     // Use the function pointer from map and pass data to fn ptr
909     if (requestFunc != nullptr) {
910         (metadata.get()->*requestFunc)(data);
911     }
912 }
913 
FillMetadata(const shared_ptr<NativeRdb::ResultSet> & resultSet,unique_ptr<Metadata> & ptr)914 int32_t MediaScannerDb::FillMetadata(const shared_ptr<NativeRdb::ResultSet> &resultSet,
915     unique_ptr<Metadata> &ptr)
916 {
917     std::vector<std::string> columnNames;
918     int32_t err = resultSet->GetAllColumnNames(columnNames);
919     if (err != NativeRdb::E_OK) {
920         MEDIA_ERR_LOG("failed to get all column names");
921         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, err},
922             {KEY_OPT_TYPE, OptType::SCAN}};
923         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
924         return E_RDB;
925     }
926 
927     for (const auto &col : columnNames) {
928         ExtractMetaFromColumn(resultSet, ptr, col);
929     }
930 
931     return E_OK;
932 }
933 
RecordError(const std::string & err)934 int32_t MediaScannerDb::RecordError(const std::string &err)
935 {
936     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
937     if (rdbStore == nullptr) {
938         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
939             {KEY_OPT_TYPE, OptType::SCAN}};
940         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
941         MEDIA_ERR_LOG("rdbStore is nullptr");
942         return E_ERR;
943     }
944 
945     ValuesBucket valuesBucket;
946     valuesBucket.PutString(MEDIA_DATA_ERROR, err);
947     int64_t outRowId = -1;
948     int32_t ret = rdbStore->Insert(outRowId, MEDIALIBRARY_ERROR_TABLE, valuesBucket);
949     if (ret) {
950         MEDIA_ERR_LOG("rdb insert err %{public}d", ret);
951         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
952             {KEY_OPT_TYPE, OptType::SCAN}};
953         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
954         return E_ERR;
955     }
956 
957     return E_OK;
958 }
959 
ReadError()960 std::set<std::string> MediaScannerDb::ReadError()
961 {
962     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
963     if (rdbStore == nullptr) {
964         MEDIA_ERR_LOG("rdbStore is nullptr");
965         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
966             {KEY_OPT_TYPE, OptType::SCAN}};
967         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
968         return {};
969     }
970 
971     AbsRdbPredicates predicates(MEDIALIBRARY_ERROR_TABLE);
972     vector<string> columns = { MEDIA_DATA_ERROR };
973     auto resultSet = rdbStore->Query(predicates, columns);
974     if (resultSet == nullptr) {
975         MEDIA_ERR_LOG("rdb query return nullptr");
976         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
977             {KEY_OPT_TYPE, OptType::SCAN}};
978         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
979         return {};
980     }
981 
982     int32_t rowCount = 0;
983     auto ret = resultSet->GetRowCount(rowCount);
984     if (ret != NativeRdb::E_OK) {
985         MEDIA_ERR_LOG("failed to get row count");
986         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
987             {KEY_OPT_TYPE, OptType::SCAN}};
988         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
989         return {};
990     }
991 
992     if (rowCount == 0) {
993         return {};
994     }
995 
996     string str;
997     set<string> errSet;
998     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
999         resultSet->GetString(0, str);
1000         errSet.insert(move(str));
1001     }
1002 
1003     return errSet;
1004 }
1005 
DeleteError(const std::string & err)1006 int32_t MediaScannerDb::DeleteError(const std::string &err)
1007 {
1008     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1009     if (rdbStore == nullptr) {
1010         MEDIA_ERR_LOG("rdbStore is nullptr");
1011         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, E_HAS_DB_ERROR},
1012             {KEY_OPT_TYPE, OptType::SCAN}};
1013         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
1014         return E_ERR;
1015     }
1016 
1017     int32_t outRowId = -1;
1018     string whereClause = MEDIA_DATA_ERROR + " = ?";
1019     vector<string> whereArgs= { err };
1020     int32_t ret = rdbStore->Delete(outRowId, MEDIALIBRARY_ERROR_TABLE, whereClause, whereArgs);
1021     if (ret) {
1022         MEDIA_ERR_LOG("rdb delete err %{public}d", ret);
1023         VariantMap map = {{KEY_ERR_FILE, __FILE__}, {KEY_ERR_LINE, __LINE__}, {KEY_ERR_CODE, ret},
1024             {KEY_OPT_TYPE, OptType::SCAN}};
1025         PostEventUtils::GetInstance().PostErrorProcess(ErrType::DB_OPT_ERR, map);
1026         return E_ERR;
1027     }
1028     MEDIA_INFO_LOG("delete error: %{public}s", err.c_str());
1029     return E_OK;
1030 }
1031 
UpdateAlbumInfo(const std::vector<std::string> & subtypes,const std::vector<std::string> & userAlbumIds,const std::vector<std::string> & sourceAlbumIds)1032 void MediaScannerDb::UpdateAlbumInfo(const std::vector<std::string> &subtypes,
1033     const std::vector<std::string> &userAlbumIds, const std::vector<std::string> &sourceAlbumIds)
1034 {
1035     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1036     if (rdbStore == nullptr) {
1037         MEDIA_ERR_LOG("rdbstore is nullptr");
1038         return;
1039     }
1040     MediaLibraryRdbUtils::UpdateSystemAlbumInternal(
1041         rdbStore, {
1042         to_string(PhotoAlbumSubType::IMAGE),
1043         to_string(PhotoAlbumSubType::VIDEO),
1044         to_string(PhotoAlbumSubType::SCREENSHOT),
1045         to_string(PhotoAlbumSubType::FAVORITE),
1046         to_string(PhotoAlbumSubType::CLOUD_ENHANCEMENT),
1047     });
1048 }
1049 
UpdateAlbumInfoByMetaData(const Metadata & metadata)1050 void MediaScannerDb::UpdateAlbumInfoByMetaData(const Metadata &metadata)
1051 {
1052     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1053     if (rdbStore == nullptr) {
1054         MEDIA_ERR_LOG("rdbstore is nullptr");
1055         return;
1056     }
1057     if (metadata.GetFileMediaType() == MEDIA_TYPE_IMAGE) {
1058         MediaLibraryRdbUtils::UpdateSystemAlbumInternal(rdbStore, { to_string(PhotoAlbumSubType::IMAGE) },
1059             metadata.GetForAdd());
1060     } else if (metadata.GetFileMediaType() == MEDIA_TYPE_VIDEO) {
1061         MediaLibraryRdbUtils::UpdateSystemAlbumInternal(rdbStore, { to_string(PhotoAlbumSubType::VIDEO) },
1062             metadata.GetForAdd());
1063     } else {
1064         MEDIA_WARN_LOG("Invalid mediaType : %{public}d", metadata.GetFileMediaType());
1065     }
1066     if (metadata.GetAlbumId() > 0) {
1067         MEDIA_INFO_LOG("albumId: %{public}d", metadata.GetAlbumId());
1068         if (metadata.GetFileId() != FILE_ID_DEFAULT) {
1069             std::string uri = PhotoColumn::PHOTO_URI_PREFIX + to_string(metadata.GetFileId());
1070             MediaLibraryRdbUtils::UpdateCommonAlbumByUri(rdbStore, {uri}, metadata.GetForAdd(), true);
1071         }
1072     } else {
1073         if (!metadata.GetOwnerPackage().empty()) {
1074             if (metadata.GetFileId() != FILE_ID_DEFAULT) {
1075                 std::string uri = PhotoColumn::PHOTO_URI_PREFIX + to_string(metadata.GetFileId());
1076                 MediaLibraryRdbUtils::UpdateSourceAlbumByUri(rdbStore, {uri}, metadata.GetForAdd(), true);
1077             }
1078         }
1079     }
1080 }
1081 
MakeFileUri(const std::string & mediaTypeUri,const Metadata & metadata)1082 std::string MediaScannerDb::MakeFileUri(const std::string &mediaTypeUri, const Metadata &metadata)
1083 {
1084     return MediaFileUtils::GetUriByExtrConditions(mediaTypeUri + "/", to_string(metadata.GetFileId()),
1085         MediaFileUtils::GetExtraUri(metadata.GetFileName(), metadata.GetFilePath())) + "?api_version=10" +
1086         "&date_modified=" + to_string(metadata.GetFileDateModified()) +
1087         "&date_taken=" + to_string(metadata.GetDateTaken());
1088 }
1089 } // namespace Media
1090 } // namespace OHOS
1091