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