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