1 /*
2 * Copyright (C) 2023 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
16 #include "medialibrary_asset_operations.h"
17
18 #include <algorithm>
19 #include <dirent.h>
20 #include <memory>
21 #include <mutex>
22 #include <sstream>
23 #include <sys/stat.h>
24
25 #include "cloud_media_asset_manager.h"
26 #include "dfx_utils.h"
27 #include "directory_ex.h"
28 #include "file_asset.h"
29 #include "media_app_uri_permission_column.h"
30 #include "media_column.h"
31 #include "media_exif.h"
32 #include "media_file_utils.h"
33 #include "media_file_uri.h"
34 #include "media_log.h"
35 #include "media_scanner_manager.h"
36 #include "media_unique_number_column.h"
37 #include "medialibrary_album_operations.h"
38 #include "medialibrary_async_worker.h"
39 #include "medialibrary_audio_operations.h"
40 #include "medialibrary_bundle_manager.h"
41 #include "medialibrary_command.h"
42 #include "medialibrary_common_utils.h"
43 #include "medialibrary_data_manager.h"
44 #include "medialibrary_data_manager_utils.h"
45 #include "medialibrary_db_const.h"
46 #include "medialibrary_errno.h"
47 #include "medialibrary_inotify.h"
48 #ifdef META_RECOVERY_SUPPORT
49 #include "medialibrary_meta_recovery.h"
50 #endif
51 #include "medialibrary_notify.h"
52 #include "medialibrary_photo_operations.h"
53 #include "medialibrary_rdb_transaction.h"
54 #include "medialibrary_rdb_utils.h"
55 #include "medialibrary_rdbstore.h"
56 #include "medialibrary_tracer.h"
57 #include "medialibrary_type_const.h"
58 #include "medialibrary_unistore_manager.h"
59 #include "medialibrary_urisensitive_operations.h"
60 #include "media_privacy_manager.h"
61 #include "mimetype_utils.h"
62 #include "multistages_capture_manager.h"
63 #ifdef MEDIALIBRARY_FEATURE_CLOUD_ENHANCEMENT
64 #include "enhancement_manager.h"
65 #endif
66 #include "permission_utils.h"
67 #include "photo_album_column.h"
68 #include "rdb_errno.h"
69 #include "rdb_predicates.h"
70 #include "rdb_store.h"
71 #include "rdb_utils.h"
72 #include "result_set_utils.h"
73 #include "thumbnail_service.h"
74 #include "uri_permission_manager_client.h"
75 #include "userfile_manager_types.h"
76 #include "value_object.h"
77 #include "values_bucket.h"
78 #include "medialibrary_formmap_operations.h"
79 #include "medialibrary_vision_operations.h"
80 #include "dfx_manager.h"
81 #include "dfx_const.h"
82 #include "moving_photo_file_utils.h"
83 #include "userfilemgr_uri.h"
84 #include "medialibrary_album_fusion_utils.h"
85 #include "unique_fd.h"
86 #include "data_secondary_directory_uri.h"
87 #include "medialibrary_restore.h"
88 #include "cloud_sync_helper.h"
89 #include "refresh_business_name.h"
90
91 using namespace std;
92 using namespace OHOS::NativeRdb;
93
94 namespace OHOS {
95 namespace Media {
96 mutex g_uniqueNumberLock;
97
98 const string DEFAULT_IMAGE_NAME = "IMG_";
99 const string DEFAULT_VIDEO_NAME = "VID_";
100 const string DEFAULT_AUDIO_NAME = "AUD_";
101 constexpr int32_t NO_DESENSITIZE = 3;
102 const string PHOTO_ALBUM_URI_PREFIX = "file://media/PhotoAlbum/";
103 constexpr int32_t UNKNOWN_VALUE = -1;
104 constexpr int32_t LOCAL_PHOTO_POSITION = 1;
105 constexpr int32_t BOTH_LOCAL_CLOUD_PHOTO_POSITION = 3;
106 constexpr int32_t MAX_PROCESS_NUM = 200;
107 constexpr int64_t INVALID_SIZE = 0;
108 static const std::string ANALYSIS_FILE_PATH = "/storage/cloud/files/highlight/music";
109
110 struct DeletedFilesParams {
111 vector<string> ids;
112 vector<string> paths;
113 vector<string> dateTakens;
114 vector<int32_t> subTypes;
115 vector<int32_t> isTemps;
116 map<string, string> displayNames;
117 map<string, string> albumNames;
118 map<string, string> ownerAlbumIds;
119 bool containsHidden = false;
120 };
121
HandleInsertOperationExt(MediaLibraryCommand & cmd)122 int32_t MediaLibraryAssetOperations::HandleInsertOperationExt(MediaLibraryCommand& cmd)
123 {
124 int errCode = E_ERR;
125 switch (cmd.GetOprnType()) {
126 case OperationType::LS_MEDIA_FILES:
127 errCode = MediaLibraryPhotoOperations::LSMediaFiles(cmd);
128 break;
129 default:
130 MEDIA_ERR_LOG("unknown operation type %{public}d", cmd.GetOprnType());
131 break;
132 }
133 return errCode;
134 }
135
HandleInsertOperation(MediaLibraryCommand & cmd)136 int32_t MediaLibraryAssetOperations::HandleInsertOperation(MediaLibraryCommand &cmd)
137 {
138 int errCode = E_ERR;
139 switch (cmd.GetOprnType()) {
140 case OperationType::CREATE:
141 errCode = CreateOperation(cmd);
142 break;
143 case OperationType::CLOSE:
144 errCode = CloseOperation(cmd);
145 break;
146 case OperationType::COMMIT_EDIT:
147 errCode = MediaLibraryPhotoOperations::CommitEditInsert(cmd);
148 if (errCode == E_SUCCESS) {
149 MediaLibraryVisionOperations::EditCommitOperation(cmd);
150 }
151 break;
152 case OperationType::REVERT_EDIT:
153 errCode = MediaLibraryPhotoOperations::RevertToOrigin(cmd);
154 if (errCode == E_SUCCESS) {
155 MediaLibraryVisionOperations::EditCommitOperation(cmd);
156 }
157 break;
158 case OperationType::SUBMIT_CACHE:
159 errCode = MediaLibraryPhotoOperations::SubmitCache(cmd);
160 break;
161 case OperationType::CUSTOM_RESTORE:
162 errCode = MediaLibraryPhotoOperations::ProcessCustomRestore(cmd);
163 break;
164 case OperationType::CUSTOM_RESTORE_CANCEL:
165 errCode = MediaLibraryPhotoOperations::CancelCustomRestore(cmd);
166 break;
167 case OperationType::ADD_FILTERS:
168 errCode = MediaLibraryPhotoOperations::AddFilters(cmd);
169 break;
170 case OperationType::SCAN_WITHOUT_ALBUM_UPDATE:
171 errCode = MediaLibraryPhotoOperations::ScanFileWithoutAlbumUpdate(cmd);
172 break;
173 case OperationType::FINISH_REQUEST_PICTURE:
174 errCode = MediaLibraryPhotoOperations::FinishRequestPicture(cmd);
175 break;
176 case OperationType::CLONE_ASSET:
177 errCode = MediaLibraryPhotoOperations::CloneSingleAsset(cmd);
178 break;
179 default:
180 errCode = HandleInsertOperationExt(cmd);
181 break;
182 }
183 return errCode;
184 }
185
CreateOperation(MediaLibraryCommand & cmd)186 int32_t MediaLibraryAssetOperations::CreateOperation(MediaLibraryCommand &cmd)
187 {
188 // CreateAsset specify type
189 switch (cmd.GetOprnObject()) {
190 case OperationObject::FILESYSTEM_PHOTO:
191 case OperationObject::PTP_OPERATION:
192 return MediaLibraryPhotoOperations::Create(cmd);
193 case OperationObject::FILESYSTEM_AUDIO:
194 return MediaLibraryAudioOperations::Create(cmd);
195 case OperationObject::FILESYSTEM_ASSET:
196 MEDIA_ERR_LOG("create asset by FileSysetm_Asset is deperated");
197 return E_INVALID_VALUES;
198 default:
199 MEDIA_ERR_LOG("error operation object: %{public}d", cmd.GetOprnObject());
200 return E_INVALID_VALUES;
201 }
202 }
203
DeleteOperation(MediaLibraryCommand & cmd)204 int32_t MediaLibraryAssetOperations::DeleteOperation(MediaLibraryCommand &cmd)
205 {
206 // delete Asset specify type
207 switch (cmd.GetOprnObject()) {
208 case OperationObject::FILESYSTEM_PHOTO:
209 return MediaLibraryPhotoOperations::Delete(cmd);
210 case OperationObject::FILESYSTEM_AUDIO:
211 return MediaLibraryAudioOperations::Delete(cmd);
212 case OperationObject::FILESYSTEM_ASSET:
213 MEDIA_ERR_LOG("delete asset by FILESYSTEM_ASSET is deperated");
214 return E_INVALID_VALUES;
215 default:
216 MEDIA_ERR_LOG("error operation object: %{public}d", cmd.GetOprnObject());
217 return E_INVALID_VALUES;
218 }
219 }
220
QueryOperation(MediaLibraryCommand & cmd,const vector<string> & columns)221 shared_ptr<NativeRdb::ResultSet> MediaLibraryAssetOperations::QueryOperation(
222 MediaLibraryCommand &cmd, const vector<string> &columns)
223 {
224 // query asset specify type
225 switch (cmd.GetOprnObject()) {
226 case OperationObject::FILESYSTEM_PHOTO:
227 case OperationObject::EDIT_DATA_EXISTS:
228 case OperationObject::MOVING_PHOTO_VIDEO_READY:
229 return MediaLibraryPhotoOperations::Query(cmd, columns);
230 case OperationObject::FILESYSTEM_AUDIO:
231 return MediaLibraryAudioOperations::Query(cmd, columns);
232 case OperationObject::FILESYSTEM_ASSET:
233 MEDIA_ERR_LOG("api9 operation is not finished");
234 return nullptr;
235 case OperationObject::PAH_MOVING_PHOTO:
236 return MediaLibraryPhotoOperations::ScanMovingPhoto(cmd, columns);
237 default:
238 MEDIA_ERR_LOG("error operation objec: %{public}d", cmd.GetOprnObject());
239 return nullptr;
240 }
241 }
242
UpdateOperation(MediaLibraryCommand & cmd)243 int32_t MediaLibraryAssetOperations::UpdateOperation(MediaLibraryCommand &cmd)
244 {
245 if (!AssetInputParamVerification::CheckParamForUpdate(cmd)) {
246 return E_INVALID_VALUES;
247 }
248
249 switch (cmd.GetOprnObject()) {
250 case OperationObject::PAH_PHOTO:
251 case OperationObject::PAH_VIDEO:
252 case OperationObject::FILESYSTEM_PHOTO:
253 case OperationObject::PTP_OPERATION:
254 return MediaLibraryPhotoOperations::Update(cmd);
255 case OperationObject::FILESYSTEM_AUDIO:
256 return MediaLibraryAudioOperations::Update(cmd);
257 case OperationObject::FILESYSTEM_ASSET:
258 MEDIA_ERR_LOG("create asset by FILESYSTEM_ASSET is deperated");
259 return E_INVALID_VALUES;
260 default:
261 MEDIA_ERR_LOG("error operation object: %{public}d", cmd.GetOprnObject());
262 return E_INVALID_VALUES;
263 }
264 }
265
OpenOperation(MediaLibraryCommand & cmd,const string & mode)266 int32_t MediaLibraryAssetOperations::OpenOperation(MediaLibraryCommand &cmd, const string &mode)
267 {
268 MediaLibraryTracer tracer;
269 tracer.Start("MediaLibraryAssetOperations::OpenOperation");
270
271 // Open specify type
272 switch (cmd.GetOprnObject()) {
273 case OperationObject::FILESYSTEM_PHOTO:
274 case OperationObject::PTP_OPERATION:
275 return MediaLibraryPhotoOperations::Open(cmd, mode);
276 case OperationObject::FILESYSTEM_AUDIO:
277 return MediaLibraryAudioOperations::Open(cmd, mode);
278 case OperationObject::HIGHLIGHT_COVER:
279 return MediaLibraryAssetOperations::OpenHighlightCover(cmd, mode);
280 case OperationObject::HIGHLIGHT_URI:
281 return MediaLibraryAssetOperations::OpenHighlightVideo(cmd, mode);
282 case OperationObject::FILESYSTEM_ASSET:
283 MEDIA_ERR_LOG("open by FILESYSTEM_ASSET is deperated");
284 return E_INVALID_VALUES;
285 default:
286 MEDIA_ERR_LOG("error operation object: %{public}d", cmd.GetOprnObject());
287 return E_INVALID_VALUES;
288 }
289 }
290
CloseOperation(MediaLibraryCommand & cmd)291 int32_t MediaLibraryAssetOperations::CloseOperation(MediaLibraryCommand &cmd)
292 {
293 // Close specify type
294 switch (cmd.GetOprnObject()) {
295 case OperationObject::FILESYSTEM_PHOTO:
296 case OperationObject::PTP_OPERATION:
297 return MediaLibraryPhotoOperations::Close(cmd);
298 case OperationObject::FILESYSTEM_AUDIO:
299 return MediaLibraryAudioOperations::Close(cmd);
300 case OperationObject::FILESYSTEM_ASSET:
301 MEDIA_ERR_LOG("close by FILESYSTEM_ASSET is deperated");
302 return E_INVALID_VALUES;
303 default:
304 MEDIA_ERR_LOG("error operation object: %{public}d", cmd.GetOprnObject());
305 return E_INVALID_VALUES;
306 }
307 }
308
DropAllTables(const shared_ptr<MediaLibraryRdbStore> rdbStore)309 static int32_t DropAllTables(const shared_ptr<MediaLibraryRdbStore> rdbStore)
310 {
311 string dropSqlRowName = "drop_table_and_view_sql";
312 string queryDropSql =
313 "SELECT 'DROP ' || type || ' IF EXISTS ' || name || ';' as " + dropSqlRowName +
314 " FROM sqlite_master" +
315 " WHERE type IN ('table', 'view') AND name NOT LIKE 'sqlite_%';";
316 auto dropSqlsResultSet = rdbStore->QuerySql(queryDropSql);
317 CHECK_AND_RETURN_RET_LOG(dropSqlsResultSet != nullptr, E_HAS_DB_ERROR, "query Drop Sql failed");
318
319 vector<string> dropSqlsVec;
320 while (dropSqlsResultSet->GoToNextRow() == NativeRdb::E_OK) {
321 int32_t columnIndex = 0;
322 CHECK_AND_RETURN_RET_LOG(dropSqlsResultSet->GetColumnIndex(dropSqlRowName, columnIndex) == NativeRdb::E_OK,
323 E_HAS_DB_ERROR, "Get drop_table_and_view_sql column failed");
324
325 string sql;
326 CHECK_AND_RETURN_RET_LOG(dropSqlsResultSet->GetString(columnIndex, sql) == NativeRdb::E_OK,
327 E_HAS_DB_ERROR, "Get drop_table_and_view_sql sql failed");
328 if (!sql.empty()) {
329 dropSqlsVec.push_back(sql);
330 }
331 }
332
333 for (const auto &dropSql : dropSqlsVec) {
334 rdbStore->ExecuteSql(dropSql);
335 }
336 return E_OK;
337 }
338
DeleteToolOperation(MediaLibraryCommand & cmd)339 int32_t MediaLibraryAssetOperations::DeleteToolOperation(MediaLibraryCommand &cmd)
340 {
341 auto valuesBucket = cmd.GetValueBucket();
342 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
343 CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "Can not get rdb store");
344 int32_t errCode = DropAllTables(rdbStore);
345 CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Drop table failed, errCode=%{public}d", errCode);
346 errCode = rdbStore->DataCallBackOnCreate();
347 UriSensitiveOperations::DeleteAllSensitiveAsync();
348 CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "DataCallBackOnCreate failed, errCode=%{public}d", errCode);
349
350 const static vector<string> DELETE_DIR_LIST = {
351 ROOT_MEDIA_DIR + PHOTO_BUCKET,
352 ROOT_MEDIA_DIR + AUDIO_BUCKET,
353 ROOT_MEDIA_DIR + CAMERA_DIR_VALUES,
354 ROOT_MEDIA_DIR + VIDEO_DIR_VALUES,
355 ROOT_MEDIA_DIR + PIC_DIR_VALUES,
356 ROOT_MEDIA_DIR + AUDIO_DIR_VALUES,
357 ROOT_MEDIA_DIR + ".thumbs",
358 ROOT_MEDIA_DIR + ".editData"
359 };
360
361 for (const string &dir : DELETE_DIR_LIST) {
362 if (!MediaFileUtils::DeleteDir(dir)) {
363 MEDIA_ERR_LOG("Delete dir %{public}s failed", dir.c_str());
364 continue;
365 }
366 if (!MediaFileUtils::CreateDirectory(dir)) {
367 MEDIA_ERR_LOG("Create dir %{public}s failed", dir.c_str());
368 };
369 }
370
371 string photoThumbsPath = ROOT_MEDIA_DIR + ".thumbs/Photo";
372 CHECK_AND_PRINT_LOG(MediaFileUtils::CreateDirectory(photoThumbsPath),
373 "Create dir %{public}s failed", photoThumbsPath.c_str());
374 return E_OK;
375 }
376
CheckOprnObject(OperationObject object)377 static bool CheckOprnObject(OperationObject object)
378 {
379 const set<OperationObject> validOprnObjectet = {
380 OperationObject::FILESYSTEM_PHOTO,
381 OperationObject::FILESYSTEM_AUDIO
382 };
383 if (validOprnObjectet.find(object) == validOprnObjectet.end()) {
384 MEDIA_ERR_LOG("input OperationObject %{public}d error!", object);
385 return false;
386 }
387 return true;
388 }
389
GetOprnObjectByMediaType(int32_t type)390 static OperationObject GetOprnObjectByMediaType(int32_t type)
391 {
392 switch (type) {
393 case MediaType::MEDIA_TYPE_IMAGE:
394 case MediaType::MEDIA_TYPE_VIDEO: {
395 return OperationObject::FILESYSTEM_PHOTO;
396 }
397 case MediaType::MEDIA_TYPE_AUDIO: {
398 return OperationObject::FILESYSTEM_AUDIO;
399 }
400 case MediaType::MEDIA_TYPE_FILE: {
401 return OperationObject::FILESYSTEM_ASSET;
402 }
403 default: {
404 return OperationObject::UNKNOWN_OBJECT;
405 }
406 }
407 }
408
FetchFileAssetFromResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,const vector<string> & columns)409 static shared_ptr<FileAsset> FetchFileAssetFromResultSet(
410 const shared_ptr<NativeRdb::ResultSet> &resultSet, const vector<string> &columns)
411 {
412 int32_t count = 0;
413 int32_t currentRowIndex = 0;
414 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, nullptr, "resultSet is nullptr");
415 CHECK_AND_RETURN_RET_LOG(
416 resultSet->GetRowCount(count) == NativeRdb::E_OK, nullptr, "Cannot get row count of resultset");
417 CHECK_AND_RETURN_RET_LOG(
418 resultSet->GetRowIndex(currentRowIndex) == NativeRdb::E_OK, nullptr, "Cannot get row index of resultset");
419 CHECK_AND_RETURN_RET_LOG(currentRowIndex >= 0 && currentRowIndex < count, nullptr, "Invalid row index");
420
421 auto fileAsset = make_shared<FileAsset>();
422 auto &map = fileAsset->GetMemberMap();
423 for (const auto &column : columns) {
424 int32_t columnIndex = 0;
425 CHECK_AND_RETURN_RET_LOG(resultSet->GetColumnIndex(column, columnIndex) == NativeRdb::E_OK,
426 nullptr, "Can not get column %{private}s index", column.c_str());
427 CHECK_AND_RETURN_RET_LOG(FILEASSET_MEMBER_MAP.find(column) != FILEASSET_MEMBER_MAP.end(), nullptr,
428 "Can not find column %{private}s from member map", column.c_str());
429 switch (FILEASSET_MEMBER_MAP.at(column)) {
430 case MEMBER_TYPE_INT32: {
431 int32_t value = 0;
432 CHECK_AND_RETURN_RET_LOG(resultSet->GetInt(columnIndex, value) == NativeRdb::E_OK, nullptr,
433 "Can not get int value from column %{private}s", column.c_str());
434 map[column] = value;
435 break;
436 }
437 case MEMBER_TYPE_INT64: {
438 int64_t value = 0;
439 CHECK_AND_RETURN_RET_LOG(resultSet->GetLong(columnIndex, value) == NativeRdb::E_OK, nullptr,
440 "Can not get long value from column %{private}s", column.c_str());
441 map[column] = value;
442 break;
443 }
444 case MEMBER_TYPE_STRING: {
445 string value;
446 CHECK_AND_RETURN_RET_LOG(resultSet->GetString(columnIndex, value) == NativeRdb::E_OK, nullptr,
447 "Can not get string value from column %{private}s", column.c_str());
448 map[column] = value;
449 break;
450 }
451 case MEMBER_TYPE_DOUBLE: {
452 double value;
453 CHECK_AND_RETURN_RET_LOG(resultSet->GetDouble(columnIndex, value) == NativeRdb::E_OK, nullptr,
454 "Can not get double value from column %{private}s", column.c_str());
455 map[column] = value;
456 break;
457 }
458 }
459 }
460 return fileAsset;
461 }
462
GetAssetFromResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,const vector<string> & columns)463 shared_ptr<FileAsset> MediaLibraryAssetOperations::GetAssetFromResultSet(
464 const shared_ptr<NativeRdb::ResultSet> &resultSet, const vector<string> &columns)
465 {
466 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, nullptr, "resultSet is nullptr");
467 int32_t count = 0;
468 CHECK_AND_RETURN_RET_LOG(resultSet->GetRowCount(count) == NativeRdb::E_OK, nullptr,
469 "Cannot get row count of resultset");
470 CHECK_AND_RETURN_RET_LOG(count == 1, nullptr, "ResultSet count is %{public}d, not 1", count);
471 CHECK_AND_RETURN_RET_LOG(resultSet->GoToFirstRow() == NativeRdb::E_OK, nullptr, "Cannot go to first row");
472 return FetchFileAssetFromResultSet(resultSet, columns);
473 }
474
GetAssetVectorFromResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,const vector<string> & columns,vector<shared_ptr<FileAsset>> & fileAssetVector)475 static int32_t GetAssetVectorFromResultSet(const shared_ptr<NativeRdb::ResultSet> &resultSet,
476 const vector<string> &columns, vector<shared_ptr<FileAsset>> &fileAssetVector)
477 {
478 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "resultSet is nullptr");
479 int32_t count = 0;
480 CHECK_AND_RETURN_RET_LOG(resultSet->GetRowCount(count) == NativeRdb::E_OK, E_HAS_DB_ERROR,
481 "Cannot get row count of resultset");
482 CHECK_AND_RETURN_RET_LOG(count > 0, E_HAS_DB_ERROR, "ResultSet count is %{public}d", count);
483
484 fileAssetVector.reserve(count);
485 for (int32_t i = 0; i < count; i++) {
486 CHECK_AND_RETURN_RET_LOG(
487 resultSet->GoToNextRow() == NativeRdb::E_OK, E_HAS_DB_ERROR, "Failed to go to next row");
488 auto fileAsset = FetchFileAssetFromResultSet(resultSet, columns);
489 CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_HAS_DB_ERROR, "Failed to fetch fileAsset from resultSet");
490 fileAssetVector.push_back(fileAsset);
491 }
492 return E_OK;
493 }
494
GetAlbumVectorFromResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,const vector<string> & columns,vector<shared_ptr<PhotoAlbum>> & PhotoAlbumVector)495 static int32_t GetAlbumVectorFromResultSet(const shared_ptr<NativeRdb::ResultSet> &resultSet,
496 const vector<string> &columns, vector<shared_ptr<PhotoAlbum>> &PhotoAlbumVector)
497 {
498 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "resultSet is nullptr");
499 int32_t count = 0;
500 CHECK_AND_RETURN_RET_LOG(resultSet->GetRowCount(count) == NativeRdb::E_OK, E_HAS_DB_ERROR,
501 "Cannot get row count of resultset");
502 CHECK_AND_RETURN_RET_LOG(count > 0, E_HAS_DB_ERROR, "ResultSet count is %{public}d", count);
503
504 PhotoAlbumVector.reserve(count);
505 for (int32_t i = 0; i < count; i++) {
506 CHECK_AND_RETURN_RET_LOG(
507 resultSet->GoToNextRow() == NativeRdb::E_OK, E_HAS_DB_ERROR, "Failed to go to next row");
508
509 PhotoAlbumVector.push_back(make_shared<PhotoAlbum>());
510 PhotoAlbumVector.back()->SetPhotoAlbumType(
511 static_cast<PhotoAlbumType>(GetInt32Val(PhotoAlbumColumns::ALBUM_TYPE, resultSet)));
512 PhotoAlbumVector.back()->SetPhotoAlbumSubType(
513 static_cast<PhotoAlbumSubType>(GetInt32Val(PhotoAlbumColumns::ALBUM_SUBTYPE, resultSet)));
514 PhotoAlbumVector.back()->SetAlbumName(GetStringVal(PhotoAlbumColumns::ALBUM_NAME, resultSet));
515 PhotoAlbumVector.back()->SetDateModified(GetInt64Val(PhotoAlbumColumns::ALBUM_DATE_MODIFIED, resultSet));
516 PhotoAlbumVector.back()->SetContainsHidden(GetInt32Val(PhotoAlbumColumns::CONTAINS_HIDDEN, resultSet));
517 PhotoAlbumVector.back()->SetOrder(GetInt32Val(PhotoAlbumColumns::ALBUM_ORDER, resultSet));
518 PhotoAlbumVector.back()->SetBundleName(GetStringVal(PhotoAlbumColumns::ALBUM_BUNDLE_NAME, resultSet));
519 PhotoAlbumVector.back()->SetLocalLanguage(GetStringVal(PhotoAlbumColumns::ALBUM_LOCAL_LANGUAGE, resultSet));
520 PhotoAlbumVector.back()->SetDateAdded(GetInt64Val(PhotoAlbumColumns::ALBUM_DATE_ADDED, resultSet));
521 PhotoAlbumVector.back()->SetIsLocal(GetInt32Val(PhotoAlbumColumns::ALBUM_IS_LOCAL, resultSet));
522 PhotoAlbumVector.back()->SetLPath(GetStringVal(PhotoAlbumColumns::ALBUM_LPATH, resultSet));
523 PhotoAlbumVector.back()->SetPriority(GetInt32Val(PhotoAlbumColumns::ALBUM_PRIORITY, resultSet));
524 PhotoAlbumVector.back()->SetAlbumId(GetInt32Val(PhotoAlbumColumns::ALBUM_ID, resultSet));
525 }
526 return E_OK;
527 }
528
CheckExist(const std::string & path)529 int32_t MediaLibraryAssetOperations::CheckExist(const std::string &path)
530 {
531 RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
532 vector<string> columns = {MediaColumn::MEDIA_FILE_PATH};
533
534 MEDIA_DEBUG_LOG("query media_file_path=%{public}s start\n", DfxUtils::GetSafePath(path).c_str());
535 predicates.EqualTo(PhotoColumn::MEDIA_FILE_PATH, path);
536
537 auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
538 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "MediaLibraryPhotoOperations error\n");
539
540 int rowCount = 0;
541 if (resultSet->GetRowCount(rowCount) != NativeRdb::E_OK) {
542 MEDIA_ERR_LOG("GetRowCount error\n");
543 return E_HAS_DB_ERROR;
544 }
545
546 MEDIA_INFO_LOG("query media_file_path end, rowCount=%{public}d\n", rowCount);
547 return (rowCount > 0) ? E_OK : E_FAIL;
548 }
549
QueryPhotosTableColumnInfo()550 std::vector<std::string> MediaLibraryAssetOperations::QueryPhotosTableColumnInfo()
551 {
552 MEDIA_DEBUG_LOG("QueryPhotosTableColumnInfo");
553 std::vector<std::string> columnInfo;
554 std::shared_ptr<MediaLibraryRdbStore> rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
555 if (rdbStore == nullptr) {
556 MEDIA_ERR_LOG("rdbStore == nullptr");
557 return columnInfo;
558 }
559
560 std::string querySql = "SELECT name FROM pragma_table_info('" + PhotoColumn::PHOTOS_TABLE + "')";
561 std::vector<std::string> sqlArgs;
562 auto resultSet = rdbStore->QuerySql(querySql, sqlArgs);
563 if (resultSet == nullptr) {
564 MEDIA_ERR_LOG("resultSet is nullptr");
565 return columnInfo;
566 }
567
568 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
569 std::string columnName = GetStringVal("name", resultSet);
570 if (FILEASSET_MEMBER_MAP.count(columnName) == 0) {
571 MEDIA_WARN_LOG("FILEASSET_MEMBER_MAP not find column: %{public}s", columnName.c_str());
572 continue;
573 }
574 columnInfo.emplace_back(columnName);
575 }
576
577 return columnInfo;
578 }
579
QueryTotalPhoto(vector<shared_ptr<FileAsset>> & fileAssetVector,int32_t batchSize)580 int32_t MediaLibraryAssetOperations::QueryTotalPhoto(vector<shared_ptr<FileAsset>> &fileAssetVector,
581 int32_t batchSize)
582 {
583 MEDIA_INFO_LOG("query total photo start\n");
584 std::vector<std::string> columnInfo = QueryPhotosTableColumnInfo();
585 if (columnInfo.empty()) {
586 MEDIA_ERR_LOG("QueryPhotosTableColumnInfo failed");
587 return E_ERR;
588 }
589
590 RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
591 predicates.BeginWrap()->EqualTo(PhotoColumn::PHOTO_METADATA_FLAGS, static_cast<int>(MetadataFlags::TYPE_NEW))->Or()
592 ->EqualTo(PhotoColumn::PHOTO_METADATA_FLAGS, static_cast<int>(MetadataFlags::TYPE_DIRTY))->Or()
593 ->IsNull(PhotoColumn::PHOTO_METADATA_FLAGS)->EndWrap();
594 predicates.And()->BeginWrap()->EqualTo(PhotoColumn::PHOTO_POSITION, "1")->Or()
595 ->EqualTo(PhotoColumn::PHOTO_POSITION, "3")->EndWrap();
596 predicates.OrderByAsc(PhotoColumn::PHOTO_METADATA_FLAGS);
597 predicates.Limit(0, batchSize);
598 auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columnInfo);
599 if (resultSet == nullptr) {
600 MEDIA_ERR_LOG("MediaLibraryPhotoOperations error\n");
601 return E_OK;
602 }
603
604 GetAssetVectorFromResultSet(resultSet, columnInfo, fileAssetVector);
605
606 MEDIA_INFO_LOG("query total photo end\n");
607 return E_OK;
608 }
609
QuerySinglePhoto(int32_t rowId)610 std::shared_ptr<FileAsset> MediaLibraryAssetOperations::QuerySinglePhoto(int32_t rowId)
611 {
612 std::vector<std::string> columnInfo = QueryPhotosTableColumnInfo();
613 if (columnInfo.empty()) {
614 MEDIA_ERR_LOG("QueryPhotosTableColumnInfo failed");
615 return nullptr;
616 }
617
618 RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
619 predicates.EqualTo(MediaColumn::MEDIA_ID, rowId);
620 auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columnInfo);
621 if (resultSet == nullptr) {
622 MEDIA_ERR_LOG("MediaLibraryPhotoOperations error\n");
623 return nullptr;
624 }
625
626 return GetAssetFromResultSet(resultSet, columnInfo);
627 }
628
QueryTotalAlbum(vector<shared_ptr<PhotoAlbum>> & photoAlbumVector)629 int32_t MediaLibraryAssetOperations::QueryTotalAlbum(vector<shared_ptr<PhotoAlbum>> &photoAlbumVector)
630 {
631 RdbPredicates predicates(PhotoAlbumColumns::TABLE);
632 vector<string> columns = {PhotoAlbumColumns::ALBUM_ID,
633 PhotoAlbumColumns::ALBUM_TYPE, PhotoAlbumColumns::ALBUM_SUBTYPE,
634 PhotoAlbumColumns::ALBUM_NAME, PhotoAlbumColumns::ALBUM_DATE_MODIFIED,
635 PhotoAlbumColumns::CONTAINS_HIDDEN, PhotoAlbumColumns::ALBUM_ORDER,
636 PhotoAlbumColumns::ALBUM_BUNDLE_NAME, PhotoAlbumColumns::ALBUM_LOCAL_LANGUAGE,
637 PhotoAlbumColumns::ALBUM_IS_LOCAL, PhotoAlbumColumns::ALBUM_DATE_ADDED,
638 PhotoAlbumColumns::ALBUM_LPATH, PhotoAlbumColumns::ALBUM_PRIORITY};
639
640 MEDIA_INFO_LOG("Start query total photo album");
641 auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
642 if (resultSet == nullptr) {
643 MEDIA_ERR_LOG("Query failed, resultSet is null");
644 return E_INVALID_ARGUMENTS;
645 }
646
647 return GetAlbumVectorFromResultSet(resultSet, columns, photoAlbumVector);
648 }
649
GetFileAssetFromDb(const string & column,const string & value,OperationObject oprnObject,const vector<string> & columns,const string & networkId)650 shared_ptr<FileAsset> MediaLibraryAssetOperations::GetFileAssetFromDb(const string &column,
651 const string &value, OperationObject oprnObject, const vector<string> &columns, const string &networkId)
652 {
653 MediaLibraryTracer tracer;
654 tracer.Start("MediaLibraryAssetOperations::GetFileAssetFromDb");
655 if (!CheckOprnObject(oprnObject) || column.empty() || value.empty()) {
656 return nullptr;
657 }
658
659 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
660 if (rdbStore == nullptr) {
661 return nullptr;
662 }
663
664 MediaLibraryCommand cmd(oprnObject, OperationType::QUERY, networkId);
665 cmd.GetAbsRdbPredicates()->EqualTo(column, value);
666
667 auto resultSet = rdbStore->Query(cmd, columns);
668 if (resultSet == nullptr) {
669 return nullptr;
670 }
671 return GetAssetFromResultSet(resultSet, columns);
672 }
673
QueryByPredicates(AbsPredicates & predicates,OperationObject oprnObject,const vector<string> & columns,const string & networkId)674 static shared_ptr<NativeRdb::ResultSet> QueryByPredicates(AbsPredicates &predicates,
675 OperationObject oprnObject, const vector<string> &columns, const string &networkId)
676 {
677 if (!CheckOprnObject(oprnObject)) {
678 return nullptr;
679 }
680
681 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
682 if (rdbStore == nullptr) {
683 return nullptr;
684 }
685
686 MediaLibraryCommand cmd(oprnObject, OperationType::QUERY, networkId);
687 cmd.GetAbsRdbPredicates()->SetWhereClause(predicates.GetWhereClause());
688 cmd.GetAbsRdbPredicates()->SetWhereArgs(predicates.GetWhereArgs());
689 cmd.GetAbsRdbPredicates()->SetOrder(predicates.GetOrder());
690 return rdbStore->Query(cmd, columns);
691 }
692
GetFileAssetFromDb(AbsPredicates & predicates,OperationObject oprnObject,const vector<string> & columns,const string & networkId)693 shared_ptr<FileAsset> MediaLibraryAssetOperations::GetFileAssetFromDb(AbsPredicates &predicates,
694 OperationObject oprnObject, const vector<string> &columns, const string &networkId)
695 {
696 auto resultSet = QueryByPredicates(predicates, oprnObject, columns, networkId);
697 if (resultSet == nullptr) {
698 return nullptr;
699 }
700 return GetAssetFromResultSet(resultSet, columns);
701 }
702
GetFileAssetVectorFromDb(AbsPredicates & predicates,OperationObject oprnObject,vector<shared_ptr<FileAsset>> & fileAssetVector,const vector<string> & columns,const string & networkId)703 int32_t MediaLibraryAssetOperations::GetFileAssetVectorFromDb(AbsPredicates &predicates, OperationObject oprnObject,
704 vector<shared_ptr<FileAsset>> &fileAssetVector, const vector<string> &columns, const string &networkId)
705 {
706 auto resultSet = QueryByPredicates(predicates, oprnObject, columns, networkId);
707 if (resultSet == nullptr) {
708 return E_HAS_DB_ERROR;
709 }
710 return GetAssetVectorFromResultSet(resultSet, columns, fileAssetVector);
711 }
712
GetFileAssetByUri(const string & uri,bool isPhoto,const std::vector<std::string> & columns,const string & pendingStatus)713 shared_ptr<FileAsset> MediaLibraryAssetOperations::GetFileAssetByUri(const string &uri, bool isPhoto,
714 const std::vector<std::string> &columns, const string &pendingStatus)
715 {
716 if (uri.empty()) {
717 MEDIA_ERR_LOG("fileUri is empty");
718 return nullptr;
719 }
720
721 string id = MediaFileUtils::GetIdFromUri(uri);
722 if (uri.empty() || (!MediaLibraryDataManagerUtils::IsNumber(id))) {
723 return nullptr;
724 }
725 shared_ptr<FileAsset> fileAsset = make_shared<FileAsset>();
726 MediaFileUri fileUri(uri);
727 if (pendingStatus.empty() || !fileUri.IsApi10()) {
728 if (isPhoto) {
729 fileAsset = GetFileAssetFromDb(MediaColumn::MEDIA_ID, id, OperationObject::FILESYSTEM_PHOTO, columns);
730 } else {
731 fileAsset = GetFileAssetFromDb(MediaColumn::MEDIA_ID, id, OperationObject::FILESYSTEM_AUDIO, columns);
732 }
733 } else {
734 string path = MediaFileUri::GetPathFromUri(uri, isPhoto);
735 if (path.empty()) {
736 if (isPhoto) {
737 fileAsset = GetFileAssetFromDb(MediaColumn::MEDIA_ID, id, OperationObject::FILESYSTEM_PHOTO, columns);
738 } else {
739 fileAsset = GetFileAssetFromDb(MediaColumn::MEDIA_ID, id, OperationObject::FILESYSTEM_AUDIO, columns);
740 }
741 } else {
742 fileAsset->SetPath(path);
743 fileAsset->SetMediaType(MediaFileUtils::GetMediaType(path));
744 if (MediaFileUtils::IsValidInteger(pendingStatus)) {
745 int32_t timePending = stoi(pendingStatus);
746 fileAsset->SetTimePending((timePending > 0) ? MediaFileUtils::UTCTimeSeconds() : timePending);
747 }
748 }
749 }
750
751 if (fileAsset == nullptr) {
752 return nullptr;
753 }
754 if (!isPhoto) {
755 fileAsset->SetMediaType(MediaType::MEDIA_TYPE_AUDIO);
756 }
757 if (MediaFileUtils::IsValidInteger(id)) {
758 fileAsset->SetId(stoi(id));
759 }
760 fileAsset->SetUri(uri);
761 return fileAsset;
762 }
763
GetVirtualPath(const string & relativePath,const string & displayName)764 static inline string GetVirtualPath(const string &relativePath, const string &displayName)
765 {
766 if (relativePath[relativePath.size() - 1] != SLASH_CHAR) {
767 return relativePath + SLASH_CHAR + displayName;
768 } else {
769 return relativePath + displayName;
770 }
771 }
772
GetAssetPackageName(const FileAsset & fileAsset,const string & bundleName)773 static string GetAssetPackageName(const FileAsset &fileAsset, const string &bundleName)
774 {
775 if (fileAsset.GetPhotoSubType() == static_cast<int32_t>(PhotoSubType::SCREENSHOT)) {
776 if (fileAsset.GetMediaType() == static_cast<int32_t>(MediaType::MEDIA_TYPE_IMAGE) ||
777 fileAsset.GetMediaType() == static_cast<int32_t>(MediaType::MEDIA_TYPE_PHOTO)) {
778 return "截图";
779 } else if (fileAsset.GetMediaType() == static_cast<int32_t>(MediaType::MEDIA_TYPE_VIDEO)) {
780 return "屏幕录制";
781 }
782 }
783 return PermissionUtils::GetPackageNameByBundleName(bundleName);
784 }
785
HandleDateAdded(const int64_t dateAdded,const MediaType type,ValuesBucket & outValues)786 static void HandleDateAdded(const int64_t dateAdded, const MediaType type, ValuesBucket &outValues)
787 {
788 outValues.PutLong(MediaColumn::MEDIA_DATE_ADDED, dateAdded);
789 if (type != MEDIA_TYPE_PHOTO) {
790 return;
791 }
792 outValues.PutString(PhotoColumn::PHOTO_DATE_YEAR,
793 MediaFileUtils::StrCreateTimeByMilliseconds(PhotoColumn::PHOTO_DATE_YEAR_FORMAT, dateAdded));
794 outValues.PutString(PhotoColumn::PHOTO_DATE_MONTH,
795 MediaFileUtils::StrCreateTimeByMilliseconds(PhotoColumn::PHOTO_DATE_MONTH_FORMAT, dateAdded));
796 outValues.PutString(PhotoColumn::PHOTO_DATE_DAY,
797 MediaFileUtils::StrCreateTimeByMilliseconds(PhotoColumn::PHOTO_DATE_DAY_FORMAT, dateAdded));
798 outValues.PutLong(MediaColumn::MEDIA_DATE_TAKEN, dateAdded);
799 }
800
HandleOwnerAlbumId(MediaLibraryCommand & cmd,ValuesBucket & outValues)801 static void HandleOwnerAlbumId(MediaLibraryCommand &cmd, ValuesBucket &outValues)
802 {
803 string ownerAlbumId;
804 ValueObject valueOwnerAlbumId;
805 if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_OWNER_ALBUM_ID, valueOwnerAlbumId)) {
806 valueOwnerAlbumId.GetString(ownerAlbumId);
807 }
808 if (!ownerAlbumId.empty()) {
809 outValues.PutString(PhotoColumn::PHOTO_OWNER_ALBUM_ID, ownerAlbumId);
810 MEDIA_INFO_LOG("insert ownerAlbumId: %{public}s", ownerAlbumId.c_str());
811 }
812 }
813
HandleCallingPackage(MediaLibraryCommand & cmd,const FileAsset & fileAsset,ValuesBucket & outValues)814 static void HandleCallingPackage(MediaLibraryCommand &cmd, const FileAsset &fileAsset, ValuesBucket &outValues)
815 {
816 if (!fileAsset.GetOwnerPackage().empty() && PermissionUtils::IsNativeSAApp()) {
817 outValues.PutString(MediaColumn::MEDIA_OWNER_PACKAGE, fileAsset.GetOwnerPackage());
818
819 int32_t callingUid = 0;
820 ValueObject value;
821 if (cmd.GetValueBucket().GetObject(MEDIA_DATA_CALLING_UID, value)) {
822 value.GetInt(callingUid);
823 }
824 outValues.PutString(MediaColumn::MEDIA_OWNER_APPID,
825 PermissionUtils::GetAppIdByBundleName(fileAsset.GetOwnerPackage(), callingUid));
826 outValues.PutString(MediaColumn::MEDIA_PACKAGE_NAME, fileAsset.GetPackageName());
827 return;
828 }
829
830 string bundleName;
831 ValueObject valueBundleName;
832 if (cmd.GetValueBucket().GetObject(MEDIA_DATA_DB_OWNER_PACKAGE, valueBundleName)) {
833 valueBundleName.GetString(bundleName);
834 }
835 if (bundleName.empty()) {
836 bundleName = cmd.GetBundleName();
837 }
838 outValues.PutString(MediaColumn::MEDIA_OWNER_PACKAGE, bundleName);
839
840 string appId;
841 ValueObject valueAppId;
842 if (cmd.GetValueBucket().GetObject(MEDIA_DATA_DB_OWNER_APPID, valueAppId)) {
843 valueAppId.GetString(appId);
844 }
845 if (appId.empty()) {
846 appId = PermissionUtils::GetAppIdByBundleName(cmd.GetBundleName());
847 }
848 outValues.PutString(MediaColumn::MEDIA_OWNER_APPID, appId);
849 string packageName;
850 ValueObject valuePackageName;
851 if (cmd.GetValueBucket().GetObject(MEDIA_DATA_DB_PACKAGE_NAME, valuePackageName)) {
852 valuePackageName.GetString(packageName);
853 }
854 if (packageName.empty() && !cmd.GetBundleName().empty()) {
855 packageName = GetAssetPackageName(fileAsset, cmd.GetBundleName());
856 }
857 if (!packageName.empty()) {
858 outValues.PutString(MediaColumn::MEDIA_PACKAGE_NAME, packageName);
859 }
860 HandleOwnerAlbumId(cmd, outValues);
861 }
862
HandleBurstPhoto(MediaLibraryCommand & cmd,ValuesBucket & outValues,const std::string displayName)863 static void HandleBurstPhoto(MediaLibraryCommand &cmd, ValuesBucket &outValues, const std::string displayName)
864 {
865 CHECK_AND_RETURN_LOG(PermissionUtils::IsNativeSAApp(),
866 "do not have permission to set burst_key or burst_cover_level");
867
868 string burstKey;
869 ValueObject value;
870 if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_BURST_KEY, value)) {
871 value.GetString(burstKey);
872 }
873 if (!burstKey.empty()) {
874 outValues.PutString(PhotoColumn::PHOTO_BURST_KEY, burstKey);
875 }
876
877 int32_t burstCoverLevel = 0;
878 if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_BURST_COVER_LEVEL, value)) {
879 value.GetInt(burstCoverLevel);
880 }
881 if (burstCoverLevel != 0) {
882 outValues.PutInt(PhotoColumn::PHOTO_BURST_COVER_LEVEL, burstCoverLevel);
883 }
884
885 int32_t dirty = static_cast<int32_t>(DirtyTypes::TYPE_NEW);
886 if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_DIRTY, value)) {
887 value.GetInt(dirty);
888 }
889 if (dirty != static_cast<int32_t>(DirtyTypes::TYPE_NEW)) {
890 outValues.PutInt(PhotoColumn::PHOTO_DIRTY, dirty);
891 }
892 stringstream result;
893 for (size_t i = 0; i < displayName.length(); i++) {
894 if (isdigit(displayName[i])) {
895 result << displayName[i];
896 }
897 }
898 outValues.Put(PhotoColumn::PHOTO_ID, result.str());
899 outValues.PutInt(PhotoColumn::PHOTO_QUALITY, static_cast<int32_t>(MultiStagesPhotoQuality::FULL));
900 }
901
ExtractHandlePhotoInfo(MediaLibraryCommand & cmd,ValuesBucket & outValues,const FileAsset & fileAsset)902 static void ExtractHandlePhotoInfo(MediaLibraryCommand &cmd,
903 ValuesBucket &outValues, const FileAsset &fileAsset)
904 {
905 ValueObject value;
906
907 int32_t stageVideoTaskStatus = UNKNOWN_VALUE;
908 if (cmd.GetValueBucket().GetObject(PhotoColumn::STAGE_VIDEO_TASK_STATUS, value)) {
909 value.GetInt(stageVideoTaskStatus);
910 }
911 if (stageVideoTaskStatus != UNKNOWN_VALUE && \
912 fileAsset.GetPhotoSubType() == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
913 outValues.PutInt(PhotoColumn::STAGE_VIDEO_TASK_STATUS, stageVideoTaskStatus);
914 }
915 }
916
UpdateEnhanceParam(MediaLibraryCommand & cmd,ValuesBucket & outValues,ValueObject & value)917 static void UpdateEnhanceParam(MediaLibraryCommand &cmd, ValuesBucket &outValues, ValueObject &value)
918 {
919 int32_t ceAvailable = static_cast<int32_t>(CloudEnhancementAvailableType::NOT_SUPPORT);
920 if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_CE_AVAILABLE, value)) {
921 value.GetInt(ceAvailable);
922 MEDIA_INFO_LOG("set ce_available: %{public}d", ceAvailable);
923 }
924 outValues.PutInt(PhotoColumn::PHOTO_CE_AVAILABLE, ceAvailable);
925
926 int32_t isAuto = static_cast<int32_t>(CloudEnhancementIsAutoType::NOT_AUTO);
927 if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_IS_AUTO, value)) {
928 value.GetInt(isAuto);
929 MEDIA_INFO_LOG("set is_auto: %{public}d", isAuto);
930 }
931 outValues.PutInt(PhotoColumn::PHOTO_IS_AUTO, isAuto);
932 }
933
HandlePhotoInfo(MediaLibraryCommand & cmd,ValuesBucket & outValues,const FileAsset & fileAsset)934 static void HandlePhotoInfo(MediaLibraryCommand &cmd, ValuesBucket &outValues, const FileAsset &fileAsset)
935 {
936 if (!PermissionUtils::IsNativeSAApp()) {
937 MEDIA_DEBUG_LOG("do not have permission to set is_temp");
938 return;
939 }
940
941 ValueObject value;
942 bool isTemp = 0;
943 if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_IS_TEMP, value)) {
944 value.GetBool(isTemp);
945 }
946 outValues.PutBool(PhotoColumn::PHOTO_IS_TEMP, isTemp);
947
948 int32_t deferredProcType = UNKNOWN_VALUE;
949 if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_DEFERRED_PROC_TYPE, value)) {
950 value.GetInt(deferredProcType);
951 }
952 if (deferredProcType != UNKNOWN_VALUE) {
953 outValues.PutInt(PhotoColumn::PHOTO_DEFERRED_PROC_TYPE, deferredProcType);
954 }
955
956 // quality、photoId、dirty for burst has been handled in HandleBurstPhoto
957 if (fileAsset.GetPhotoSubType() == static_cast<int32_t>(PhotoSubType::BURST)) {
958 return;
959 }
960
961 int32_t photoQuality = UNKNOWN_VALUE;
962 if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_QUALITY, value)) {
963 value.GetInt(photoQuality);
964 }
965 if (photoQuality != UNKNOWN_VALUE) {
966 outValues.PutInt(PhotoColumn::PHOTO_QUALITY, photoQuality);
967 }
968 if (photoQuality == static_cast<int32_t>(MultiStagesPhotoQuality::LOW)) {
969 outValues.PutInt(PhotoColumn::PHOTO_DIRTY, -1); // prevent uploading low-quality photo
970 }
971
972 std::string photoId;
973 if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_ID, value)) {
974 value.GetString(photoId);
975 }
976 if (!photoId.empty()) {
977 outValues.PutString(PhotoColumn::PHOTO_ID, photoId);
978 }
979
980 UpdateEnhanceParam(cmd, outValues, value);
981
982 ExtractHandlePhotoInfo(cmd, outValues, fileAsset);
983 }
984
FillAssetInfo(MediaLibraryCommand & cmd,const FileAsset & fileAsset)985 static void FillAssetInfo(MediaLibraryCommand &cmd, const FileAsset &fileAsset)
986 {
987 // Fill basic file information into DB
988 const string& displayName = fileAsset.GetDisplayName();
989 int64_t nowTime = MediaFileUtils::UTCTimeMilliSeconds();
990 ValuesBucket assetInfo;
991 assetInfo.PutInt(MediaColumn::MEDIA_TYPE, fileAsset.GetMediaType());
992 string extension = ScannerUtils::GetFileExtension(displayName);
993 assetInfo.PutString(MediaColumn::MEDIA_MIME_TYPE,
994 MimeTypeUtils::GetMimeTypeFromExtension(extension));
995 assetInfo.PutString(MediaColumn::MEDIA_FILE_PATH, fileAsset.GetPath());
996 if (cmd.GetApi() == MediaLibraryApi::API_OLD) {
997 assetInfo.PutString(MediaColumn::MEDIA_RELATIVE_PATH, fileAsset.GetRelativePath());
998 assetInfo.PutString(MediaColumn::MEDIA_VIRTURL_PATH,
999 GetVirtualPath(fileAsset.GetRelativePath(), fileAsset.GetDisplayName()));
1000 } else {
1001 assetInfo.PutLong(MediaColumn::MEDIA_TIME_PENDING, fileAsset.GetTimePending());
1002 }
1003 assetInfo.PutString(MediaColumn::MEDIA_NAME, displayName);
1004 assetInfo.PutString(MediaColumn::MEDIA_TITLE, MediaFileUtils::GetTitleFromDisplayName(displayName));
1005 if (cmd.GetOprnObject() == OperationObject::FILESYSTEM_PHOTO) {
1006 assetInfo.PutString(PhotoColumn::PHOTO_MEDIA_SUFFIX, extension);
1007 assetInfo.PutInt(PhotoColumn::PHOTO_SUBTYPE, fileAsset.GetPhotoSubType());
1008 assetInfo.PutString(PhotoColumn::CAMERA_SHOT_KEY, fileAsset.GetCameraShotKey());
1009 HandlePhotoInfo(cmd, assetInfo, fileAsset);
1010 if (fileAsset.GetPhotoSubType() == static_cast<int32_t>(PhotoSubType::BURST)) {
1011 HandleBurstPhoto(cmd, assetInfo, displayName);
1012 }
1013 }
1014
1015 HandleCallingPackage(cmd, fileAsset, assetInfo);
1016
1017 assetInfo.PutString(MediaColumn::MEDIA_DEVICE_NAME, cmd.GetDeviceName());
1018 HandleDateAdded(nowTime,
1019 cmd.GetOprnObject() == OperationObject::FILESYSTEM_PHOTO ? MEDIA_TYPE_PHOTO : MEDIA_TYPE_DEFAULT,
1020 assetInfo);
1021 cmd.SetValueBucket(assetInfo);
1022 }
1023
GetOwnerPermissionBucket(MediaLibraryCommand & cmd,int64_t fileId,int32_t callingUid)1024 static ValuesBucket GetOwnerPermissionBucket(MediaLibraryCommand &cmd, int64_t fileId, int32_t callingUid)
1025 {
1026 int64_t tokenId = 0;
1027 string tokenIdFromClient = cmd.GetQuerySetParam("tokenId");
1028 tokenId = static_cast<int64_t>(std::atoi(tokenIdFromClient.c_str()));
1029 if (tokenId == 0) {
1030 if (callingUid > 0 && PermissionUtils::IsNativeSAApp()) {
1031 string bundleName;
1032 PermissionUtils::GetClientBundle(callingUid, bundleName);
1033 string appId = PermissionUtils::GetAppIdByBundleName(bundleName, callingUid);
1034 PermissionUtils::GetMainTokenId(appId, tokenId);
1035 }
1036 }
1037 if (tokenId == 0) {
1038 tokenId = PermissionUtils::GetTokenId();
1039 }
1040 string tableName = cmd.GetTableName();
1041 TableType mediaType;
1042 if (tableName == PhotoColumn::PHOTOS_TABLE) {
1043 mediaType = TableType::TYPE_PHOTOS;
1044 } else {
1045 mediaType = TableType::TYPE_AUDIOS;
1046 }
1047 ValuesBucket valuesBucket;
1048 valuesBucket.Put(AppUriPermissionColumn::FILE_ID, static_cast<int32_t>(fileId));
1049 valuesBucket.Put(AppUriPermissionColumn::URI_TYPE, static_cast<int32_t>(mediaType));
1050 valuesBucket.Put(AppUriPermissionColumn::PERMISSION_TYPE,
1051 AppUriPermissionColumn::PERMISSION_PERSIST_READ_WRITE);
1052 valuesBucket.Put(AppUriPermissionColumn::TARGET_TOKENID, (int64_t)tokenId);
1053 valuesBucket.Put(AppUriPermissionColumn::SOURCE_TOKENID, (int64_t)tokenId);
1054 valuesBucket.Put(AppUriPermissionColumn::DATE_MODIFIED, MediaFileUtils::UTCTimeMilliSeconds());
1055 return valuesBucket;
1056 }
1057
InsertAssetInDb(std::shared_ptr<TransactionOperations> trans,MediaLibraryCommand & cmd,const FileAsset & fileAsset)1058 int32_t MediaLibraryAssetOperations::InsertAssetInDb(std::shared_ptr<TransactionOperations> trans,
1059 MediaLibraryCommand &cmd, const FileAsset &fileAsset)
1060 {
1061 // All values inserted in this function are the base property for files
1062 if (trans == nullptr) {
1063 return E_HAS_DB_ERROR;
1064 }
1065
1066 if (!fileAsset.GetPath().empty() && MediaFileUtils::IsFileExists(fileAsset.GetPath())) {
1067 MEDIA_ERR_LOG("file %{private}s exists now", fileAsset.GetPath().c_str());
1068 return E_FILE_EXIST;
1069 }
1070 int32_t callingUid = 0;
1071 ValueObject value;
1072 if (cmd.GetValueBucket().GetObject(MEDIA_DATA_CALLING_UID, value)) {
1073 value.GetInt(callingUid);
1074 }
1075 FillAssetInfo(cmd, fileAsset);
1076
1077 int64_t outRowId = -1;
1078 int32_t errCode = trans->Insert(cmd, outRowId);
1079 if (errCode != NativeRdb::E_OK) {
1080 MEDIA_ERR_LOG("Insert into db failed, errCode = %{public}d", errCode);
1081 return E_HAS_DB_ERROR;
1082 }
1083 MEDIA_INFO_LOG("insert success, rowId = %{public}d", (int)outRowId);
1084 auto fileId = outRowId;
1085 ValuesBucket valuesBucket = GetOwnerPermissionBucket(cmd, fileId, callingUid);
1086 int64_t tmpOutRowId = -1;
1087 MediaLibraryCommand cmdPermission(Uri(MEDIALIBRARY_GRANT_URIPERM_URI), valuesBucket);
1088 errCode = trans->Insert(cmdPermission, tmpOutRowId);
1089 if (errCode != NativeRdb::E_OK) {
1090 MEDIA_ERR_LOG("Insert into db failed, errCode = %{public}d", errCode);
1091 return E_HAS_DB_ERROR;
1092 }
1093 MEDIA_INFO_LOG("insert uripermission success, rowId = %{public}d", (int)tmpOutRowId);
1094 return static_cast<int32_t>(outRowId);
1095 }
1096
CheckTypeFromRootDir(const std::string & rootDirName,int32_t type)1097 static bool CheckTypeFromRootDir(const std::string &rootDirName, int32_t type)
1098 {
1099 // "Camera/"
1100 if (!strcmp(rootDirName.c_str(), CAMERA_DIR_VALUES.c_str())) {
1101 if (type == MEDIA_TYPE_IMAGE || type == MEDIA_TYPE_VIDEO) {
1102 return true;
1103 }
1104 }
1105 // "Videos/"
1106 if (!strcmp(rootDirName.c_str(), VIDEO_DIR_VALUES.c_str())) {
1107 if (type == MEDIA_TYPE_VIDEO) {
1108 return true;
1109 }
1110 }
1111 // "Pictures/"
1112 if (!strcmp(rootDirName.c_str(), PIC_DIR_VALUES.c_str())) {
1113 if (type == MEDIA_TYPE_IMAGE) {
1114 return true;
1115 }
1116 }
1117 // "Audios/"
1118 if (!strcmp(rootDirName.c_str(), AUDIO_DIR_VALUES.c_str())) {
1119 if (type == MEDIA_TYPE_AUDIO) {
1120 return true;
1121 }
1122 }
1123 // "Docs/Documents/" and "Docs/Download"
1124 if (!strcmp(rootDirName.c_str(), DOCS_PATH.c_str())) {
1125 return true;
1126 }
1127 MEDIA_ERR_LOG("Cannot match rootDir %{private}s and mediaType %{public}d",
1128 rootDirName.c_str(), type);
1129 return false;
1130 }
1131
CheckWithType(bool isContains,const string & displayName,const string & extention,int32_t mediaType)1132 int32_t MediaLibraryAssetOperations::CheckWithType(bool isContains, const string &displayName,
1133 const string &extention, int32_t mediaType)
1134 {
1135 string name = isContains ? displayName : extention;
1136 int32_t errCode = isContains ? CheckDisplayNameWithType(name, mediaType) : CheckExtWithType(name, mediaType);
1137 CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode,
1138 "Failed to Check Dir and extention, (displayName or extention)=%{private}s, mediaType=%{public}d",
1139 name.c_str(), mediaType);
1140 return errCode;
1141 }
1142
CheckDisplayNameWithType(const string & displayName,int32_t mediaType)1143 int32_t MediaLibraryAssetOperations::CheckDisplayNameWithType(const string &displayName, int32_t mediaType)
1144 {
1145 int32_t ret = MediaFileUtils::CheckDisplayName(displayName);
1146 CHECK_AND_RETURN_RET_LOG(ret == E_OK, E_INVALID_DISPLAY_NAME, "Check DisplayName failed, "
1147 "displayName=%{private}s", displayName.c_str());
1148
1149 string ext = MediaFileUtils::GetExtensionFromPath(displayName);
1150 CHECK_AND_RETURN_RET_LOG(!ext.empty(), E_INVALID_DISPLAY_NAME, "invalid extension, displayName=%{private}s",
1151 displayName.c_str());
1152
1153 auto typeFromExt = MediaFileUtils::GetMediaType(displayName);
1154 CHECK_AND_RETURN_RET_LOG(typeFromExt == mediaType, E_CHECK_MEDIATYPE_MATCH_EXTENSION_FAIL,
1155 "cannot match, mediaType=%{public}d, ext=%{private}s, type from ext=%{public}d",
1156 mediaType, ext.c_str(), typeFromExt);
1157 return E_OK;
1158 }
1159
CheckExtWithType(const string & extention,int32_t mediaType)1160 int32_t MediaLibraryAssetOperations::CheckExtWithType(const string &extention, int32_t mediaType)
1161 {
1162 string mimeType = MimeTypeUtils::GetMimeTypeFromExtension(extention);
1163 auto typeFromExt = MimeTypeUtils::GetMediaTypeFromMimeType(mimeType);
1164 CHECK_AND_RETURN_RET_LOG(typeFromExt == mediaType, E_CHECK_MEDIATYPE_MATCH_EXTENSION_FAIL,
1165 "cannot match, mediaType=%{public}d, ext=%{public}s, type from ext=%{public}d",
1166 mediaType, extention.c_str(), typeFromExt);
1167 return E_OK;
1168 }
1169
CheckRelativePathWithType(const string & relativePath,int32_t mediaType)1170 int32_t MediaLibraryAssetOperations::CheckRelativePathWithType(const string &relativePath, int32_t mediaType)
1171 {
1172 int32_t ret = MediaFileUtils::CheckRelativePath(relativePath);
1173 CHECK_AND_RETURN_RET_LOG(ret == E_OK, E_INVALID_PATH, "Check relativePath failed, "
1174 "relativePath=%{private}s", relativePath.c_str());
1175
1176 // get rootdir and check if it match mediatype
1177 string rootDirName;
1178 MediaFileUtils::GetRootDirFromRelativePath(relativePath, rootDirName);
1179 CHECK_AND_RETURN_RET_LOG(!rootDirName.empty(), E_INVALID_PATH, "Cannot get rootdirName");
1180
1181 bool isValid = CheckTypeFromRootDir(rootDirName, mediaType);
1182 CHECK_AND_RETURN_RET(isValid, E_CHECK_MEDIATYPE_FAIL);
1183 return E_OK;
1184 }
1185
GetAssetRootDir(int32_t mediaType,string & rootDirPath)1186 void MediaLibraryAssetOperations::GetAssetRootDir(int32_t mediaType, string &rootDirPath)
1187 {
1188 map<int, string> rootDir = {
1189 { MEDIA_TYPE_FILE, DOCUMENT_BUCKET + SLASH_CHAR },
1190 { MEDIA_TYPE_VIDEO, PHOTO_BUCKET + SLASH_CHAR },
1191 { MEDIA_TYPE_IMAGE, PHOTO_BUCKET + SLASH_CHAR },
1192 { MEDIA_TYPE_AUDIO, AUDIO_BUCKET + SLASH_CHAR },
1193 };
1194 if (rootDir.count(mediaType) == 0) {
1195 rootDirPath = rootDir[MEDIA_TYPE_FILE];
1196 } else {
1197 rootDirPath = rootDir[mediaType];
1198 }
1199 }
1200
SetAssetPathInCreate(FileAsset & fileAsset,std::shared_ptr<TransactionOperations> trans)1201 int32_t MediaLibraryAssetOperations::SetAssetPathInCreate(FileAsset &fileAsset,
1202 std::shared_ptr<TransactionOperations> trans)
1203 {
1204 if (!fileAsset.GetPath().empty()) {
1205 return E_OK;
1206 }
1207 string extension = MediaFileUtils::GetExtensionFromPath(fileAsset.GetDisplayName());
1208 string filePath;
1209 int32_t uniqueId = CreateAssetUniqueId(fileAsset.GetMediaType(), trans);
1210 int32_t errCode = CreateAssetPathById(uniqueId, fileAsset.GetMediaType(), extension, filePath);
1211 if (errCode != E_OK) {
1212 MEDIA_ERR_LOG("Create Asset Path failed, errCode=%{public}d", errCode);
1213 return errCode;
1214 }
1215
1216 // filePath can not be empty
1217 fileAsset.SetPath(filePath);
1218 return E_OK;
1219 }
1220
SetAssetPath(FileAsset & fileAsset,const string & extension,std::shared_ptr<TransactionOperations> trans)1221 int32_t MediaLibraryAssetOperations::SetAssetPath(FileAsset &fileAsset, const string &extension,
1222 std::shared_ptr<TransactionOperations> trans)
1223 {
1224 string filePath;
1225 int32_t uniqueId = CreateAssetUniqueId(fileAsset.GetMediaType(), trans);
1226 int32_t errCode = CreateAssetPathById(uniqueId, fileAsset.GetMediaType(), extension, filePath);
1227 if (errCode != E_OK) {
1228 MEDIA_ERR_LOG("Create Asset Path failed, errCode=%{public}d", errCode);
1229 return errCode;
1230 }
1231
1232 // filePath can not be empty
1233 fileAsset.SetPath(filePath);
1234 string fileName = MediaFileUtils::GetFileName(filePath);
1235 string displayName = fileName.substr(0, fileName.find('_')) + '_' + fileName.substr(fileName.rfind('_') + 1);
1236 fileAsset.SetDisplayName(displayName);
1237 return E_OK;
1238 }
1239
DeleteAssetInDb(MediaLibraryCommand & cmd,std::shared_ptr<AccurateRefresh::AssetAccurateRefresh> assetRefresh)1240 int32_t MediaLibraryAssetOperations::DeleteAssetInDb(MediaLibraryCommand &cmd,
1241 std::shared_ptr<AccurateRefresh::AssetAccurateRefresh> assetRefresh)
1242 {
1243 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1244 if (rdbStore == nullptr) {
1245 return E_HAS_DB_ERROR;
1246 }
1247
1248 string strDeleteCondition = cmd.GetAbsRdbPredicates()->GetWhereClause();
1249 if (strDeleteCondition.empty()) {
1250 string strRow = cmd.GetOprnFileId();
1251 if (strRow.empty() || !MediaLibraryDataManagerUtils::IsNumber(strRow)) {
1252 MEDIA_ERR_LOG("MediaLibraryAssetOperations DeleteFile: Index not digit, fileIdStr=%{private}s",
1253 strRow.c_str());
1254 return E_INVALID_FILEID;
1255 }
1256 cmd.GetAbsRdbPredicates()->EqualTo(MediaColumn::MEDIA_ID, strRow);
1257 }
1258
1259 int32_t deletedRows = E_HAS_DB_ERROR;
1260 int32_t result = -1;
1261 if (assetRefresh == nullptr) {
1262 result = rdbStore->Delete(cmd, deletedRows);
1263 } else {
1264 result = assetRefresh->LogicalDeleteReplaceByUpdate(cmd, deletedRows);
1265 }
1266 if (result != NativeRdb::E_OK) {
1267 MEDIA_ERR_LOG("Delete operation failed. Result %{public}d.", result);
1268 }
1269
1270 return deletedRows;
1271 }
1272
UpdateFileName(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,bool & isNameChanged)1273 int32_t MediaLibraryAssetOperations::UpdateFileName(MediaLibraryCommand &cmd,
1274 const shared_ptr<FileAsset> &fileAsset, bool &isNameChanged)
1275 {
1276 ValuesBucket &values = cmd.GetValueBucket();
1277 ValueObject valueObject;
1278 string newTitle;
1279 string newDisplayName;
1280 bool containsTitle = false;
1281 bool containsDisplayName = false;
1282
1283 if (values.GetObject(MediaColumn::MEDIA_TITLE, valueObject)) {
1284 valueObject.GetString(newTitle);
1285 containsTitle = true;
1286 }
1287 if (values.GetObject(MediaColumn::MEDIA_NAME, valueObject)) {
1288 valueObject.GetString(newDisplayName);
1289 containsDisplayName = true;
1290 }
1291 if ((!containsTitle) && (!containsDisplayName)) {
1292 // do not need to update
1293 return E_OK;
1294 }
1295 if (containsTitle && containsDisplayName &&
1296 (MediaFileUtils::GetTitleFromDisplayName(newDisplayName) != newTitle)) {
1297 MEDIA_ERR_LOG("new displayName [%{private}s] and new title [%{private}s] is not same",
1298 newDisplayName.c_str(), newTitle.c_str());
1299 return E_INVALID_DISPLAY_NAME;
1300 }
1301 if (!containsTitle) {
1302 newTitle = MediaFileUtils::GetTitleFromDisplayName(newDisplayName);
1303 }
1304 if (!containsDisplayName) {
1305 newDisplayName = newTitle + "." + MediaFileUtils::SplitByChar(fileAsset->GetDisplayName(), '.');
1306 }
1307
1308 int32_t ret = CheckDisplayNameWithType(newDisplayName, fileAsset->GetMediaType());
1309 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "Input displayName invalid %{private}s", newDisplayName.c_str());
1310 values.PutString(MediaColumn::MEDIA_TITLE, newTitle);
1311 values.PutString(MediaColumn::MEDIA_NAME, newDisplayName);
1312 if (cmd.GetTableName() == PhotoColumn::PHOTOS_TABLE) {
1313 values.PutString(PhotoColumn::PHOTO_MEDIA_SUFFIX, ScannerUtils::GetFileExtension(newDisplayName));
1314 }
1315 isNameChanged = true;
1316 return E_OK;
1317 }
1318
SetUserComment(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset)1319 int32_t MediaLibraryAssetOperations::SetUserComment(MediaLibraryCommand &cmd,
1320 const shared_ptr<FileAsset> &fileAsset)
1321 {
1322 ValuesBucket &values = cmd.GetValueBucket();
1323 ValueObject valueObject;
1324 string newUserComment;
1325
1326 if (values.GetObject(PhotoColumn::PHOTO_USER_COMMENT, valueObject)) {
1327 valueObject.GetString(newUserComment);
1328 } else {
1329 return E_OK;
1330 }
1331
1332 uint32_t err = 0;
1333 SourceOptions opts;
1334 string filePath = fileAsset->GetFilePath();
1335 string extension = MediaFileUtils::GetExtensionFromPath(filePath);
1336 opts.formatHint = "image/" + extension;
1337 std::unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(filePath, opts, err);
1338 bool cond = (err != 0 || imageSource == nullptr);
1339 CHECK_AND_RETURN_RET_LOG(!cond, E_OK, "Failed to obtain image source, err = %{public}d", err);
1340
1341 string userComment;
1342 err = imageSource->GetImagePropertyString(0, PHOTO_DATA_IMAGE_USER_COMMENT, userComment);
1343 CHECK_AND_RETURN_RET_LOG(err == 0, E_OK, "Image does not exist user comment in exif, no need to modify");
1344 err = imageSource->ModifyImageProperty(0, PHOTO_DATA_IMAGE_USER_COMMENT, newUserComment, filePath);
1345 CHECK_AND_PRINT_LOG(err == 0, "Modify image property user comment failed");
1346 return E_OK;
1347 }
1348
UpdateRelativePath(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,bool & isNameChanged)1349 int32_t MediaLibraryAssetOperations::UpdateRelativePath(MediaLibraryCommand &cmd,
1350 const shared_ptr<FileAsset> &fileAsset, bool &isNameChanged)
1351 {
1352 string newRelativePath;
1353 ValuesBucket &values = cmd.GetValueBucket();
1354 ValueObject valueObject;
1355 if (values.GetObject(MediaColumn::MEDIA_RELATIVE_PATH, valueObject)) {
1356 valueObject.GetString(newRelativePath);
1357 } else {
1358 // relativePath is not modified
1359 return E_OK;
1360 }
1361 MediaFileUtils::FormatRelativePath(newRelativePath);
1362
1363 if (newRelativePath == fileAsset->GetRelativePath()) {
1364 // relativepath has not been modified
1365 return E_OK;
1366 }
1367
1368 int32_t errCode = CheckRelativePathWithType(newRelativePath, fileAsset->GetMediaType());
1369 if (errCode != E_SUCCESS) {
1370 MEDIA_ERR_LOG("Check RelativePath failed");
1371 return errCode;
1372 }
1373 values.Delete(MediaColumn::MEDIA_RELATIVE_PATH);
1374 values.PutString(MediaColumn::MEDIA_RELATIVE_PATH, newRelativePath);
1375
1376 isNameChanged = true;
1377 return E_OK;
1378 }
1379
UpdateVirtualPath(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset)1380 void MediaLibraryAssetOperations::UpdateVirtualPath(MediaLibraryCommand &cmd,
1381 const shared_ptr<FileAsset> &fileAsset)
1382 {
1383 string relativePath;
1384 string displayName;
1385 ValuesBucket &values = cmd.GetValueBucket();
1386 ValueObject valueObject;
1387
1388 if (values.GetObject(MediaColumn::MEDIA_NAME, valueObject)) {
1389 valueObject.GetString(displayName);
1390 } else {
1391 displayName = fileAsset->GetDisplayName();
1392 }
1393
1394 if (values.GetObject(MediaColumn::MEDIA_RELATIVE_PATH, valueObject)) {
1395 valueObject.GetString(relativePath);
1396 } else {
1397 relativePath = fileAsset->GetRelativePath();
1398 }
1399
1400 if (relativePath.back() != '/') {
1401 relativePath += '/';
1402 }
1403 string virtualPath = relativePath + displayName;
1404 values.PutString(MediaColumn::MEDIA_VIRTURL_PATH, virtualPath);
1405 }
1406
UpdateFileInDb(MediaLibraryCommand & cmd)1407 int32_t MediaLibraryAssetOperations::UpdateFileInDb(MediaLibraryCommand &cmd)
1408 {
1409 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1410 if (rdbStore == nullptr) {
1411 return E_HAS_DB_ERROR;
1412 }
1413
1414 int32_t updateRows = 0;
1415 int32_t result = rdbStore->Update(cmd, updateRows);
1416 if (result != NativeRdb::E_OK || updateRows <= 0) {
1417 MEDIA_ERR_LOG("Update File failed. Result %{public}d.", result);
1418 return E_HAS_DB_ERROR;
1419 }
1420
1421 return updateRows;
1422 }
1423
OpenFileWithPrivacy(const string & filePath,const string & mode,const string & fileId,int32_t type)1424 int32_t MediaLibraryAssetOperations::OpenFileWithPrivacy(const string &filePath, const string &mode,
1425 const string &fileId, int32_t type)
1426 {
1427 std::string absFilePath;
1428 if (!PathToRealPath(filePath, absFilePath)) {
1429 MEDIA_ERR_LOG("Failed to get real path: %{public}s", DfxUtils::GetSafePath(filePath).c_str());
1430 return E_ERR;
1431 }
1432 MEDIA_DEBUG_LOG("Open with privacy type:%{public}d", type);
1433 return MediaPrivacyManager(absFilePath, mode, fileId, type).Open();
1434 }
1435
SetPendingTime(const shared_ptr<FileAsset> & fileAsset,int64_t pendingTime)1436 static int32_t SetPendingTime(const shared_ptr<FileAsset> &fileAsset, int64_t pendingTime)
1437 {
1438 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1439 if (rdbStore == nullptr) {
1440 return E_HAS_DB_ERROR;
1441 }
1442
1443 MediaLibraryCommand updatePendingCmd(GetOprnObjectByMediaType(fileAsset->GetMediaType()),
1444 OperationType::UPDATE);
1445 updatePendingCmd.GetAbsRdbPredicates()->EqualTo(MediaColumn::MEDIA_ID,
1446 to_string(fileAsset->GetId()));
1447 ValuesBucket values;
1448 values.PutLong(MediaColumn::MEDIA_TIME_PENDING, pendingTime);
1449 updatePendingCmd.SetValueBucket(values);
1450 int32_t rowId = 0;
1451 int32_t result = rdbStore->Update(updatePendingCmd, rowId);
1452 if (result != NativeRdb::E_OK || rowId <= 0) {
1453 MEDIA_ERR_LOG("Update File pending failed. Result %{public}d.", result);
1454 return E_HAS_DB_ERROR;
1455 }
1456 return E_OK;
1457 }
1458
CreateFileAndSetPending(const shared_ptr<FileAsset> & fileAsset,int64_t pendingTime)1459 static int32_t CreateFileAndSetPending(const shared_ptr<FileAsset> &fileAsset, int64_t pendingTime)
1460 {
1461 int32_t errCode = MediaFileUtils::CreateAsset(fileAsset->GetPath());
1462 if (errCode != E_OK) {
1463 MEDIA_ERR_LOG("Create asset failed, path=%{private}s", fileAsset->GetPath().c_str());
1464 return errCode;
1465 }
1466
1467 return SetPendingTime(fileAsset, pendingTime);
1468 }
1469
SolvePendingStatus(const shared_ptr<FileAsset> & fileAsset,const string & mode)1470 static int32_t SolvePendingStatus(const shared_ptr<FileAsset> &fileAsset, const string &mode)
1471 {
1472 int64_t pendingTime = fileAsset->GetTimePending();
1473 if (pendingTime != 0) {
1474 if (mode == MEDIA_FILEMODE_READONLY) {
1475 MEDIA_ERR_LOG("FileAsset [%{private}s] pending status is %{public}ld and open mode is READ_ONLY",
1476 fileAsset->GetUri().c_str(), (long) pendingTime);
1477 return E_IS_PENDING_ERROR;
1478 }
1479 string networkId = MediaFileUtils::GetNetworkIdFromUri(fileAsset->GetUri());
1480 if (!networkId.empty()) {
1481 MEDIA_ERR_LOG("Can not open remote [%{private}s] pending file", networkId.c_str());
1482 return E_IS_PENDING_ERROR;
1483 }
1484 if (pendingTime == UNCREATE_FILE_TIMEPENDING) {
1485 int32_t errCode = CreateFileAndSetPending(fileAsset, UNCLOSE_FILE_TIMEPENDING);
1486 return errCode;
1487 }
1488 if (pendingTime == UNOPEN_FILE_COMPONENT_TIMEPENDING) {
1489 int32_t errCode = SetPendingTime(fileAsset, UNCLOSE_FILE_TIMEPENDING);
1490 return errCode;
1491 }
1492 }
1493 return E_OK;
1494 }
1495
CreateDirectoryAndAsset(const string path)1496 static int32_t CreateDirectoryAndAsset(const string path)
1497 {
1498 string dir = MediaFileUtils::GetParentPath(path);
1499 if (!MediaFileUtils::CreateDirectory(dir)) {
1500 MEDIA_ERR_LOG("Create dir failed, dir=%{private}s", dir.c_str());
1501 return E_INVALID_VALUES;
1502 }
1503 int32_t errCode = MediaFileUtils::CreateAsset(path);
1504 if (errCode != E_OK) {
1505 MEDIA_ERR_LOG("Create asset failed, path=%{private}s", path.c_str());
1506 return errCode;
1507 }
1508 return E_OK;
1509 }
1510
SolveMovingPhotoVideoCreation(const string & imagePath,const string & mode,bool isMovingPhotoVideo)1511 static int32_t SolveMovingPhotoVideoCreation(const string &imagePath, const string &mode, bool isMovingPhotoVideo)
1512 {
1513 if (mode == MEDIA_FILEMODE_READONLY || !isMovingPhotoVideo) {
1514 return E_OK;
1515 }
1516 string videoPath = MediaFileUtils::GetMovingPhotoVideoPath(imagePath);
1517 if (MediaFileUtils::IsFileExists(videoPath)) {
1518 return E_OK;
1519 }
1520 int32_t errCode = MediaFileUtils::CreateAsset(videoPath);
1521 CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode,
1522 "Create moving photo asset failed, path=%{private}s", videoPath.c_str());
1523 return E_OK;
1524 }
1525
IsNotMusicFile(const std::string & path)1526 static bool IsNotMusicFile(const std::string &path)
1527 {
1528 return (path.find(ANALYSIS_FILE_PATH) == string::npos);
1529 }
1530
OpenAsset(const shared_ptr<FileAsset> & fileAsset,const string & mode,MediaLibraryApi api,bool isMovingPhotoVideo,int32_t type)1531 int32_t MediaLibraryAssetOperations::OpenAsset(const shared_ptr<FileAsset> &fileAsset, const string &mode,
1532 MediaLibraryApi api, bool isMovingPhotoVideo, int32_t type)
1533 {
1534 MediaLibraryTracer tracer;
1535 tracer.Start("MediaLibraryAssetOperations::OpenAsset");
1536
1537 if (fileAsset == nullptr) {
1538 return E_INVALID_VALUES;
1539 }
1540
1541 string lowerMode = mode;
1542 transform(lowerMode.begin(), lowerMode.end(), lowerMode.begin(), ::tolower);
1543 if (!MediaFileUtils::CheckMode(lowerMode)) {
1544 return E_INVALID_MODE;
1545 }
1546
1547 string path;
1548 if (api == MediaLibraryApi::API_10) {
1549 int32_t errCode = SolvePendingStatus(fileAsset, mode);
1550 if (errCode != E_OK) {
1551 MEDIA_ERR_LOG("Solve pending status failed, errCode=%{public}d", errCode);
1552 return errCode;
1553 }
1554 path = fileAsset->GetPath();
1555 SolveMovingPhotoVideoCreation(path, mode, isMovingPhotoVideo);
1556 } else {
1557 // If below API10, TIME_PENDING is 0 after asset created, so if file is not exist, create an empty one
1558 if (!MediaFileUtils::IsFileExists(fileAsset->GetPath())) {
1559 MEDIA_INFO_LOG("create empty file for %{public}s, path: %{private}s", fileAsset->GetUri().c_str(),
1560 fileAsset->GetPath().c_str());
1561 int32_t errCode = CreateDirectoryAndAsset(fileAsset->GetPath());
1562 CHECK_AND_RETURN_RET(errCode == E_OK, errCode);
1563 }
1564 path = MediaFileUtils::UpdatePath(fileAsset->GetPath(), fileAsset->GetUri());
1565 }
1566
1567 string fileId = MediaFileUtils::GetIdFromUri(fileAsset->GetUri());
1568 MEDIA_DEBUG_LOG("Asset Operation:OpenAsset, type is %{public}d", type);
1569 int32_t fd = OpenFileWithPrivacy(path, lowerMode, fileId, type);
1570 if (fd < 0) {
1571 MEDIA_ERR_LOG(
1572 "open file, userId: %{public}d, uri: %{public}s, path: %{private}s, fd %{public}d, errno %{public}d",
1573 fileAsset->GetUserId(), fileAsset->GetUri().c_str(), fileAsset->GetPath().c_str(), fd, errno);
1574 return E_HAS_FS_ERROR;
1575 }
1576 tracer.Start("AddWatchList");
1577 if (mode.find(MEDIA_FILEMODE_WRITEONLY) != string::npos && !isMovingPhotoVideo && IsNotMusicFile(path)) {
1578 auto watch = MediaLibraryInotify::GetInstance();
1579 if (watch != nullptr) {
1580 MEDIA_INFO_LOG("enter inotify, path = %{public}s, fileId = %{public}d",
1581 DfxUtils::GetSafePath(path).c_str(), fileAsset->GetId());
1582 watch->AddWatchList(path, fileAsset->GetUri(), MediaLibraryApi::API_10);
1583 }
1584 }
1585 tracer.Finish();
1586 return fd;
1587 }
1588
CloseAsset(const shared_ptr<FileAsset> & fileAsset,bool isCreateThumbSync)1589 int32_t MediaLibraryAssetOperations::CloseAsset(const shared_ptr<FileAsset> &fileAsset, bool isCreateThumbSync)
1590 {
1591 if (fileAsset == nullptr) {
1592 return E_INVALID_VALUES;
1593 }
1594
1595 // remove inotify event since there is close cmd
1596 auto watch = MediaLibraryInotify::GetInstance();
1597 if (watch != nullptr) {
1598 string uri = fileAsset->GetUri();
1599 watch->RemoveByFileUri(uri, MediaLibraryApi::API_10);
1600 MEDIA_DEBUG_LOG("watch RemoveByFileUri, uri:%{private}s", uri.c_str());
1601 }
1602
1603 string path = fileAsset->GetPath();
1604 // if pending == 0, scan
1605 // if pending == UNCREATE_FILE_TIMEPENDING, not occur under normal conditions
1606 // if pending == UNCLOSE_FILE_TIMEPENDING, set pending = 0 and scan
1607 // if pending == UNOPEN_FILE_COMPONENT_TIMEPENDING, not allowed to close
1608 // if pending is timestamp, do nothing
1609 if (fileAsset->GetTimePending() == 0 || fileAsset->GetTimePending() == UNCLOSE_FILE_TIMEPENDING) {
1610 if (fileAsset->GetTimePending() == UNCLOSE_FILE_TIMEPENDING) {
1611 ScanFile(path, isCreateThumbSync, false);
1612 } else {
1613 ScanFile(path, isCreateThumbSync, true);
1614 }
1615 return E_OK;
1616 } else if (fileAsset->GetTimePending() == UNCREATE_FILE_TIMEPENDING ||
1617 fileAsset->GetTimePending() == UNOPEN_FILE_COMPONENT_TIMEPENDING) {
1618 MEDIA_ERR_LOG("This asset [%{public}d] pending status cannot close", fileAsset->GetId());
1619 return E_IS_PENDING_ERROR;
1620 } else if (fileAsset->GetTimePending() > 0) {
1621 MEDIA_WARN_LOG("This asset [%{public}d] is in pending", fileAsset->GetId());
1622 return E_OK;
1623 } else {
1624 MEDIA_ERR_LOG("This asset [%{public}d] pending status is invalid", fileAsset->GetId());
1625 return E_INVALID_VALUES;
1626 }
1627 }
1628
OpenHighlightCover(MediaLibraryCommand & cmd,const string & mode)1629 int32_t MediaLibraryAssetOperations::OpenHighlightCover(MediaLibraryCommand &cmd, const string &mode)
1630 {
1631 MediaLibraryTracer tracer;
1632 tracer.Start("MediaLibraryAssetOperations::OpenHighlightCover");
1633 string uriStr = cmd.GetUriStringWithoutSegment();
1634 string path = MediaFileUtils::GetHighlightPath(uriStr);
1635 CHECK_AND_RETURN_RET_LOG(path.length() != 0, E_INVALID_URI,
1636 "Open highlight cover invalid uri : %{public}s", uriStr.c_str());
1637
1638 shared_ptr<FileAsset> fileAsset = make_shared<FileAsset>();
1639 fileAsset->SetPath(path);
1640 fileAsset->SetUri(uriStr);
1641 return OpenAsset(fileAsset, mode, cmd.GetApi(), false);
1642 }
1643
OpenHighlightVideo(MediaLibraryCommand & cmd,const string & mode)1644 int32_t MediaLibraryAssetOperations::OpenHighlightVideo(MediaLibraryCommand &cmd, const string &mode)
1645 {
1646 MediaLibraryTracer tracer;
1647 tracer.Start("MediaLibraryAssetOperations::OpenHighlightVideo");
1648 string uriStr = cmd.GetUriStringWithoutSegment();
1649 string path = MediaFileUtils::GetHighlightVideoPath(uriStr);
1650
1651 CHECK_AND_RETURN_RET_LOG(path.length() != 0, E_INVALID_URI,
1652 "Open highlight video invalid uri : %{public}s", uriStr.c_str());
1653 shared_ptr<FileAsset> fileAsset = make_shared<FileAsset>();
1654 fileAsset->SetPath(path);
1655 fileAsset->SetUri(uriStr);
1656 return OpenAsset(fileAsset, mode, cmd.GetApi(), false);
1657 }
1658
InvalidateThumbnail(const string & fileId,int32_t type)1659 void MediaLibraryAssetOperations::InvalidateThumbnail(const string &fileId, int32_t type)
1660 {
1661 string tableName;
1662 switch (type) {
1663 case MediaType::MEDIA_TYPE_IMAGE:
1664 case MediaType::MEDIA_TYPE_VIDEO: {
1665 tableName = PhotoColumn::PHOTOS_TABLE;
1666 break;
1667 }
1668 case MediaType::MEDIA_TYPE_AUDIO: {
1669 tableName = AudioColumn::AUDIOS_TABLE;
1670 break;
1671 }
1672 default: {
1673 MEDIA_ERR_LOG("Can not match this type %{public}d", type);
1674 return;
1675 }
1676 }
1677 ThumbnailService::GetInstance()->HasInvalidateThumbnail(fileId, tableName);
1678 }
1679
ScanFile(const string & path,bool isCreateThumbSync,bool isInvalidateThumb,bool isForceScan,int32_t fileId,std::shared_ptr<Media::Picture> resultPicture)1680 void MediaLibraryAssetOperations::ScanFile(const string &path, bool isCreateThumbSync, bool isInvalidateThumb,
1681 bool isForceScan, int32_t fileId, std::shared_ptr<Media::Picture> resultPicture)
1682 {
1683 // Force Scan means medialibrary will scan file without checking E_SCANNED
1684 shared_ptr<ScanAssetCallback> scanAssetCallback = make_shared<ScanAssetCallback>();
1685 if (scanAssetCallback == nullptr) {
1686 MEDIA_ERR_LOG("Failed to create scan file callback object");
1687 return;
1688 }
1689 scanAssetCallback->SetOriginalPhotoPicture(resultPicture);
1690 if (isCreateThumbSync) {
1691 scanAssetCallback->SetSync(true);
1692 }
1693 if (!isInvalidateThumb) {
1694 scanAssetCallback->SetIsInvalidateThumb(false);
1695 }
1696
1697 int ret = MediaScannerManager::GetInstance()->ScanFileSync(path, scanAssetCallback, MediaLibraryApi::API_10,
1698 isForceScan, fileId);
1699 if (ret != 0) {
1700 MEDIA_ERR_LOG("Scan file failed with error: %{public}d", ret);
1701 }
1702 }
1703
ScanFileWithoutAlbumUpdate(const string & path,bool isCreateThumbSync,bool isInvalidateThumb,bool isForceScan,int32_t fileId,std::shared_ptr<Media::Picture> resultPicture)1704 void MediaLibraryAssetOperations::ScanFileWithoutAlbumUpdate(const string &path, bool isCreateThumbSync,
1705 bool isInvalidateThumb, bool isForceScan, int32_t fileId, std::shared_ptr<Media::Picture> resultPicture)
1706 {
1707 // Force Scan means medialibrary will scan file without checking E_SCANNED
1708 shared_ptr<ScanAssetCallback> scanAssetCallback = make_shared<ScanAssetCallback>();
1709 if (scanAssetCallback == nullptr) {
1710 MEDIA_ERR_LOG("Failed to create scan file callback object");
1711 return;
1712 }
1713 scanAssetCallback->SetOriginalPhotoPicture(resultPicture);
1714 if (isCreateThumbSync) {
1715 scanAssetCallback->SetSync(true);
1716 }
1717 if (!isInvalidateThumb) {
1718 scanAssetCallback->SetIsInvalidateThumb(false);
1719 }
1720
1721 int ret = MediaScannerManager::GetInstance()->ScanFileSyncWithoutAlbumUpdate(path, scanAssetCallback,
1722 MediaLibraryApi::API_10, isForceScan, fileId);
1723 CHECK_AND_PRINT_LOG(ret == 0, "Scan file failed with error: %{public}d", ret);
1724 }
1725
GetEditDataDirPath(const string & path)1726 string MediaLibraryAssetOperations::GetEditDataDirPath(const string &path)
1727 {
1728 if (path.length() < ROOT_MEDIA_DIR.length()) {
1729 return "";
1730 }
1731 return MEDIA_EDIT_DATA_DIR + path.substr(ROOT_MEDIA_DIR.length());
1732 }
1733
GetEditDataSourcePath(const string & path)1734 string MediaLibraryAssetOperations::GetEditDataSourcePath(const string &path)
1735 {
1736 string parentPath = GetEditDataDirPath(path);
1737 if (parentPath.empty()) {
1738 return "";
1739 }
1740 return parentPath + "/source." + MediaFileUtils::GetExtensionFromPath(path);
1741 }
1742
GetEditDataPath(const string & path)1743 string MediaLibraryAssetOperations::GetEditDataPath(const string &path)
1744 {
1745 string parentPath = GetEditDataDirPath(path);
1746 if (parentPath.empty()) {
1747 return "";
1748 }
1749 return parentPath + "/editdata";
1750 }
1751
GetEditDataCameraPath(const string & path)1752 string MediaLibraryAssetOperations::GetEditDataCameraPath(const string &path)
1753 {
1754 string parentPath = GetEditDataDirPath(path);
1755 if (parentPath.empty()) {
1756 return "";
1757 }
1758 return parentPath + "/editdata_camera";
1759 }
1760
GetAssetCacheDir()1761 string MediaLibraryAssetOperations::GetAssetCacheDir()
1762 {
1763 string cacheOwner = MediaLibraryBundleManager::GetInstance()->GetClientBundleName();
1764 if (cacheOwner.empty()) {
1765 cacheOwner = "common"; // Create cache file in common dir if there is no bundleName.
1766 }
1767 return MEDIA_CACHE_DIR + cacheOwner;
1768 }
1769
UpdateAlbumsAndSendNotifyInTrash(AsyncTaskData * data)1770 static void UpdateAlbumsAndSendNotifyInTrash(AsyncTaskData *data)
1771 {
1772 if (data == nullptr) {
1773 return;
1774 }
1775 DeleteNotifyAsyncTaskData* notifyData = static_cast<DeleteNotifyAsyncTaskData*>(data);
1776
1777 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1778 if (rdbStore == nullptr) {
1779 MEDIA_ERR_LOG("Can not get rdbstore");
1780 return;
1781 }
1782 if (notifyData->refresh_ != nullptr) {
1783 notifyData->refresh_->RefreshAlbum();
1784 notifyData->refresh_->Notify();
1785 } else {
1786 MediaLibraryRdbUtils::UpdateAllAlbums(rdbStore, {notifyData->notifyUri});
1787 }
1788
1789 auto watch = MediaLibraryNotify::GetInstance();
1790 if (watch == nullptr) {
1791 MEDIA_ERR_LOG("Can not get MediaLibraryNotify");
1792 return;
1793 }
1794 if (notifyData->trashDate > 0) {
1795 watch->Notify(notifyData->notifyUri, NotifyType::NOTIFY_REMOVE);
1796 watch->Notify(notifyData->notifyUri, NotifyType::NOTIFY_ALBUM_REMOVE_ASSET);
1797 } else {
1798 watch->Notify(notifyData->notifyUri, NotifyType::NOTIFY_ADD);
1799 watch->Notify(notifyData->notifyUri, NotifyType::NOTIFY_ALBUM_ADD_ASSET);
1800 }
1801
1802 int trashAlbumId = watch->GetAlbumIdBySubType(PhotoAlbumSubType::TRASH);
1803 if (trashAlbumId <= 0) {
1804 return;
1805 }
1806 NotifyType type = (notifyData->trashDate > 0) ? NotifyType::NOTIFY_ALBUM_ADD_ASSET :
1807 NotifyType::NOTIFY_ALBUM_REMOVE_ASSET;
1808 watch->Notify(notifyData->notifyUri, type, trashAlbumId);
1809 vector<int64_t> formIds;
1810 MediaLibraryFormMapOperations::GetFormMapFormId(notifyData->notifyUri, formIds);
1811 if (!formIds.empty()) {
1812 MediaLibraryFormMapOperations::PublishedChange("", formIds, false);
1813 }
1814 }
1815
SendTrashNotify(MediaLibraryCommand & cmd,int32_t rowId,const string & extraUri,shared_ptr<AccurateRefresh::AssetAccurateRefresh> assetRefresh)1816 int32_t MediaLibraryAssetOperations::SendTrashNotify(MediaLibraryCommand &cmd, int32_t rowId, const string &extraUri,
1817 shared_ptr<AccurateRefresh::AssetAccurateRefresh> assetRefresh)
1818 {
1819 ValueObject value;
1820 int64_t trashDate = 0;
1821 if (!cmd.GetValueBucket().GetObject(PhotoColumn::MEDIA_DATE_TRASHED, value)) {
1822 return E_DO_NOT_NEDD_SEND_NOTIFY;
1823 }
1824
1825 value.GetLong(trashDate);
1826
1827 string prefix;
1828 if (cmd.GetOprnObject() == OperationObject::FILESYSTEM_PHOTO) {
1829 prefix = PhotoColumn::PHOTO_URI_PREFIX;
1830 } else if (cmd.GetOprnObject() == OperationObject::FILESYSTEM_AUDIO) {
1831 prefix = AudioColumn::AUDIO_URI_PREFIX;
1832 } else {
1833 return E_OK;
1834 }
1835
1836 string notifyUri = MediaFileUtils::GetUriByExtrConditions(prefix, to_string(rowId), extraUri);
1837 shared_ptr<MediaLibraryAsyncWorker> asyncWorker = MediaLibraryAsyncWorker::GetInstance();
1838 if (asyncWorker == nullptr) {
1839 MEDIA_ERR_LOG("Can not get asyncWorker");
1840 return E_ERR;
1841 }
1842 DeleteNotifyAsyncTaskData* taskData = new (std::nothrow) DeleteNotifyAsyncTaskData();
1843 if (taskData == nullptr) {
1844 MEDIA_ERR_LOG("Failed to new taskData");
1845 return E_ERR;
1846 }
1847 taskData->notifyUri = notifyUri;
1848 taskData->trashDate = trashDate;
1849 taskData->refresh_ = assetRefresh;
1850 shared_ptr<MediaLibraryAsyncTask> notifyAsyncTask = make_shared<MediaLibraryAsyncTask>(
1851 UpdateAlbumsAndSendNotifyInTrash, taskData);
1852 if (notifyAsyncTask != nullptr) {
1853 asyncWorker->AddTask(notifyAsyncTask, true);
1854 } else {
1855 MEDIA_ERR_LOG("Start UpdateAlbumsAndSendNotifyInTrash failed");
1856 }
1857 return E_OK;
1858 }
1859
SendFavoriteNotify(MediaLibraryCommand & cmd,shared_ptr<FileAsset> & fileAsset,const string & extraUri,shared_ptr<AccurateRefresh::AssetAccurateRefresh> assetRefresh)1860 void MediaLibraryAssetOperations::SendFavoriteNotify(MediaLibraryCommand &cmd, shared_ptr<FileAsset> &fileAsset,
1861 const string &extraUri, shared_ptr<AccurateRefresh::AssetAccurateRefresh> assetRefresh)
1862 {
1863 ValueObject value;
1864 int32_t isFavorite = 0;
1865 if (!cmd.GetValueBucket().GetObject(PhotoColumn::MEDIA_IS_FAV, value)) {
1866 return;
1867 }
1868 value.GetInt(isFavorite);
1869
1870 if (assetRefresh == nullptr) {
1871 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1872 CHECK_AND_RETURN_LOG(rdbStore != nullptr, "Failed to get rdbStore.");
1873 MediaLibraryRdbUtils::UpdateSystemAlbumInternal(rdbStore, { to_string(PhotoAlbumSubType::FAVORITE) });
1874 CHECK_AND_RETURN_LOG(fileAsset != nullptr, "fileAsset is nullptr");
1875 if (fileAsset->IsHidden()) {
1876 MediaLibraryRdbUtils::UpdateSysAlbumHiddenState(rdbStore, { to_string(PhotoAlbumSubType::FAVORITE) });
1877 }
1878 } else {
1879 assetRefresh->RefreshAlbum();
1880 }
1881
1882 auto watch = MediaLibraryNotify::GetInstance();
1883 CHECK_AND_RETURN_LOG(watch != nullptr, "Can not get MediaLibraryNotify Instance");
1884 if (cmd.GetOprnObject() != OperationObject::FILESYSTEM_PHOTO) {
1885 return;
1886 }
1887 int favAlbumId = watch->GetAlbumIdBySubType(PhotoAlbumSubType::FAVORITE);
1888 if (favAlbumId <= 0) {
1889 return;
1890 }
1891
1892 NotifyType type = (isFavorite) ? NotifyType::NOTIFY_ALBUM_ADD_ASSET : NotifyType::NOTIFY_ALBUM_REMOVE_ASSET;
1893 watch->Notify(
1894 MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(fileAsset->GetId()), extraUri),
1895 type, favAlbumId);
1896 }
1897
SendModifyUserCommentNotify(MediaLibraryCommand & cmd,int32_t rowId,const string & extraUri)1898 int32_t MediaLibraryAssetOperations::SendModifyUserCommentNotify(MediaLibraryCommand &cmd, int32_t rowId,
1899 const string &extraUri)
1900 {
1901 if (cmd.GetOprnType() != OperationType::SET_USER_COMMENT) {
1902 return E_DO_NOT_NEDD_SEND_NOTIFY;
1903 }
1904
1905 auto watch = MediaLibraryNotify::GetInstance();
1906 CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_ERR, "Can not get MediaLibraryNotify Instance");
1907 watch->Notify(MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(rowId), extraUri),
1908 NotifyType::NOTIFY_UPDATE);
1909 return E_OK;
1910 }
1911
GetAlbumIdByPredicates(const string & whereClause,const vector<string> & whereArgs)1912 int32_t MediaLibraryAssetOperations::GetAlbumIdByPredicates(const string &whereClause, const vector<string> &whereArgs)
1913 {
1914 size_t pos = whereClause.find(PhotoColumn::PHOTO_OWNER_ALBUM_ID);
1915 CHECK_AND_RETURN_RET_LOG(pos != string::npos, E_ERR, "Predicates whereClause is invalid");
1916 size_t argsIndex = 0;
1917 for (size_t i = 0; i < pos; ++i) {
1918 if (whereClause[i] == '?') {
1919 argsIndex++;
1920 }
1921 }
1922 if (argsIndex > whereArgs.size() - 1) {
1923 MEDIA_ERR_LOG("whereArgs is invalid");
1924 return E_ERR;
1925 }
1926 auto albumId = whereArgs[argsIndex];
1927 CHECK_AND_RETURN_RET(!MediaLibraryDataManagerUtils::IsNumber(albumId), std::atoi(albumId.c_str()));
1928 return E_ERR;
1929 }
1930
UpdateOwnerAlbumIdOnMove(MediaLibraryCommand & cmd,int32_t & targetAlbumId,int32_t & oriAlbumId)1931 void MediaLibraryAssetOperations::UpdateOwnerAlbumIdOnMove(MediaLibraryCommand &cmd,
1932 int32_t &targetAlbumId, int32_t &oriAlbumId)
1933 {
1934 ValueObject value;
1935 if (!cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_OWNER_ALBUM_ID, value)) {
1936 return;
1937 }
1938 value.GetInt(targetAlbumId);
1939 auto whereClause = cmd.GetAbsRdbPredicates()->GetWhereClause();
1940 auto whereArgs = cmd.GetAbsRdbPredicates()->GetWhereArgs();
1941 oriAlbumId = GetAlbumIdByPredicates(whereClause, whereArgs);
1942
1943 MEDIA_INFO_LOG("Move Assets, ori album id is %{public}d, target album id is %{public}d", oriAlbumId, targetAlbumId);
1944 }
1945
SetPendingTrue(const shared_ptr<FileAsset> & fileAsset)1946 int32_t MediaLibraryAssetOperations::SetPendingTrue(const shared_ptr<FileAsset> &fileAsset)
1947 {
1948 // time_pending = 0, means file is created, not allowed
1949 // time_pending = UNCREATE_FILE_TIMEPENDING, means file is not created yet, create an empty one
1950 // time_pending = UNCLOSE_FILE_TIMEPENDING, means file is not close yet, set pending time
1951 // time_pending = UNOPEN_FILE_COMPONENT_TIMEPENDING, means file is created but not open, set pending time
1952 // time_pending is timestamp, update it
1953 int64_t timestamp = MediaFileUtils::UTCTimeSeconds();
1954 if (timestamp <= 0) {
1955 MEDIA_ERR_LOG("Get timestamp failed, timestamp:%{public}ld", (long) timestamp);
1956 return E_INVALID_TIMESTAMP;
1957 }
1958 if (fileAsset->GetTimePending() == 0) {
1959 MEDIA_ERR_LOG("fileAsset time_pending is 0, not allowed");
1960 return E_INVALID_VALUES;
1961 } else if (fileAsset->GetTimePending() == UNCREATE_FILE_TIMEPENDING) {
1962 int32_t errCode = CreateFileAndSetPending(fileAsset, timestamp);
1963 if (errCode != E_OK) {
1964 MEDIA_ERR_LOG("Create asset failed, id=%{public}d", fileAsset->GetId());
1965 return errCode;
1966 }
1967 } else if (fileAsset->GetTimePending() == UNCLOSE_FILE_TIMEPENDING ||
1968 fileAsset->GetTimePending() == UNOPEN_FILE_COMPONENT_TIMEPENDING ||
1969 fileAsset->GetTimePending() > 0) {
1970 int32_t errCode = SetPendingTime(fileAsset, timestamp);
1971 if (errCode != E_OK) {
1972 MEDIA_ERR_LOG("Set pending time failed, id=%{public}d", fileAsset->GetId());
1973 return errCode;
1974 }
1975 } else {
1976 MEDIA_ERR_LOG("fileAsset time_pending is invalid, time_pending:%{public}ld, id=%{public}d",
1977 (long) fileAsset->GetTimePending(), fileAsset->GetId());
1978 return E_INVALID_VALUES;
1979 }
1980
1981 return E_OK;
1982 }
1983
SetPendingFalse(const shared_ptr<FileAsset> & fileAsset)1984 int32_t MediaLibraryAssetOperations::SetPendingFalse(const shared_ptr<FileAsset> &fileAsset)
1985 {
1986 // time_pending = 0, only return
1987 // time_pending = UNCREATE_FILE_TIMEPENDING, means file is not created yet, not allowed
1988 // time_pending = UNCLOSE_FILE_TIMEPENDING, means file is not close yet, not allowed
1989 // time_pending = UNOPEN_FILE_COMPONENT_TIMEPENDING, means file is created but not open, not allowed
1990 // time_pending is timestamp, scan and set pending time = 0
1991 if (fileAsset->GetTimePending() == 0) {
1992 return E_OK;
1993 } else if (fileAsset->GetTimePending() == UNCREATE_FILE_TIMEPENDING) {
1994 MEDIA_ERR_LOG("file is not created yet, not allowed, id=%{public}d", fileAsset->GetId());
1995 return E_INVALID_VALUES;
1996 } else if (fileAsset->GetTimePending() == UNCLOSE_FILE_TIMEPENDING) {
1997 MEDIA_ERR_LOG("file is not close yet, not allowed, id=%{public}d", fileAsset->GetId());
1998 return E_INVALID_VALUES;
1999 } else if (fileAsset->GetTimePending() == UNOPEN_FILE_COMPONENT_TIMEPENDING) {
2000 MEDIA_ERR_LOG("file is created but not open, not allowed, id=%{public}d", fileAsset->GetId());
2001 return E_INVALID_VALUES;
2002 } else if (fileAsset->GetTimePending() > 0) {
2003 ScanFile(fileAsset->GetPath(), true, true);
2004 } else {
2005 MEDIA_ERR_LOG("fileAsset time_pending is invalid, time_pending:%{public}ld, id=%{public}d",
2006 (long) fileAsset->GetTimePending(), fileAsset->GetId());
2007 return E_INVALID_VALUES;
2008 }
2009 return E_OK;
2010 }
2011
IsCoverContentChange(string & fileId)2012 void MediaLibraryAssetOperations::IsCoverContentChange(string &fileId)
2013 {
2014 CHECK_AND_RETURN_LOG(MediaFileUtils::IsValidInteger(fileId), "invalid input param");
2015 CHECK_AND_RETURN_LOG(stoi(fileId) > 0, "fileId is invalid");
2016 AccurateRefresh::AlbumAccurateRefresh albumRefresh;
2017 if (albumRefresh.IsCoverContentChange(fileId)) {
2018 MEDIA_INFO_LOG("Album Cover Content has Changed, fileId: %{public}s", fileId.c_str());
2019 }
2020 }
2021
SetPendingStatus(MediaLibraryCommand & cmd)2022 int32_t MediaLibraryAssetOperations::SetPendingStatus(MediaLibraryCommand &cmd)
2023 {
2024 int32_t pendingStatus = 0;
2025 if (!GetInt32FromValuesBucket(cmd.GetValueBucket(), MediaColumn::MEDIA_TIME_PENDING, pendingStatus)) {
2026 return E_INVALID_VALUES;
2027 }
2028
2029 vector<string> columns = {
2030 MediaColumn::MEDIA_ID,
2031 MediaColumn::MEDIA_FILE_PATH,
2032 MediaColumn::MEDIA_TYPE,
2033 MediaColumn::MEDIA_TIME_PENDING
2034 };
2035 auto fileAsset = GetFileAssetFromDb(*(cmd.GetAbsRdbPredicates()), cmd.GetOprnObject(), columns);
2036 if (fileAsset == nullptr) {
2037 return E_INVALID_VALUES;
2038 }
2039 if (pendingStatus == 1) {
2040 return SetPendingTrue(fileAsset);
2041 } else if (pendingStatus == 0) {
2042 return SetPendingFalse(fileAsset);
2043 } else {
2044 MEDIA_ERR_LOG("pendingStatus is invalid, pendingStatus:%{public}d", pendingStatus);
2045 return E_INVALID_VALUES;
2046 }
2047 }
2048
ConvertMediaPathFromCloudPath(const string & path)2049 static string ConvertMediaPathFromCloudPath(const string &path)
2050 {
2051 // if input path is /storage/cloud/xxx, return /storage/media/local/xxx
2052 string mediaPath = "/storage/media/local/";
2053 string cloudPath = "/storage/cloud/";
2054 string newPath = path;
2055 if (newPath.find(cloudPath) != string::npos) {
2056 newPath.replace(newPath.find(cloudPath), cloudPath.length(), mediaPath);
2057 }
2058 return newPath;
2059 }
2060
GrantUriPermission(const string & uri,const string & bundleName,const string & path,bool isMovingPhoto)2061 int32_t MediaLibraryAssetOperations::GrantUriPermission(const string &uri, const string &bundleName,
2062 const string &path, bool isMovingPhoto)
2063 {
2064 if (uri.empty() || path.empty()) {
2065 MEDIA_ERR_LOG("uri or path is empty, uri:%{private}s, path:%{private}s", uri.c_str(), path.c_str());
2066 return E_INVALID_VALUES;
2067 }
2068 if (bundleName.empty()) {
2069 MEDIA_WARN_LOG("bundleName is empty, bundleName:%{private}s", bundleName.c_str());
2070 return E_OK;
2071 }
2072 if (!MediaFileUtils::CreateFile(path)) {
2073 MEDIA_ERR_LOG("Can not create file, path: %{private}s, errno: %{public}d", path.c_str(), errno);
2074 return E_HAS_FS_ERROR;
2075 }
2076
2077 if (isMovingPhoto && !MediaFileUtils::CreateFile(MediaFileUtils::GetMovingPhotoVideoPath(path))) {
2078 MEDIA_ERR_LOG("Failed to create video of moving photo, errno: %{public}d", errno);
2079 return E_HAS_FS_ERROR;
2080 }
2081
2082 return E_OK;
2083 }
2084
GetInt32FromValuesBucket(const NativeRdb::ValuesBucket & values,const std::string & column,int32_t & value)2085 bool MediaLibraryAssetOperations::GetInt32FromValuesBucket(const NativeRdb::ValuesBucket &values,
2086 const std::string &column, int32_t &value)
2087 {
2088 ValueObject valueObject;
2089 if (values.GetObject(column, valueObject)) {
2090 valueObject.GetInt(value);
2091 } else {
2092 return false;
2093 }
2094 return true;
2095 }
2096
CreateExtUriForV10Asset(FileAsset & fileAsset)2097 std::string MediaLibraryAssetOperations::CreateExtUriForV10Asset(FileAsset &fileAsset)
2098 {
2099 const std::string &filePath = fileAsset.GetPath();
2100 const std::string &displayName = fileAsset.GetDisplayName();
2101 auto mediaType = fileAsset.GetMediaType();
2102 if (filePath.empty() || displayName.empty() || mediaType < 0) {
2103 MEDIA_ERR_LOG("param invalid, filePath %{private}s or displayName %{private}s invalid failed.",
2104 filePath.c_str(), displayName.c_str());
2105 return "";
2106 }
2107
2108 string extrUri = MediaFileUtils::GetExtraUri(displayName, filePath);
2109 return MediaFileUtils::GetUriByExtrConditions(ML_FILE_URI_PREFIX + MediaFileUri::GetMediaTypeUri(mediaType,
2110 MEDIA_API_VERSION_V10) + "/", to_string(fileAsset.GetId()), extrUri);
2111 }
2112
GetStringFromValuesBucket(const NativeRdb::ValuesBucket & values,const std::string & column,string & value)2113 bool MediaLibraryAssetOperations::GetStringFromValuesBucket(const NativeRdb::ValuesBucket &values,
2114 const std::string &column, string &value)
2115 {
2116 ValueObject valueObject;
2117 if (values.GetObject(column, valueObject)) {
2118 valueObject.GetString(value);
2119 } else {
2120 return false;
2121 }
2122 return true;
2123 }
2124
CreateAssetUniqueId(int32_t type,std::shared_ptr<TransactionOperations> trans)2125 int32_t MediaLibraryAssetOperations::CreateAssetUniqueId(int32_t type,
2126 std::shared_ptr<TransactionOperations> trans)
2127 {
2128 string typeString;
2129 switch (type) {
2130 case MediaType::MEDIA_TYPE_IMAGE:
2131 typeString += IMAGE_ASSET_TYPE;
2132 break;
2133 case MediaType::MEDIA_TYPE_VIDEO:
2134 typeString += VIDEO_ASSET_TYPE;
2135 break;
2136 case MediaType::MEDIA_TYPE_AUDIO:
2137 typeString += AUDIO_ASSET_TYPE;
2138 break;
2139 default:
2140 MEDIA_ERR_LOG("This type %{public}d can not get unique id", type);
2141 return E_INVALID_VALUES;
2142 }
2143
2144 const string updateSql = "UPDATE " + ASSET_UNIQUE_NUMBER_TABLE + " SET " + UNIQUE_NUMBER +
2145 "=" + UNIQUE_NUMBER + "+1" " WHERE " + ASSET_MEDIA_TYPE + "='" + typeString + "';";
2146 const string querySql = "SELECT " + UNIQUE_NUMBER + " FROM " + ASSET_UNIQUE_NUMBER_TABLE +
2147 " WHERE " + ASSET_MEDIA_TYPE + "='" + typeString + "';";
2148
2149 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2150 if (rdbStore == nullptr) {
2151 return E_HAS_DB_ERROR;
2152 }
2153 lock_guard<mutex> lock(g_uniqueNumberLock);
2154 int32_t errCode;
2155 if (trans == nullptr) {
2156 errCode = rdbStore->ExecuteSql(updateSql);
2157 } else {
2158 errCode = trans->ExecuteSql(updateSql);
2159 }
2160 if (errCode < 0) {
2161 MEDIA_ERR_LOG("execute update unique number failed, ret=%{public}d", errCode);
2162 return errCode;
2163 }
2164
2165 auto resultSet = rdbStore->QuerySql(querySql);
2166 if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
2167 return E_HAS_DB_ERROR;
2168 }
2169 return GetInt32Val(UNIQUE_NUMBER, resultSet);
2170 }
2171
CreateAssetUniqueIds(int32_t type,int32_t num,int32_t & startUniqueNumber)2172 int32_t MediaLibraryAssetOperations::CreateAssetUniqueIds(int32_t type, int32_t num, int32_t &startUniqueNumber)
2173 {
2174 if (num == 0) {
2175 return E_OK;
2176 }
2177 string typeString;
2178 switch (type) {
2179 case MediaType::MEDIA_TYPE_IMAGE:
2180 typeString = IMAGE_ASSET_TYPE;
2181 break;
2182 case MediaType::MEDIA_TYPE_VIDEO:
2183 typeString = VIDEO_ASSET_TYPE;
2184 break;
2185 case MediaType::MEDIA_TYPE_AUDIO:
2186 typeString = AUDIO_ASSET_TYPE;
2187 break;
2188 default:
2189 MEDIA_ERR_LOG("This type %{public}d can not get unique id", type);
2190 return E_INVALID_VALUES;
2191 }
2192
2193 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2194 CHECK_AND_RETURN_RET(rdbStore != nullptr, E_HAS_DB_ERROR);
2195 const string updateSql = "UPDATE " + ASSET_UNIQUE_NUMBER_TABLE + " SET " + UNIQUE_NUMBER +
2196 "=" + UNIQUE_NUMBER + "+" + to_string(num) + " WHERE " + ASSET_MEDIA_TYPE + "='" + typeString + "';";
2197 const string querySql = "SELECT " + UNIQUE_NUMBER + " FROM " + ASSET_UNIQUE_NUMBER_TABLE +
2198 " WHERE " + ASSET_MEDIA_TYPE + "='" + typeString + "';";
2199 lock_guard<mutex> lock(g_uniqueNumberLock);
2200 int32_t errCode = E_OK;
2201 std::shared_ptr<TransactionOperations> trans = make_shared<TransactionOperations>(__func__);
2202 std::function<int(void)> func = [&]()->int {
2203 errCode = trans->ExecuteSql(updateSql);
2204 CHECK_AND_RETURN_RET_LOG(errCode >= 0, errCode, "CreateAssetUniqueIds ExecuteSql err, ret=%{public}d",
2205 errCode);
2206 auto resultSet = trans->QueryByStep(querySql);
2207 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "CreateAssetUniqueIds resultSet is null");
2208 if (resultSet->GoToFirstRow() != NativeRdb::E_OK) {
2209 MEDIA_ERR_LOG("CreateAssetUniqueIds first row empty");
2210 resultSet->Close();
2211 return E_HAS_DB_ERROR;
2212 }
2213 int32_t endUniqueNumber = GetInt32Val(UNIQUE_NUMBER, resultSet);
2214 resultSet->Close();
2215 startUniqueNumber = endUniqueNumber - num;
2216 MEDIA_INFO_LOG("CreateAssetUniqueIds type: %{public}d, num: %{public}d, startUniqueNumber: %{public}d",
2217 type, num, startUniqueNumber);
2218 return E_OK;
2219 };
2220 errCode = trans->RetryTrans(func);
2221 CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "CreateAssetUniqueIds err, ret=%{public}d", errCode);
2222 return E_OK;
2223 }
2224
CreateAssetRealName(int32_t fileId,int32_t mediaType,const string & extension,string & name)2225 int32_t MediaLibraryAssetOperations::CreateAssetRealName(int32_t fileId, int32_t mediaType,
2226 const string &extension, string &name)
2227 {
2228 string fileNumStr = to_string(fileId);
2229 if (fileId <= ASSET_MAX_COMPLEMENT_ID) {
2230 size_t fileIdLen = fileNumStr.length();
2231 fileNumStr = ("00" + fileNumStr).substr(fileIdLen - 1);
2232 }
2233
2234 string mediaTypeStr;
2235 switch (mediaType) {
2236 case MediaType::MEDIA_TYPE_IMAGE:
2237 mediaTypeStr = DEFAULT_IMAGE_NAME;
2238 break;
2239 case MediaType::MEDIA_TYPE_VIDEO:
2240 mediaTypeStr = DEFAULT_VIDEO_NAME;
2241 break;
2242 case MediaType::MEDIA_TYPE_AUDIO:
2243 mediaTypeStr = DEFAULT_AUDIO_NAME;
2244 break;
2245 default:
2246 MEDIA_ERR_LOG("This mediatype %{public}d can not get real name", mediaType);
2247 return E_INVALID_VALUES;
2248 }
2249
2250 static const int32_t CONFLICT_TIME = 100;
2251 if (extension.length() == 0) {
2252 name = mediaTypeStr + to_string(MediaFileUtils::UTCTimeSeconds() + CONFLICT_TIME) + "_" + fileNumStr;
2253 } else {
2254 name = mediaTypeStr + to_string(MediaFileUtils::UTCTimeSeconds() + CONFLICT_TIME) + "_" +
2255 fileNumStr + "." + extension;
2256 }
2257 return E_OK;
2258 }
2259
PrepareAssetDir(const string & dirPath)2260 static inline int32_t PrepareAssetDir(const string &dirPath)
2261 {
2262 CHECK_AND_RETURN_RET(!dirPath.empty(), E_INVALID_PATH);
2263 if (!MediaFileUtils::IsFileExists(dirPath)) {
2264 bool ret = MediaFileUtils::CreateDirectory(dirPath);
2265 CHECK_AND_RETURN_RET_LOG(ret, E_CHECK_DIR_FAIL, "Create Dir Failed! dirPath=%{private}s",
2266 dirPath.c_str());
2267 }
2268 return E_OK;
2269 }
2270
CreateAssetPathById(int32_t fileId,int32_t mediaType,const string & extension,string & filePath)2271 int32_t MediaLibraryAssetOperations::CreateAssetPathById(int32_t fileId, int32_t mediaType,
2272 const string &extension, string &filePath)
2273 {
2274 string mediaDirPath;
2275 GetAssetRootDir(mediaType, mediaDirPath);
2276 if (mediaDirPath.empty()) {
2277 return E_INVALID_VALUES;
2278 }
2279
2280 int32_t bucketNum = 0;
2281 int32_t errCode = MediaFileUri::CreateAssetBucket(fileId, bucketNum);
2282 if (errCode != E_OK) {
2283 return errCode;
2284 }
2285
2286 string realName;
2287 errCode = CreateAssetRealName(fileId, mediaType, extension, realName);
2288 if (errCode != E_OK) {
2289 return errCode;
2290 }
2291
2292 string dirPath = ROOT_MEDIA_DIR + mediaDirPath + to_string(bucketNum);
2293 errCode = PrepareAssetDir(dirPath);
2294 if (errCode != E_OK) {
2295 return errCode;
2296 }
2297
2298 filePath = dirPath + "/" + realName;
2299 return E_OK;
2300 }
2301
2302 const std::unordered_map<std::string, std::vector<VerifyFunction>>
2303 AssetInputParamVerification::UPDATE_VERIFY_PARAM_MAP = {
2304 { MediaColumn::MEDIA_ID, { Forbidden } },
2305 { MediaColumn::MEDIA_FILE_PATH, { Forbidden } },
2306 { MediaColumn::MEDIA_SIZE, { Forbidden } },
2307 { MediaColumn::MEDIA_TITLE, { IsStringNotNull } },
2308 { MediaColumn::MEDIA_NAME, { IsStringNotNull } },
2309 { MediaColumn::MEDIA_TYPE, { Forbidden } },
2310 { MediaColumn::MEDIA_MIME_TYPE, { Forbidden } },
2311 { MediaColumn::MEDIA_OWNER_PACKAGE, { Forbidden } },
2312 { MediaColumn::MEDIA_OWNER_APPID, { Forbidden } },
2313 { MediaColumn::MEDIA_PACKAGE_NAME, { Forbidden } },
2314 { MediaColumn::MEDIA_DEVICE_NAME, { Forbidden } },
2315 { MediaColumn::MEDIA_DATE_MODIFIED, { Forbidden } },
2316 { MediaColumn::MEDIA_DATE_ADDED, { Forbidden } },
2317 { MediaColumn::MEDIA_DATE_TAKEN, { Forbidden } },
2318 { MediaColumn::MEDIA_DURATION, { Forbidden } },
2319 { MediaColumn::MEDIA_TIME_PENDING, { IsInt64, IsUniqueValue } },
2320 { MediaColumn::MEDIA_IS_FAV, { IsBool, IsUniqueValue } },
2321 { MediaColumn::MEDIA_DATE_TRASHED, { IsInt64, IsUniqueValue } },
2322 { MediaColumn::MEDIA_DATE_DELETED, { IsInt64, IsUniqueValue } },
2323 { MediaColumn::MEDIA_HIDDEN, { IsBool, IsUniqueValue } },
2324 { MediaColumn::MEDIA_PARENT_ID, { IsInt64, IsBelowApi9 } },
2325 { MediaColumn::MEDIA_RELATIVE_PATH, { IsString, IsBelowApi9 } },
2326 { MediaColumn::MEDIA_VIRTURL_PATH, { Forbidden } },
2327 { PhotoColumn::PHOTO_ORIENTATION, { IsInt64 } },
2328 { PhotoColumn::PHOTO_LATITUDE, { Forbidden } },
2329 { PhotoColumn::PHOTO_LONGITUDE, { Forbidden } },
2330 { PhotoColumn::PHOTO_HEIGHT, { Forbidden } },
2331 { PhotoColumn::PHOTO_WIDTH, { Forbidden } },
2332 { PhotoColumn::PHOTO_LCD_VISIT_TIME, { IsInt64 } },
2333 { PhotoColumn::PHOTO_EDIT_TIME, { IsInt64 } },
2334 { AudioColumn::AUDIO_ALBUM, { Forbidden } },
2335 { AudioColumn::AUDIO_ARTIST, { Forbidden } },
2336 { PhotoColumn::CAMERA_SHOT_KEY, { IsString } },
2337 { PhotoColumn::PHOTO_USER_COMMENT, { IsString } },
2338 { PhotoColumn::PHOTO_ID, { IsString } },
2339 { PhotoColumn::PHOTO_QUALITY, { IsInt32 } },
2340 { PhotoColumn::PHOTO_FIRST_VISIT_TIME, { IsInt64 } },
2341 { PhotoColumn::PHOTO_DEFERRED_PROC_TYPE, { IsInt32 } },
2342 { PhotoColumn::PHOTO_SUBTYPE, { IsInt32 } },
2343 { PhotoColumn::MOVING_PHOTO_EFFECT_MODE, { IsInt32 } },
2344 { PhotoColumn::PHOTO_COVER_POSITION, { IsInt64 } },
2345 { PhotoColumn::PHOTO_IS_TEMP, { IsBool } },
2346 { PhotoColumn::PHOTO_DIRTY, { IsInt32 } },
2347 { PhotoColumn::PHOTO_DETAIL_TIME, { IsStringNotNull } },
2348 { PhotoColumn::PHOTO_OWNER_ALBUM_ID, { IsInt32 } },
2349 { PhotoColumn::PHOTO_CE_AVAILABLE, { IsInt32 } },
2350 { PhotoColumn::SUPPORTED_WATERMARK_TYPE, { IsInt32 } },
2351 { PhotoColumn::PHOTO_IS_AUTO, { IsInt32 } },
2352 { PhotoColumn::PHOTO_IS_RECENT_SHOW, { IsBool, IsUniqueValue } },
2353 };
2354
CheckParamForUpdate(MediaLibraryCommand & cmd)2355 bool AssetInputParamVerification::CheckParamForUpdate(MediaLibraryCommand &cmd)
2356 {
2357 ValuesBucket &values = cmd.GetValueBucket();
2358 map<string, ValueObject> valuesMap;
2359 values.GetAll(valuesMap);
2360 for (auto &iter : valuesMap) {
2361 if (UPDATE_VERIFY_PARAM_MAP.find(iter.first) == UPDATE_VERIFY_PARAM_MAP.end()) {
2362 MEDIA_ERR_LOG("param [%{private}s] is not allowed", iter.first.c_str());
2363 return false;
2364 }
2365 for (auto &verifyFunc : UPDATE_VERIFY_PARAM_MAP.at(iter.first)) {
2366 if (!verifyFunc(iter.second, cmd)) {
2367 MEDIA_ERR_LOG("verify param [%{private}s] failed", iter.first.c_str());
2368 return false;
2369 }
2370 }
2371 }
2372 return true;
2373 }
2374
Forbidden(ValueObject & value,MediaLibraryCommand & cmd)2375 bool AssetInputParamVerification::Forbidden(ValueObject &value, MediaLibraryCommand &cmd)
2376 {
2377 return false;
2378 }
2379
IsInt32(ValueObject & value,MediaLibraryCommand & cmd)2380 bool AssetInputParamVerification::IsInt32(ValueObject &value, MediaLibraryCommand &cmd)
2381 {
2382 if (value.GetType() == ValueObjectType::TYPE_INT) {
2383 return true;
2384 }
2385 return false;
2386 }
2387
IsInt64(ValueObject & value,MediaLibraryCommand & cmd)2388 bool AssetInputParamVerification::IsInt64(ValueObject &value, MediaLibraryCommand &cmd)
2389 {
2390 if (value.GetType() == ValueObjectType::TYPE_INT) {
2391 return true;
2392 }
2393 return false;
2394 }
2395
IsBool(ValueObject & value,MediaLibraryCommand & cmd)2396 bool AssetInputParamVerification::IsBool(ValueObject &value, MediaLibraryCommand &cmd)
2397 {
2398 if (value.GetType() == ValueObjectType::TYPE_BOOL) {
2399 return true;
2400 }
2401 if (value.GetType() == ValueObjectType::TYPE_INT) {
2402 int32_t ret;
2403 value.GetInt(ret);
2404 if (ret == 0 || ret == 1) {
2405 return true;
2406 }
2407 }
2408 return false;
2409 }
2410
IsString(ValueObject & value,MediaLibraryCommand & cmd)2411 bool AssetInputParamVerification::IsString(ValueObject &value, MediaLibraryCommand &cmd)
2412 {
2413 CHECK_AND_RETURN_RET(value.GetType() != ValueObjectType::TYPE_STRING, true);
2414 return false;
2415 }
2416
IsDouble(ValueObject & value,MediaLibraryCommand & cmd)2417 bool AssetInputParamVerification::IsDouble(ValueObject &value, MediaLibraryCommand &cmd)
2418 {
2419 CHECK_AND_RETURN_RET(value.GetType() != ValueObjectType::TYPE_DOUBLE, true);
2420 return false;
2421 }
2422
IsBelowApi9(ValueObject & value,MediaLibraryCommand & cmd)2423 bool AssetInputParamVerification::IsBelowApi9(ValueObject &value, MediaLibraryCommand &cmd)
2424 {
2425 CHECK_AND_RETURN_RET(cmd.GetApi() != MediaLibraryApi::API_OLD, true);
2426 return false;
2427 }
2428
IsStringNotNull(ValueObject & value,MediaLibraryCommand & cmd)2429 bool AssetInputParamVerification::IsStringNotNull(ValueObject &value, MediaLibraryCommand &cmd)
2430 {
2431 if (value.GetType() != ValueObjectType::TYPE_STRING) {
2432 return false;
2433 }
2434 string str;
2435 value.GetString(str);
2436 if (str.empty()) {
2437 return false;
2438 }
2439 return true;
2440 }
2441
IsUniqueValue(ValueObject & value,MediaLibraryCommand & cmd)2442 bool AssetInputParamVerification::IsUniqueValue(ValueObject &value, MediaLibraryCommand &cmd)
2443 {
2444 // whether this is the unique value in ValuesBucket
2445 map<string, ValueObject> valuesMap;
2446 cmd.GetValueBucket().GetAll(valuesMap);
2447 if (valuesMap.size() != 1) {
2448 return false;
2449 }
2450 return true;
2451 }
2452
CreateThumbnailFileScaned(const string & uri,const string & path,bool isSync,std::shared_ptr<Media::Picture> originalPhotoPicture)2453 static void CreateThumbnailFileScaned(const string &uri, const string &path, bool isSync,
2454 std::shared_ptr<Media::Picture> originalPhotoPicture)
2455 {
2456 if (ThumbnailService::GetInstance() == nullptr) {
2457 return;
2458 }
2459 CHECK_AND_RETURN_LOG(!uri.empty(), "Uri is empty");
2460 int32_t err = 0;
2461 if (originalPhotoPicture != nullptr) {
2462 err = ThumbnailService::GetInstance()->CreateThumbnailFileScanedWithPicture(
2463 uri, path, originalPhotoPicture, isSync);
2464 } else {
2465 err = ThumbnailService::GetInstance()->CreateThumbnailFileScaned(uri, path, isSync);
2466 }
2467 CHECK_AND_RETURN_LOG(err == E_SUCCESS, "ThumbnailService CreateThumbnailFileScaned failed : %{public}d", err);
2468 }
2469
OnScanFinished(const int32_t status,const string & uri,const string & path)2470 int32_t MediaLibraryAssetOperations::ScanAssetCallback::OnScanFinished(const int32_t status,
2471 const string &uri, const string &path)
2472 {
2473 if (status == E_SCANNED) {
2474 MEDIA_DEBUG_LOG("Asset is scannned");
2475 return E_OK;
2476 } else if (status != E_OK) {
2477 MEDIA_ERR_LOG("Scan is failed, status = %{public}d, skip create thumbnail", status);
2478 return status;
2479 }
2480
2481 string fileId = MediaFileUtils::GetIdFromUri(uri);
2482 int32_t type = MediaFileUtils::GetMediaType(path);
2483 if (this->isInvalidateThumb && PhotoFileUtils::IsThumbnailExists(path) &&
2484 !PhotoFileUtils::IsThumbnailLatest(path)) {
2485 InvalidateThumbnail(fileId, type);
2486 }
2487 CreateThumbnailFileScaned(uri, path, this->isCreateThumbSync, originalPhotoPicture);
2488 MediaFileUtils::DeleteFile(MovingPhotoFileUtils::GetLivePhotoCachePath(path));
2489
2490 #ifdef META_RECOVERY_SUPPORT
2491 int32_t id;
2492 if (StrToInt(fileId, id)) {
2493 MediaLibraryMetaRecovery::GetInstance().WriteSingleMetaDataById(id);
2494 }
2495 #endif
2496
2497 if (this->isInvalidateThumb) {
2498 IsCoverContentChange(fileId);
2499 }
2500 return E_OK;
2501 }
2502
TaskDataFileProccess(DeleteFilesTask * taskData)2503 static void TaskDataFileProccess(DeleteFilesTask *taskData)
2504 {
2505 for (size_t i = 0; i < taskData->paths_.size(); i++) {
2506 string filePath = taskData->paths_[i];
2507 string fileId = i < taskData->ids_.size() ? taskData->ids_[i] : "";
2508 MEDIA_INFO_LOG("Delete file id: %{public}s, path: %{public}s", fileId.c_str(), filePath.c_str());
2509 bool cond = (!MediaFileUtils::DeleteFile(filePath) && (errno != ENOENT));
2510 CHECK_AND_WARN_LOG(!cond, "Failed to delete file, errno: %{public}d, path: %{private}s",
2511 errno, filePath.c_str());
2512
2513 #ifdef META_RECOVERY_SUPPORT
2514 MediaLibraryMetaRecovery::DeleteMetaDataByPath(filePath);
2515
2516 #endif
2517 if (taskData->subTypes_[i] == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
2518 // delete video file of moving photo
2519 string videoPath = MediaFileUtils::GetMovingPhotoVideoPath(filePath);
2520 bool conds = (!MediaFileUtils::DeleteFile(videoPath) && (errno != ENOENT));
2521 CHECK_AND_WARN_LOG(!conds, "Failed to delete video file, errno: %{public}d, path: %{private}s",
2522 errno, videoPath.c_str());
2523
2524 string livePhotoPath = MovingPhotoFileUtils::GetLivePhotoCachePath(filePath);
2525 conds = (MediaFileUtils::IsFileExists(livePhotoPath) && !MediaFileUtils::DeleteFile(livePhotoPath));
2526 CHECK_AND_WARN_LOG(!conds, "Failed to delete cache live photo, errno: %{public}d, path: %{private}s",
2527 errno, livePhotoPath.c_str());
2528 }
2529 }
2530
2531 ThumbnailService::GetInstance()->BatchDeleteThumbnailDirAndAstc(
2532 taskData->table_, taskData->ids_, taskData->paths_, taskData->dateTakens_);
2533 if (taskData->table_ == PhotoColumn::PHOTOS_TABLE) {
2534 for (const auto &path : taskData->paths_) {
2535 MediaLibraryPhotoOperations::DeleteRevertMessage(path);
2536 }
2537 }
2538 }
2539
DeleteFiles(AsyncTaskData * data)2540 static void DeleteFiles(AsyncTaskData *data)
2541 {
2542 MediaLibraryTracer tracer;
2543 tracer.Start("DeleteFiles");
2544 if (data == nullptr) {
2545 return;
2546 }
2547 auto *taskData = static_cast<DeleteFilesTask *>(data);
2548 if (taskData->refresh_ != nullptr) {
2549 taskData->refresh_->RefreshAlbum();
2550 }
2551
2552 DeleteBehaviorData dataInfo {taskData->displayNames_, taskData->albumNames_, taskData->ownerAlbumIds_};
2553 DfxManager::GetInstance()->HandleDeleteBehavior(DfxType::ALBUM_DELETE_ASSETS, taskData->deleteRows_,
2554 taskData->notifyUris_, taskData->bundleName_, dataInfo);
2555 auto watch = MediaLibraryNotify::GetInstance();
2556 CHECK_AND_RETURN_LOG(watch != nullptr, "Can not get MediaLibraryNotify Instance");
2557 int trashAlbumId = watch->GetAlbumIdBySubType(PhotoAlbumSubType::TRASH);
2558 if (trashAlbumId <= 0) {
2559 MEDIA_WARN_LOG("Failed to get trash album id: %{public}d", trashAlbumId);
2560 return;
2561 }
2562 size_t uriSize = taskData->notifyUris_.size() > taskData->isTemps_.size() ? taskData->isTemps_.size() :
2563 taskData->notifyUris_.size();
2564 for (size_t index = 0; index < uriSize; index++) {
2565 if (taskData->isTemps_[index]) {
2566 continue;
2567 }
2568 watch->Notify(MediaFileUtils::Encode(taskData->notifyUris_[index]), NotifyType::NOTIFY_ALBUM_REMOVE_ASSET,
2569 trashAlbumId);
2570 }
2571 if (taskData->refresh_ != nullptr) {
2572 taskData->refresh_->Notify();
2573 }
2574 TaskDataFileProccess(taskData);
2575 }
2576
HandleAudiosResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,DeletedFilesParams & filesParams)2577 void HandleAudiosResultSet(const shared_ptr<NativeRdb::ResultSet> &resultSet, DeletedFilesParams &filesParams)
2578 {
2579 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2580 filesParams.ids.push_back(
2581 to_string(get<int32_t>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_ID, resultSet, TYPE_INT32))));
2582 filesParams.paths.push_back(get<string>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_FILE_PATH,
2583 resultSet, TYPE_STRING)));
2584 filesParams.dateTakens.push_back(get<string>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_DATE_TAKEN,
2585 resultSet, TYPE_STRING)));
2586 filesParams.subTypes.push_back(static_cast<int32_t>(PhotoSubType::DEFAULT));
2587 }
2588 }
2589
HandlePhotosResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,DeletedFilesParams & filesParams)2590 void HandlePhotosResultSet(const shared_ptr<NativeRdb::ResultSet> &resultSet, DeletedFilesParams &filesParams)
2591 {
2592 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2593 filesParams.ids.push_back(
2594 to_string(get<int32_t>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_ID, resultSet, TYPE_INT32))));
2595 filesParams.paths.push_back(get<string>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_FILE_PATH,
2596 resultSet, TYPE_STRING)));
2597 filesParams.dateTakens.push_back(get<string>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_DATE_TAKEN,
2598 resultSet, TYPE_STRING)));
2599 filesParams.subTypes.push_back(
2600 get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::PHOTO_SUBTYPE, resultSet, TYPE_INT32)));
2601 filesParams.isTemps.push_back(
2602 get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::PHOTO_IS_TEMP, resultSet, TYPE_INT32)));
2603 filesParams.displayNames.insert({
2604 to_string(get<int32_t>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_ID, resultSet, TYPE_INT32))),
2605 get<string>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_NAME, resultSet, TYPE_STRING))});
2606 filesParams.ownerAlbumIds.insert({
2607 to_string(get<int32_t>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_ID, resultSet, TYPE_INT32))),
2608 to_string(get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::PHOTO_OWNER_ALBUM_ID, resultSet,
2609 TYPE_INT32)))});
2610 MultiStagesCaptureManager::RemovePhotosWithResultSet(resultSet, false);
2611 if (filesParams.containsHidden) {
2612 continue;
2613 }
2614 int32_t hidden = get<int32_t>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_HIDDEN, resultSet,
2615 TYPE_INT32));
2616 if (hidden > 0) {
2617 filesParams.containsHidden = true;
2618 }
2619 }
2620 }
2621
QueryFileInfoAndHandleRemovePhotos(const AbsRdbPredicates & predicates,DeletedFilesParams & filesParams)2622 int32_t QueryFileInfoAndHandleRemovePhotos(const AbsRdbPredicates &predicates, DeletedFilesParams &filesParams)
2623 {
2624 vector<string> columns = {
2625 MediaColumn::MEDIA_ID,
2626 MediaColumn::MEDIA_FILE_PATH,
2627 MediaColumn::MEDIA_DATE_TAKEN,
2628 PhotoColumn::PHOTO_IS_TEMP
2629 };
2630
2631 if (predicates.GetTableName() == PhotoColumn::PHOTOS_TABLE) {
2632 columns.push_back(PhotoColumn::PHOTO_SUBTYPE);
2633 columns.push_back(MediaColumn::MEDIA_NAME);
2634 columns.push_back(PhotoColumn::PHOTO_OWNER_ALBUM_ID);
2635 columns.push_back(MEDIA_DATA_DB_PHOTO_ID);
2636 columns.push_back(MEDIA_DATA_DB_PHOTO_QUALITY);
2637 columns.push_back(MEDIA_DATA_DB_MEDIA_TYPE);
2638 columns.push_back(MEDIA_DATA_DB_STAGE_VIDEO_TASK_STATUS);
2639 columns.push_back(MediaColumn::MEDIA_HIDDEN);
2640 }
2641
2642 auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
2643 if (resultSet == nullptr) {
2644 return E_HAS_DB_ERROR;
2645 }
2646
2647 if (predicates.GetTableName() == PhotoColumn::PHOTOS_TABLE) {
2648 HandlePhotosResultSet(resultSet, filesParams);
2649 } else if (predicates.GetTableName() == AudioColumn::AUDIOS_TABLE) {
2650 HandleAudiosResultSet(resultSet, filesParams);
2651 } else {
2652 MEDIA_WARN_LOG("Invalid table name.");
2653 }
2654 return E_OK;
2655 }
2656
GetFileAssetsFromResultSet(const shared_ptr<NativeRdb::ResultSet> & resultSet,const vector<string> & fileColumns,vector<shared_ptr<FileAsset>> & fileAssets)2657 static int32_t GetFileAssetsFromResultSet(const shared_ptr<NativeRdb::ResultSet> &resultSet,
2658 const vector<string> &fileColumns, vector<shared_ptr<FileAsset>> &fileAssets)
2659 {
2660 CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "The provided resultSet is nullptr");
2661 int32_t fileCount = 0;
2662 CHECK_AND_RETURN_RET_LOG(resultSet->GetRowCount(fileCount) == NativeRdb::E_OK, E_HAS_DB_ERROR,
2663 "Cannot get fileCount of resultset");
2664 CHECK_AND_RETURN_RET_LOG(fileCount > 0, E_HAS_DB_ERROR, "ResultSet fileCount is %{public}d", fileCount);
2665
2666 fileAssets.reserve(fileCount);
2667 for (int32_t i = 0; i < fileCount; i++) {
2668 CHECK_AND_RETURN_RET_LOG(
2669 resultSet->GoToNextRow() == NativeRdb::E_OK, E_HAS_DB_ERROR, "Failed to go to next row");
2670 auto fileAsset = FetchFileAssetFromResultSet(resultSet, fileColumns);
2671 CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_HAS_DB_ERROR, "Failed to fetch fileAsset from resultSet");
2672 fileAssets.push_back(fileAsset);
2673 }
2674 resultSet->Close();
2675 return E_OK;
2676 }
2677
GetAssetSize(const std::string & extraPath)2678 static int64_t GetAssetSize(const std::string &extraPath)
2679 {
2680 MEDIA_DEBUG_LOG("GetAssetSize start.");
2681 string absExtraPath;
2682 CHECK_AND_RETURN_RET_LOG(PathToRealPath(extraPath, absExtraPath), static_cast<int64_t>(E_ERR),
2683 "file is not real path: %{private}s", extraPath.c_str());
2684
2685 UniqueFd fd(open(absExtraPath.c_str(), O_RDONLY));
2686 CHECK_AND_RETURN_RET_LOG(fd.Get() != E_ERR, static_cast<int64_t>(E_ERR),
2687 "failed to open extra file");
2688
2689 struct stat st;
2690 CHECK_AND_RETURN_RET_LOG(fstat(fd.Get(), &st) == E_OK, static_cast<int64_t>(E_ERR),
2691 "failed to get file size");
2692 off_t fileSize = st.st_size;
2693 return static_cast<int64_t>(fileSize);
2694 }
2695
PushMovingPhotoExternalPath(const std::string & path,const std::string & logTarget,vector<string> & attachment)2696 static void PushMovingPhotoExternalPath(const std::string &path, const std::string &logTarget,
2697 vector<string> &attachment)
2698 {
2699 CHECK_AND_RETURN_WARN_LOG(!path.empty(), "%{public}s is invalid.", logTarget.c_str());
2700 attachment.push_back(path);
2701 }
2702
GetMovingPhotoExternalInfo(ExternalInfo & exInfo,vector<string> & attachment)2703 static void GetMovingPhotoExternalInfo(ExternalInfo &exInfo, vector<string> &attachment)
2704 {
2705 MEDIA_DEBUG_LOG("GetMovingPhotoExternalInfo start.");
2706 CHECK_AND_RETURN(MovingPhotoFileUtils::IsMovingPhoto(exInfo.subType, exInfo.effectMode, exInfo.originalSubType));
2707
2708 exInfo.videoPath = MovingPhotoFileUtils::GetMovingPhotoVideoPath(exInfo.path);
2709 exInfo.extraPath = MovingPhotoFileUtils::GetMovingPhotoExtraDataPath(exInfo.path);
2710 exInfo.photoImagePath = MovingPhotoFileUtils::GetSourceMovingPhotoImagePath(exInfo.path);
2711 exInfo.photoVideoPath = MovingPhotoFileUtils::GetSourceMovingPhotoVideoPath(exInfo.path);
2712 exInfo.cachePath = MovingPhotoFileUtils::GetLivePhotoCachePath(exInfo.path);
2713 PushMovingPhotoExternalPath(exInfo.videoPath, "videoPath", attachment);
2714 PushMovingPhotoExternalPath(exInfo.extraPath, "extraPath", attachment);
2715 PushMovingPhotoExternalPath(exInfo.photoImagePath, "photoImagePath", attachment);
2716 PushMovingPhotoExternalPath(exInfo.photoVideoPath, "photoVideoPath", attachment);
2717 PushMovingPhotoExternalPath(exInfo.cachePath, "cachePath", attachment);
2718 MEDIA_INFO_LOG("videoPath is %{public}s, extraPath is %{public}s, photoImagePath is %{public}s, \
2719 photoVideoPath is %{public}s, cachePath is %{public}s.", DfxUtils::GetSafePath(exInfo.videoPath).c_str(),
2720 DfxUtils::GetSafePath(exInfo.extraPath).c_str(), DfxUtils::GetSafePath(exInfo.photoImagePath).c_str(),
2721 DfxUtils::GetSafePath(exInfo.photoVideoPath).c_str(), DfxUtils::GetSafePath(exInfo.cachePath).c_str());
2722 exInfo.sizeMp4 = GetAssetSize(exInfo.videoPath);
2723 exInfo.sizeExtra = GetAssetSize(exInfo.extraPath);
2724 if (exInfo.sizeMp4 <= INVALID_SIZE) {
2725 MEDIA_WARN_LOG("failed to get mp4 size.");
2726 } else {
2727 exInfo.size += exInfo.sizeMp4;
2728 }
2729 if (exInfo.sizeExtra <= INVALID_SIZE) {
2730 MEDIA_WARN_LOG("failed to get extra size.");
2731 } else {
2732 exInfo.size += exInfo.sizeExtra;
2733 }
2734 MEDIA_DEBUG_LOG("MovingPhoto size is %{public}" PRId64, exInfo.size);
2735 }
2736
GetEditPhotoExternalInfo(ExternalInfo & exInfo,vector<string> & attachment)2737 static void GetEditPhotoExternalInfo(ExternalInfo &exInfo, vector<string> &attachment)
2738 {
2739 MEDIA_DEBUG_LOG("GetEditPhotoExternalInfo start.");
2740 CHECK_AND_RETURN_LOG(exInfo.editTime != 0, "editTime is zero");
2741
2742 exInfo.editDataPath = PhotoFileUtils::GetEditDataPath(exInfo.path);
2743 exInfo.editDataCameraPath = PhotoFileUtils::GetEditDataCameraPath(exInfo.path);
2744 exInfo.editDataSourcePath = PhotoFileUtils::GetEditDataSourcePath(exInfo.path);
2745 PushMovingPhotoExternalPath(exInfo.editDataPath, "editDataPath", attachment);
2746 PushMovingPhotoExternalPath(exInfo.editDataCameraPath, "editDataCameraPath", attachment);
2747 PushMovingPhotoExternalPath(exInfo.editDataSourcePath, "editDataSourcePath", attachment);
2748 MEDIA_INFO_LOG("editDataPath is %{public}s, editDataCameraPath is %{public}s, editDataSourcePath is %{public}s",
2749 DfxUtils::GetSafePath(exInfo.editDataPath).c_str(), DfxUtils::GetSafePath(exInfo.editDataCameraPath).c_str(),
2750 DfxUtils::GetSafePath(exInfo.editDataSourcePath).c_str());
2751 }
2752
GetCleanFileInfo(shared_ptr<FileAsset> & fileAssetPtr)2753 static CleanFileInfo GetCleanFileInfo(shared_ptr<FileAsset> &fileAssetPtr)
2754 {
2755 MEDIA_DEBUG_LOG("GetCleanFileInfo start.");
2756 CHECK_AND_RETURN_RET_LOG(fileAssetPtr != nullptr, {}, "GetCleanFileInfo fileAssetPtr is nullptr.");
2757
2758 CleanFileInfo cleanFileInfo;
2759 ExternalInfo externalInfo;
2760 externalInfo.path = fileAssetPtr->GetPath();
2761 externalInfo.size = fileAssetPtr->GetSize();
2762 if (externalInfo.size == INVALID_SIZE) {
2763 externalInfo.size = GetAssetSize(externalInfo.path);
2764 CHECK_AND_RETURN_RET_LOG(externalInfo.size > INVALID_SIZE, {}, "failed to get asset size.");
2765 }
2766 MEDIA_INFO_LOG("path is %{public}s", DfxUtils::GetSafePath(externalInfo.path).c_str());
2767 externalInfo.cloudId = fileAssetPtr->GetCloudId();
2768 externalInfo.subType = fileAssetPtr->GetPhotoSubType();
2769 externalInfo.effectMode = fileAssetPtr->GetMovingPhotoEffectMode();
2770 externalInfo.originalSubType = fileAssetPtr->GetOriginalSubType();
2771 GetMovingPhotoExternalInfo(externalInfo, cleanFileInfo.attachment);
2772 MEDIA_DEBUG_LOG("size is %{public}" PRId64, externalInfo.size);
2773 externalInfo.dateModified = fileAssetPtr->GetDateModified();
2774 externalInfo.displayName = fileAssetPtr->GetDisplayName();
2775 externalInfo.editTime = fileAssetPtr->GetPhotoEditTime();
2776 GetEditPhotoExternalInfo(externalInfo, cleanFileInfo.attachment);
2777 cleanFileInfo.cloudId = externalInfo.cloudId;
2778 cleanFileInfo.size = externalInfo.size;
2779 cleanFileInfo.modifiedTime = externalInfo.dateModified;
2780 cleanFileInfo.path = externalInfo.path;
2781 cleanFileInfo.fileName = MediaFileUtils::GetFileName(externalInfo.path);
2782 return cleanFileInfo;
2783 }
2784
GetBurstFileInfo(const string & key,vector<CleanFileInfo> & fileInfos)2785 static int32_t GetBurstFileInfo(const string &key, vector<CleanFileInfo> &fileInfos)
2786 {
2787 MEDIA_DEBUG_LOG("GetBurstFileInfo start.");
2788 AbsRdbPredicates rbdPredicates(PhotoColumn::PHOTOS_TABLE);
2789 rbdPredicates.EqualTo(PhotoColumn::PHOTO_BURST_KEY, key);
2790 vector<string> columns = {
2791 PhotoColumn::PHOTO_CLOUD_ID,
2792 MediaColumn::MEDIA_SIZE,
2793 MediaColumn::MEDIA_DATE_MODIFIED,
2794 MediaColumn::MEDIA_FILE_PATH,
2795 MediaColumn::MEDIA_NAME,
2796 MediaColumn::MEDIA_ID,
2797 PhotoColumn::PHOTO_POSITION,
2798 PhotoColumn::PHOTO_BURST_KEY,
2799 PhotoColumn::PHOTO_SUBTYPE,
2800 PhotoColumn::MOVING_PHOTO_EFFECT_MODE,
2801 PhotoColumn::PHOTO_ORIGINAL_SUBTYPE,
2802 PhotoColumn::PHOTO_EDIT_TIME,
2803 };
2804
2805 auto resultSet = MediaLibraryRdbStore::QueryWithFilter(rbdPredicates, columns);
2806 vector<shared_ptr<FileAsset>> fileAssetVector;
2807 GetFileAssetsFromResultSet(resultSet, columns, fileAssetVector);
2808 CHECK_AND_RETURN_RET_LOG(!fileAssetVector.empty(), E_HAS_DB_ERROR,
2809 "GetBurstFileInfo fileAssetVector is empty.");
2810 for (auto& fileAssetPtr : fileAssetVector) {
2811 fileInfos.push_back(GetCleanFileInfo(fileAssetPtr));
2812 }
2813 return E_OK;
2814 }
2815
BatchDeleteLocalAndCloud(const vector<CleanFileInfo> & fileInfos,const map<string,int32_t> & notifyMap)2816 static void BatchDeleteLocalAndCloud(const vector<CleanFileInfo> &fileInfos, const map<string, int32_t> ¬ifyMap)
2817 {
2818 CHECK_AND_RETURN_LOG(!fileInfos.empty(), "Batch delete local and cloud fileInfo is empty.");
2819 vector<string> failCloudId;
2820 MediaLibraryTracer tracer;
2821 tracer.Start("BatchDeleteLocalAndCloud");
2822 auto ret = CloudSyncManager::GetInstance().BatchCleanFile(fileInfos, failCloudId);
2823 if (ret != 0) {
2824 MEDIA_ERR_LOG("Failed to delete local and cloud photos permanently.");
2825 return;
2826 }
2827
2828 auto watch = MediaLibraryNotify::GetInstance();
2829 CHECK_AND_RETURN_LOG(watch != nullptr, "watch is nullptr");
2830 for (const auto &fileInfo : fileInfos) {
2831 string cloudId = fileInfo.cloudId;
2832 if (find(failCloudId.begin(), failCloudId.end(), cloudId) != failCloudId.end()) {
2833 MEDIA_ERR_LOG("Failed to delete, cloudId is %{public}s.", cloudId.c_str());
2834 continue;
2835 }
2836 if (notifyMap.find(cloudId) != notifyMap.end()) {
2837 watch->Notify(PhotoColumn::PHOTO_URI_PREFIX + to_string(notifyMap.at(cloudId)), NotifyType::NOTIFY_UPDATE);
2838 }
2839 }
2840 }
2841
DeleteLocalAndCloudPhotos(vector<shared_ptr<FileAsset>> & subFileAsset)2842 static int32_t DeleteLocalAndCloudPhotos(vector<shared_ptr<FileAsset>> &subFileAsset)
2843 {
2844 MediaLibraryTracer tracer;
2845 tracer.Start("DeleteLocalAndCloudPhotos");
2846 MEDIA_DEBUG_LOG("DeleteLocalAndCloudPhotos start.");
2847 vector<CleanFileInfo> fileInfos;
2848 if (subFileAsset.empty()) {
2849 MEDIA_INFO_LOG("DeleteLocalAndCloudPhotos subFileAsset is empty.");
2850 return E_OK;
2851 }
2852
2853 map<string, int32_t> notifyMap;
2854 for (auto& fileAssetPtr : subFileAsset) {
2855 CHECK_AND_CONTINUE(fileAssetPtr != nullptr);
2856 notifyMap[fileAssetPtr->GetCloudId()] = fileAssetPtr->GetId();
2857 string burst_key = fileAssetPtr->GetBurstKey();
2858 if (burst_key != "") {
2859 GetBurstFileInfo(burst_key, fileInfos);
2860 continue;
2861 }
2862 fileInfos.push_back(GetCleanFileInfo(fileAssetPtr));
2863 }
2864 vector<CleanFileInfo> subFileInfo;
2865 int32_t count = 0;
2866 for (const auto& element : fileInfos) {
2867 MEDIA_INFO_LOG("delete local and cloud file displayName is %{public}s", element.fileName.c_str());
2868 subFileInfo.push_back(element);
2869 count++;
2870 if (count == MAX_PROCESS_NUM) {
2871 BatchDeleteLocalAndCloud(subFileInfo, notifyMap);
2872 subFileInfo.clear();
2873 count = 0;
2874 }
2875 }
2876 if (!subFileInfo.empty()) {
2877 BatchDeleteLocalAndCloud(subFileInfo, notifyMap);
2878 }
2879 return E_OK;
2880 }
2881
DeleteDbByIds(const string & table,vector<string> & ids,const bool compatible,shared_ptr<AccurateRefresh::AssetAccurateRefresh> refresh)2882 static int32_t DeleteDbByIds(const string &table, vector<string> &ids, const bool compatible,
2883 shared_ptr<AccurateRefresh::AssetAccurateRefresh> refresh)
2884 {
2885 AbsRdbPredicates predicates(table);
2886 predicates.In(MediaColumn::MEDIA_ID, ids);
2887 if (!compatible) {
2888 predicates.GreaterThan(MediaColumn::MEDIA_DATE_TRASHED, to_string(0));
2889 }
2890 int32_t deletedRows = 0;
2891 int32_t err = refresh->LogicalDeleteReplaceByUpdate(predicates, deletedRows);
2892 if (err != E_OK) {
2893 MEDIA_ERR_LOG("Failed to execute delete, err: %{public}d", err);
2894 MediaLibraryRestore::GetInstance().CheckRestore(err);
2895 return E_HAS_DB_ERROR;
2896 }
2897 CloudSyncHelper::GetInstance()->StartSync();
2898 return deletedRows;
2899 }
2900
GetAlbumNamesById(DeletedFilesParams & filesParams)2901 static void GetAlbumNamesById(DeletedFilesParams &filesParams)
2902 {
2903 MediaLibraryTracer tracer;
2904 tracer.Start("GetAlbumNamesById");
2905 CHECK_AND_RETURN_LOG(!filesParams.ownerAlbumIds.empty(), "ownerAlbumIds is empty");
2906 vector<string> ownerAlbumIdList;
2907 set<string> albumIdSet;
2908 for (const auto &fileId : filesParams.ownerAlbumIds) {
2909 albumIdSet.insert(fileId.second);
2910 }
2911 ownerAlbumIdList.assign(albumIdSet.begin(), albumIdSet.end());
2912 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2913 CHECK_AND_RETURN_LOG(uniStore != nullptr, "rdbstore is nullptr");
2914 MediaLibraryCommand queryAlbumMapCmd(OperationObject::PAH_ALBUM, OperationType::QUERY);
2915 queryAlbumMapCmd.GetAbsRdbPredicates()->In(PhotoAlbumColumns::ALBUM_ID, ownerAlbumIdList);
2916 auto resultSet = uniStore->Query(queryAlbumMapCmd, {PhotoAlbumColumns::ALBUM_ID, PhotoAlbumColumns::ALBUM_NAME});
2917 CHECK_AND_RETURN_LOG(resultSet != nullptr, "Failed to query resultSet");
2918 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2919 filesParams.albumNames.insert({
2920 to_string(get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoAlbumColumns::ALBUM_ID, resultSet,
2921 TYPE_INT32))),
2922 get<string>(ResultSetUtils::GetValFromColumn(PhotoAlbumColumns::ALBUM_NAME, resultSet,
2923 TYPE_STRING))});
2924 }
2925 resultSet->Close();
2926 }
2927
2928 /**
2929 * @brief Delete files permanently from system.
2930 *
2931 * @param predicates Files to delete.
2932 * @param isAging Whether in aging process.
2933 * @param compatible API8 interfaces can delete files directly without trash.
2934 * true: Delete files, may including non-trashed files.
2935 * false: Only delete files that were already trashed.
2936 * @return Return deleted rows
2937 */
DeleteFromDisk(AbsRdbPredicates & predicates,const bool isAging,const bool compatible)2938 int32_t MediaLibraryAssetOperations::DeleteFromDisk(AbsRdbPredicates &predicates,
2939 const bool isAging, const bool compatible)
2940 {
2941 MediaLibraryTracer tracer;
2942 tracer.Start("DeleteFromDisk");
2943 MEDIA_INFO_LOG("DeleteFromDisk start");
2944 vector<string> whereArgs = predicates.GetWhereArgs();
2945 MediaLibraryRdbStore::ReplacePredicatesUriToId(predicates);
2946 vector<string> agingNotifyUris;
2947
2948 // Query asset uris for notify before delete.
2949 if (isAging) {
2950 MediaLibraryNotify::GetNotifyUris(predicates, agingNotifyUris);
2951 }
2952 DeletedFilesParams fileParams;
2953 int32_t deletedRows = 0;
2954 int32_t ret = QueryFileInfoAndHandleRemovePhotos(predicates, fileParams);
2955 CHECK_AND_RETURN_RET_LOG(ret == E_OK, E_HAS_DB_ERROR, "query db error");
2956 GetAlbumNamesById(fileParams);
2957 CHECK_AND_RETURN_RET_LOG(!fileParams.ids.empty(), deletedRows, "Failed to delete files in db, ids size: 0");
2958
2959 // delete cloud enhanacement task
2960 #ifdef MEDIALIBRARY_FEATURE_CLOUD_ENHANCEMENT
2961 vector<string> photoIds;
2962 EnhancementManager::GetInstance().RemoveTasksInternal(fileParams.ids, photoIds);
2963 #endif
2964 auto assetRefresh = make_shared<AccurateRefresh::AssetAccurateRefresh>(
2965 AccurateRefresh::DELETE_PHOTOS_BUSSINESS_NAME);
2966 deletedRows = DeleteDbByIds(predicates.GetTableName(), fileParams.ids, compatible, assetRefresh);
2967 CHECK_AND_RETURN_RET_LOG(deletedRows > 0, deletedRows,
2968 "Failed to delete files in db, deletedRows: %{public}d, ids size: %{public}zu",
2969 deletedRows, fileParams.ids.size());
2970
2971 MEDIA_INFO_LOG("Delete files in db, deletedRows: %{public}d", deletedRows);
2972 auto asyncWorker = MediaLibraryAsyncWorker::GetInstance();
2973 CHECK_AND_RETURN_RET_LOG(asyncWorker != nullptr, E_ERR, "Can not get asyncWorker");
2974
2975 const vector<string> ¬ifyUris = isAging ? agingNotifyUris : whereArgs;
2976 string bundleName = MediaLibraryBundleManager::GetInstance()->GetClientBundleName();
2977 auto *taskData = new (nothrow) DeleteFilesTask(fileParams.ids, fileParams.paths, notifyUris,
2978 fileParams.dateTakens, fileParams.subTypes,
2979 predicates.GetTableName(), deletedRows, bundleName, fileParams.containsHidden);
2980 CHECK_AND_RETURN_RET_LOG(taskData != nullptr, E_ERR, "Failed to alloc async data for Delete From Disk!");
2981 taskData->SetOtherInfos(fileParams.displayNames, fileParams.albumNames, fileParams.ownerAlbumIds);
2982 taskData->isTemps_.swap(fileParams.isTemps);
2983 taskData->SetAssetAccurateRefresh(assetRefresh);
2984 auto deleteFilesTask = make_shared<MediaLibraryAsyncTask>(DeleteFiles, taskData);
2985 CHECK_AND_RETURN_RET_LOG(deleteFilesTask != nullptr, E_ERR, "Failed to create async task for deleting files.");
2986 asyncWorker->AddTask(deleteFilesTask, true);
2987
2988 CloudMediaAssetManager::GetInstance().SetIsThumbnailUpdate();
2989 return deletedRows;
2990 }
2991
GetAlbumTypeSubTypeById(const string & albumId,PhotoAlbumType & type,PhotoAlbumSubType & subType)2992 static int32_t GetAlbumTypeSubTypeById(const string &albumId, PhotoAlbumType &type, PhotoAlbumSubType &subType)
2993 {
2994 RdbPredicates predicates(PhotoAlbumColumns::TABLE);
2995 predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, albumId);
2996 vector<string> columns = { PhotoAlbumColumns::ALBUM_TYPE, PhotoAlbumColumns::ALBUM_SUBTYPE };
2997 auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
2998 if (resultSet == nullptr) {
2999 MEDIA_ERR_LOG("album id %{private}s is not exist", albumId.c_str());
3000 return E_INVALID_ARGUMENTS;
3001 }
3002 CHECK_AND_RETURN_RET_LOG(resultSet->GoToFirstRow() == NativeRdb::E_OK, E_INVALID_ARGUMENTS,
3003 "album id is not exist");
3004 type = static_cast<PhotoAlbumType>(GetInt32Val(PhotoAlbumColumns::ALBUM_TYPE, resultSet));
3005 subType = static_cast<PhotoAlbumSubType>(GetInt32Val(PhotoAlbumColumns::ALBUM_SUBTYPE, resultSet));
3006 resultSet->Close();
3007 return E_SUCCESS;
3008 }
3009
NotifyPhotoAlbum(const vector<int32_t> & changedAlbumIds,std::shared_ptr<AccurateRefresh::AssetAccurateRefresh> assetRefresh)3010 static void NotifyPhotoAlbum(const vector<int32_t> &changedAlbumIds,
3011 std::shared_ptr<AccurateRefresh::AssetAccurateRefresh> assetRefresh)
3012 {
3013 if (changedAlbumIds.size() <= 0) {
3014 return;
3015 }
3016 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
3017 if (rdbStore == nullptr) {
3018 MEDIA_ERR_LOG("Can not get rdbstore");
3019 return;
3020 }
3021 for (int32_t albumId : changedAlbumIds) {
3022 MEDIA_DEBUG_LOG("NotifyPortraitAlbum album id is %{public}d", albumId);
3023 PhotoAlbumType type;
3024 PhotoAlbumSubType subType;
3025 int32_t ret = GetAlbumTypeSubTypeById(to_string(albumId), type, subType);
3026 if (ret != E_SUCCESS) {
3027 MEDIA_ERR_LOG("Get album type and subType by album id failed");
3028 continue;
3029 }
3030 }
3031 if (assetRefresh == nullptr) {
3032 MEDIA_ERR_LOG("assetRefresh is nullptr");
3033 return;
3034 }
3035 assetRefresh->RefreshAlbum(static_cast<NotifyAlbumType>(NotifyAlbumType::SYS_ALBUM | NotifyAlbumType::USER_ALBUM |
3036 NotifyAlbumType::SOURCE_ALBUM));
3037 MediaLibraryRdbUtils::UpdateAnalysisAlbumInternal(rdbStore);
3038 assetRefresh->Notify();
3039 }
3040
DeleteNormalPhotoPermanently(shared_ptr<FileAsset> & fileAsset,std::shared_ptr<AccurateRefresh::AssetAccurateRefresh> assetRefresh)3041 int32_t MediaLibraryAssetOperations::DeleteNormalPhotoPermanently(shared_ptr<FileAsset> &fileAsset,
3042 std::shared_ptr<AccurateRefresh::AssetAccurateRefresh> assetRefresh)
3043 {
3044 MediaLibraryTracer tracer;
3045 tracer.Start("DeleteNormalPhotoPermanently");
3046 CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_HAS_DB_ERROR,
3047 "Photo Asset is nullptr");
3048 string filePath = fileAsset->GetPath();
3049 string displayName = fileAsset->GetDisplayName();
3050 MEDIA_INFO_LOG("Delete Photo displayName is %{public}s", displayName.c_str());
3051 MEDIA_DEBUG_LOG("Delete Photo path is %{public}s", filePath.c_str());
3052 CHECK_AND_RETURN_RET_LOG(!filePath.empty(), E_INVALID_PATH, "get file path failed");
3053 bool res = MediaFileUtils::DeleteFile(filePath);
3054 CHECK_AND_RETURN_RET_LOG(res, E_HAS_FS_ERROR, "Delete photo file failed, errno: %{public}d", errno);
3055
3056 //delete thumbnail
3057 int32_t fileId = fileAsset->GetId();
3058 MediaLibraryAssetOperations::InvalidateThumbnail(to_string(fileId), fileAsset->GetMediaType());
3059
3060 // delete file in db
3061 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_PHOTO, OperationType::DELETE);
3062 cmd.GetAbsRdbPredicates()->EqualTo(PhotoColumn::MEDIA_ID, to_string(fileId));
3063 int32_t deleteRows = DeleteAssetInDb(cmd, assetRefresh);
3064 MEDIA_DEBUG_LOG("Total delete row in db is %{public}d", deleteRows);
3065 CHECK_AND_RETURN_RET_LOG(deleteRows > 0, E_HAS_DB_ERROR,
3066 "Delete photo in database failed, errCode=%{public}d", deleteRows);
3067
3068 auto watch = MediaLibraryNotify::GetInstance();
3069 CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_HAS_FS_ERROR, "watch is nullptr");
3070 string notifyDeleteUri =
3071 MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(fileId),
3072 MediaFileUtils::GetExtraUri(displayName, filePath));
3073 watch->Notify(notifyDeleteUri, NotifyType::NOTIFY_REMOVE);
3074 std::vector<std::string> notifyDeleteUris;
3075 notifyDeleteUris.push_back(notifyDeleteUri);
3076 auto dfxManager = DfxManager::GetInstance();
3077 if (dfxManager != nullptr) {
3078 DeletedFilesParams fileParams;
3079 fileParams.ownerAlbumIds.insert({to_string(fileId), to_string(fileAsset->GetOwnerAlbumId())});
3080 GetAlbumNamesById(fileParams);
3081 DeleteBehaviorData dataInfo {{{to_string(fileId), displayName}},
3082 fileParams.albumNames, fileParams.ownerAlbumIds };
3083 dfxManager->HandleDeleteBehavior(DfxType::DELETE_LOCAL_ASSETS_PERMANENTLY, deleteRows,
3084 notifyDeleteUris, "", dataInfo);
3085 }
3086 MediaLibraryPhotoOperations::DeleteRevertMessage(filePath);
3087 return E_OK;
3088 }
3089
DeletePhotoPermanentlyFromVector(vector<shared_ptr<FileAsset>> & fileAssetVector)3090 static int32_t DeletePhotoPermanentlyFromVector(vector<shared_ptr<FileAsset>> &fileAssetVector)
3091 {
3092 for (auto& fileAssetPtr : fileAssetVector) {
3093 MEDIA_DEBUG_LOG("Delete photo display name %{public}s", fileAssetPtr->GetDisplayName().c_str());
3094 CHECK_AND_RETURN_RET_LOG(fileAssetPtr != nullptr, E_HAS_DB_ERROR,
3095 "Photo Asset is nullptr");
3096 MediaLibraryAssetOperations::DeleteNormalPhotoPermanently(fileAssetPtr);
3097 }
3098 return E_OK;
3099 }
3100
DeleteBurstPhotoPermanently(shared_ptr<FileAsset> & fileAsset)3101 static int32_t DeleteBurstPhotoPermanently(shared_ptr<FileAsset> &fileAsset)
3102 {
3103 MEDIA_DEBUG_LOG("DeleteBurstPhotoPermanently begin");
3104 CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_HAS_DB_ERROR,
3105 "Photo Asset is nullptr");
3106 string burstKey = fileAsset->GetBurstKey();
3107 MEDIA_DEBUG_LOG("Deleteburst is %{public}s", burstKey.c_str());
3108 CHECK_AND_RETURN_RET(burstKey != "", E_OK);
3109
3110 vector<shared_ptr<FileAsset>> burstFileAssetVector;
3111 AbsRdbPredicates rbdPredicates(PhotoColumn::PHOTOS_TABLE);
3112 rbdPredicates.EqualTo(PhotoColumn::PHOTO_BURST_KEY, burstKey);
3113 vector<string> columns = {
3114 MediaColumn::MEDIA_FILE_PATH,
3115 MediaColumn::MEDIA_ID,
3116 MediaColumn::MEDIA_TYPE,
3117 };
3118 auto resultSet = MediaLibraryRdbStore::QueryWithFilter(rbdPredicates, columns);
3119 GetFileAssetsFromResultSet(resultSet, columns, burstFileAssetVector);
3120 DeletePhotoPermanentlyFromVector(burstFileAssetVector);
3121 return E_OK;
3122 }
3123
DeleteMovingPhotoPermanently(shared_ptr<FileAsset> & fileAsset)3124 static int32_t DeleteMovingPhotoPermanently(shared_ptr<FileAsset> &fileAsset)
3125 {
3126 CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_HAS_DB_ERROR, "Photo Asset is nullptr");
3127 int32_t subType = fileAsset->GetPhotoSubType();
3128 int32_t effectMode = fileAsset->GetMovingPhotoEffectMode();
3129 int32_t originalSubType = fileAsset->GetOriginalSubType();
3130 if (MovingPhotoFileUtils::IsMovingPhoto(subType, effectMode, originalSubType)) {
3131 string path = fileAsset->GetPath();
3132 string videoPath = MovingPhotoFileUtils::GetMovingPhotoVideoPath(path);
3133 if (!MediaFileUtils::DeleteFile(videoPath)) {
3134 MEDIA_INFO_LOG("delete video path is %{public}s, errno: %{public}d",
3135 DfxUtils::GetSafePath(videoPath).c_str(), errno);
3136 }
3137 string exVideoPath = MovingPhotoFileUtils::GetMovingPhotoExtraDataPath(path);
3138 if (!MediaFileUtils::DeleteFile(exVideoPath)) {
3139 MEDIA_INFO_LOG("delete extra video path is %{public}s, errno: %{public}d",
3140 DfxUtils::GetSafePath(exVideoPath).c_str(), errno);
3141 }
3142 string sourceImagePath = MovingPhotoFileUtils::GetSourceMovingPhotoImagePath(path);
3143 if (!MediaFileUtils::DeleteFile(sourceImagePath)) {
3144 MEDIA_INFO_LOG("delete source image path is %{public}s, errno: %{public}d",
3145 DfxUtils::GetSafePath(sourceImagePath).c_str(), errno);
3146 }
3147 string sourceVideoPath = MovingPhotoFileUtils::GetSourceMovingPhotoVideoPath(path);
3148 if (!MediaFileUtils::DeleteFile(sourceVideoPath)) {
3149 MEDIA_INFO_LOG("delete source video path is %{public}s, errno: %{public}d",
3150 DfxUtils::GetSafePath(sourceVideoPath).c_str(), errno);
3151 }
3152 string livePhotoCachePath = MovingPhotoFileUtils::GetLivePhotoCachePath(path);
3153 if (!MediaFileUtils::DeleteFile(livePhotoCachePath)) {
3154 MEDIA_INFO_LOG("delete live photo cache path is %{public}s, errno: %{public}d",
3155 DfxUtils::GetSafePath(livePhotoCachePath).c_str(), errno);
3156 }
3157 }
3158 return E_OK;
3159 }
3160
DeleteEditPhotoPermanently(shared_ptr<FileAsset> & fileAsset)3161 static int32_t DeleteEditPhotoPermanently(shared_ptr<FileAsset> &fileAsset)
3162 {
3163 CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_HAS_DB_ERROR,
3164 "Photo Asset is nullptr");
3165 int64_t editTime = fileAsset->GetPhotoEditTime();
3166 if (editTime != 0) {
3167 string path = fileAsset->GetPath();
3168 string editDataPath = PhotoFileUtils::GetEditDataPath(path);
3169 MEDIA_DEBUG_LOG("edit photo editDataPath path is %{public}s", editDataPath.c_str());
3170 if (!MediaFileUtils::DeleteFile(editDataPath)) {
3171 MEDIA_INFO_LOG("delete edit data path is %{public}s, errno: %{public}d",
3172 DfxUtils::GetSafePath(editDataPath).c_str(), errno);
3173 }
3174 string editDataCameraPath = PhotoFileUtils::GetEditDataCameraPath(path);
3175 if (!MediaFileUtils::DeleteFile(editDataCameraPath)) {
3176 MEDIA_INFO_LOG("delete edit data camera path is %{public}s, errno: %{public}d",
3177 DfxUtils::GetSafePath(editDataCameraPath).c_str(), errno);
3178 }
3179 }
3180 return E_OK;
3181 }
3182
DeleteLocalPhotoPermanently(shared_ptr<FileAsset> & fileAsset,vector<shared_ptr<FileAsset>> & subFileAssetVector,std::shared_ptr<AccurateRefresh::AssetAccurateRefresh> assetRefresh)3183 static int32_t DeleteLocalPhotoPermanently(shared_ptr<FileAsset> &fileAsset,
3184 vector<shared_ptr<FileAsset>> &subFileAssetVector,
3185 std::shared_ptr<AccurateRefresh::AssetAccurateRefresh> assetRefresh)
3186 {
3187 CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_HAS_DB_ERROR,
3188 "Photo Asset is nullptr");
3189 int32_t position = fileAsset->GetPosition();
3190 MEDIA_DEBUG_LOG("Photo position is %{public}d", position);
3191 if (position == LOCAL_PHOTO_POSITION) {
3192 int32_t id = fileAsset->GetId();
3193 CHECK_AND_PRINT_LOG(DeleteEditPhotoPermanently(fileAsset) == E_OK,
3194 "Delete edit photo file failed id %{public}d", id);
3195
3196 CHECK_AND_PRINT_LOG(DeleteMovingPhotoPermanently(fileAsset) == E_OK,
3197 "Delete moving photo file failed id %{public}d", id);
3198
3199 CHECK_AND_PRINT_LOG(DeleteBurstPhotoPermanently(fileAsset) == E_OK,
3200 "Delete moving photo file failed id %{public}d", id);
3201
3202 CHECK_AND_PRINT_LOG(MediaLibraryAssetOperations::DeleteNormalPhotoPermanently(fileAsset, assetRefresh) == E_OK,
3203 "Delete moving photo file failed id %{public}d", id);
3204 }
3205 if (position == CLOUD_PHOTO_POSITION) {
3206 MEDIA_DEBUG_LOG("Don't delete cloud Photo");
3207 }
3208 if (position == BOTH_LOCAL_CLOUD_PHOTO_POSITION) {
3209 subFileAssetVector.push_back(fileAsset);
3210 }
3211 return E_OK;
3212 }
3213
DeletePermanently(AbsRdbPredicates & predicates,const bool isAging,std::shared_ptr<AccurateRefresh::AssetAccurateRefresh> assetRefresh)3214 int32_t MediaLibraryAssetOperations::DeletePermanently(AbsRdbPredicates &predicates, const bool isAging,
3215 std::shared_ptr<AccurateRefresh::AssetAccurateRefresh> assetRefresh)
3216 {
3217 if (assetRefresh == nullptr) {
3218 assetRefresh = make_shared<AccurateRefresh::AssetAccurateRefresh>(
3219 AccurateRefresh::DELETE_PHOTOS_COMPLETED_BUSSINESS_NAME);
3220 }
3221 MEDIA_DEBUG_LOG("DeletePermanently begin");
3222 MediaLibraryTracer tracer;
3223 tracer.Start("DeletePermanently");
3224 MediaLibraryRdbStore::ReplacePredicatesUriToId(predicates);
3225 vector<string> agingNotifyUris;
3226
3227 // Query asset uris for notify before delete.
3228 if (isAging) {
3229 MediaLibraryNotify::GetNotifyUris(predicates, agingNotifyUris);
3230 }
3231
3232 vector<string> columns = {
3233 PhotoColumn::PHOTO_CLOUD_ID,
3234 MediaColumn::MEDIA_SIZE,
3235 MediaColumn::MEDIA_DATE_MODIFIED,
3236 MediaColumn::MEDIA_FILE_PATH,
3237 MediaColumn::MEDIA_NAME,
3238 MediaColumn::MEDIA_ID,
3239 PhotoColumn::PHOTO_POSITION,
3240 PhotoColumn::PHOTO_BURST_KEY,
3241 MediaColumn::MEDIA_TYPE,
3242 PhotoColumn::PHOTO_SUBTYPE,
3243 PhotoColumn::MOVING_PHOTO_EFFECT_MODE,
3244 PhotoColumn::PHOTO_ORIGINAL_SUBTYPE,
3245 PhotoColumn::PHOTO_EDIT_TIME,
3246 PhotoColumn::PHOTO_OWNER_ALBUM_ID,
3247 };
3248 auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
3249 vector<shared_ptr<FileAsset>> fileAssetVector;
3250 vector<shared_ptr<FileAsset>> subFileAssetVector;
3251 std::set<int32_t> changedAlbumIds;
3252 GetAssetVectorFromResultSet(resultSet, columns, fileAssetVector);
3253 if (resultSet != nullptr) {
3254 resultSet->Close();
3255 }
3256 for (auto& fileAssetPtr : fileAssetVector) {
3257 DeleteLocalPhotoPermanently(fileAssetPtr, subFileAssetVector, assetRefresh);
3258 changedAlbumIds.insert(fileAssetPtr->GetOwnerAlbumId());
3259 }
3260
3261 //delete both local and cloud image
3262 DeleteLocalAndCloudPhotos(subFileAssetVector);
3263 NotifyPhotoAlbum(std::vector<int32_t>(changedAlbumIds.begin(), changedAlbumIds.end()), assetRefresh);
3264 return E_OK;
3265 }
3266 } // namespace Media
3267 } // namespace OHOS