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