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