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