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