• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_photo_operations.h"
17 
18 #include <memory>
19 #include <mutex>
20 #include <thread>
21 #include <nlohmann/json.hpp>
22 
23 #include "abs_shared_result_set.h"
24 #include "directory_ex.h"
25 #include "duplicate_photo_operation.h"
26 #include "file_asset.h"
27 #include "file_utils.h"
28 #include "image_source.h"
29 #include "media_analysis_helper.h"
30 #include "image_packer.h"
31 #include "iservice_registry.h"
32 #include "media_change_effect.h"
33 #include "media_column.h"
34 #include "media_exif.h"
35 #include "media_file_uri.h"
36 #include "media_file_utils.h"
37 #include "media_log.h"
38 #include "medialibrary_album_fusion_utils.h"
39 #include "medialibrary_album_operations.h"
40 #include "medialibrary_analysis_album_operations.h"
41 #include "medialibrary_asset_operations.h"
42 #include "medialibrary_command.h"
43 #include "medialibrary_data_manager_utils.h"
44 #include "medialibrary_db_const.h"
45 #include "medialibrary_errno.h"
46 #include "medialibrary_inotify.h"
47 #include "medialibrary_notify.h"
48 #include "medialibrary_object_utils.h"
49 #include "medialibrary_rdb_utils.h"
50 #include "medialibrary_rdb_transaction.h"
51 #include "medialibrary_rdbstore.h"
52 #include "medialibrary_tracer.h"
53 #include "medialibrary_type_const.h"
54 #include "medialibrary_uripermission_operations.h"
55 #include "mimetype_utils.h"
56 #include "multistages_capture_manager.h"
57 #include "multistages_photo_capture_manager.h"
58 #include "multistages_moving_photo_capture_manager.h"
59 #ifdef MEDIALIBRARY_FEATURE_CLOUD_ENHANCEMENT
60 #include "enhancement_manager.h"
61 #endif
62 #include "parameters.h"
63 #include "permission_utils.h"
64 #include "photo_album_column.h"
65 #include "photo_custom_restore_operation.h"
66 #include "photo_map_column.h"
67 #include "photo_map_operations.h"
68 #include "picture.h"
69 #include "image_type.h"
70 #include "picture_manager_thread.h"
71 
72 #include "rdb_predicates.h"
73 #include "result_set_utils.h"
74 #include "thumbnail_const.h"
75 #include "thumbnail_service.h"
76 #include "uri.h"
77 #include "userfile_manager_types.h"
78 #include "value_object.h"
79 #include "values_bucket.h"
80 #include "medialibrary_formmap_operations.h"
81 #include "medialibrary_vision_operations.h"
82 #include "dfx_manager.h"
83 #include "dfx_utils.h"
84 #include "moving_photo_file_utils.h"
85 #include "hi_audit.h"
86 #include "video_composition_callback_imp.h"
87 
88 using namespace OHOS::DataShare;
89 using namespace std;
90 using namespace OHOS::NativeRdb;
91 using namespace OHOS::RdbDataShareAdapter;
92 
93 namespace OHOS {
94 namespace Media {
95 static const string ANALYSIS_HAS_DATA = "1";
96 const string PHOTO_ALBUM_URI_PREFIX_V0 = "file://media/PhotoAlbum/";
97 constexpr int SAVE_PHOTO_WAIT_MS = 300;
98 constexpr int TASK_NUMBER_MAX = 5;
99 
100 constexpr int32_t CROSS_POLICY_ERR = 18;
101 constexpr int32_t ORIENTATION_0 = 1;
102 constexpr int32_t ORIENTATION_90 = 6;
103 constexpr int32_t ORIENTATION_180 = 3;
104 constexpr int32_t ORIENTATION_270 = 8;
105 constexpr int32_t OFFSET = 5;
106 constexpr int32_t ZERO_ASCII = '0';
107 const std::string SET_LOCATION_KEY = "set_location";
108 const std::string SET_LOCATION_VALUE = "1";
109 const std::string SET_DISPLAY_NAME_KEY = "set_displayName";
110 const std::string CAN_FALLBACK = "can_fallback";
111 const std::string OLD_DISPLAY_NAME = "old_displayName";
112 const std::string EDITDATA = "{\"system\":\"\"}";
113 
114 enum ImageFileType : int32_t {
115     JPEG = 1,
116     HEIF = 2
117 };
118 
119 const std::string MULTI_USER_URI_FLAG = "user=";
120 
121 const std::string MIME_TYPE_JPEG = "image/jpeg";
122 
123 const std::string MIME_TYPE_HEIF = "image/heif";
124 
125 const std::string EXTENSION_JPEG = ".jpg";
126 
127 const std::string EXTENSION_HEIF = ".heic";
128 
129 const std::unordered_map<ImageFileType, std::string> IMAGE_FILE_TYPE_MAP = {
130     {JPEG, MIME_TYPE_JPEG},
131     {HEIF, MIME_TYPE_HEIF},
132 };
133 
134 const std::unordered_map<ImageFileType, std::string> IMAGE_EXTENSION_MAP = {
135     {JPEG, EXTENSION_JPEG},
136     {HEIF, EXTENSION_HEIF},
137 };
138 shared_ptr<PhotoEditingRecord> PhotoEditingRecord::instance_ = nullptr;
139 mutex PhotoEditingRecord::mutex_;
140 std::mutex MediaLibraryPhotoOperations::saveCameraPhotoMutex_;
141 std::condition_variable MediaLibraryPhotoOperations::condition_;
142 std::string MediaLibraryPhotoOperations::lastPhotoId_ = "default";
Create(MediaLibraryCommand & cmd)143 int32_t MediaLibraryPhotoOperations::Create(MediaLibraryCommand &cmd)
144 {
145     switch (cmd.GetApi()) {
146         case MediaLibraryApi::API_10:
147             return CreateV10(cmd);
148         case MediaLibraryApi::API_OLD:
149             return CreateV9(cmd);
150         default:
151             MEDIA_ERR_LOG("get api failed");
152             return E_FAIL;
153     }
154 }
155 
DeleteCache(MediaLibraryCommand & cmd)156 int32_t MediaLibraryPhotoOperations::DeleteCache(MediaLibraryCommand& cmd)
157 {
158     string uriString = cmd.GetUriStringWithoutSegment();
159     CHECK_AND_RETURN_RET(MediaFileUtils::StartsWith(uriString, PhotoColumn::PHOTO_CACHE_URI_PREFIX), E_INVALID_VALUES);
160 
161     string fileName = uriString.substr(PhotoColumn::PHOTO_CACHE_URI_PREFIX.size());
162     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CheckDisplayName(fileName) == E_OK, E_INVALID_URI,
163         "Check fileName failed, fileName=%{private}s", fileName.c_str());
164     string cacheDir = GetAssetCacheDir();
165     string path = cacheDir + "/" + fileName;
166     if (!MediaFileUtils::DeleteFile(path)) {
167         MEDIA_ERR_LOG("Delete cache file failed, errno: %{public}d, uri: %{private}s", errno, uriString.c_str());
168         return E_HAS_FS_ERROR;
169     }
170     return E_OK;
171 }
172 
Delete(MediaLibraryCommand & cmd)173 int32_t MediaLibraryPhotoOperations::Delete(MediaLibraryCommand& cmd)
174 {
175     // delete file in .cache
176     if (MediaFileUtils::StartsWith(cmd.GetUri().ToString(), PhotoColumn::PHOTO_CACHE_URI_PREFIX)) {
177         return DeleteCache(cmd);
178     }
179 
180     string fileId = cmd.GetOprnFileId();
181     vector<string> columns = {
182         PhotoColumn::MEDIA_ID,
183         PhotoColumn::MEDIA_FILE_PATH,
184         PhotoColumn::MEDIA_RELATIVE_PATH,
185         PhotoColumn::MEDIA_TYPE
186     };
187     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(*(cmd.GetAbsRdbPredicates()),
188         cmd.GetOprnObject(), columns);
189     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_FILEID, "Get fileAsset failed, fileId: %{private}s",
190         fileId.c_str());
191     int32_t deleteRow = DeletePhoto(fileAsset, cmd.GetApi());
192     CHECK_AND_RETURN_RET_LOG(deleteRow >= 0, deleteRow, "delete photo failed, deleteRow=%{public}d", deleteRow);
193 
194     return deleteRow;
195 }
196 
GetAlbumTypeSubTypeById(const string & albumId,PhotoAlbumType & type,PhotoAlbumSubType & subType)197 static int32_t GetAlbumTypeSubTypeById(const string &albumId, PhotoAlbumType &type, PhotoAlbumSubType &subType)
198 {
199     RdbPredicates predicates(PhotoAlbumColumns::TABLE);
200     predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, albumId);
201     vector<string> columns = { PhotoAlbumColumns::ALBUM_TYPE, PhotoAlbumColumns::ALBUM_SUBTYPE };
202     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
203     if (resultSet == nullptr) {
204         MEDIA_ERR_LOG("album id %{private}s is not exist", albumId.c_str());
205         return E_INVALID_ARGUMENTS;
206     }
207     CHECK_AND_RETURN_RET_LOG(resultSet->GoToFirstRow() == NativeRdb::E_OK, E_INVALID_ARGUMENTS,
208         "album id is not exist");
209     type = static_cast<PhotoAlbumType>(GetInt32Val(PhotoAlbumColumns::ALBUM_TYPE, resultSet));
210     subType = static_cast<PhotoAlbumSubType>(GetInt32Val(PhotoAlbumColumns::ALBUM_SUBTYPE, resultSet));
211     resultSet->Close();
212     return E_SUCCESS;
213 }
214 
GetPredicatesByAlbumId(const string & albumId,RdbPredicates & predicates)215 static int32_t GetPredicatesByAlbumId(const string &albumId, RdbPredicates &predicates)
216 {
217     PhotoAlbumType type;
218     PhotoAlbumSubType subType;
219     CHECK_AND_RETURN_RET_LOG(GetAlbumTypeSubTypeById(albumId, type, subType) == E_SUCCESS, E_INVALID_ARGUMENTS,
220         "invalid album uri");
221 
222     if ((!PhotoAlbum::CheckPhotoAlbumType(type)) || (!PhotoAlbum::CheckPhotoAlbumSubType(subType))) {
223         MEDIA_ERR_LOG("album id %{private}s type:%d subtype:%d", albumId.c_str(), type, subType);
224         return E_INVALID_ARGUMENTS;
225     }
226 
227     if (PhotoAlbum::IsUserPhotoAlbum(type, subType)) {
228         PhotoAlbumColumns::GetUserAlbumPredicates(stoi(albumId), predicates, false);
229         return E_SUCCESS;
230     }
231 
232     if (PhotoAlbum::IsSourceAlbum(type, subType)) {
233         PhotoAlbumColumns::GetSourceAlbumPredicates(stoi(albumId), predicates, false);
234         return E_SUCCESS;
235     }
236 
237     if ((type != PhotoAlbumType::SYSTEM) || (subType == PhotoAlbumSubType::USER_GENERIC) ||
238         (subType == PhotoAlbumSubType::ANY)) {
239         MEDIA_ERR_LOG("album id %{private}s type:%d subtype:%d", albumId.c_str(), type, subType);
240         return E_INVALID_ARGUMENTS;
241     }
242     PhotoAlbumColumns::GetSystemAlbumPredicates(subType, predicates, false);
243     return E_SUCCESS;
244 }
245 
GetValidOrderClause(const DataSharePredicates & predicate,string & clause)246 static bool GetValidOrderClause(const DataSharePredicates &predicate, string &clause)
247 {
248     constexpr int32_t FIELD_IDX = 0;
249     vector<OperationItem> operations;
250     const auto &items = predicate.GetOperationList();
251     int32_t count = 0;
252     clause = "ROW_NUMBER() OVER (ORDER BY ";
253     for (const auto &item : items) {
254         if (item.operation == ORDER_BY_ASC) {
255             count++;
256             clause += static_cast<string>(item.GetSingle(FIELD_IDX)) + " ASC) as " + PHOTO_INDEX;
257         } else if (item.operation == ORDER_BY_DESC) {
258             count++;
259             clause += static_cast<string>(item.GetSingle(FIELD_IDX)) + " DESC) as " + PHOTO_INDEX;
260         }
261     }
262 
263     // only support orderby with one item
264     return (count == 1);
265 }
266 
AppendValidOrderClause(MediaLibraryCommand & cmd,RdbPredicates & predicates,const string & photoId)267 static bool AppendValidOrderClause(MediaLibraryCommand &cmd, RdbPredicates &predicates, const string &photoId)
268 {
269     constexpr int32_t FIELD_IDX = 0;
270     const auto &items = cmd.GetDataSharePred().GetOperationList();
271     int32_t count = 0;
272     string dateType;
273     string comparisonOperator;
274     for (const auto &item : items) {
275         if (item.operation == ORDER_BY_ASC) {
276             count++;
277             dateType = static_cast<string>(item.GetSingle(FIELD_IDX)) == MediaColumn::MEDIA_DATE_TAKEN ?
278                 MediaColumn::MEDIA_DATE_TAKEN : MediaColumn::MEDIA_DATE_ADDED;
279             comparisonOperator = " <= ";
280         } else if (item.operation == ORDER_BY_DESC) {
281             count++;
282             dateType = static_cast<string>(item.GetSingle(FIELD_IDX)) == MediaColumn::MEDIA_DATE_TAKEN ?
283                 MediaColumn::MEDIA_DATE_TAKEN : MediaColumn::MEDIA_DATE_ADDED;
284             comparisonOperator = " >= ";
285         }
286     }
287     string columnName = " (" + dateType + ", " + MediaColumn::MEDIA_ID + ") ";
288     string value = " (SELECT " + dateType + ", " + MediaColumn::MEDIA_ID + " FROM " +
289         PhotoColumn::PHOTOS_TABLE + " WHERE " + MediaColumn::MEDIA_ID + " = " + photoId + ") ";
290     string whereClause = predicates.GetWhereClause();
291     whereClause += " AND " + columnName + comparisonOperator + value;
292     predicates.SetWhereClause(whereClause);
293 
294     // only support orderby with one item
295     return (count == 1);
296 }
297 
HandleAlbumIndexOfUri(MediaLibraryCommand & cmd,const string & photoId,const string & albumId)298 static shared_ptr<NativeRdb::ResultSet> HandleAlbumIndexOfUri(MediaLibraryCommand &cmd, const string &photoId,
299     const string &albumId)
300 {
301     string orderClause;
302     CHECK_AND_RETURN_RET_LOG(GetValidOrderClause(cmd.GetDataSharePred(), orderClause), nullptr, "invalid orderby");
303     vector<string> columns;
304     columns.push_back(orderClause);
305     columns.push_back(MediaColumn::MEDIA_ID);
306     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
307     CHECK_AND_RETURN_RET_LOG(GetPredicatesByAlbumId(albumId, predicates) == E_SUCCESS, nullptr, "invalid album uri");
308     return MediaLibraryRdbStore::GetIndexOfUri(predicates, columns, photoId);
309 }
310 
HandleIndexOfUri(MediaLibraryCommand & cmd,RdbPredicates & predicates,const string & photoId,const string & albumId)311 static shared_ptr<NativeRdb::ResultSet> HandleIndexOfUri(MediaLibraryCommand &cmd, RdbPredicates &predicates,
312     const string &photoId, const string &albumId)
313 {
314     CHECK_AND_RETURN_RET(albumId.empty(), HandleAlbumIndexOfUri(cmd, photoId, albumId));
315     string indexClause = " COUNT(*) as " + PHOTO_INDEX;
316     vector<string> columns;
317     columns.push_back(indexClause);
318     predicates.And()->EqualTo(
319         PhotoColumn::PHOTO_SYNC_STATUS, std::to_string(static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE)));
320     predicates.And()->EqualTo(
321         PhotoColumn::PHOTO_CLEAN_FLAG, std::to_string(static_cast<int32_t>(CleanType::TYPE_NOT_CLEAN)));
322     CHECK_AND_RETURN_RET_LOG(AppendValidOrderClause(cmd, predicates, photoId), nullptr, "invalid orderby");
323     return MediaLibraryRdbStore::GetIndexOfUriForPhotos(predicates, columns, photoId);
324 }
325 
HandleAnalysisIndex(MediaLibraryCommand & cmd,const string & photoId,const string & albumId)326 static shared_ptr<NativeRdb::ResultSet> HandleAnalysisIndex(MediaLibraryCommand &cmd,
327     const string &photoId, const string &albumId)
328 {
329     string orderClause;
330     CHECK_AND_RETURN_RET_LOG(GetValidOrderClause(cmd.GetDataSharePred(), orderClause), nullptr, "invalid orderby");
331     CHECK_AND_RETURN_RET_LOG(albumId.size() > 0, nullptr, "null albumId");
332     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
333     PhotoAlbumColumns::GetAnalysisAlbumPredicates(stoi(albumId), predicates, false);
334     vector<string> columns;
335     columns.push_back(orderClause);
336     columns.push_back(MediaColumn::MEDIA_ID);
337     return MediaLibraryRdbStore::GetIndexOfUri(predicates, columns, photoId);
338 }
339 
Query(MediaLibraryCommand & cmd,const vector<string> & columns)340 shared_ptr<NativeRdb::ResultSet> MediaLibraryPhotoOperations::Query(
341     MediaLibraryCommand &cmd, const vector<string> &columns)
342 {
343     RdbPredicates predicates = RdbUtils::ToPredicates(cmd.GetDataSharePred(), PhotoColumn::PHOTOS_TABLE);
344     if (cmd.GetOprnType() == OperationType::INDEX || cmd.GetOprnType() == OperationType::ANALYSIS_INDEX) {
345         constexpr int32_t COLUMN_SIZE = 2;
346         CHECK_AND_RETURN_RET_LOG(columns.size() >= COLUMN_SIZE, nullptr, "invalid id param");
347         constexpr int32_t PHOTO_ID_INDEX = 0;
348         constexpr int32_t ALBUM_ID_INDEX = 1;
349         string photoId = columns[PHOTO_ID_INDEX];
350         string albumId;
351         if (!columns[ALBUM_ID_INDEX].empty()) {
352             albumId = columns[ALBUM_ID_INDEX];
353         }
354         if (cmd.GetOprnType() == OperationType::ANALYSIS_INDEX) {
355             return HandleAnalysisIndex(cmd, photoId, albumId);
356         }
357         return HandleIndexOfUri(cmd, predicates, photoId, albumId);
358     }
359     CHECK_AND_RETURN_RET(cmd.GetOprnType() != OperationType::FIND_DUPLICATE_ASSETS,
360         DuplicatePhotoOperation::GetAllDuplicateAssets(predicates, columns));
361     CHECK_AND_RETURN_RET(cmd.GetOprnType() != OperationType::FIND_DUPLICATE_ASSETS_TO_DELETE,
362         DuplicatePhotoOperation::GetDuplicateAssetsToDelete(predicates, columns));
363     CHECK_AND_RETURN_RET(cmd.GetOprnType() != OperationType::UPDATE_SEARCH_INDEX,
364         MediaLibraryRdbStore::Query(predicates, columns));
365     CHECK_AND_RETURN_RET(cmd.GetOprnType() != OperationType::EDIT_DATA_EXISTS,
366         MediaLibraryRdbStore::QueryEditDataExists(predicates));
367     MediaLibraryRdbUtils::AddQueryIndex(predicates, columns);
368     return MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
369 }
370 
Update(MediaLibraryCommand & cmd)371 int32_t MediaLibraryPhotoOperations::Update(MediaLibraryCommand &cmd)
372 {
373     switch (cmd.GetApi()) {
374         case MediaLibraryApi::API_10:
375             return UpdateV10(cmd);
376         case MediaLibraryApi::API_OLD:
377             return UpdateV9(cmd);
378         default:
379             MEDIA_ERR_LOG("get api failed");
380             return E_FAIL;
381     }
382 
383     return E_OK;
384 }
385 
386 const static vector<string> PHOTO_COLUMN_VECTOR = {
387     PhotoColumn::MEDIA_FILE_PATH,
388     PhotoColumn::MEDIA_TYPE,
389     PhotoColumn::MEDIA_TIME_PENDING,
390     PhotoColumn::PHOTO_SUBTYPE,
391     PhotoColumn::PHOTO_COVER_POSITION,
392     PhotoColumn::MOVING_PHOTO_EFFECT_MODE,
393     PhotoColumn::PHOTO_BURST_COVER_LEVEL,
394     PhotoColumn::PHOTO_POSITION,
395     MediaColumn::MEDIA_HIDDEN,
396     MediaColumn::MEDIA_DATE_TRASHED,
397 };
398 
CheckOpenMovingPhoto(int32_t photoSubType,int32_t effectMode,const string & request)399 bool CheckOpenMovingPhoto(int32_t photoSubType, int32_t effectMode, const string& request)
400 {
401     return photoSubType == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO) ||
402         (effectMode == static_cast<int32_t>(MovingPhotoEffectMode::IMAGE_ONLY) &&
403         request == SOURCE_REQUEST);
404 }
405 
ProcessMovingPhotoOprnKey(MediaLibraryCommand & cmd,shared_ptr<FileAsset> & fileAsset,const string & id,bool & isMovingPhotoVideo)406 static int32_t ProcessMovingPhotoOprnKey(MediaLibraryCommand& cmd, shared_ptr<FileAsset>& fileAsset, const string& id,
407     bool& isMovingPhotoVideo)
408 {
409     string movingPhotoOprnKey = cmd.GetQuerySetParam(MEDIA_MOVING_PHOTO_OPRN_KEYWORD);
410     if (movingPhotoOprnKey == OPEN_MOVING_PHOTO_VIDEO ||
411         movingPhotoOprnKey == CREATE_MOVING_PHOTO_VIDEO ||
412         movingPhotoOprnKey == OPEN_MOVING_PHOTO_VIDEO_CLOUD) {
413         bool isTemp = movingPhotoOprnKey == CREATE_MOVING_PHOTO_VIDEO;
414         CHECK_AND_RETURN_RET_LOG(CheckOpenMovingPhoto(fileAsset->GetPhotoSubType(),
415             fileAsset->GetMovingPhotoEffectMode(), cmd.GetQuerySetParam(MEDIA_OPERN_KEYWORD)),
416             E_INVALID_VALUES,
417             "Non-moving photo is requesting moving photo operation, file id: %{public}s, actual subtype: %{public}d",
418             id.c_str(), fileAsset->GetPhotoSubType());
419         string imagePath = fileAsset->GetPath();
420         string inputPath = isTemp ? MediaFileUtils::GetTempMovingPhotoVideoPath(imagePath)
421             : MediaFileUtils::GetMovingPhotoVideoPath(imagePath);
422         fileAsset->SetPath(inputPath);
423         isMovingPhotoVideo = true;
424         if (movingPhotoOprnKey == OPEN_MOVING_PHOTO_VIDEO_CLOUD && fileAsset->GetPosition() == POSITION_CLOUD) {
425             fileAsset->SetPath(imagePath);
426             isMovingPhotoVideo = false;
427         }
428     } else if (movingPhotoOprnKey == OPEN_PRIVATE_LIVE_PHOTO) {
429         CHECK_AND_RETURN_RET_LOG(fileAsset->GetPhotoSubType() == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO),
430             E_INVALID_VALUES,
431             "Non-moving photo is requesting moving photo operation, file id: %{public}s, actual subtype: %{public}d",
432             id.c_str(), fileAsset->GetPhotoSubType());
433         string livePhotoPath;
434         CHECK_AND_RETURN_RET_LOG(MovingPhotoFileUtils::ConvertToLivePhoto(fileAsset->GetPath(),
435             fileAsset->GetCoverPosition(), livePhotoPath) == E_OK,
436             E_INVALID_VALUES,
437             "Failed convert to live photo");
438         fileAsset->SetPath(livePhotoPath);
439     } else if (movingPhotoOprnKey == OPEN_PRIVATE_MOVING_PHOTO_METADATA) {
440         string extraDataPath = MovingPhotoFileUtils::GetMovingPhotoExtraDataPath(fileAsset->GetPath());
441         fileAsset->SetPath(extraDataPath);
442     }
443     return E_OK;
444 }
445 
UpdateLastVisitTime(MediaLibraryCommand & cmd,const string & id)446 static void UpdateLastVisitTime(MediaLibraryCommand &cmd, const string &id)
447 {
448     if (cmd.GetTableName() != PhotoColumn::PHOTOS_TABLE) {
449         return;
450     }
451     std::thread([=] {
452         int32_t changedRows = MediaLibraryRdbStore::UpdateLastVisitTime(id);
453         if (changedRows <= 0) {
454             MEDIA_ERR_LOG("update lastVisitTime Failed, changedRows = %{public}d.", changedRows);
455         }
456     }).detach();
457 }
458 
GetType(string & uri,int32_t & type)459 static void GetType(string &uri, int32_t &type)
460 {
461     size_t pos = uri.find("type=");
462     if (pos != uri.npos) {
463         type = uri[pos + OFFSET] - ZERO_ASCII;
464     }
465 }
466 
CheckPermissionToOpenFileAsset(const shared_ptr<FileAsset> & fileAsset)467 static bool CheckPermissionToOpenFileAsset(const shared_ptr<FileAsset>& fileAsset)
468 {
469     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, false, "File asset is nullptr");
470 
471     if (PermissionUtils::IsRootShell()) {
472         return true;
473     }
474 
475     if (fileAsset->GetDateTrashed() > 0) {
476         if (!(PermissionUtils::IsSystemApp() || PermissionUtils::IsNativeSAApp() ||
477             (PermissionUtils::IsHdcShell() &&
478             OHOS::system::GetBoolParameter("const.security.developermode.state", true)))) {
479             MEDIA_ERR_LOG("Non-system app is not allowed to open trashed photo, %{public}d, %{public}d, %{public}d, "
480                 "%{public}d", PermissionUtils::IsSystemApp(), PermissionUtils::IsNativeSAApp(),
481                 PermissionUtils::IsHdcShell(),
482                 OHOS::system::GetBoolParameter("const.security.developermode.state", true));
483             return false;
484         }
485     }
486 
487     if (fileAsset->IsHidden() && fileAsset->GetDateTrashed() == 0) {
488         CHECK_AND_RETURN_RET_LOG(PermissionUtils::CheckCallerPermission(PERM_MANAGE_PRIVATE_PHOTOS),
489             false, "MANAGE_PRIVATE_PHOTOS permission is required to open hidden photo");
490 
491         if (!(PermissionUtils::IsSystemApp() || PermissionUtils::IsNativeSAApp() ||
492             (PermissionUtils::IsHdcShell() &&
493             OHOS::system::GetBoolParameter("const.security.developermode.state", true)))) {
494             MEDIA_ERR_LOG("Non-system app is not allowed to open hidden photo, %{public}d, %{public}d, %{public}d, "
495                 "%{public}d", PermissionUtils::IsSystemApp(), PermissionUtils::IsNativeSAApp(),
496                 PermissionUtils::IsHdcShell(),
497                 OHOS::system::GetBoolParameter("const.security.developermode.state", true));
498             return false;
499         }
500     }
501 
502     return true;
503 }
504 
Open(MediaLibraryCommand & cmd,const string & mode)505 int32_t MediaLibraryPhotoOperations::Open(MediaLibraryCommand &cmd, const string &mode)
506 {
507     MediaLibraryTracer tracer;
508     tracer.Start("MediaLibraryPhotoOperations::Open");
509 
510     bool isCacheOperation = false;
511     int32_t errCode = OpenCache(cmd, mode, isCacheOperation);
512     if (errCode != E_OK || isCacheOperation) {
513         return errCode;
514     }
515     bool isSkipEdit = true;
516     errCode = OpenEditOperation(cmd, isSkipEdit);
517     if (errCode != E_OK || !isSkipEdit) {
518         return errCode;
519     }
520     string uriString = cmd.GetUriStringWithoutSegment();
521     string id = MediaFileUtils::GetIdFromUri(uriString);
522     CHECK_AND_RETURN_RET(!uriString.empty() && MediaLibraryDataManagerUtils::IsNumber(id), E_INVALID_URI);
523     string pendingStatus = cmd.GetQuerySetParam(MediaColumn::MEDIA_TIME_PENDING);
524     string cmdUri = cmd.GetUri().ToString();
525     size_t pos = cmdUri.find(MULTI_USER_URI_FLAG);
526     string userId = "";
527     if (pos != std::string::npos) {
528         userId = cmdUri.substr(pos + MULTI_USER_URI_FLAG.length());
529         uriString = uriString + "?" + MULTI_USER_URI_FLAG + userId;
530     }
531     shared_ptr<FileAsset> fileAsset = GetFileAssetByUri(uriString, true,  PHOTO_COLUMN_VECTOR, pendingStatus);
532     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_URI,
533         "Get FileAsset From Uri Failed, uri:%{public}s", uriString.c_str());
534     CHECK_AND_RETURN_RET_LOG(CheckPermissionToOpenFileAsset(fileAsset),
535         E_PERMISSION_DENIED, "Open not allowed");
536 
537     bool isMovingPhotoVideo = false;
538     errCode = ProcessMovingPhotoOprnKey(cmd, fileAsset, id, isMovingPhotoVideo);
539     CHECK_AND_RETURN_RET(errCode == E_OK, errCode);
540     UpdateLastVisitTime(cmd, id);
541     string uri = cmd.GetUri().ToString();
542     int32_t type = -1;
543     GetType(uri, type);
544     MEDIA_DEBUG_LOG("After spliting, uri is %{public}s", uri.c_str());
545     MEDIA_DEBUG_LOG("After spliting, type is %{public}d", type);
546     if (uriString.find(PhotoColumn::PHOTO_URI_PREFIX) != string::npos) {
547         return OpenAsset(fileAsset, mode, MediaLibraryApi::API_10, isMovingPhotoVideo, type);
548     }
549     return OpenAsset(fileAsset, mode, cmd.GetApi(), type);
550 }
551 
Close(MediaLibraryCommand & cmd)552 int32_t MediaLibraryPhotoOperations::Close(MediaLibraryCommand &cmd)
553 {
554     const ValuesBucket &values = cmd.GetValueBucket();
555     string uriString;
556     CHECK_AND_RETURN_RET(GetStringFromValuesBucket(values, MEDIA_DATA_DB_URI, uriString), E_INVALID_VALUES);
557     string pendingStatus = cmd.GetQuerySetParam(MediaColumn::MEDIA_TIME_PENDING);
558 
559     shared_ptr<FileAsset> fileAsset = GetFileAssetByUri(uriString, true, PHOTO_COLUMN_VECTOR, pendingStatus);
560     if (fileAsset == nullptr) {
561         MEDIA_ERR_LOG("Get FileAsset From Uri Failed, uri:%{public}s", uriString.c_str());
562         return E_INVALID_URI;
563     }
564 
565     int32_t isSync = 0;
566     int32_t errCode = 0;
567     if (GetInt32FromValuesBucket(cmd.GetValueBucket(), CLOSE_CREATE_THUMB_STATUS, isSync) &&
568         isSync == CREATE_THUMB_SYNC_STATUS) {
569         errCode = CloseAsset(fileAsset, true);
570     } else {
571         errCode = CloseAsset(fileAsset, false);
572     }
573     return errCode;
574 }
575 
SetPhotoTypeByRelativePath(const string & relativePath,FileAsset & fileAsset)576 static inline void SetPhotoTypeByRelativePath(const string &relativePath, FileAsset &fileAsset)
577 {
578     int32_t subType = static_cast<int32_t>(PhotoSubType::DEFAULT);
579     if (relativePath.compare(CAMERA_PATH) == 0) {
580         subType = static_cast<int32_t>(PhotoSubType::CAMERA);
581     } else if (relativePath.compare(SCREEN_RECORD_PATH) == 0 ||
582         relativePath.compare(SCREEN_SHOT_PATH) == 0) {
583         subType = static_cast<int32_t>(PhotoSubType::SCREENSHOT);
584     }
585 
586     fileAsset.SetPhotoSubType(subType);
587 }
588 
SetPhotoSubTypeFromCmd(MediaLibraryCommand & cmd,FileAsset & fileAsset)589 static inline void SetPhotoSubTypeFromCmd(MediaLibraryCommand &cmd, FileAsset &fileAsset)
590 {
591     int32_t subType = static_cast<int32_t>(PhotoSubType::DEFAULT);
592     ValueObject value;
593     if (cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_SUBTYPE, value)) {
594         value.GetInt(subType);
595     }
596     fileAsset.SetPhotoSubType(subType);
597 }
598 
SetCameraShotKeyFromCmd(MediaLibraryCommand & cmd,FileAsset & fileAsset)599 static inline void SetCameraShotKeyFromCmd(MediaLibraryCommand &cmd, FileAsset &fileAsset)
600 {
601     string cameraShotKey;
602     ValueObject value;
603     if (cmd.GetValueBucket().GetObject(PhotoColumn::CAMERA_SHOT_KEY, value)) {
604         value.GetString(cameraShotKey);
605     }
606     fileAsset.SetCameraShotKey(cameraShotKey);
607 }
608 
GetCallingUid(MediaLibraryCommand & cmd)609 static inline int32_t GetCallingUid(MediaLibraryCommand &cmd)
610 {
611     int32_t callingUid = 0;
612     ValueObject value;
613     if (cmd.GetValueBucket().GetObject(MEDIA_DATA_CALLING_UID, value)) {
614         value.GetInt(callingUid);
615     }
616     return callingUid;
617 }
618 
SetCallingPackageName(MediaLibraryCommand & cmd,FileAsset & fileAsset)619 static inline void SetCallingPackageName(MediaLibraryCommand &cmd, FileAsset &fileAsset)
620 {
621     int32_t callingUid = GetCallingUid(cmd);
622     if (callingUid == 0) {
623         return;
624     }
625     string bundleName;
626     PermissionUtils::GetClientBundle(callingUid, bundleName);
627     fileAsset.SetOwnerPackage(bundleName);
628     string packageName;
629     PermissionUtils::GetPackageName(callingUid, packageName);
630     fileAsset.SetPackageName(packageName);
631 }
632 
CreateV9(MediaLibraryCommand & cmd)633 int32_t MediaLibraryPhotoOperations::CreateV9(MediaLibraryCommand& cmd)
634 {
635     FileAsset fileAsset;
636     ValuesBucket &values = cmd.GetValueBucket();
637 
638     string displayName;
639     CHECK_AND_RETURN_RET(GetStringFromValuesBucket(values, PhotoColumn::MEDIA_NAME, displayName),
640         E_HAS_DB_ERROR);
641     fileAsset.SetDisplayName(displayName);
642 
643     string relativePath;
644     CHECK_AND_RETURN_RET(GetStringFromValuesBucket(values, PhotoColumn::MEDIA_RELATIVE_PATH, relativePath),
645         E_HAS_DB_ERROR);
646     fileAsset.SetRelativePath(relativePath);
647     MediaFileUtils::FormatRelativePath(relativePath);
648 
649     int32_t mediaType = 0;
650     CHECK_AND_RETURN_RET(GetInt32FromValuesBucket(values, PhotoColumn::MEDIA_TYPE, mediaType),
651         E_HAS_DB_ERROR);
652     fileAsset.SetMediaType(static_cast<MediaType>(mediaType));
653 
654     int32_t errCode = CheckRelativePathWithType(relativePath, mediaType);
655     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to Check RelativePath and Extention, "
656         "relativePath=%{private}s, mediaType=%{public}d", relativePath.c_str(), mediaType);
657     SetPhotoTypeByRelativePath(relativePath, fileAsset);
658     errCode = CheckDisplayNameWithType(displayName, mediaType);
659     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to Check Dir and Extention, "
660         "displayName=%{private}s, mediaType=%{public}d", displayName.c_str(), mediaType);
661     std::shared_ptr<TransactionOperations> trans = make_shared<TransactionOperations>(__func__);
662     int32_t outRow = -1;
663     std::function<int(void)> func = [&]()->int {
664         errCode = SetAssetPathInCreate(fileAsset, trans);
665         CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode,
666             "Failed to Solve FileAsset Path and Name, displayName=%{private}s", displayName.c_str());
667 
668         outRow = InsertAssetInDb(trans, cmd, fileAsset);
669         if (outRow <= 0) {
670             MEDIA_ERR_LOG("insert file in db failed, error = %{public}d", outRow);
671             return E_HAS_DB_ERROR;
672         }
673         return errCode;
674     };
675     errCode = trans->RetryTrans(func);
676     if (errCode != E_OK) {
677         MEDIA_ERR_LOG("CreateV9: tans finish fail!, ret:%{public}d", errCode);
678         return errCode;
679     }
680     return outRow;
681 }
682 
PhotosAddAsset(const int & albumId,const string & assetId,const string & extrUri)683 void PhotosAddAsset(const int &albumId, const string &assetId, const string &extrUri)
684 {
685     auto watch = MediaLibraryNotify::GetInstance();
686     CHECK_AND_RETURN_LOG(watch != nullptr, "Can not get MediaLibraryNotify Instance");
687     watch->Notify(MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, assetId, extrUri),
688         NotifyType::NOTIFY_ALBUM_ADD_ASSET, albumId);
689 }
690 
SolvePhotoAlbumInCreate(MediaLibraryCommand & cmd,FileAsset & fileAsset)691 void MediaLibraryPhotoOperations::SolvePhotoAlbumInCreate(MediaLibraryCommand &cmd, FileAsset &fileAsset)
692 {
693     ValuesBucket &values = cmd.GetValueBucket();
694     string albumUri;
695     GetStringFromValuesBucket(values, MEDIA_DATA_DB_ALBUM_ID, albumUri);
696     if (!albumUri.empty()) {
697         PhotosAddAsset(stoi(MediaFileUtils::GetIdFromUri(albumUri)), to_string(fileAsset.GetId()),
698             MediaFileUtils::GetExtraUri(fileAsset.GetDisplayName(), fileAsset.GetPath()));
699     }
700 }
701 
SetAssetDisplayName(const string & displayName,FileAsset & fileAsset,bool & isContains)702 static void SetAssetDisplayName(const string &displayName, FileAsset &fileAsset, bool &isContains)
703 {
704     fileAsset.SetDisplayName(displayName);
705     isContains = true;
706 }
707 
CreateV10(MediaLibraryCommand & cmd)708 int32_t MediaLibraryPhotoOperations::CreateV10(MediaLibraryCommand &cmd)
709 {
710     FileAsset fileAsset;
711     ValuesBucket &values = cmd.GetValueBucket();
712     string displayName;
713     string extention;
714     bool isContains = false;
715     bool isNeedGrant = false;
716     if (GetStringFromValuesBucket(values, PhotoColumn::MEDIA_NAME, displayName)) {
717         SetAssetDisplayName(displayName, fileAsset, isContains);
718         fileAsset.SetTimePending(UNCREATE_FILE_TIMEPENDING);
719     } else {
720         CHECK_AND_RETURN_RET(GetStringFromValuesBucket(values, ASSET_EXTENTION, extention), E_HAS_DB_ERROR);
721         isNeedGrant = true;
722         fileAsset.SetTimePending(UNOPEN_FILE_COMPONENT_TIMEPENDING);
723         string title;
724         if (GetStringFromValuesBucket(values, PhotoColumn::MEDIA_TITLE, title)) {
725             displayName = title + "." + extention;
726             SetAssetDisplayName(displayName, fileAsset, isContains);
727         }
728     }
729     int32_t mediaType = 0;
730     CHECK_AND_RETURN_RET(GetInt32FromValuesBucket(values, PhotoColumn::MEDIA_TYPE, mediaType), E_HAS_DB_ERROR);
731     fileAsset.SetMediaType(static_cast<MediaType>(mediaType));
732     SetPhotoSubTypeFromCmd(cmd, fileAsset);
733     SetCameraShotKeyFromCmd(cmd, fileAsset);
734     SetCallingPackageName(cmd, fileAsset);
735     // Check rootdir and extention
736     int32_t errCode = CheckWithType(isContains, displayName, extention, mediaType);
737     CHECK_AND_RETURN_RET(errCode == E_OK, errCode);
738     std::shared_ptr<TransactionOperations> trans = make_shared<TransactionOperations>(__func__);
739     int32_t outRow = -1;
740     std::function<int(void)> func = [&]()->int {
741         errCode = isContains ? SetAssetPathInCreate(fileAsset, trans) : SetAssetPath(fileAsset, extention, trans);
742         CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to Set Path, Name=%{private}s", displayName.c_str());
743         outRow = InsertAssetInDb(trans, cmd, fileAsset);
744         AuditLog auditLog = { true, "USER BEHAVIOR", "ADD", "io", 1, "running", "ok" };
745         HiAudit::GetInstance().Write(auditLog);
746         CHECK_AND_RETURN_RET_LOG(outRow > 0, E_HAS_DB_ERROR, "insert file in db failed, error = %{public}d", outRow);
747         fileAsset.SetId(outRow);
748         SolvePhotoAlbumInCreate(cmd, fileAsset);
749         return errCode;
750     };
751     errCode = trans->RetryTrans(func);
752     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "CreateV10: trans retry fail!, ret:%{public}d", errCode);
753     string fileUri = CreateExtUriForV10Asset(fileAsset);
754     if (isNeedGrant) {
755         bool isMovingPhoto = fileAsset.GetPhotoSubType() == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO);
756         int32_t ret = GrantUriPermission(fileUri, cmd.GetBundleName(), fileAsset.GetPath(), isMovingPhoto);
757         CHECK_AND_RETURN_RET(ret == E_OK, ret);
758     }
759     cmd.SetResult(fileUri);
760     return outRow;
761 }
762 
DeletePhoto(const shared_ptr<FileAsset> & fileAsset,MediaLibraryApi api)763 int32_t MediaLibraryPhotoOperations::DeletePhoto(const shared_ptr<FileAsset> &fileAsset, MediaLibraryApi api)
764 {
765     string filePath = fileAsset->GetPath();
766     CHECK_AND_RETURN_RET_LOG(!filePath.empty(), E_INVALID_PATH, "get file path failed");
767     bool res = MediaFileUtils::DeleteFile(filePath);
768     CHECK_AND_RETURN_RET_LOG(res, E_HAS_FS_ERROR, "Delete photo file failed, errno: %{public}d", errno);
769 
770     // delete thumbnail
771     int32_t fileId = fileAsset->GetId();
772     InvalidateThumbnail(to_string(fileId), fileAsset->GetMediaType());
773 
774     string displayName = fileAsset->GetDisplayName();
775     // delete file in db
776     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_PHOTO, OperationType::DELETE);
777     cmd.GetAbsRdbPredicates()->EqualTo(PhotoColumn::MEDIA_ID, to_string(fileId));
778     int32_t deleteRows = DeleteAssetInDb(cmd);
779     CHECK_AND_RETURN_RET_LOG(deleteRows > 0, E_HAS_DB_ERROR,
780         "Delete photo in database failed, errCode=%{public}d", deleteRows);
781 
782     auto watch = MediaLibraryNotify::GetInstance();
783     CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_ERR, "Can not get MediaLibraryNotify Instance");
784     string notifyDeleteUri =
785         MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(deleteRows),
786         (api == MediaLibraryApi::API_10 ? MediaFileUtils::GetExtraUri(displayName, filePath) : ""));
787     watch->Notify(notifyDeleteUri, NotifyType::NOTIFY_REMOVE);
788 
789     DeleteRevertMessage(filePath);
790     return deleteRows;
791 }
792 
TrashPhotosSendNotify(vector<string> & notifyUris,shared_ptr<AlbumData> albumData)793 void MediaLibraryPhotoOperations::TrashPhotosSendNotify(vector<string> &notifyUris,
794     shared_ptr<AlbumData> albumData)
795 {
796     auto watch = MediaLibraryNotify::GetInstance();
797     CHECK_AND_RETURN_LOG(watch != nullptr, "Can not get MediaLibraryNotify Instance");
798     int trashAlbumId = watch->GetAlbumIdBySubType(PhotoAlbumSubType::TRASH);
799     CHECK_AND_RETURN_LOG(trashAlbumId > 0,
800         "Skip to send trash photos notify, trashAlbumId=%{public}d", trashAlbumId);
801     CHECK_AND_RETURN_LOG(!notifyUris.empty(), "Skip to send trash photos notify, notifyUris is empty.");
802     if (notifyUris.size() == 1) {
803         if (albumData != nullptr && albumData->isHidden.size() != 0) {
804             watch->Notify(notifyUris[0], albumData->isHidden[0] ?
805                 NotifyType::NOTIFY_UPDATE : NotifyType::NOTIFY_REMOVE);
806         } else {
807             watch->Notify(notifyUris[0], NotifyType::NOTIFY_REMOVE);
808         }
809         watch->Notify(notifyUris[0], NotifyType::NOTIFY_ALBUM_REMOVE_ASSET);
810         watch->Notify(notifyUris[0], NotifyType::NOTIFY_ALBUM_ADD_ASSET, trashAlbumId);
811     } else {
812         watch->Notify(PhotoColumn::PHOTO_URI_PREFIX, NotifyType::NOTIFY_UPDATE);
813         watch->Notify(PhotoAlbumColumns::ALBUM_URI_PREFIX, NotifyType::NOTIFY_REMOVE);
814         for (auto &uri : notifyUris) {
815             watch->Notify(uri, NotifyType::NOTIFY_REMOVE);
816         }
817     }
818     vector<int64_t> formIds;
819     for (const auto &notifyUri : notifyUris) {
820         MediaLibraryFormMapOperations::GetFormMapFormId(notifyUri.c_str(), formIds);
821     }
822     if (!formIds.empty()) {
823         MediaLibraryFormMapOperations::PublishedChange("", formIds, false);
824     }
825 }
826 
GetPhotoHiddenStatus(std::shared_ptr<AlbumData> data,const string & assetId)827 static void GetPhotoHiddenStatus(std::shared_ptr<AlbumData> data, const string& assetId)
828 {
829     if (data == nullptr) {
830         return;
831     }
832     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
833     CHECK_AND_RETURN_LOG(rdbStore != nullptr, "Failed to get rdbStore.");
834     const std::string queryAssetHiddenInfo = "SELECT hidden FROM Photos WHERE file_id = " + assetId;
835     shared_ptr<NativeRdb::ResultSet> resultSet = rdbStore->QuerySql(queryAssetHiddenInfo);
836     if (resultSet == nullptr) {
837         return;
838     }
839     int32_t isHidden = 0;
840     if (resultSet->GoToNextRow() == NativeRdb::E_OK) {
841         int32_t isHiddenIndex = -1;
842         resultSet->GetColumnIndex(MediaColumn::MEDIA_HIDDEN, isHiddenIndex);
843         if (resultSet->GetInt(isHiddenIndex, isHidden) != NativeRdb::E_OK) {
844             return;
845         }
846     }
847     data->isHidden.push_back(isHidden);
848 }
849 
UpdateSourcePath(const vector<string> & whereArgs,std::shared_ptr<AlbumData> data)850 void MediaLibraryPhotoOperations::UpdateSourcePath(const vector<string> &whereArgs, std::shared_ptr<AlbumData> data)
851 {
852     if (whereArgs.empty()) {
853         MEDIA_WARN_LOG("whereArgs is empty");
854         return;
855     }
856 
857     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
858     CHECK_AND_RETURN_LOG(rdbStore != nullptr, "RdbStore is null");
859 
860     std::string inClause;
861     for (size_t i = 0; i < whereArgs.size(); ++i) {
862         if (i > 0) {
863             inClause += ",";
864         }
865         inClause += whereArgs[i];
866         if (i == 0) {
867             GetPhotoHiddenStatus(data, whereArgs[i]);
868         }
869     }
870 
871     const std::string updateSql = "UPDATE Photos"
872         " SET source_path = ( SELECT"
873         " '/storage/emulated/0' || COALESCE(PhotoAlbum.lpath, '/Pictures/其它') || '/' || SubPhotos.display_name "
874         " FROM Photos AS SubPhotos "
875         " LEFT JOIN PhotoAlbum ON SubPhotos.owner_album_id = PhotoAlbum.album_id "
876         " WHERE SubPhotos.file_id = Photos.file_id"
877         " LIMIT 1"
878         ") "
879         "WHERE file_id IN (" + inClause + ")";
880 
881     int32_t result = rdbStore->ExecuteSql(updateSql);
882     CHECK_AND_PRINT_LOG(result == NativeRdb::E_OK, "Failed to update source path, error code: %{private}d", result);
883 }
884 
TrashPhotos(MediaLibraryCommand & cmd)885 int32_t MediaLibraryPhotoOperations::TrashPhotos(MediaLibraryCommand &cmd)
886 {
887     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
888     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "Failed to get rdb store.");
889 
890     NativeRdb::RdbPredicates rdbPredicate = RdbUtils::ToPredicates(cmd.GetDataSharePred(),
891         PhotoColumn::PHOTOS_TABLE);
892     vector<string> notifyUris = rdbPredicate.GetWhereArgs();
893     MediaLibraryRdbStore::ReplacePredicatesUriToId(rdbPredicate);
894 
895     MultiStagesCaptureManager::RemovePhotos(rdbPredicate, true);
896     std::shared_ptr<AlbumData> albumData = std::make_shared<AlbumData>();
897     UpdateSourcePath(rdbPredicate.GetWhereArgs(), albumData);
898     ValuesBucket values;
899     values.Put(MediaColumn::MEDIA_DATE_TRASHED, MediaFileUtils::UTCTimeMilliSeconds());
900     cmd.SetValueBucket(values);
901     int32_t updatedRows = rdbStore->UpdateWithDateTime(values, rdbPredicate);
902     CHECK_AND_RETURN_RET_LOG(updatedRows >= 0, E_HAS_DB_ERROR, "Trash photo failed. Result %{public}d.", updatedRows);
903     // delete cloud enhanacement task
904 #ifdef MEDIALIBRARY_FEATURE_CLOUD_ENHANCEMENT
905     vector<string> ids = rdbPredicate.GetWhereArgs();
906     vector<string> photoIds;
907     EnhancementManager::GetInstance().CancelTasksInternal(ids, photoIds, CloudEnhancementAvailableType::TRASH);
908 #endif
909     MediaAnalysisHelper::StartMediaAnalysisServiceAsync(
910         static_cast<int32_t>(MediaAnalysisProxy::ActivateServiceType::START_UPDATE_INDEX), notifyUris);
911     MediaLibraryRdbUtils::UpdateAllAlbums(rdbStore, notifyUris, NotifyAlbumType::SYS_ALBUM, false,
912         AlbumOperationType::DELETE_PHOTO);
913     CHECK_AND_WARN_LOG(static_cast<size_t>(updatedRows) == notifyUris.size(),
914         "Try to notify %{public}zu items, but only %{public}d items updated.", notifyUris.size(), updatedRows);
915     TrashPhotosSendNotify(notifyUris, albumData);
916     DfxManager::GetInstance()->HandleDeleteBehavior(DfxType::TRASH_PHOTO, updatedRows, notifyUris);
917     return updatedRows;
918 }
919 
GetPhotoIdByFileId(int32_t fileId,std::string & photoId)920 int32_t GetPhotoIdByFileId(int32_t fileId, std::string &photoId)
921 {
922     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
923     predicates.EqualTo(MediaColumn::MEDIA_ID, std::to_string(fileId));
924 
925     std::vector<std::string> columns = { PhotoColumn::PHOTO_ID };
926     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
927     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr && resultSet->GoToFirstRow() == NativeRdb::E_OK,
928         E_FILE_EXIST, "result set is empty");
929 
930     photoId = GetStringVal(PhotoColumn::PHOTO_ID, resultSet);
931     return E_OK;
932 }
933 
DiscardCameraPhoto(MediaLibraryCommand & cmd)934 static int32_t DiscardCameraPhoto(MediaLibraryCommand &cmd)
935 {
936     std::string fileId = cmd.GetQuerySetParam(PhotoColumn::MEDIA_ID);
937     bool isClearCachedPicture = false;
938     std::string photoId;
939     int32_t ret = E_ERR;
940     if (!fileId.empty() && MediaLibraryDataManagerUtils::IsNumber(fileId)) {
941         MEDIA_INFO_LOG("MultistagesCapture start discard fileId: %{public}s.", fileId.c_str());
942         isClearCachedPicture = true;
943         ret = GetPhotoIdByFileId(stoi(fileId), photoId);
944         if (ret != E_OK || photoId.empty()) {
945             MEDIA_WARN_LOG("MultistagesCapture Memory leak may occur, please check yuv picture.");
946             isClearCachedPicture = false;
947         }
948     }
949 
950     if (isClearCachedPicture) {
951         MEDIA_INFO_LOG("MultistagesCapture start clear cached picture, photoId: %{public}s.", photoId.c_str());
952         auto pictureManagerThread = PictureManagerThread::GetInstance();
953         if (pictureManagerThread != nullptr) {
954             pictureManagerThread->DeleteDataWithImageId(photoId, LOW_QUALITY_PICTURE);
955         }
956         MultiStagesPhotoCaptureManager::GetInstance().CancelProcessRequest(photoId);
957     }
958 
959     NativeRdb::RdbPredicates rdbPredicate = RdbUtils::ToPredicates(cmd.GetDataSharePred(),
960         PhotoColumn::PHOTOS_TABLE);
961     vector<string> notifyUris = rdbPredicate.GetWhereArgs();
962     MediaLibraryRdbStore::ReplacePredicatesUriToId(rdbPredicate);
963     ret = MediaLibraryAssetOperations::DeleteFromDisk(rdbPredicate, false, true);
964     MEDIA_INFO_LOG("MultistagesCapture discard end, ret: %{public}d.", ret);
965     return ret;
966 }
967 
GetUriWithoutSeg(const string & oldUri)968 static string GetUriWithoutSeg(const string &oldUri)
969 {
970     size_t questionMaskPoint = oldUri.rfind('?');
971     if (questionMaskPoint != string::npos) {
972         return oldUri.substr(0, questionMaskPoint);
973     }
974     return oldUri;
975 }
976 
UpdateDirtyWithoutIsTemp(RdbPredicates & predicates)977 static int32_t UpdateDirtyWithoutIsTemp(RdbPredicates &predicates)
978 {
979     ValuesBucket valuesBucketDirty;
980     valuesBucketDirty.Put(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyType::TYPE_NEW));
981     int32_t updateDirtyRows = MediaLibraryRdbStore::UpdateWithDateTime(valuesBucketDirty, predicates);
982     return updateDirtyRows;
983 }
984 
UpdateIsTempAndDirty(MediaLibraryCommand & cmd,const string & fileId)985 static int32_t UpdateIsTempAndDirty(MediaLibraryCommand &cmd, const string &fileId)
986 {
987     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
988     predicates.EqualTo(PhotoColumn::MEDIA_ID, fileId);
989     ValuesBucket values;
990     values.Put(PhotoColumn::PHOTO_IS_TEMP, false);
991 
992     int32_t updateDirtyRows = 0;
993     if (cmd.GetQuerySetParam(PhotoColumn::PHOTO_DIRTY) == to_string(static_cast<int32_t>(DirtyType::TYPE_NEW))) {
994         // Only third-party app save photo, it will bring dirty flag
995         // The photo saved by third-party apps, whether of low or high quality, should set dirty to TYPE_NEW
996         // Every subtype of photo saved by third-party apps, should set dirty to TYPE_NEW
997         // Need to change the quality to high quality before updating
998         values.Put(PhotoColumn::PHOTO_QUALITY, static_cast<int32_t>(MultiStagesPhotoQuality::FULL));
999         values.Put(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyType::TYPE_NEW));
1000         updateDirtyRows = MediaLibraryRdbStore::UpdateWithDateTime(values, predicates);
1001         CHECK_AND_RETURN_RET_LOG(updateDirtyRows >= 0, E_ERR, "update third party photo temp and dirty flag fail.");
1002         return updateDirtyRows;
1003     }
1004 
1005     string subTypeStr = cmd.GetQuerySetParam(PhotoColumn::PHOTO_SUBTYPE);
1006     CHECK_AND_RETURN_RET_LOG(!subTypeStr.empty(), E_ERR, "get subType fail");
1007     int32_t subType = stoi(subTypeStr);
1008     if (subType == static_cast<int32_t>(PhotoSubType::BURST)) {
1009         predicates.EqualTo(PhotoColumn::PHOTO_QUALITY, to_string(static_cast<int32_t>(MultiStagesPhotoQuality::FULL)));
1010         predicates.EqualTo(PhotoColumn::PHOTO_SUBTYPE, to_string(static_cast<int32_t>(PhotoSubType::BURST)));
1011         values.Put(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyType::TYPE_NEW));
1012         updateDirtyRows = MediaLibraryRdbStore::UpdateWithDateTime(values, predicates);
1013         CHECK_AND_RETURN_RET_LOG(updateDirtyRows >= 0, E_ERR, "burst photo update temp and dirty flag fail.");
1014         return updateDirtyRows;
1015     }
1016 
1017     int32_t updateIsTempRows = MediaLibraryRdbStore::UpdateWithDateTime(values, predicates);
1018     CHECK_AND_RETURN_RET_LOG(updateIsTempRows >= 0, E_ERR, "update temp flag fail.");
1019     if (subType != static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
1020         predicates.EqualTo(PhotoColumn::PHOTO_QUALITY, to_string(static_cast<int32_t>(MultiStagesPhotoQuality::FULL)));
1021         predicates.NotEqualTo(PhotoColumn::PHOTO_SUBTYPE, to_string(static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)));
1022         updateDirtyRows = UpdateDirtyWithoutIsTemp(predicates);
1023         CHECK_AND_RETURN_RET_LOG(updateDirtyRows >= 0, E_ERR, "update dirty flag fail.");
1024     }
1025     return updateDirtyRows;
1026 }
1027 
SaveCameraPhoto(MediaLibraryCommand & cmd)1028 int32_t MediaLibraryPhotoOperations::SaveCameraPhoto(MediaLibraryCommand &cmd)
1029 {
1030     MediaLibraryTracer tracer;
1031     tracer.Start("MediaLibraryPhotoOperations::SaveCameraPhoto");
1032     string fileId = cmd.GetQuerySetParam(PhotoColumn::MEDIA_ID);
1033     if (fileId.empty()) {
1034         MEDIA_ERR_LOG("MultistagesCapture, get fileId fail");
1035         return 0;
1036     }
1037     MEDIA_INFO_LOG("MultistagesCapture, start fileId: %{public}s", fileId.c_str());
1038     tracer.Start("MediaLibraryPhotoOperations::UpdateIsTempAndDirty");
1039     int32_t ret = UpdateIsTempAndDirty(cmd, fileId);
1040     tracer.Finish();
1041     CHECK_AND_RETURN_RET(ret >= 0, 0);
1042     string fileType = cmd.GetQuerySetParam(IMAGE_FILE_TYPE);
1043     tracer.Start("MediaLibraryPhotoOperations::SavePicture");
1044     std::shared_ptr<Media::Picture> resultPicture = nullptr;
1045     if (!fileType.empty()) {
1046         SavePicture(stoi(fileType), stoi(fileId), resultPicture);
1047     }
1048     tracer.Finish();
1049 
1050     string needScanStr = cmd.GetQuerySetParam(MEDIA_OPERN_KEYWORD);
1051     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(PhotoColumn::MEDIA_ID, fileId,
1052                                                          OperationObject::FILESYSTEM_PHOTO, PHOTO_COLUMN_VECTOR);
1053     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, 0, "MultistagesCapture, get fileAsset fail");
1054     string path = fileAsset->GetPath();
1055     int32_t burstCoverLevel = fileAsset->GetBurstCoverLevel();
1056     tracer.Start("MediaLibraryPhotoOperations::Scan");
1057     if (!path.empty()) {
1058         if (burstCoverLevel == static_cast<int32_t>(BurstCoverLevelType::COVER)) {
1059             ScanFile(path, false, true, true, stoi(fileId), resultPicture);
1060         } else {
1061             MediaLibraryAssetOperations::ScanFileWithoutAlbumUpdate(
1062                 path, false, true, true, stoi(fileId), resultPicture);
1063         }
1064     }
1065     tracer.Finish();
1066     MEDIA_INFO_LOG("MultistagesCapture Success, ret: %{public}d, needScanStr: %{public}s", ret, needScanStr.c_str());
1067     return ret;
1068 }
1069 
SetVideoEnhancementAttr(MediaLibraryCommand & cmd)1070 int32_t MediaLibraryPhotoOperations::SetVideoEnhancementAttr(MediaLibraryCommand &cmd)
1071 {
1072     string videoId = cmd.GetQuerySetParam(PhotoColumn::PHOTO_ID);
1073     string fileId = cmd.GetQuerySetParam(MediaColumn::MEDIA_ID);
1074     string filePath = cmd.GetQuerySetParam(MediaColumn::MEDIA_FILE_PATH);
1075     MultiStagesVideoCaptureManager::GetInstance().AddVideo(videoId, fileId, filePath);
1076     return E_OK;
1077 }
1078 
GetHiddenState(const ValuesBucket & values)1079 static int32_t GetHiddenState(const ValuesBucket &values)
1080 {
1081     ValueObject obj;
1082     auto ret = values.GetObject(MediaColumn::MEDIA_HIDDEN, obj);
1083     CHECK_AND_RETURN_RET(ret, E_INVALID_VALUES);
1084     int32_t hiddenState = 0;
1085     ret = obj.GetInt(hiddenState);
1086     CHECK_AND_RETURN_RET(ret == E_OK, E_INVALID_VALUES);
1087     return hiddenState == 0 ? 0 : 1;
1088 }
1089 
SkipNotifyIfBurstMember(vector<string> & notifyUris)1090 static void SkipNotifyIfBurstMember(vector<string> &notifyUris)
1091 {
1092     vector<string> tempUris;
1093     vector<string> ids;
1094     unordered_map<string, string> idUriMap;
1095     for (auto& uri : notifyUris) {
1096         string fileId = MediaLibraryDataManagerUtils::GetFileIdFromPhotoUri(uri);
1097         if (fileId.empty()) {
1098             return;
1099         }
1100         ids.push_back(fileId);
1101         idUriMap.insert({fileId, uri});
1102     }
1103     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1104     vector<string> columns = {
1105         MediaColumn::MEDIA_ID,
1106     };
1107     NativeRdb::RdbPredicates rdbPredicates(PhotoColumn::PHOTOS_TABLE);
1108     rdbPredicates.In(MediaColumn::MEDIA_ID, ids);
1109     rdbPredicates.NotEqualTo(PhotoColumn::PHOTO_BURST_COVER_LEVEL, static_cast<int32_t>(BurstCoverLevelType::MEMBER));
1110     auto resultSet = uniStore->Query(rdbPredicates, columns);
1111     if (resultSet == nullptr) {
1112         MEDIA_ERR_LOG("IsAssetReadyById failed");
1113         return;
1114     }
1115     unordered_map<string, string>::iterator iter;
1116     while (resultSet->GoToNextRow() == E_OK) {
1117         int32_t fileId = get<int32_t>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_ID,
1118             resultSet, TYPE_INT32));
1119         if ((iter = idUriMap.find(to_string(fileId))) != idUriMap.end()) {
1120             tempUris.push_back(iter->second);
1121         }
1122     }
1123     resultSet->Close();
1124     notifyUris.swap(tempUris);
1125 }
1126 
SendHideNotify(vector<string> & notifyUris,const int32_t hiddenState)1127 static void SendHideNotify(vector<string> &notifyUris, const int32_t hiddenState)
1128 {
1129     auto watch = MediaLibraryNotify::GetInstance();
1130     CHECK_AND_RETURN_LOG(watch != nullptr, "notify watch is nullptr");
1131     int hiddenAlbumId = watch->GetAlbumIdBySubType(PhotoAlbumSubType::HIDDEN);
1132     CHECK_AND_RETURN_LOG(hiddenAlbumId > 0, "hiddenAlbumId is invalid");
1133 
1134     NotifyType assetNotifyType;
1135     NotifyType albumNotifyType;
1136     NotifyType hiddenAlbumNotifyType;
1137     if (hiddenState > 0) {
1138         assetNotifyType = NotifyType::NOTIFY_REMOVE;
1139         albumNotifyType = NotifyType::NOTIFY_ALBUM_REMOVE_ASSET;
1140         hiddenAlbumNotifyType = NotifyType::NOTIFY_ALBUM_ADD_ASSET;
1141     } else {
1142         assetNotifyType = NotifyType::NOTIFY_ADD;
1143         albumNotifyType = NotifyType::NOTIFY_ALBUM_ADD_ASSET;
1144         hiddenAlbumNotifyType = NotifyType::NOTIFY_ALBUM_REMOVE_ASSET;
1145     }
1146     vector<int64_t> formIds;
1147     SkipNotifyIfBurstMember(notifyUris);
1148     for (auto &notifyUri : notifyUris) {
1149         watch->Notify(notifyUri, assetNotifyType);
1150         watch->Notify(notifyUri, albumNotifyType, 0, true);
1151         watch->Notify(notifyUri, hiddenAlbumNotifyType, hiddenAlbumId);
1152         if (!hiddenState) {
1153             watch->Notify(notifyUri, NotifyType::NOTIFY_THUMB_ADD);
1154         }
1155         MediaLibraryFormMapOperations::GetFormMapFormId(notifyUri.c_str(), formIds);
1156     }
1157     if (!formIds.empty()) {
1158         MediaLibraryFormMapOperations::PublishedChange("", formIds, false);
1159     }
1160 }
1161 
HidePhotos(MediaLibraryCommand & cmd)1162 static int32_t HidePhotos(MediaLibraryCommand &cmd)
1163 {
1164     MediaLibraryTracer tracer;
1165     tracer.Start("MediaLibraryPhotoOperations::HidePhotos");
1166 
1167     int32_t hiddenState = GetHiddenState(cmd.GetValueBucket());
1168     CHECK_AND_RETURN_RET(hiddenState >= 0, hiddenState);
1169 
1170     RdbPredicates predicates = RdbUtils::ToPredicates(cmd.GetDataSharePred(), PhotoColumn::PHOTOS_TABLE);
1171     vector<string> notifyUris = predicates.GetWhereArgs();
1172     MediaLibraryRdbStore::ReplacePredicatesUriToId(predicates);
1173     if (hiddenState != 0) {
1174         MediaLibraryPhotoOperations::UpdateSourcePath(predicates.GetWhereArgs());
1175     } else {
1176         MediaLibraryAlbumOperations::DealwithNoAlbumAssets(predicates.GetWhereArgs());
1177     }
1178     ValuesBucket values;
1179     values.Put(MediaColumn::MEDIA_HIDDEN, hiddenState);
1180     if (predicates.GetTableName() == PhotoColumn::PHOTOS_TABLE) {
1181         values.PutLong(PhotoColumn::PHOTO_HIDDEN_TIME,
1182             hiddenState ? MediaFileUtils::UTCTimeMilliSeconds() : 0);
1183     }
1184     int32_t changedRows = MediaLibraryRdbStore::UpdateWithDateTime(values, predicates);
1185     CHECK_AND_RETURN_RET(changedRows >= 0, changedRows);
1186     MediaAnalysisHelper::StartMediaAnalysisServiceAsync(
1187         static_cast<int32_t>(MediaAnalysisProxy::ActivateServiceType::START_UPDATE_INDEX), notifyUris);
1188     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1189     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "Failed to get rdbStore.");
1190     MediaLibraryRdbUtils::UpdateAllAlbums(rdbStore, notifyUris, NotifyAlbumType::SYS_ALBUM, false,
1191         hiddenState != 0 ? AlbumOperationType::HIDE_PHOTO : AlbumOperationType::UNHIDE_PHOTO);
1192     SendHideNotify(notifyUris, hiddenState);
1193     return changedRows;
1194 }
1195 
GetFavoriteState(const ValuesBucket & values)1196 static int32_t GetFavoriteState(const ValuesBucket& values)
1197 {
1198     ValueObject obj;
1199     bool isValid = values.GetObject(PhotoColumn::MEDIA_IS_FAV, obj);
1200     CHECK_AND_RETURN_RET(isValid, E_INVALID_VALUES);
1201 
1202     int32_t favoriteState = -1;
1203     int ret = obj.GetInt(favoriteState);
1204     bool cond = (ret != E_OK || (favoriteState != 0 && favoriteState != 1));
1205     CHECK_AND_RETURN_RET(!cond, E_INVALID_VALUES);
1206     return favoriteState;
1207 }
1208 
BatchSetFavorite(MediaLibraryCommand & cmd)1209 static int32_t BatchSetFavorite(MediaLibraryCommand& cmd)
1210 {
1211     int32_t favoriteState = GetFavoriteState(cmd.GetValueBucket());
1212     CHECK_AND_RETURN_RET_LOG(favoriteState >= 0, favoriteState, "Failed to get favoriteState");
1213     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1214     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "Failed to get rdbStore");
1215 
1216     RdbPredicates predicates = RdbUtils::ToPredicates(cmd.GetDataSharePred(), PhotoColumn::PHOTOS_TABLE);
1217     vector<string> notifyUris = predicates.GetWhereArgs();
1218     MediaLibraryRdbStore::ReplacePredicatesUriToId(predicates);
1219     ValuesBucket values;
1220     values.Put(PhotoColumn::MEDIA_IS_FAV, favoriteState);
1221     int32_t updatedRows = rdbStore->UpdateWithDateTime(values, predicates);
1222     CHECK_AND_RETURN_RET_LOG(updatedRows >= 0, E_HAS_DB_ERROR, "Failed to set favorite, err: %{public}d", updatedRows);
1223 
1224     MediaLibraryRdbUtils::UpdateSystemAlbumInternal(rdbStore, { to_string(PhotoAlbumSubType::FAVORITE) });
1225     MediaLibraryRdbUtils::UpdateSysAlbumHiddenState(rdbStore, { to_string(PhotoAlbumSubType::FAVORITE) });
1226 
1227     auto watch = MediaLibraryNotify::GetInstance();
1228     CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_ERR, "Can not get MediaLibraryNotify Instance");
1229     int favAlbumId = watch->GetAlbumIdBySubType(PhotoAlbumSubType::FAVORITE);
1230     if (favAlbumId > 0) {
1231         NotifyType type = favoriteState ? NotifyType::NOTIFY_ALBUM_ADD_ASSET : NotifyType::NOTIFY_ALBUM_REMOVE_ASSET;
1232         for (const string& notifyUri : notifyUris) {
1233             watch->Notify(notifyUri, type, favAlbumId);
1234         }
1235     } else {
1236         MEDIA_WARN_LOG("Favorite album not found, failed to notify favorite album.");
1237     }
1238 
1239     for (const string& notifyUri : notifyUris) {
1240         watch->Notify(notifyUri, NotifyType::NOTIFY_UPDATE);
1241     }
1242 
1243     CHECK_AND_WARN_LOG(static_cast<size_t>(updatedRows) == notifyUris.size(),
1244         "Try to notify %{public}zu items, but only %{public}d items updated.", notifyUris.size(), updatedRows);
1245     return updatedRows;
1246 }
1247 
BatchSetUserComment(MediaLibraryCommand & cmd)1248 int32_t MediaLibraryPhotoOperations::BatchSetUserComment(MediaLibraryCommand& cmd)
1249 {
1250     vector<shared_ptr<FileAsset>> fileAssetVector;
1251     vector<string> columns = { PhotoColumn::MEDIA_ID, PhotoColumn::MEDIA_FILE_PATH,
1252         PhotoColumn::MEDIA_TYPE, PhotoColumn::MEDIA_NAME };
1253     MediaLibraryRdbStore::ReplacePredicatesUriToId(*(cmd.GetAbsRdbPredicates()));
1254 
1255     int32_t errCode = GetFileAssetVectorFromDb(*(cmd.GetAbsRdbPredicates()),
1256         OperationObject::FILESYSTEM_PHOTO, fileAssetVector, columns);
1257     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode,
1258         "Failed to query file asset vector from db, errCode=%{private}d", errCode);
1259 
1260     for (const auto& fileAsset : fileAssetVector) {
1261         errCode = SetUserComment(cmd, fileAsset);
1262         CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to set user comment, errCode=%{private}d", errCode);
1263     }
1264 
1265     int32_t updateRows = UpdateFileInDb(cmd);
1266     CHECK_AND_RETURN_RET_LOG(updateRows >= 0, updateRows,
1267         "Update Photo in database failed, updateRows=%{public}d", updateRows);
1268 
1269     auto watch = MediaLibraryNotify::GetInstance();
1270     CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_ERR, "Can not get MediaLibraryNotify Instance");
1271     for (const auto& fileAsset : fileAssetVector) {
1272         string extraUri = MediaFileUtils::GetExtraUri(fileAsset->GetDisplayName(), fileAsset->GetPath());
1273         string assetUri = MediaFileUtils::GetUriByExtrConditions(
1274             PhotoColumn::PHOTO_URI_PREFIX, to_string(fileAsset->GetId()), extraUri);
1275         watch->Notify(assetUri, NotifyType::NOTIFY_UPDATE);
1276     }
1277     return updateRows;
1278 }
1279 
1280 static const std::unordered_map<int, int> ORIENTATION_MAP = {
1281     {0, ORIENTATION_0},
1282     {90, ORIENTATION_90},
1283     {180, ORIENTATION_180},
1284     {270, ORIENTATION_270}
1285 };
1286 
CreateImageSource(const std::shared_ptr<FileAsset> & fileAsset,std::unique_ptr<ImageSource> & imageSource)1287 static int32_t CreateImageSource(
1288     const std::shared_ptr<FileAsset> &fileAsset, std::unique_ptr<ImageSource> &imageSource)
1289 {
1290     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_VALUES, "fileAsset is null");
1291     string filePath = fileAsset->GetFilePath();
1292     string extension = MediaFileUtils::GetExtensionFromPath(filePath);
1293     SourceOptions opts;
1294     opts.formatHint = "image/" + extension;
1295     uint32_t err = E_OK;
1296     imageSource = ImageSource::CreateImageSource(filePath, opts, err);
1297     if (err != E_OK || imageSource == nullptr) {
1298         MEDIA_ERR_LOG("Failed to obtain image exif, err = %{public}d", err);
1299         return E_INVALID_VALUES;
1300     }
1301     return E_OK;
1302 }
1303 
UpdateOrientationAllExif(MediaLibraryCommand & cmd,const std::shared_ptr<FileAsset> & fileAsset,string & currentOrientation)1304 int32_t MediaLibraryPhotoOperations::UpdateOrientationAllExif(
1305     MediaLibraryCommand &cmd, const std::shared_ptr<FileAsset> &fileAsset, string &currentOrientation)
1306 {
1307     std::unique_ptr<ImageSource> imageSource;
1308     uint32_t err = E_OK;
1309     if (CreateImageSource(fileAsset, imageSource) != E_OK) {
1310         return E_INVALID_VALUES;
1311     }
1312 
1313     err = imageSource->GetImagePropertyString(0, PHOTO_DATA_IMAGE_ORIENTATION, currentOrientation);
1314     if (err != E_OK) {
1315         currentOrientation = "";
1316         MEDIA_WARN_LOG("The rotation angle exlf of the image is empty");
1317     }
1318 
1319     MEDIA_INFO_LOG("Update image exif information, DisplayName=%{private}s, Orientation=%{private}d",
1320         fileAsset->GetDisplayName().c_str(), fileAsset->GetOrientation());
1321 
1322     ValuesBucket &values = cmd.GetValueBucket();
1323     ValueObject valueObject;
1324     if (!values.GetObject(PhotoColumn::PHOTO_ORIENTATION, valueObject)) {
1325         return E_OK;
1326     }
1327     int32_t cmdOrientation;
1328     valueObject.GetInt(cmdOrientation);
1329 
1330     auto imageSourceOrientation = ORIENTATION_MAP.find(cmdOrientation);
1331     if (imageSourceOrientation == ORIENTATION_MAP.end()) {
1332         MEDIA_ERR_LOG("imageSourceOrientation value is invalid.");
1333         return E_INVALID_VALUES;
1334     }
1335 
1336     string exifStr = fileAsset->GetAllExif();
1337     if (!exifStr.empty() && nlohmann::json::accept(exifStr)) {
1338         nlohmann::json exifJson = nlohmann::json::parse(exifStr, nullptr, false);
1339         exifJson["Orientation"] = imageSourceOrientation->second;
1340         exifStr = exifJson.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
1341         values.PutString(PhotoColumn::PHOTO_ALL_EXIF, exifStr);
1342     }
1343 
1344     err = imageSource->ModifyImageProperty(0, PHOTO_DATA_IMAGE_ORIENTATION,
1345         std::to_string(imageSourceOrientation->second), fileAsset->GetFilePath());
1346     if (err != E_OK) {
1347         MEDIA_ERR_LOG("Modify image property all exif failed, err = %{public}d", err);
1348         return E_INVALID_VALUES;
1349     }
1350     return E_OK;
1351 }
1352 
UpdateOrientationExif(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,bool & orientationUpdated,string & currentOrientation)1353 int32_t MediaLibraryPhotoOperations::UpdateOrientationExif(MediaLibraryCommand &cmd,
1354     const shared_ptr<FileAsset> &fileAsset, bool &orientationUpdated, string &currentOrientation)
1355 {
1356     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_VALUES, "fileAsset is null");
1357     ValuesBucket &values = cmd.GetValueBucket();
1358     ValueObject valueObject;
1359     if (!values.GetObject(PhotoColumn::PHOTO_ORIENTATION, valueObject)) {
1360         MEDIA_INFO_LOG("No need update orientation.");
1361         return E_OK;
1362     }
1363     bool cond = ((fileAsset->GetMediaType() != MEDIA_TYPE_IMAGE) ||
1364         (fileAsset->GetPhotoSubType() == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)));
1365     CHECK_AND_RETURN_RET_LOG(!cond,
1366         E_INVALID_VALUES, "Only images support rotation.");
1367     int32_t errCode = UpdateOrientationAllExif(cmd, fileAsset, currentOrientation);
1368     if (errCode == E_OK) {
1369         orientationUpdated = true;
1370     }
1371     return errCode;
1372 }
1373 
UpdateAlbumOnSystemMoveAssets(const int32_t & oriAlbumId,const int32_t & targetAlbumId)1374 void UpdateAlbumOnSystemMoveAssets(const int32_t &oriAlbumId, const int32_t &targetAlbumId)
1375 {
1376     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1377     CHECK_AND_RETURN_LOG(rdbStore != nullptr, "Failed to get rdbStore.");
1378     MediaLibraryRdbUtils::UpdateUserAlbumInternal(
1379         rdbStore, { to_string(oriAlbumId), to_string(targetAlbumId) });
1380     MediaLibraryRdbUtils::UpdateSourceAlbumInternal(
1381         rdbStore, { to_string(oriAlbumId), to_string(targetAlbumId) });
1382 }
1383 
IsSystemAlbumMovement(MediaLibraryCommand & cmd)1384 bool IsSystemAlbumMovement(MediaLibraryCommand &cmd)
1385 {
1386     auto whereClause = cmd.GetAbsRdbPredicates()->GetWhereClause();
1387     auto whereArgs = cmd.GetAbsRdbPredicates()->GetWhereArgs();
1388     int32_t oriAlbumId = MediaLibraryAssetOperations::GetAlbumIdByPredicates(whereClause, whereArgs);
1389     PhotoAlbumType type;
1390     PhotoAlbumSubType subType;
1391     CHECK_AND_RETURN_RET_LOG(GetAlbumTypeSubTypeById(to_string(oriAlbumId), type, subType) == E_SUCCESS, false,
1392         "move assets invalid album uri");
1393     bool cond = ((!PhotoAlbum::CheckPhotoAlbumType(type)) || (!PhotoAlbum::CheckPhotoAlbumSubType(subType)));
1394     CHECK_AND_RETURN_RET_LOG(!cond, false,
1395         "album id %{private}s type:%d subtype:%d", to_string(oriAlbumId).c_str(), type, subType);
1396 
1397     return type == PhotoAlbumType::SYSTEM;
1398 }
1399 
GetSystemMoveAssets(AbsRdbPredicates & predicates)1400 void GetSystemMoveAssets(AbsRdbPredicates &predicates)
1401 {
1402     const vector<string> &whereUriArgs = predicates.GetWhereArgs();
1403     CHECK_AND_RETURN_LOG(whereUriArgs.size() > 1, "Move vector empty when move from system album");
1404     vector<string> whereIdArgs;
1405     whereIdArgs.reserve(whereUriArgs.size() - 1);
1406     for (size_t i = 1; i < whereUriArgs.size(); ++i) {
1407         whereIdArgs.push_back(whereUriArgs[i]);
1408     }
1409     predicates.SetWhereArgs(whereIdArgs);
1410 }
1411 
PrepareUpdateArgs(MediaLibraryCommand & cmd,std::map<int32_t,std::vector<int32_t>> & ownerAlbumIds,vector<string> & assetString,RdbPredicates & predicates)1412 int32_t PrepareUpdateArgs(MediaLibraryCommand &cmd, std::map<int32_t, std::vector<int32_t>> &ownerAlbumIds,
1413     vector<string> &assetString, RdbPredicates &predicates)
1414 {
1415     auto assetVector = cmd.GetAbsRdbPredicates()->GetWhereArgs();
1416     for (const auto &fileAsset : assetVector) {
1417         assetString.push_back(fileAsset);
1418     }
1419 
1420     predicates.And()->In(PhotoColumn::MEDIA_ID, assetString);
1421     vector<string> columns = { PhotoColumn::PHOTO_OWNER_ALBUM_ID, PhotoColumn::MEDIA_ID };
1422     auto resultSetQuery = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
1423     CHECK_AND_RETURN_RET_LOG(resultSetQuery != nullptr, E_INVALID_ARGUMENTS, "album id is not exist");
1424     while (resultSetQuery->GoToNextRow() == NativeRdb::E_OK) {
1425         int32_t albumId = 0;
1426         albumId = GetInt32Val(PhotoColumn::PHOTO_OWNER_ALBUM_ID, resultSetQuery);
1427         ownerAlbumIds[albumId].push_back(GetInt32Val(MediaColumn::MEDIA_ID, resultSetQuery));
1428     }
1429     resultSetQuery->Close();
1430     return E_OK;
1431 }
1432 
UpdateSystemRows(MediaLibraryCommand & cmd)1433 int32_t UpdateSystemRows(MediaLibraryCommand &cmd)
1434 {
1435     std::map<int32_t, std::vector<int32_t>> ownerAlbumIds;
1436     vector<string> assetString;
1437     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
1438     CHECK_AND_RETURN_RET(PrepareUpdateArgs(cmd, ownerAlbumIds, assetString, predicates) == E_OK, E_INVALID_ARGUMENTS);
1439 
1440     ValueObject value;
1441     int32_t targetAlbumId = 0;
1442     CHECK_AND_RETURN_RET_LOG(cmd.GetValueBucket().GetObject(PhotoColumn::PHOTO_OWNER_ALBUM_ID, value),
1443         E_INVALID_ARGUMENTS, "get owner album id fail when move from system album");
1444     value.GetInt(targetAlbumId);
1445     ValuesBucket values;
1446     values.Put(PhotoColumn::PHOTO_OWNER_ALBUM_ID, to_string(targetAlbumId));
1447     int32_t changedRows = MediaLibraryRdbStore::UpdateWithDateTime(values, predicates);
1448     CHECK_AND_RETURN_RET_LOG(changedRows >= 0, changedRows, "Update owner album id fail when move from system album");
1449     if (!assetString.empty()) {
1450         MediaAnalysisHelper::AsyncStartMediaAnalysisService(
1451             static_cast<int32_t>(MediaAnalysisProxy::ActivateServiceType::START_UPDATE_INDEX), assetString);
1452     }
1453     for (auto it = ownerAlbumIds.begin(); it != ownerAlbumIds.end(); it++) {
1454         MEDIA_INFO_LOG("System album move assets target album id is: %{public}s", to_string(it->first).c_str());
1455         int32_t oriAlbumId = it->first;
1456         UpdateAlbumOnSystemMoveAssets(oriAlbumId, targetAlbumId);
1457         auto watch = MediaLibraryNotify::GetInstance();
1458         if (watch == nullptr) {
1459             MEDIA_ERR_LOG("Can not get MediaLibraryNotify Instance");
1460             continue;
1461         }
1462         for (const auto &id : it->second) {
1463             watch->Notify(PhotoColumn::PHOTO_URI_PREFIX + to_string(id),
1464                 NotifyType::NOTIFY_ALBUM_REMOVE_ASSET, oriAlbumId);
1465             watch->Notify(PhotoColumn::PHOTO_URI_PREFIX + to_string(id),
1466                 NotifyType::NOTIFY_ALBUM_ADD_ASSET, targetAlbumId);
1467         }
1468     }
1469     return changedRows;
1470 }
1471 
BatchSetOwnerAlbumId(MediaLibraryCommand & cmd)1472 int32_t MediaLibraryPhotoOperations::BatchSetOwnerAlbumId(MediaLibraryCommand &cmd)
1473 {
1474     vector<shared_ptr<FileAsset>> fileAssetVector;
1475     vector<string> columns = { PhotoColumn::MEDIA_ID, PhotoColumn::MEDIA_FILE_PATH,
1476         PhotoColumn::MEDIA_TYPE, PhotoColumn::MEDIA_NAME };
1477     MediaLibraryRdbStore::ReplacePredicatesUriToId(*(cmd.GetAbsRdbPredicates()));
1478 
1479     // Check if move from system album
1480     if (IsSystemAlbumMovement(cmd)) {
1481         MEDIA_INFO_LOG("Move assets from system album");
1482         GetSystemMoveAssets(*(cmd.GetAbsRdbPredicates()));
1483         int32_t updateSysRows = UpdateSystemRows(cmd);
1484         return updateSysRows;
1485     }
1486 
1487     int32_t errCode = GetFileAssetVectorFromDb(*(cmd.GetAbsRdbPredicates()),
1488         OperationObject::FILESYSTEM_PHOTO, fileAssetVector, columns);
1489     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode,
1490         "Failed to query file asset vector from db, errCode=%{private}d", errCode);
1491 
1492     int32_t updateRows = UpdateFileInDb(cmd);
1493     CHECK_AND_RETURN_RET_LOG(updateRows >= 0, updateRows,
1494         "Update Photo in database failed, updateRows=%{public}d", updateRows);
1495     int32_t targetAlbumId = 0;
1496     int32_t oriAlbumId = 0;
1497     vector<string> idsToUpdateIndex;
1498     UpdateOwnerAlbumIdOnMove(cmd, targetAlbumId, oriAlbumId);
1499     auto watch =  MediaLibraryNotify::GetInstance();
1500     for (const auto &fileAsset : fileAssetVector) {
1501         idsToUpdateIndex.push_back(to_string(fileAsset->GetId()));
1502         string extraUri = MediaFileUtils::GetExtraUri(fileAsset->GetDisplayName(), fileAsset->GetPath());
1503         string assetUri = MediaFileUtils::GetUriByExtrConditions(
1504             PhotoColumn::PHOTO_URI_PREFIX, to_string(fileAsset->GetId()), extraUri);
1505         watch->Notify(assetUri, NotifyType::NOTIFY_UPDATE);
1506         watch->Notify(assetUri, NotifyType::NOTIFY_ALBUM_ADD_ASSET, targetAlbumId);
1507         watch->Notify(assetUri, NotifyType::NOTIFY_ALBUM_REMOVE_ASSET, oriAlbumId);
1508     }
1509     if (!idsToUpdateIndex.empty()) {
1510         MediaAnalysisHelper::AsyncStartMediaAnalysisService(
1511             static_cast<int32_t>(MediaAnalysisProxy::ActivateServiceType::START_UPDATE_INDEX), idsToUpdateIndex);
1512     }
1513     return updateRows;
1514 }
1515 
GetRecentShowState(const ValuesBucket & values)1516 static int32_t GetRecentShowState(const ValuesBucket& values)
1517 {
1518     ValueObject obj;
1519     bool isValid = values.GetObject(PhotoColumn::PHOTO_IS_RECENT_SHOW, obj);
1520     CHECK_AND_RETURN_RET(isValid, E_INVALID_VALUES);
1521 
1522     int32_t recentShowState = -1;
1523     int ret = obj.GetInt(recentShowState);
1524     bool cond = (ret != E_OK || (recentShowState != 0 && recentShowState != 1));
1525     CHECK_AND_RETURN_RET(!cond, E_INVALID_VALUES);
1526     return recentShowState;
1527 }
1528 
BatchSetRecentShow(MediaLibraryCommand & cmd)1529 int32_t MediaLibraryPhotoOperations::BatchSetRecentShow(MediaLibraryCommand &cmd)
1530 {
1531     int32_t recentShowState = GetRecentShowState(cmd.GetValueBucket());
1532     CHECK_AND_RETURN_RET_LOG(recentShowState >= 0, recentShowState, "Failed to get recentShowState");
1533     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1534     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "Failed to get rdbStore");
1535 
1536     RdbPredicates predicates = RdbUtils::ToPredicates(cmd.GetDataSharePred(), PhotoColumn::PHOTOS_TABLE);
1537     vector<string> notifyUris = predicates.GetWhereArgs();
1538     MediaLibraryRdbStore::ReplacePredicatesUriToId(predicates);
1539     ValuesBucket values;
1540     values.Put(PhotoColumn::PHOTO_IS_RECENT_SHOW, recentShowState);
1541     int32_t updatedRows = rdbStore->UpdateWithDateTime(values, predicates);
1542     CHECK_AND_RETURN_RET_LOG(updatedRows >= 0, E_HAS_DB_ERROR, "Failed to set recentShow, err: %{public}d",
1543         updatedRows);
1544     return updatedRows;
1545 }
1546 
RevertOrientation(const shared_ptr<FileAsset> & fileAsset,string & currentOrientation)1547 static void RevertOrientation(const shared_ptr<FileAsset> &fileAsset, string &currentOrientation)
1548 {
1549     CHECK_AND_RETURN_LOG(fileAsset != nullptr, "fileAsset is null");
1550     std::unique_ptr<ImageSource> imageSource;
1551     int32_t err = CreateImageSource(fileAsset, imageSource);
1552     CHECK_AND_RETURN_LOG(err == E_OK, "Failed to obtain image exif information, err = %{public}d", err);
1553     uint32_t ret = imageSource->ModifyImageProperty(
1554         0,
1555         PHOTO_DATA_IMAGE_ORIENTATION,
1556         currentOrientation.empty() ? ANALYSIS_HAS_DATA : currentOrientation,
1557         fileAsset->GetFilePath()
1558     );
1559     CHECK_AND_RETURN_LOG(ret == E_OK, "Rollback of exlf information failed, err = %{public}d", ret);
1560 }
1561 
CreateThumbnailFileScaned(const string & uri,const string & path,bool isSync)1562 static void CreateThumbnailFileScaned(const string &uri, const string &path, bool isSync)
1563 {
1564     auto thumbnailService = ThumbnailService::GetInstance();
1565     if (thumbnailService == nullptr || uri.empty()) {
1566         return;
1567     }
1568 
1569     int32_t err = thumbnailService->CreateThumbnailFileScaned(uri, path, isSync);
1570     if (err != E_SUCCESS) {
1571         MEDIA_ERR_LOG("ThumbnailService CreateThumbnailFileScaned failed: %{public}d", err);
1572     }
1573 }
1574 
CreateThumbnailFileScan(const shared_ptr<FileAsset> & fileAsset,string & extraUri,bool orientationUpdated,bool isNeedScan)1575 void MediaLibraryPhotoOperations::CreateThumbnailFileScan(const shared_ptr<FileAsset> &fileAsset, string &extraUri,
1576     bool orientationUpdated, bool isNeedScan)
1577 {
1578     CHECK_AND_RETURN_LOG(fileAsset != nullptr, "fileAsset is null");
1579     if (orientationUpdated) {
1580         auto watch = MediaLibraryNotify::GetInstance();
1581         CHECK_AND_RETURN_LOG(watch != nullptr, "Can not get MediaLibraryNotify Instance");
1582         ScanFile(fileAsset->GetPath(), true, false, true);
1583         watch->Notify(MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX,
1584             to_string(fileAsset->GetId()), extraUri), NotifyType::NOTIFY_THUMB_UPDATE);
1585     }
1586     if (isNeedScan) {
1587         ScanFile(fileAsset->GetPath(), true, true, true);
1588         return;
1589     }
1590 }
1591 
HandleUpdateIndex(MediaLibraryCommand & cmd,string id)1592 void HandleUpdateIndex(MediaLibraryCommand &cmd, string id)
1593 {
1594     set<string> targetColumns = {"user_comment", "title"};
1595     bool needUpdate = false;
1596 
1597     map<string, ValueObject> valuesMap;
1598     cmd.GetValueBucket().GetAll(valuesMap);
1599     for (auto i : valuesMap) {
1600         if (targetColumns.find(i.first) != targetColumns.end()) {
1601             MEDIA_INFO_LOG("need update index");
1602             needUpdate = true;
1603             break;
1604         }
1605     }
1606     if (needUpdate) {
1607         MediaAnalysisHelper::AsyncStartMediaAnalysisService(
1608             static_cast<int32_t>(MediaAnalysisProxy::ActivateServiceType::START_UPDATE_INDEX), {id});
1609     }
1610 }
1611 
HandleNeedSetDisplayName(MediaLibraryCommand & cmd,shared_ptr<FileAsset> & fileAsset,bool & isNeedScan)1612 int32_t MediaLibraryPhotoOperations::HandleNeedSetDisplayName(
1613     MediaLibraryCommand &cmd, shared_ptr<FileAsset> &fileAsset, bool &isNeedScan)
1614 {
1615     if (IsSetDisplayName(cmd)) {
1616         bool ret = UpdateFileBySetDisplayName(cmd, fileAsset);
1617         if (!ret) {
1618             MEDIA_ERR_LOG("Failed to setDisplayName due to update file, displayName: %{public}s",
1619                 fileAsset->GetDisplayName().c_str());
1620             RevertSetDisplayName(cmd, fileAsset);
1621             ScanFile(fileAsset->GetPath(), true, true, true);
1622             return E_ERR;
1623         }
1624         isNeedScan = true;
1625         // 这里要设置下资产的path和displayname
1626         string newDisplayName = cmd.GetQuerySetParam(SET_DISPLAY_NAME_KEY);
1627         std::string newPath = MediaFileUtils::UnSplitByChar(fileAsset->GetPath(), '.') + "." +
1628                               MediaFileUtils::GetExtensionFromPath(newDisplayName);
1629         fileAsset->SetPath(newPath);
1630         fileAsset->SetDisplayName(newDisplayName);
1631     }
1632     return E_OK;
1633 }
1634 
HandleNeedSetDisplayName(MediaLibraryCommand & cmd,shared_ptr<FileAsset> & fileAsset)1635 int32_t MediaLibraryPhotoOperations::HandleNeedSetDisplayName(
1636     MediaLibraryCommand &cmd, shared_ptr<FileAsset> &fileAsset)
1637 {
1638     if (IsSetDisplayName(cmd)) {
1639         CHECK_AND_RETURN_RET_LOG(UpdateDbBySetDisplayName(cmd, fileAsset) == NativeRdb::E_OK, E_FAIL,
1640             "Failed to setDisplayName, fileId: %{public}d.", fileAsset->GetId());
1641         bool ret = UpdateFileBySetDisplayName(cmd, fileAsset);
1642         int32_t id = fileAsset->GetId();
1643         if (!ret) {
1644             MEDIA_ERR_LOG("Failed to setDisplayName due to updateFile fail, fileId: %{public}d.", id);
1645             RevertSetDisplayName(cmd, fileAsset);
1646             ScanFile(fileAsset->GetPath(), true, true, true);
1647             return E_FAIL;
1648         }
1649         // 这里要设置下资产的path和displayname
1650         std::string newDisplayName = cmd.GetQuerySetParam(SET_DISPLAY_NAME_KEY);
1651         std::string newPath = MediaFileUtils::UnSplitByChar(fileAsset->GetPath(), '.') + "." +
1652                             MediaFileUtils::GetExtensionFromPath(newDisplayName);
1653         fileAsset->SetPath(newPath);
1654         fileAsset->SetDisplayName(newDisplayName);
1655     }
1656     return E_OK;
1657 }
1658 
RenameEditDataDirBySetDisplayName(MediaLibraryCommand & cmd,shared_ptr<FileAsset> & fileAsset)1659 int32_t MediaLibraryPhotoOperations::RenameEditDataDirBySetDisplayName(
1660     MediaLibraryCommand &cmd, shared_ptr<FileAsset> &fileAsset)
1661 {
1662     if (!IsSetDisplayName(cmd)) {
1663         return E_OK;
1664     }
1665     CHECK_AND_RETURN_RET_LOG(CheckUriBySetDisplayName(cmd), false, "Failed to check uri.");
1666     std::string oldDisplayName = cmd.GetQuerySetParam(OLD_DISPLAY_NAME);
1667     std::string newPath = fileAsset->GetPath();
1668     std::string oldPath =
1669         MediaFileUtils::UnSplitByChar(newPath, '.') + "." + MediaFileUtils::GetExtensionFromPath(oldDisplayName);
1670     std::string newEditDataFloder = MediaLibraryAssetOperations::GetEditDataDirPath(newPath);
1671     CHECK_AND_RETURN_RET_LOG(!newEditDataFloder.empty(), E_INVALID_URI, "Can not get new editdara dir path");
1672     std::string oldEditDataFloder = MediaLibraryAssetOperations::GetEditDataDirPath(oldPath);
1673     CHECK_AND_RETURN_RET_LOG(!oldEditDataFloder.empty(), E_INVALID_URI, "Can not get old editdara dir path");
1674     if (MediaFileUtils::IsDirectory(oldEditDataFloder)) {
1675         MEDIA_INFO_LOG("oldEditDataFloder is exist.");
1676         if (!MediaFileUtils::RenameDir(oldEditDataFloder, newEditDataFloder)) {
1677             // 如果这里失败,那这里要回退至资产初始状态,数据库先更新回原始状态,资产名字要回退至初始
1678             MEDIA_ERR_LOG("Failed to rename eitddatadir: %{public}s", oldEditDataFloder.c_str());
1679             RevertSetDisplayName(cmd, fileAsset);
1680             return E_FAIL;
1681         }
1682     } else if (cmd.GetQuerySetParam(OLD_DISPLAY_NAME) == "1") {
1683         // 如果这里失败,那这里之前未成功生成editdata目录
1684         MEDIA_ERR_LOG("editdata path is not directory: %{public}s", oldEditDataFloder.c_str());
1685         RevertSetDisplayName(cmd, fileAsset);
1686         return E_FAIL;
1687     }
1688     return E_OK;
1689 }
1690 
UpdateFileAsset(MediaLibraryCommand & cmd)1691 int32_t MediaLibraryPhotoOperations::UpdateFileAsset(MediaLibraryCommand &cmd)
1692 {
1693     vector<string> columns = {
1694         PhotoColumn::MEDIA_ID, PhotoColumn::MEDIA_FILE_PATH, PhotoColumn::MEDIA_TYPE, PhotoColumn::MEDIA_NAME,
1695         PhotoColumn::MEDIA_TITLE, PhotoColumn::PHOTO_SUBTYPE, PhotoColumn::PHOTO_EDIT_TIME, MediaColumn::MEDIA_HIDDEN,
1696         PhotoColumn::MOVING_PHOTO_EFFECT_MODE, PhotoColumn::PHOTO_ORIENTATION, PhotoColumn::PHOTO_ALL_EXIF,
1697         PhotoColumn::PHOTO_DIRTY, PhotoColumn::MEDIA_DATE_TAKEN, PhotoColumn::MEDIA_MIME_TYPE};
1698     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(*(cmd.GetAbsRdbPredicates()),
1699         OperationObject::FILESYSTEM_PHOTO, columns);
1700     CHECK_AND_RETURN_RET(fileAsset != nullptr, E_INVALID_VALUES);
1701     bool isNeedScan = false;
1702     int32_t errCode = RevertToOriginalEffectMode(cmd, fileAsset, isNeedScan);
1703     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to revert original effect mode: %{public}d", errCode);
1704 
1705     // Update if FileAsset.title or FileAsset.displayName is modified
1706     bool isNameChanged = false;
1707     errCode = UpdateFileName(cmd, fileAsset, isNameChanged);
1708     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Update Photo Name failed, fileName=%{private}s",
1709         fileAsset->GetDisplayName().c_str());
1710 
1711     bool orientationUpdated = false;
1712     string currentOrientation = "";
1713     errCode = UpdateOrientationExif(cmd, fileAsset, orientationUpdated, currentOrientation);
1714     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Update allexif failed, allexif=%{private}s",
1715         fileAsset->GetAllExif().c_str());
1716 
1717     int32_t rowId = UpdateFileInDb(cmd);
1718     if (rowId < 0) {
1719         MEDIA_ERR_LOG("Update Photo In database failed, rowId=%{public}d", rowId);
1720         RevertOrientation(fileAsset, currentOrientation);
1721         return rowId;
1722     }
1723     if (cmd.GetOprnType() == OperationType::SET_USER_COMMENT) {
1724         errCode = SetUserComment(cmd, fileAsset);
1725         CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Edit user comment errCode = %{private}d", errCode);
1726     }
1727     CHECK_AND_RETURN_RET_LOG(HandleNeedSetDisplayName(cmd, fileAsset, isNeedScan) == E_OK, errCode,
1728         "Failed to update file");
1729     HandleUpdateIndex(cmd, to_string(fileAsset->GetId()));
1730     string extraUri = MediaFileUtils::GetExtraUri(fileAsset->GetDisplayName(), fileAsset->GetPath());
1731     errCode = SendTrashNotify(cmd, fileAsset->GetId(), extraUri);
1732     if (errCode == E_OK) {
1733         return rowId;
1734     }
1735     SendFavoriteNotify(cmd, fileAsset, extraUri);
1736     SendModifyUserCommentNotify(cmd, fileAsset->GetId(), extraUri);
1737 
1738     CHECK_AND_RETURN_RET_LOG(RenameEditDataDirBySetDisplayName(cmd, fileAsset) == E_OK, E_FAIL,
1739         "failed to setdisplayname due to rename editdatadir fail. filename is %{puiblic}s",
1740         fileAsset->GetDisplayName().c_str());
1741     CreateThumbnailFileScan(fileAsset, extraUri, orientationUpdated, isNeedScan);
1742     auto watch = MediaLibraryNotify::GetInstance();
1743     CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_ERR, "Can not get MediaLibraryNotify Instance");
1744     watch->Notify(MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(fileAsset->GetId()),
1745         extraUri), NotifyType::NOTIFY_UPDATE);
1746     return rowId;
1747 }
1748 
UpdateV10(MediaLibraryCommand & cmd)1749 int32_t MediaLibraryPhotoOperations::UpdateV10(MediaLibraryCommand &cmd)
1750 {
1751     switch (cmd.GetOprnType()) {
1752         case OperationType::TRASH_PHOTO:
1753             return TrashPhotos(cmd);
1754         case OperationType::UPDATE_PENDING:
1755             return SetPendingStatus(cmd);
1756         case OperationType::HIDE:
1757             return HidePhotos(cmd);
1758         case OperationType::BATCH_UPDATE_FAV:
1759             return BatchSetFavorite(cmd);
1760         case OperationType::BATCH_UPDATE_USER_COMMENT:
1761             return BatchSetUserComment(cmd);
1762         case OperationType::BATCH_UPDATE_OWNER_ALBUM_ID:
1763             return BatchSetOwnerAlbumId(cmd);
1764         case OperationType::BATCH_UPDATE_RECENT_SHOW:
1765             return BatchSetRecentShow(cmd);
1766         case OperationType::DISCARD_CAMERA_PHOTO:
1767             return DiscardCameraPhoto(cmd);
1768         case OperationType::SAVE_CAMERA_PHOTO:
1769             return SaveCameraPhoto(cmd);
1770         case OperationType::SAVE_PICTURE:
1771             return ForceSavePicture(cmd);
1772         case OperationType::SET_VIDEO_ENHANCEMENT_ATTR:
1773             return SetVideoEnhancementAttr(cmd);
1774         case OperationType::DEGENERATE_MOVING_PHOTO:
1775             return DegenerateMovingPhoto(cmd);
1776         case OperationType::SET_OWNER_ALBUM_ID:
1777             return UpdateOwnerAlbumId(cmd);
1778         case OperationType::UPDATE_SUPPORTED_WATERMARK_TYPE:
1779             return UpdateSupportedWatermarkType(cmd);
1780         default:
1781             return UpdateFileAsset(cmd);
1782     }
1783     return E_OK;
1784 }
1785 
UpdateV9(MediaLibraryCommand & cmd)1786 int32_t MediaLibraryPhotoOperations::UpdateV9(MediaLibraryCommand &cmd)
1787 {
1788     vector<string> columns = {
1789         PhotoColumn::MEDIA_ID,
1790         PhotoColumn::MEDIA_FILE_PATH,
1791         PhotoColumn::MEDIA_TYPE,
1792         PhotoColumn::MEDIA_NAME,
1793         PhotoColumn::MEDIA_RELATIVE_PATH,
1794         MediaColumn::MEDIA_HIDDEN
1795     };
1796     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(*(cmd.GetAbsRdbPredicates()),
1797         OperationObject::FILESYSTEM_PHOTO, columns);
1798     CHECK_AND_RETURN_RET(fileAsset != nullptr, E_INVALID_VALUES);
1799 
1800     // Update if FileAsset.title or FileAsset.displayName is modified
1801     bool isNameChanged = false;
1802     int32_t errCode = UpdateFileName(cmd, fileAsset, isNameChanged);
1803     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Update Photo Name failed, fileName=%{private}s",
1804         fileAsset->GetDisplayName().c_str());
1805     errCode = UpdateRelativePath(cmd, fileAsset, isNameChanged);
1806     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Update Photo RelativePath failed, relativePath=%{private}s",
1807         fileAsset->GetRelativePath().c_str());
1808     if (isNameChanged) {
1809         UpdateVirtualPath(cmd, fileAsset);
1810     }
1811 
1812     int32_t rowId = UpdateFileInDb(cmd);
1813     if (rowId < 0) {
1814         MEDIA_ERR_LOG("Update Photo In database failed, rowId=%{public}d", rowId);
1815         return rowId;
1816     }
1817 
1818     errCode = SendTrashNotify(cmd, fileAsset->GetId());
1819     CHECK_AND_RETURN_RET(errCode != E_OK, rowId);
1820     SendFavoriteNotify(cmd, fileAsset);
1821     auto watch = MediaLibraryNotify::GetInstance();
1822     CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_ERR, "Can not get MediaLibraryNotify Instance");
1823     watch->Notify(MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(fileAsset->GetId())),
1824         NotifyType::NOTIFY_UPDATE);
1825     return rowId;
1826 }
1827 
OpenCache(MediaLibraryCommand & cmd,const string & mode,bool & isCacheOperation)1828 int32_t MediaLibraryPhotoOperations::OpenCache(MediaLibraryCommand& cmd, const string& mode, bool& isCacheOperation)
1829 {
1830     isCacheOperation = false;
1831     string uriString = cmd.GetUriStringWithoutSegment();
1832     if (!MediaFileUtils::StartsWith(uriString, PhotoColumn::PHOTO_CACHE_URI_PREFIX)) {
1833         return E_OK;
1834     }
1835 
1836     isCacheOperation = true;
1837     string fileName = uriString.substr(PhotoColumn::PHOTO_CACHE_URI_PREFIX.size());
1838     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CheckDisplayName(fileName) == E_OK, E_INVALID_URI,
1839         "Check fileName failed, fileName=%{private}s", fileName.c_str());
1840     MediaType mediaType = MediaFileUtils::GetMediaType(fileName);
1841     CHECK_AND_RETURN_RET_LOG(mediaType == MediaType::MEDIA_TYPE_IMAGE || mediaType == MediaType::MEDIA_TYPE_VIDEO,
1842         E_INVALID_URI, "Check mediaType failed, fileName=%{private}s, mediaType=%{public}d", fileName.c_str(),
1843         mediaType);
1844 
1845     string cacheDir = GetAssetCacheDir();
1846     string path = cacheDir + "/" + fileName;
1847     string fileId = MediaFileUtils::GetIdFromUri(uriString);
1848 
1849     if (mode == MEDIA_FILEMODE_READONLY) {
1850         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileExists(path), E_HAS_FS_ERROR,
1851             "Cache file does not exist, path=%{private}s", path.c_str());
1852         return OpenFileWithPrivacy(path, mode, fileId);
1853     }
1854     CHECK_AND_RETURN_RET_LOG(
1855         MediaFileUtils::CreateDirectory(cacheDir), E_HAS_FS_ERROR, "Cannot create dir %{private}s", cacheDir.c_str());
1856     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateAsset(path) == E_SUCCESS, E_HAS_FS_ERROR,
1857         "Create cache file failed, path=%{private}s", path.c_str());
1858     return OpenFileWithPrivacy(path, mode, fileId);
1859 }
1860 
OpenEditOperation(MediaLibraryCommand & cmd,bool & isSkip)1861 int32_t MediaLibraryPhotoOperations::OpenEditOperation(MediaLibraryCommand &cmd, bool &isSkip)
1862 {
1863     isSkip = true;
1864     string operationKey = cmd.GetQuerySetParam(MEDIA_OPERN_KEYWORD);
1865     if (operationKey.empty()) {
1866         return E_OK;
1867     }
1868     if (operationKey == EDIT_DATA_REQUEST) {
1869         isSkip = false;
1870         return RequestEditData(cmd);
1871     } else if (operationKey == SOURCE_REQUEST) {
1872         isSkip = false;
1873         return RequestEditSource(cmd);
1874     } else if (operationKey == COMMIT_REQUEST) {
1875         isSkip = false;
1876         return CommitEditOpen(cmd);
1877     }
1878 
1879     return E_OK;
1880 }
1881 
1882 const static vector<string> EDITED_COLUMN_VECTOR = {
1883     PhotoColumn::MEDIA_FILE_PATH,
1884     MediaColumn::MEDIA_NAME,
1885     PhotoColumn::PHOTO_EDIT_TIME,
1886     PhotoColumn::MEDIA_TIME_PENDING,
1887     PhotoColumn::MEDIA_DATE_TRASHED,
1888     PhotoColumn::PHOTO_SUBTYPE,
1889     PhotoColumn::MOVING_PHOTO_EFFECT_MODE,
1890     PhotoColumn::PHOTO_ORIGINAL_SUBTYPE,
1891     MediaColumn::MEDIA_DATE_TAKEN,
1892 };
1893 
CheckFileAssetStatus(const shared_ptr<FileAsset> & fileAsset,bool checkMovingPhoto=false)1894 static int32_t CheckFileAssetStatus(const shared_ptr<FileAsset>& fileAsset, bool checkMovingPhoto = false)
1895 {
1896     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_URI, "FileAsset is nullptr");
1897     CHECK_AND_RETURN_RET_LOG(fileAsset->GetDateTrashed() == 0, E_IS_RECYCLED, "FileAsset is in recycle");
1898     CHECK_AND_RETURN_RET_LOG(fileAsset->GetTimePending() == 0, E_IS_PENDING_ERROR, "FileAsset is in pending");
1899     if (checkMovingPhoto) {
1900         CHECK_AND_RETURN_RET_LOG((fileAsset->GetPhotoSubType() == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO) ||
1901             fileAsset->GetMovingPhotoEffectMode() == static_cast<int32_t>(MovingPhotoEffectMode::IMAGE_ONLY)),
1902             E_INVALID_VALUES, "FileAsset is not moving photo");
1903     }
1904     return E_OK;
1905 }
1906 
RequestEditData(MediaLibraryCommand & cmd)1907 int32_t MediaLibraryPhotoOperations::RequestEditData(MediaLibraryCommand &cmd)
1908 {
1909     string uriString = cmd.GetUriStringWithoutSegment();
1910     string id = MediaFileUtils::GetIdFromUri(uriString);
1911     if (uriString.empty() || (!MediaLibraryDataManagerUtils::IsNumber(id))) {
1912         return E_INVALID_URI;
1913     }
1914 
1915     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(PhotoColumn::MEDIA_ID, id,
1916         OperationObject::FILESYSTEM_PHOTO, EDITED_COLUMN_VECTOR);
1917     int32_t err = CheckFileAssetStatus(fileAsset);
1918     CHECK_AND_RETURN_RET_LOG(err == E_OK, err, "Failed to check status of fileAsset: %{private}s", uriString.c_str());
1919 
1920     string path = fileAsset->GetFilePath();
1921     CHECK_AND_RETURN_RET_LOG(!path.empty(), E_INVALID_URI, "Can not get file path, uri=%{private}s",
1922         uriString.c_str());
1923 
1924     string editDataPath = GetEditDataPath(path);
1925     string dataPath = editDataPath;
1926     if (!MediaFileUtils::IsFileExists(dataPath)) {
1927         dataPath = GetEditDataCameraPath(path);
1928     }
1929     CHECK_AND_RETURN_RET_LOG(!dataPath.empty(), E_INVALID_PATH, "Get edit data path from path %{private}s failed",
1930         dataPath.c_str());
1931     if (fileAsset->GetPhotoEditTime() == 0 && !MediaFileUtils::IsFileExists(dataPath)) {
1932         MEDIA_INFO_LOG("File %{private}s does not have edit data", uriString.c_str());
1933         dataPath = editDataPath;
1934         string dataPathDir = GetEditDataDirPath(path);
1935         CHECK_AND_RETURN_RET_LOG(!dataPathDir.empty(), E_INVALID_PATH,
1936             "Get edit data dir path from path %{private}s failed", path.c_str());
1937         if (!MediaFileUtils::IsDirectory(dataPathDir)) {
1938             CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateDirectory(dataPathDir), E_HAS_FS_ERROR,
1939                 "Failed to create dir %{private}s", dataPathDir.c_str());
1940         }
1941         err = MediaFileUtils::CreateAsset(dataPath);
1942         CHECK_AND_RETURN_RET_LOG(err == E_SUCCESS || err == E_FILE_EXIST, E_HAS_FS_ERROR,
1943             "Failed to create file %{private}s", dataPath.c_str());
1944     } else {
1945         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileExists(dataPath), E_HAS_FS_ERROR,
1946             "File %{public}s has edit at %{public}ld, but cannot get editdata", uriString.c_str(),
1947             (long)fileAsset->GetPhotoEditTime());
1948     }
1949 
1950     return OpenFileWithPrivacy(dataPath, "r", id);
1951 }
1952 
RequestEditSource(MediaLibraryCommand & cmd)1953 int32_t MediaLibraryPhotoOperations::RequestEditSource(MediaLibraryCommand &cmd)
1954 {
1955     string uriString = cmd.GetUriStringWithoutSegment();
1956     string id = MediaFileUtils::GetIdFromUri(uriString);
1957     if (uriString.empty() || (!MediaLibraryDataManagerUtils::IsNumber(id))) {
1958         return E_INVALID_URI;
1959     }
1960     CHECK_AND_RETURN_RET_LOG(!PhotoEditingRecord::GetInstance()->IsInRevertOperation(stoi(id)),
1961         E_IS_IN_COMMIT, "File %{public}s is in revert, can not request source", id.c_str());
1962     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(PhotoColumn::MEDIA_ID, id,
1963         OperationObject::FILESYSTEM_PHOTO, EDITED_COLUMN_VECTOR);
1964     int32_t err = CheckFileAssetStatus(fileAsset);
1965     CHECK_AND_RETURN_RET_LOG(err == E_OK, err, "Failed to check status of fileAsset: %{private}s", uriString.c_str());
1966     string path = fileAsset->GetFilePath();
1967     CHECK_AND_RETURN_RET_LOG(!path.empty(), E_INVALID_URI,
1968         "Can not get file path, uri=%{private}s", uriString.c_str());
1969     string movingPhotoVideoPath = "";
1970     bool isMovingPhotoVideoRequest =
1971         cmd.GetQuerySetParam(MEDIA_MOVING_PHOTO_OPRN_KEYWORD) == OPEN_MOVING_PHOTO_VIDEO;
1972     if (isMovingPhotoVideoRequest) {
1973         CHECK_AND_RETURN_RET_LOG(
1974             CheckOpenMovingPhoto(fileAsset->GetPhotoSubType(), fileAsset->GetMovingPhotoEffectMode(),
1975                 cmd.GetQuerySetParam(MEDIA_OPERN_KEYWORD)),
1976             E_INVALID_VALUES,
1977             "Non-moving photo requesting moving photo operation, file id: %{public}s, actual subtype: %{public}d",
1978             id.c_str(), fileAsset->GetPhotoSubType());
1979         movingPhotoVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(path);
1980     }
1981 
1982     string sourcePath = isMovingPhotoVideoRequest ?
1983         MediaFileUtils::GetMovingPhotoVideoPath(GetEditDataSourcePath(path)) :
1984         GetEditDataSourcePath(path);
1985     if (sourcePath.empty() || !MediaFileUtils::IsFileExists(sourcePath)) {
1986         MEDIA_INFO_LOG("sourcePath does not exist: %{private}s", sourcePath.c_str());
1987         return OpenFileWithPrivacy(isMovingPhotoVideoRequest ? movingPhotoVideoPath : path, "r", id);
1988     }
1989     return OpenFileWithPrivacy(sourcePath, "r", id);
1990 }
1991 
CommitEditOpen(MediaLibraryCommand & cmd)1992 int32_t MediaLibraryPhotoOperations::CommitEditOpen(MediaLibraryCommand &cmd)
1993 {
1994     string uriString = cmd.GetUriStringWithoutSegment();
1995     string id = MediaFileUtils::GetIdFromUri(uriString);
1996     if (uriString.empty() || (!MediaLibraryDataManagerUtils::IsNumber(id))) {
1997         return E_INVALID_URI;
1998     }
1999 
2000     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(PhotoColumn::MEDIA_ID, id,
2001         OperationObject::FILESYSTEM_PHOTO, EDITED_COLUMN_VECTOR);
2002     if (fileAsset == nullptr) {
2003         MEDIA_ERR_LOG("Get FileAsset From Uri Failed, uri:%{public}s", uriString.c_str());
2004         return E_INVALID_URI;
2005     }
2006     int32_t fileId = stoi(id);  // after MediaLibraryDataManagerUtils::IsNumber, id must be number
2007     CHECK_AND_RETURN_RET(PhotoEditingRecord::GetInstance()->StartCommitEdit(fileId), E_IS_IN_REVERT);
2008     int32_t fd = CommitEditOpenExecute(fileAsset);
2009     if (fd < 0) {
2010         PhotoEditingRecord::GetInstance()->EndCommitEdit(fileId);
2011     }
2012     return fd;
2013 }
2014 
CommitEditOpenExecute(const shared_ptr<FileAsset> & fileAsset)2015 int32_t MediaLibraryPhotoOperations::CommitEditOpenExecute(const shared_ptr<FileAsset> &fileAsset)
2016 {
2017     int32_t err = CheckFileAssetStatus(fileAsset);
2018     CHECK_AND_RETURN_RET(err == E_OK, err);
2019     string path = fileAsset->GetFilePath();
2020     CHECK_AND_RETURN_RET_LOG(!path.empty(), E_INVALID_URI, "Can not get file path");
2021     if (fileAsset->GetPhotoEditTime() == 0) {
2022         string sourceDirPath = GetEditDataDirPath(path);
2023         CHECK_AND_RETURN_RET_LOG(!sourceDirPath.empty(), E_INVALID_URI, "Can not get edit dir path");
2024         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateDirectory(sourceDirPath), E_HAS_FS_ERROR,
2025             "Can not create dir %{private}s", sourceDirPath.c_str());
2026         string sourcePath = GetEditDataSourcePath(path);
2027         CHECK_AND_RETURN_RET_LOG(!sourcePath.empty(), E_INVALID_URI, "Can not get edit source path");
2028         if (!MediaFileUtils::IsFileExists(sourcePath)) {
2029             CHECK_AND_RETURN_RET_LOG(MediaFileUtils::ModifyAsset(path, sourcePath) == E_SUCCESS, E_HAS_FS_ERROR,
2030                 "Move file failed, srcPath:%{private}s, newPath:%{private}s", path.c_str(), sourcePath.c_str());
2031             CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateFile(path), E_HAS_FS_ERROR,
2032                 "Create file failed, path:%{private}s", path.c_str());
2033         } else {
2034             MEDIA_WARN_LOG("Unexpected source file already exists for a not-edited asset, display name: %{private}s",
2035                 fileAsset->GetDisplayName().c_str());
2036         }
2037     }
2038 
2039     string fileId = MediaFileUtils::GetIdFromUri(fileAsset->GetUri());
2040     return OpenFileWithPrivacy(path, "rw", fileId);
2041 }
2042 
UpdateEditTime(int32_t fileId,int64_t time)2043 static int32_t UpdateEditTime(int32_t fileId, int64_t time)
2044 {
2045     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2046     CHECK_AND_RETURN_RET(rdbStore != nullptr, E_HAS_DB_ERROR);
2047     MediaLibraryCommand updatePendingCmd(OperationObject::FILESYSTEM_PHOTO, OperationType::UPDATE);
2048     updatePendingCmd.GetAbsRdbPredicates()->EqualTo(MediaColumn::MEDIA_ID, to_string(fileId));
2049     ValuesBucket updateValues;
2050     updateValues.PutLong(PhotoColumn::PHOTO_EDIT_TIME, time);
2051     updatePendingCmd.SetValueBucket(updateValues);
2052     int32_t rowId = 0;
2053     int32_t result = rdbStore->Update(updatePendingCmd, rowId);
2054     CHECK_AND_RETURN_RET_LOG(result == NativeRdb::E_OK && rowId > 0, E_HAS_DB_ERROR,
2055         "Update File pending failed. Result %{public}d.", result);
2056     return E_OK;
2057 }
2058 
RevertMetadata(int32_t fileId,int64_t time,int32_t effectMode,int32_t photoSubType)2059 static int32_t RevertMetadata(int32_t fileId, int64_t time, int32_t effectMode, int32_t photoSubType)
2060 {
2061     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2062     CHECK_AND_RETURN_RET(rdbStore != nullptr, E_HAS_DB_ERROR);
2063     MediaLibraryCommand cmd(OperationObject::FILESYSTEM_PHOTO, OperationType::UPDATE);
2064     cmd.GetAbsRdbPredicates()->EqualTo(MediaColumn::MEDIA_ID, to_string(fileId));
2065     ValuesBucket updateValues;
2066     updateValues.PutLong(PhotoColumn::PHOTO_EDIT_TIME, time);
2067     if (effectMode == static_cast<int32_t>(MovingPhotoEffectMode::IMAGE_ONLY)) {
2068         updateValues.PutInt(PhotoColumn::MOVING_PHOTO_EFFECT_MODE,
2069             static_cast<int32_t>(MovingPhotoEffectMode::DEFAULT));
2070         updateValues.PutInt(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(PhotoSubType::MOVING_PHOTO));
2071     } else if (photoSubType == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO) &&
2072         effectMode != static_cast<int32_t>(MovingPhotoEffectMode::DEFAULT)) {
2073         updateValues.PutInt(PhotoColumn::MOVING_PHOTO_EFFECT_MODE,
2074             static_cast<int32_t>(MovingPhotoEffectMode::DEFAULT));
2075     }
2076     cmd.SetValueBucket(updateValues);
2077     int32_t rowId = 0;
2078     int32_t result = rdbStore->Update(cmd, rowId);
2079     CHECK_AND_RETURN_RET_LOG(result == NativeRdb::E_OK && rowId > 0, E_HAS_DB_ERROR,
2080         "Failed to revert metadata. Result %{public}d.", result);
2081     return E_OK;
2082 }
2083 
UpdateEffectMode(int32_t fileId,int32_t effectMode)2084 static int32_t UpdateEffectMode(int32_t fileId, int32_t effectMode)
2085 {
2086     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2087     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "Failed to get rdbStore when updating effect mode");
2088 
2089     MediaLibraryCommand updateCmd(OperationObject::FILESYSTEM_PHOTO, OperationType::UPDATE);
2090     updateCmd.GetAbsRdbPredicates()->EqualTo(MediaColumn::MEDIA_ID, to_string(fileId));
2091     ValuesBucket updateValues;
2092     updateValues.PutInt(PhotoColumn::MOVING_PHOTO_EFFECT_MODE, effectMode);
2093     if (effectMode == static_cast<int32_t>(MovingPhotoEffectMode::IMAGE_ONLY)) {
2094         updateValues.PutInt(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(PhotoSubType::DEFAULT));
2095     } else {
2096         updateValues.PutInt(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(PhotoSubType::MOVING_PHOTO));
2097     }
2098     updateCmd.SetValueBucket(updateValues);
2099 
2100     int32_t updateRows = -1;
2101     int32_t errCode = rdbStore->Update(updateCmd, updateRows);
2102     CHECK_AND_RETURN_RET_LOG(errCode == NativeRdb::E_OK && updateRows >= 0, E_HAS_DB_ERROR,
2103         "Update effect mode failed. errCode:%{public}d, updateRows:%{public}d.", errCode, updateRows);
2104     return E_OK;
2105 }
2106 
UpdateMimeType(const int32_t & fileId,const std::string mimeType)2107 static int32_t UpdateMimeType(const int32_t &fileId, const std::string mimeType)
2108 {
2109     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2110     if (rdbStore == nullptr) {
2111         MEDIA_ERR_LOG("Failed to get rdbStore when updating mime type");
2112         return E_HAS_DB_ERROR;
2113     }
2114     MediaLibraryCommand updateCmd(OperationObject::FILESYSTEM_PHOTO, OperationType::UPDATE);
2115     updateCmd.GetAbsRdbPredicates()->EqualTo(MediaColumn::MEDIA_ID, to_string(fileId));
2116     ValuesBucket updateValues;
2117 
2118     updateCmd.SetValueBucket(updateValues);
2119     int32_t updateRows = -1;
2120     int32_t errCode = rdbStore->Update(updateCmd, updateRows);
2121     if (errCode != NativeRdb::E_OK || updateRows < 0) {
2122         MEDIA_ERR_LOG("Update mime type failed. errCode:%{public}d, updateRows:%{public}d.", errCode, updateRows);
2123         return E_HAS_DB_ERROR;
2124     }
2125     return E_OK;
2126 }
2127 
GetModityExtensionPath(std::string & path,std::string & modifyFilePath,const std::string & extension)2128 static void GetModityExtensionPath(std::string &path, std::string &modifyFilePath, const std::string &extension)
2129 {
2130     size_t pos = path.find_last_of('.');
2131     modifyFilePath = path.substr(0, pos) + extension;
2132 }
2133 
Move(const string & srcPath,const string & destPath)2134 static int32_t Move(const string& srcPath, const string& destPath)
2135 {
2136     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileExists(srcPath), E_NO_SUCH_FILE,
2137         "srcPath: %{private}s does not exist!", srcPath.c_str());
2138 
2139     CHECK_AND_RETURN_RET_LOG(!destPath.empty(), E_INVALID_VALUES, "Failed to check empty destPath");
2140 
2141     int32_t ret = rename(srcPath.c_str(), destPath.c_str());
2142     if (ret < 0) {
2143         MEDIA_ERR_LOG("Failed to rename, src: %{public}s, dest: %{public}s, ret: %{public}d, errno: %{public}d",
2144             srcPath.c_str(), destPath.c_str(), ret, errno);
2145         if (errno == CROSS_POLICY_ERR) {
2146             ret = MediaFileUtils::CopyFileAndDelSrc(srcPath, destPath) ? 0 : -1;
2147             MEDIA_INFO_LOG("sendfile result:%{public}d", ret);
2148         }
2149     }
2150     return ret;
2151 }
2152 
UpdateExtension(const int32_t & fileId,std::string & mimeType,const int32_t & fileType,std::string & oldFilePath)2153 int32_t MediaLibraryPhotoOperations::UpdateExtension(const int32_t &fileId, std::string &mimeType,
2154     const int32_t &fileType, std::string &oldFilePath)
2155 {
2156     ImageFileType type = static_cast<ImageFileType>(fileType);
2157     auto itr = IMAGE_FILE_TYPE_MAP.find(type);
2158     CHECK_AND_RETURN_RET_LOG(itr != IMAGE_FILE_TYPE_MAP.end(), E_INVALID_ARGUMENTS,
2159         "fileType : %{public} is not support", fileType);
2160     mimeType = itr->second;
2161     auto extensionItr = IMAGE_EXTENSION_MAP.find(type);
2162     CHECK_AND_RETURN_RET_LOG(itr != IMAGE_EXTENSION_MAP.end(), E_INVALID_ARGUMENTS,
2163         "fileType : %{public} is not support", fileType);
2164     std::string extension = extensionItr->second;
2165     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2166     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "Failed to get rdbStore when updating mime type");
2167     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(PhotoColumn::MEDIA_ID, to_string(fileId),
2168                                                          OperationObject::FILESYSTEM_PHOTO, EDITED_COLUMN_VECTOR);
2169     std::string filePath = fileAsset->GetFilePath();
2170     std::string displayName = fileAsset->GetDisplayName();
2171     std::string modifyFilePath;
2172     std::string modifyDisplayName;
2173     GetModityExtensionPath(filePath, modifyFilePath, extension);
2174     GetModityExtensionPath(displayName, modifyDisplayName, extension);
2175     MEDIA_DEBUG_LOG("modifyFilePath:%{public}s", modifyFilePath.c_str());
2176     MEDIA_DEBUG_LOG("modifyDisplayName:%{public}s", modifyDisplayName.c_str());
2177     if ((modifyFilePath == filePath) && (modifyDisplayName == displayName)) {
2178         return E_OK;
2179     }
2180     UpdateEditDataPath(filePath, extension);
2181     MediaLibraryCommand updateCmd(OperationObject::FILESYSTEM_PHOTO, OperationType::UPDATE);
2182     updateCmd.GetAbsRdbPredicates()->EqualTo(MediaColumn::MEDIA_ID, to_string(fileId));
2183     ValuesBucket updateValues;
2184     updateValues.PutString(MediaColumn::MEDIA_FILE_PATH, modifyFilePath);
2185     updateValues.PutString(MediaColumn::MEDIA_NAME, modifyDisplayName);
2186     updateValues.PutString(MediaColumn::MEDIA_MIME_TYPE, mimeType);
2187     updateValues.PutString(PhotoColumn::PHOTO_MEDIA_SUFFIX, ScannerUtils::GetFileExtension(modifyDisplayName));
2188     updateCmd.SetValueBucket(updateValues);
2189     int32_t updateRows = -1;
2190     int32_t errCode = rdbStore->Update(updateCmd, updateRows);
2191     CHECK_AND_RETURN_RET_LOG(errCode == NativeRdb::E_OK && updateRows >= 0, E_HAS_DB_ERROR,
2192         "Update extension failed. errCode:%{public}d, updateRows:%{public}d.", errCode, updateRows);
2193     oldFilePath = filePath;
2194     return E_OK;
2195 }
2196 
UpdateEditDataPath(std::string filePath,const std::string & extension)2197 void MediaLibraryPhotoOperations::UpdateEditDataPath(std::string filePath, const std::string &extension)
2198 {
2199     string editDataPath = GetEditDataDirPath(filePath);
2200     string tempOutputPath = editDataPath;
2201     size_t pos = tempOutputPath.find_last_of('.');
2202     if (pos != string::npos) {
2203         tempOutputPath.replace(pos, extension.length(), extension);
2204         rename(editDataPath.c_str(), tempOutputPath.c_str());
2205         MEDIA_DEBUG_LOG("rename, src: %{public}s, dest: %{public}s",
2206             editDataPath.c_str(), tempOutputPath.c_str());
2207     }
2208 }
2209 
DeleteAbnormalFile(std::string & assetPath,const int32_t & fileId,const std::string & oldFilePath)2210 void MediaLibraryPhotoOperations::DeleteAbnormalFile(std::string &assetPath, const int32_t &fileId,
2211     const std::string &oldFilePath)
2212 {
2213     MEDIA_INFO_LOG("DeleteAbnormalFile fileId:%{public}d, assetPath = %{public}s", fileId, assetPath.c_str());
2214     MediaLibraryObjectUtils::ScanFileAsync(assetPath, to_string(fileId), MediaLibraryApi::API_10);
2215     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
2216     vector<string> columns = { MediaColumn::MEDIA_ID, MediaColumn::MEDIA_FILE_PATH};
2217     string whereClause = MediaColumn::MEDIA_FILE_PATH + "= ?";
2218     vector<string> args = {oldFilePath};
2219     predicates.SetWhereClause(whereClause);
2220     predicates.SetWhereArgs(args);
2221     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
2222     if (resultSet->GoToFirstRow() != NativeRdb::E_OK) {
2223         MediaFileUtils::DeleteFile(oldFilePath);
2224         DeleteRevertMessage(oldFilePath);
2225         return;
2226     }
2227     int32_t fileIdTemp = GetInt32Val(MediaColumn::MEDIA_ID, resultSet);
2228     string filePathTemp = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
2229     resultSet->Close();
2230     MEDIA_INFO_LOG("DeleteAbnormalFile fileId:%{public}d, filePathTemp = %{public}s", fileIdTemp, filePathTemp.c_str());
2231     auto oldFileAsset = GetFileAssetFromDb(PhotoColumn::MEDIA_ID, to_string(fileIdTemp),
2232                                            OperationObject::FILESYSTEM_PHOTO, EDITED_COLUMN_VECTOR);
2233     if (oldFileAsset != nullptr) {
2234         int32_t deleteRow = DeletePhoto(oldFileAsset, MediaLibraryApi::API_10);
2235         if (deleteRow < 0) {
2236             MEDIA_ERR_LOG("delete photo failed, deleteRow=%{public}d", deleteRow);
2237         }
2238     }
2239 }
2240 
CommitEditInsert(MediaLibraryCommand & cmd)2241 int32_t MediaLibraryPhotoOperations::CommitEditInsert(MediaLibraryCommand &cmd)
2242 {
2243     const ValuesBucket &values = cmd.GetValueBucket();
2244     string editData;
2245     int32_t id = 0;
2246     if (!GetInt32FromValuesBucket(values, PhotoColumn::MEDIA_ID, id)) {
2247         MEDIA_ERR_LOG("Failed to get fileId");
2248         PhotoEditingRecord::GetInstance()->EndCommitEdit(id);
2249         return E_INVALID_VALUES;
2250     }
2251     if (!GetStringFromValuesBucket(values, EDIT_DATA, editData)) {
2252         MEDIA_ERR_LOG("Failed to get editdata");
2253         PhotoEditingRecord::GetInstance()->EndCommitEdit(id);
2254         return E_INVALID_VALUES;
2255     }
2256 
2257     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(PhotoColumn::MEDIA_ID, to_string(id),
2258         OperationObject::FILESYSTEM_PHOTO, EDITED_COLUMN_VECTOR);
2259     if (fileAsset == nullptr) {
2260         MEDIA_ERR_LOG("Get FileAsset Failed, fileId=%{public}d", id);
2261         PhotoEditingRecord::GetInstance()->EndCommitEdit(id);
2262         return E_INVALID_VALUES;
2263     }
2264     fileAsset->SetId(id);
2265     int32_t ret = CommitEditInsertExecute(fileAsset, editData);
2266     PhotoEditingRecord::GetInstance()->EndCommitEdit(id);
2267     MEDIA_INFO_LOG("commit edit finished, fileId=%{public}d", id);
2268     return ret;
2269 }
2270 
NotifyFormMap(const int32_t fileId,const string & path,const bool isSave)2271 static void NotifyFormMap(const int32_t fileId, const string& path, const bool isSave)
2272 {
2273     string uri = MediaLibraryFormMapOperations::GetUriByFileId(fileId, path);
2274     CHECK_AND_RETURN_LOG(!uri.empty(), "Failed to GetUriByFileId(%{public}d, %{private}s)", fileId, path.c_str());
2275 
2276     vector<int64_t> formIds;
2277     MediaLibraryFormMapOperations::GetFormMapFormId(uri.c_str(), formIds);
2278     if (!formIds.empty()) {
2279         MediaLibraryFormMapOperations::PublishedChange(uri, formIds, isSave);
2280     }
2281 }
2282 
CommitEditInsertExecute(const shared_ptr<FileAsset> & fileAsset,const string & editData)2283 int32_t MediaLibraryPhotoOperations::CommitEditInsertExecute(const shared_ptr<FileAsset> &fileAsset,
2284     const string &editData)
2285 {
2286     int32_t errCode = CheckFileAssetStatus(fileAsset);
2287     CHECK_AND_RETURN_RET(errCode == E_OK, errCode);
2288 
2289     string path = fileAsset->GetPath();
2290     CHECK_AND_RETURN_RET_LOG(!path.empty(), E_INVALID_VALUES, "File path is empty");
2291     string editDataPath = GetEditDataPath(path);
2292     CHECK_AND_RETURN_RET_LOG(!editDataPath.empty(), E_INVALID_VALUES, "EditData path is empty");
2293     if (!MediaFileUtils::IsFileExists(editDataPath)) {
2294         string dataPathDir = GetEditDataDirPath(path);
2295         CHECK_AND_RETURN_RET_LOG(!dataPathDir.empty(), E_INVALID_PATH,
2296             "Get edit data dir path from path %{private}s failed", path.c_str());
2297         if (!MediaFileUtils::IsDirectory(dataPathDir)) {
2298             CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateDirectory(dataPathDir), E_HAS_FS_ERROR,
2299                 "Failed to create dir %{private}s", dataPathDir.c_str());
2300         }
2301         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateAsset(editDataPath) == E_SUCCESS, E_HAS_FS_ERROR,
2302             "Failed to create file %{private}s", editDataPath.c_str());
2303     }
2304     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::WriteStrToFile(editDataPath, editData), E_HAS_FS_ERROR,
2305         "Failed to write editdata path:%{private}s", editDataPath.c_str());
2306 
2307     MediaLibraryRdbUtils::UpdateSystemAlbumInternal(
2308         MediaLibraryUnistoreManager::GetInstance().GetRdbStore(), {
2309         to_string(PhotoAlbumSubType::IMAGE),
2310         to_string(PhotoAlbumSubType::VIDEO),
2311         to_string(PhotoAlbumSubType::SCREENSHOT),
2312         to_string(PhotoAlbumSubType::FAVORITE),
2313         to_string(PhotoAlbumSubType::CLOUD_ENHANCEMENT),
2314     });
2315     errCode = UpdateEditTime(fileAsset->GetId(), MediaFileUtils::UTCTimeSeconds());
2316     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to update edit time, fileId:%{public}d",
2317         fileAsset->GetId());
2318     ScanFile(path, false, true, true);
2319     NotifyFormMap(fileAsset->GetId(), fileAsset->GetFilePath(), false);
2320     return E_OK;
2321 }
2322 
RevertToOrigin(MediaLibraryCommand & cmd)2323 int32_t MediaLibraryPhotoOperations::RevertToOrigin(MediaLibraryCommand &cmd)
2324 {
2325     const ValuesBucket &values = cmd.GetValueBucket();
2326     int32_t fileId = 0;
2327     CHECK_AND_RETURN_RET_LOG(GetInt32FromValuesBucket(values, PhotoColumn::MEDIA_ID, fileId), E_INVALID_VALUES,
2328         "Failed to get fileId");
2329 
2330     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(PhotoColumn::MEDIA_ID, to_string(fileId),
2331         OperationObject::FILESYSTEM_PHOTO, EDITED_COLUMN_VECTOR);
2332     if (fileAsset == nullptr) {
2333         MEDIA_ERR_LOG("Get FileAsset From Uri Failed, fileId:%{public}d", fileId);
2334         return E_INVALID_VALUES;
2335     }
2336     fileAsset->SetId(fileId);
2337     CHECK_AND_RETURN_RET(PhotoEditingRecord::GetInstance()->StartRevert(fileId), E_IS_IN_COMMIT);
2338 
2339     int32_t errCode = DoRevertEdit(fileAsset);
2340     PhotoEditingRecord::GetInstance()->EndRevert(fileId);
2341     return errCode;
2342 }
2343 
UpdateMovingPhotoSubtype(int32_t fileId,int32_t currentPhotoSubType)2344 int32_t MediaLibraryPhotoOperations::UpdateMovingPhotoSubtype(int32_t fileId, int32_t currentPhotoSubType)
2345 {
2346     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2347     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "Failed to get rdbStore when updating subtype");
2348 
2349     int32_t updatePhotoSubType = currentPhotoSubType == static_cast<int32_t>(PhotoSubType::DEFAULT) ?
2350         static_cast<int32_t>(PhotoSubType::MOVING_PHOTO) : static_cast<int32_t>(PhotoSubType::DEFAULT);
2351     MediaLibraryCommand updateCmd(OperationObject::FILESYSTEM_PHOTO, OperationType::UPDATE);
2352     updateCmd.GetAbsRdbPredicates()->EqualTo(MediaColumn::MEDIA_ID, to_string(fileId));
2353     ValuesBucket updateValues;
2354     updateValues.PutInt(PhotoColumn::PHOTO_SUBTYPE, updatePhotoSubType);
2355     if (currentPhotoSubType == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
2356         updateValues.PutInt(PhotoColumn::PHOTO_ORIGINAL_SUBTYPE, static_cast<int32_t>(PhotoSubType::MOVING_PHOTO));
2357     }
2358     updateCmd.SetValueBucket(updateValues);
2359     int32_t updateRows = -1;
2360     int32_t errCode = rdbStore->Update(updateCmd, updateRows);
2361     CHECK_AND_RETURN_RET_LOG(errCode == NativeRdb::E_OK && updateRows >= 0, E_HAS_DB_ERROR,
2362         "Update subtype field failed. errCode:%{public}d, updateRows:%{public}d", errCode, updateRows);
2363     return E_OK;
2364 }
2365 
ResetOcrInfo(const int32_t & fileId)2366 void ResetOcrInfo(const int32_t &fileId)
2367 {
2368     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2369     CHECK_AND_RETURN_LOG(rdbStore != nullptr, "MediaLibrary rdbStore is nullptr!");
2370     string sqlDeleteOcr = "DELETE FROM " + VISION_OCR_TABLE + " WHERE file_id = " + to_string(fileId) + ";" +
2371         " UPDATE " + VISION_TOTAL_TABLE + " SET ocr = 0 WHERE file_id = " + to_string(fileId) + ";";
2372 
2373     int ret = rdbStore->ExecuteSql(sqlDeleteOcr);
2374     CHECK_AND_RETURN_LOG(ret == NativeRdb::E_OK,
2375         "Update ocr info failed, ret = %{public}d, file id is %{public}d", ret, fileId);
2376 }
2377 
GetSourceFileFromEditPath(const std::string & path,const std::shared_ptr<FileAsset> & fileAsset)2378 std::string MediaLibraryPhotoOperations::GetSourceFileFromEditPath(const std::string &path,
2379     const std::shared_ptr<FileAsset> &fileAsset)
2380 {
2381     if (fileAsset == nullptr) {
2382         MEDIA_ERR_LOG("fileAsset is nullptr");
2383         return "";
2384     }
2385     std::string sourcePath;
2386     string parentPath = GetEditDataDirPath(path);
2387     std::vector<string> fileNames = MediaFileUtils::GetFileNameFromDir(parentPath);
2388     if (fileNames.empty()) {
2389         return "";
2390     }
2391     bool isMovingPhoto = MovingPhotoFileUtils::IsMovingPhoto(
2392         fileAsset->GetPhotoSubType(), fileAsset->GetMovingPhotoEffectMode(), fileAsset->GetOriginalSubType());
2393     // 这里处理动态照片,动态照片editdata下存在两个source文件,source.jpg\source.mp4,此处要取出jpg,跳过mp4
2394     for (auto &filename : fileNames) {
2395         if (MediaFileUtils::UnSplitByChar(filename, '.') == "source") {
2396             if (isMovingPhoto && MediaFileUtils::SplitByChar(filename, '.') == "mp4") {
2397                 continue;
2398             }
2399             return parentPath + "/" + filename;
2400         }
2401     }
2402     return "";
2403 }
2404 
UpdateDbByRevertToOrigin(std::shared_ptr<FileAsset> & fileAsset,std::string & path,const std::string & sourcePath)2405 int32_t MediaLibraryPhotoOperations::UpdateDbByRevertToOrigin(
2406     std::shared_ptr<FileAsset> &fileAsset, std::string &path, const std::string &sourcePath)
2407 {
2408     if (MediaFileUtils::GetExtensionFromPath(path) == MediaFileUtils::GetExtensionFromPath(sourcePath)) {
2409         return E_OK;
2410     }
2411     MEDIA_INFO_LOG("UpdateDbByRevertToOrigin enter, fileId: %{public}d.", fileAsset->GetId());
2412     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_VALUES, "fileAsset is nullptr");
2413     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2414     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_INVALID_VALUES, "UpdateDbByRevertToOrigin rdbStore is nullptr!");
2415     int32_t id = fileAsset->GetId();
2416     NativeRdb::ValuesBucket values;
2417     path = MediaFileUtils::UnSplitByChar(path, '.') + "." + MediaFileUtils::GetExtensionFromPath(sourcePath);
2418     std::string displayName = MediaFileUtils::UnSplitByChar(fileAsset->GetDisplayName(), '.') + "." +
2419                               MediaFileUtils::GetExtensionFromPath(sourcePath);
2420     std::string mimeType = MediaFileUtils::GetMimeTypeFromDisplayName(displayName);
2421     std::string extension = MediaFileUtils::GetExtensionFromPath(displayName);
2422     values.PutString(MediaColumn::MEDIA_NAME, displayName);
2423     values.PutString(MediaColumn::MEDIA_FILE_PATH, path);
2424     values.PutString(MediaColumn::MEDIA_MIME_TYPE, mimeType);
2425     values.PutString(PhotoColumn::PHOTO_MEDIA_SUFFIX, extension);
2426     if (fileAsset->GetDirty() == static_cast<int32_t>(DirtyTypes::TYPE_SYNCED)) {
2427         values.PutInt(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyTypes::TYPE_FDIRTY));
2428     }
2429     values.PutLong(PhotoColumn::PHOTO_LAST_VISIT_TIME, MediaFileUtils::UTCTimeMilliSeconds());
2430     values.PutLong(PhotoColumn::PHOTO_META_DATE_MODIFIED, MediaFileUtils::UTCTimeMilliSeconds());
2431     values.PutLong(PhotoColumn::MEDIA_DATE_MODIFIED, MediaFileUtils::UTCTimeMilliSeconds());
2432     std::string whereClauses = MediaColumn::MEDIA_ID + " = ?";
2433     std::vector<std::string> whereArgs = {std::to_string(id)};
2434 
2435     int32_t updateRows = 0;
2436     int32_t ret = rdbStore->Update(updateRows, PhotoColumn::PHOTOS_TABLE, values, whereClauses, whereArgs);
2437     CHECK_AND_RETURN_RET_LOG((ret == NativeRdb::E_OK && updateRows >= 0),
2438         E_ERR, "failed to update, ret: %{public}d, updateRows: %{public}d.", ret, updateRows);
2439     int64_t dataTaken = fileAsset->GetDateTaken();
2440     std::string oldPath = fileAsset->GetPath();
2441     bool isThumbnailInvalidate =  ThumbnailService::GetInstance()->HasInvalidateThumbnail(
2442         to_string(id), PhotoColumn::PHOTOS_TABLE, oldPath, to_string(dataTaken));
2443     if (isThumbnailInvalidate) {
2444         int32_t userId = -1;
2445         string thumbPath = MediaFileUtils::GetThumbDir(oldPath, userId);
2446         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::DeleteDir(thumbPath), E_ERR, "failed to update.");
2447     }
2448     fileAsset->SetPath(path);
2449     MEDIA_INFO_LOG("UpdateDbByRevertToOrigin end.");
2450     return ret;
2451 }
2452 
RenameEditDataDirByRevert(const std::string & editDataDir,const std::string & path)2453 int32_t MediaLibraryPhotoOperations::RenameEditDataDirByRevert(
2454     const std::string &editDataDir, const std::string &path)
2455 {
2456     if (MediaFileUtils::GetExtensionFromPath(path) == MediaFileUtils::GetExtensionFromPath(editDataDir)) {
2457         return E_OK;
2458     }
2459     string newEditDataDir =
2460         MediaFileUtils::UnSplitByChar(editDataDir, '.') + "." + MediaFileUtils::GetExtensionFromPath(path);
2461     if (!MediaFileUtils::RenameDir(editDataDir, newEditDataDir)) {
2462         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::DeleteDir(editDataDir), E_FAIL, "Can not delete old editdata dir");
2463     }
2464     return E_OK;
2465 }
2466 
DoRevertEdit(std::shared_ptr<FileAsset> & fileAsset)2467 int32_t MediaLibraryPhotoOperations::DoRevertEdit(std::shared_ptr<FileAsset> &fileAsset)
2468 {
2469     MEDIA_INFO_LOG("begin to do revertEdit");
2470     int32_t errCode = CheckFileAssetStatus(fileAsset);
2471     CHECK_AND_RETURN_RET(errCode == E_OK, errCode);
2472     int32_t fileId = fileAsset->GetId();
2473     if (fileAsset->GetPhotoEditTime() == 0) {
2474         MEDIA_INFO_LOG("File %{public}d is not edit", fileId);
2475         return E_OK;
2476     }
2477 
2478     string path = fileAsset->GetFilePath();
2479     CHECK_AND_RETURN_RET_LOG(!path.empty(), E_INVALID_URI, "Can not get file path, fileId=%{public}d", fileId);
2480 
2481     int32_t subtype = static_cast<int32_t>(fileAsset->GetPhotoSubType());
2482     int32_t movingPhotoSubtype = static_cast<int32_t>(PhotoSubType::MOVING_PHOTO);
2483     if (fileAsset->GetOriginalSubType() == movingPhotoSubtype) {
2484         errCode = UpdateMovingPhotoSubtype(fileAsset->GetId(), subtype);
2485         CHECK_AND_RETURN_RET_LOG(errCode == E_OK, E_HAS_DB_ERROR, "Failed to update movingPhoto subtype");
2486     }
2487 
2488     // 由于displayname可能被修改过,source文件cmd后缀与其上级目录后缀可能不相同,所以要检索EditDataDir目录下source文件
2489     string sourcePath = GetSourceFileFromEditPath(path, fileAsset);
2490     string editDataDir = GetEditDataDirPath(path);
2491     CHECK_AND_RETURN_RET_LOG(!sourcePath.empty(), E_INVALID_URI, "Cannot get source path, id=%{public}d", fileId);
2492     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileExists(sourcePath), E_NO_SUCH_FILE, "Can not get source file");
2493 
2494     string editDataPath = GetEditDataPath(path);
2495     CHECK_AND_RETURN_RET_LOG(!editDataPath.empty(), E_INVALID_URI, "Cannot get editdata path, id=%{public}d", fileId);
2496 
2497     errCode = RevertMetadata(fileId, 0, fileAsset->GetMovingPhotoEffectMode(), fileAsset->GetPhotoSubType());
2498     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, E_HAS_DB_ERROR, "Failed to update data, fileId=%{public}d", fileId);
2499 
2500     ResetOcrInfo(fileId);
2501     if (MediaFileUtils::IsFileExists(editDataPath)) {
2502         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::DeleteFile(editDataPath), E_HAS_FS_ERROR,
2503             "Failed to delete edit data, path:%{private}s", editDataPath.c_str());
2504     }
2505 
2506     if (MediaFileUtils::IsFileExists(path)) {
2507         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::DeleteFile(path), E_HAS_FS_ERROR,
2508             "Failed to delete asset, path:%{private}s", path.c_str());
2509     }
2510     // 处理文件之前,需先更新数据库,并修改资产中的path信息,同步更新path变量
2511     CHECK_AND_RETURN_RET_LOG(UpdateDbByRevertToOrigin(fileAsset, path, sourcePath) == E_OK, E_FAIL,
2512         "Failed to UpdateDbByRevertToOrigin to photo");
2513     CHECK_AND_RETURN_RET_LOG(DoRevertFilters(fileAsset, path, sourcePath) == E_OK, E_FAIL,
2514         "Failed to DoRevertFilters to photo");
2515     // 此时如果有修改过后缀,则老的editdata dir依然存在,扫描会生成新的editdata dir,需删除老的editdata dir,某则再次修改后缀会失败,且此时path已经修改回回退之后的路径
2516     // 此处简洁概述就是:editdata目录要始终和photo下资产的后缀保持一致
2517     CHECK_AND_RETURN_RET_LOG(RenameEditDataDirByRevert(editDataDir, path) == E_OK, E_FAIL,
2518         "Failed to delete old editdatadir");
2519     ScanFile(path, true, true, true);
2520     // revert cloud enhancement ce_available
2521 #ifdef MEDIALIBRARY_FEATURE_CLOUD_ENHANCEMENT
2522     EnhancementManager::GetInstance().RevertEditUpdateInternal(fileId);
2523 #endif
2524     NotifyFormMap(fileAsset->GetId(), fileAsset->GetFilePath(), false);
2525     MEDIA_INFO_LOG("end to do revertEdit");
2526     return E_OK;
2527 }
2528 
DoRevertAfterAddFiltersFailed(const std::shared_ptr<FileAsset> & fileAsset,const std::string & path,const std::string & sourcePath)2529 int32_t MediaLibraryPhotoOperations::DoRevertAfterAddFiltersFailed(const std::shared_ptr<FileAsset> &fileAsset,
2530     const std::string &path, const std::string &sourcePath)
2531 {
2532     MEDIA_WARN_LOG("Failed to add filters to photo.");
2533     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CopyFileUtil(sourcePath, path), E_HAS_FS_ERROR,
2534         "Failed to copy source file.");
2535 
2536     string editDataPath = GetEditDataPath(path);
2537     CHECK_AND_RETURN_RET_LOG(!editDataPath.empty(), E_INVALID_VALUES, "EditData path is empty");
2538     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateFile(editDataPath), E_HAS_FS_ERROR,
2539         "Failed to create editdata file %{private}s", editDataPath.c_str());
2540     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::WriteStrToFile(editDataPath, EDITDATA), E_HAS_FS_ERROR,
2541         "Failed to write editdata:%{private}s", editDataPath.c_str());
2542     return E_OK;
2543 }
2544 
DoRevertFilters(const std::shared_ptr<FileAsset> & fileAsset,std::string & path,std::string & sourcePath)2545 int32_t MediaLibraryPhotoOperations::DoRevertFilters(const std::shared_ptr<FileAsset> &fileAsset,
2546     std::string &path, std::string &sourcePath)
2547 {
2548     string editDataCameraPath = GetEditDataCameraPath(path);
2549     int32_t subtype = static_cast<int32_t>(fileAsset->GetPhotoSubType());
2550     if (!MediaFileUtils::IsFileExists(editDataCameraPath)) {
2551         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::ModifyAsset(sourcePath, path) == E_OK, E_HAS_FS_ERROR,
2552             "Can not modify %{private}s to %{private}s", sourcePath.c_str(), path.c_str());
2553         int32_t movingPhotoSubtype = static_cast<int32_t>(PhotoSubType::MOVING_PHOTO);
2554         if (MovingPhotoFileUtils::IsMovingPhoto(subtype,
2555             fileAsset->GetMovingPhotoEffectMode(), fileAsset->GetOriginalSubType())) {
2556             string videoPath = MediaFileUtils::GetMovingPhotoVideoPath(path);
2557             string sourceVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(sourcePath);
2558             CHECK_AND_RETURN_RET_LOG(Move(sourceVideoPath, videoPath) == E_OK, E_HAS_FS_ERROR,
2559                 "Can not move %{private}s to %{private}s", sourceVideoPath.c_str(), videoPath.c_str());
2560         }
2561     } else {
2562         string editData;
2563         CHECK_AND_RETURN_RET_LOG(ReadEditdataFromFile(editDataCameraPath, editData) == E_OK, E_HAS_FS_ERROR,
2564             "Failed to read editdata, path=%{public}s", editDataCameraPath.c_str());
2565         if (AddFiltersToPhoto(sourcePath, path, editData) != E_OK) {
2566             CHECK_AND_RETURN_RET_LOG(DoRevertAfterAddFiltersFailed(fileAsset, path, sourcePath) == E_OK, E_HAS_FS_ERROR,
2567                 "Failed to do revertAfterAddFiltersFailed");
2568         }
2569         if (MovingPhotoFileUtils::IsMovingPhoto(subtype,
2570             fileAsset->GetMovingPhotoEffectMode(), fileAsset->GetOriginalSubType())) {
2571             CHECK_AND_RETURN_RET_LOG(AddFiltersToVideoExecute(fileAsset, false) == E_OK, E_FAIL,
2572                 "Failed to add filters to video");
2573         }
2574     }
2575     return E_OK;
2576 }
2577 
DeleteRevertMessage(const string & path)2578 void MediaLibraryPhotoOperations::DeleteRevertMessage(const string &path)
2579 {
2580     CHECK_AND_RETURN_LOG(!path.empty(), "Input path is empty");
2581 
2582     string editDirPath = GetEditDataDirPath(path);
2583     CHECK_AND_RETURN_LOG(!editDirPath.empty(), "Can not get edit data dir path from path %{private}s", path.c_str());
2584 
2585     CHECK_AND_RETURN_LOG(MediaFileUtils::IsDirectory(editDirPath), "Edit dir path is not exist.");
2586 
2587     CHECK_AND_RETURN_LOG(MediaFileUtils::DeleteDir(editDirPath),
2588         "Failed to delete %{private}s dir, filePath is %{private}s", editDirPath.c_str(), path.c_str());
2589 }
2590 
IsNeedRevertEffectMode(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,int32_t & effectMode)2591 bool MediaLibraryPhotoOperations::IsNeedRevertEffectMode(MediaLibraryCommand& cmd,
2592     const shared_ptr<FileAsset>& fileAsset, int32_t& effectMode)
2593 {
2594     if (fileAsset->GetPhotoSubType() != static_cast<int32_t>(PhotoSubType::MOVING_PHOTO) &&
2595         fileAsset->GetMovingPhotoEffectMode() != static_cast<int32_t>(MovingPhotoEffectMode::IMAGE_ONLY)) {
2596         return false;
2597     }
2598     if (fileAsset->GetPhotoEditTime() != 0) {
2599         ProcessEditedEffectMode(cmd);
2600         return false;
2601     }
2602 
2603     if (!GetInt32FromValuesBucket(cmd.GetValueBucket(), PhotoColumn::MOVING_PHOTO_EFFECT_MODE, effectMode) ||
2604         (effectMode != static_cast<int32_t>(MovingPhotoEffectMode::DEFAULT) &&
2605         effectMode != static_cast<int32_t>(MovingPhotoEffectMode::IMAGE_ONLY))) {
2606         return false;
2607     }
2608     return true;
2609 }
2610 
ProcessEditedEffectMode(MediaLibraryCommand & cmd)2611 void MediaLibraryPhotoOperations::ProcessEditedEffectMode(MediaLibraryCommand& cmd)
2612 {
2613     int32_t effectMode = 0;
2614     if (!GetInt32FromValuesBucket(
2615         cmd.GetValueBucket(), PhotoColumn::MOVING_PHOTO_EFFECT_MODE, effectMode) ||
2616         effectMode != static_cast<int32_t>(MovingPhotoEffectMode::IMAGE_ONLY)) {
2617         return;
2618     }
2619     ValuesBucket& updateValues = cmd.GetValueBucket();
2620     updateValues.PutInt(PhotoColumn::MOVING_PHOTO_EFFECT_MODE, effectMode);
2621     updateValues.PutInt(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(PhotoSubType::DEFAULT));
2622 }
2623 
RevertToOriginalEffectMode(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,bool & isNeedScan)2624 int32_t MediaLibraryPhotoOperations::RevertToOriginalEffectMode(
2625     MediaLibraryCommand& cmd, const shared_ptr<FileAsset>& fileAsset, bool& isNeedScan)
2626 {
2627     isNeedScan = false;
2628     int32_t effectMode{0};
2629     if (!IsNeedRevertEffectMode(cmd, fileAsset, effectMode)) {
2630         return E_OK;
2631     }
2632     isNeedScan = true;
2633     ValuesBucket& updateValues = cmd.GetValueBucket();
2634     updateValues.PutInt(PhotoColumn::MOVING_PHOTO_EFFECT_MODE, effectMode);
2635     if (effectMode == static_cast<int32_t>(MovingPhotoEffectMode::IMAGE_ONLY)) {
2636         updateValues.PutInt(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(PhotoSubType::DEFAULT));
2637     } else {
2638         updateValues.PutInt(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(PhotoSubType::MOVING_PHOTO));
2639     }
2640 
2641     string imagePath = fileAsset->GetFilePath();
2642     string sourceImagePath = GetEditDataSourcePath(imagePath);
2643     CHECK_AND_RETURN_RET_LOG(!sourceImagePath.empty(), E_INVALID_PATH, "Cannot get source image path");
2644     string sourceVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(sourceImagePath);
2645     CHECK_AND_RETURN_RET_LOG(!sourceVideoPath.empty(), E_INVALID_PATH, "Cannot get source video path");
2646 
2647     bool isSourceImageExist = MediaFileUtils::IsFileExists(sourceImagePath);
2648     bool isSourceVideoExist = MediaFileUtils::IsFileExists(sourceVideoPath);
2649     if (!isSourceImageExist || !isSourceVideoExist) {
2650         MEDIA_INFO_LOG("isSourceImageExist=%{public}d, isSourceVideoExist=%{public}d",
2651             isSourceImageExist, isSourceVideoExist);
2652         isNeedScan = false;
2653         return E_OK;
2654     }
2655     string videoPath = MediaFileUtils::GetMovingPhotoVideoPath(imagePath);
2656     int32_t errCode = Move(sourceVideoPath, videoPath);
2657     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, E_HAS_FS_ERROR, "Failed to move video from %{private}s to %{private}s",
2658         sourceVideoPath.c_str(), videoPath.c_str());
2659     string editDataCameraPath = GetEditDataCameraPath(imagePath);
2660     if (!MediaFileUtils::IsFileExists(editDataCameraPath)) {
2661         errCode = Move(sourceImagePath, imagePath);
2662         CHECK_AND_RETURN_RET_LOG(errCode == E_OK, E_HAS_FS_ERROR,
2663             "Failed to move image from %{private}s to %{private}s",
2664             sourceImagePath.c_str(), imagePath.c_str());
2665     } else {
2666         string editData;
2667         CHECK_AND_RETURN_RET_LOG(ReadEditdataFromFile(editDataCameraPath, editData) == E_OK, E_HAS_FS_ERROR,
2668             "Failed to read editdata, path=%{public}s", editDataCameraPath.c_str());
2669         CHECK_AND_RETURN_RET_LOG(AddFiltersToPhoto(sourceImagePath, imagePath, editData) == E_OK,
2670             E_FAIL, "Failed to add filters to photo");
2671     }
2672     return E_OK;
2673 }
2674 
MoveCacheFile(MediaLibraryCommand & cmd,int32_t subtype,const string & cachePath,const string & destPath)2675 int32_t MediaLibraryPhotoOperations::MoveCacheFile(
2676     MediaLibraryCommand& cmd, int32_t subtype, const string& cachePath, const string& destPath)
2677 {
2678     if (subtype != static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
2679         return Move(cachePath, destPath);
2680     }
2681 
2682     // write moving photo
2683     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CheckMovingPhotoImage(cachePath), E_INVALID_MOVING_PHOTO,
2684         "Failed to check image of moving photo");
2685     string cacheMovingPhotoVideoName;
2686     if (GetStringFromValuesBucket(cmd.GetValueBucket(), CACHE_MOVING_PHOTO_VIDEO_NAME, cacheMovingPhotoVideoName) &&
2687             !cacheMovingPhotoVideoName.empty()) {
2688         string cacheVideoPath = GetAssetCacheDir() + "/" + cacheMovingPhotoVideoName;
2689         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CheckMovingPhotoVideo(cacheVideoPath), E_INVALID_MOVING_PHOTO,
2690             "Failed to check video of moving photo");
2691         string destVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(destPath);
2692         int32_t errCode = Move(cacheVideoPath, destVideoPath);
2693         CHECK_AND_RETURN_RET_LOG(errCode == E_OK, E_FILE_OPER_FAIL,
2694             "Failed to move moving photo video from %{private}s to %{private}s, errCode: %{public}d",
2695             cacheVideoPath.c_str(), destVideoPath.c_str(), errCode);
2696     }
2697     return Move(cachePath, destPath);
2698 }
2699 
CheckCacheCmd(MediaLibraryCommand & cmd,int32_t subtype,const string & displayName)2700 bool MediaLibraryPhotoOperations::CheckCacheCmd(MediaLibraryCommand& cmd, int32_t subtype, const string& displayName)
2701 {
2702     string cacheFileName;
2703     CHECK_AND_RETURN_RET_LOG(GetStringFromValuesBucket(cmd.GetValueBucket(), CACHE_FILE_NAME, cacheFileName), false,
2704         "Failed to get cache file name");
2705     string cacheMimeType = MimeTypeUtils::GetMimeTypeFromExtension(MediaFileUtils::GetExtensionFromPath(cacheFileName));
2706     string assetMimeType = MimeTypeUtils::GetMimeTypeFromExtension(MediaFileUtils::GetExtensionFromPath(displayName));
2707 
2708     if (cacheMimeType.compare(assetMimeType) != 0) {
2709         MEDIA_ERR_LOG("cache mime type %{public}s mismatches the asset %{public}s",
2710             cacheMimeType.c_str(), assetMimeType.c_str());
2711         return false;
2712     }
2713 
2714     int32_t id = 0;
2715     bool isCreation = !GetInt32FromValuesBucket(cmd.GetValueBucket(), PhotoColumn::MEDIA_ID, id);
2716     if (subtype == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO) && isCreation) {
2717         string movingPhotoVideoName;
2718         bool containsVideo = GetStringFromValuesBucket(cmd.GetValueBucket(),
2719             CACHE_MOVING_PHOTO_VIDEO_NAME, movingPhotoVideoName);
2720         CHECK_AND_RETURN_RET_LOG(containsVideo, false, "Failed to get video when creating moving photo");
2721 
2722         string videoExtension = MediaFileUtils::GetExtensionFromPath(movingPhotoVideoName);
2723         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CheckMovingPhotoVideoExtension(videoExtension), false,
2724             "Failed to check video of moving photo, extension: %{public}s", videoExtension.c_str());
2725     }
2726     return true;
2727 }
2728 
ParseMediaAssetEditData(MediaLibraryCommand & cmd,string & editData)2729 int32_t MediaLibraryPhotoOperations::ParseMediaAssetEditData(MediaLibraryCommand& cmd, string& editData)
2730 {
2731     string compatibleFormat;
2732     string formatVersion;
2733     string data;
2734     const ValuesBucket& values = cmd.GetValueBucket();
2735     bool containsCompatibleFormat = GetStringFromValuesBucket(values, COMPATIBLE_FORMAT, compatibleFormat);
2736     bool containsFormatVersion = GetStringFromValuesBucket(values, FORMAT_VERSION, formatVersion);
2737     bool containsData = GetStringFromValuesBucket(values, EDIT_DATA, data);
2738     bool notContainsEditData = !containsCompatibleFormat && !containsFormatVersion && !containsData;
2739     bool containsEditData = containsCompatibleFormat && containsFormatVersion && containsData;
2740     if (!containsEditData && !notContainsEditData) {
2741         MEDIA_ERR_LOG(
2742             "Failed to parse edit data, compatibleFormat: %{public}s, formatVersion: %{public}s, data: %{public}s",
2743             compatibleFormat.c_str(), formatVersion.c_str(), data.c_str());
2744         return E_INVALID_VALUES;
2745     }
2746 
2747     nlohmann::json editDataJson;
2748     string bundleName = cmd.GetBundleName();
2749     editDataJson[COMPATIBLE_FORMAT] = compatibleFormat.empty() ? bundleName : compatibleFormat;
2750     editDataJson[FORMAT_VERSION] = formatVersion;
2751     editDataJson[EDIT_DATA] = data;
2752     editDataJson[APP_ID] = bundleName;
2753     editData = editDataJson.dump();
2754     return E_OK;
2755 }
2756 
ParseCloudEnhancementEditData(string & editData)2757 void MediaLibraryPhotoOperations::ParseCloudEnhancementEditData(string& editData)
2758 {
2759     CHECK_AND_RETURN_LOG(nlohmann::json::accept(editData),
2760         "Failed to verify the editData format, editData is: %{private}s", editData.c_str());
2761     string editDataJsonStr;
2762     nlohmann::json jsonObject = nlohmann::json::parse(editData);
2763     if (jsonObject.contains(EDIT_DATA)) {
2764         editDataJsonStr = jsonObject[EDIT_DATA];
2765         nlohmann::json editDataJson = nlohmann::json::parse(editDataJsonStr, nullptr, false);
2766         if (editDataJson.is_discarded()) {
2767             MEDIA_INFO_LOG("editDataJson parse failed");
2768             return;
2769         }
2770         string editDataStr = editDataJson.dump();
2771         editData = editDataStr;
2772     }
2773 }
2774 
IsSetEffectMode(MediaLibraryCommand & cmd)2775 bool MediaLibraryPhotoOperations::IsSetEffectMode(MediaLibraryCommand &cmd)
2776 {
2777     int32_t effectMode;
2778     return GetInt32FromValuesBucket(cmd.GetValueBucket(), PhotoColumn::MOVING_PHOTO_EFFECT_MODE, effectMode);
2779 }
2780 
IsContainsData(MediaLibraryCommand & cmd)2781 bool MediaLibraryPhotoOperations::IsContainsData(MediaLibraryCommand &cmd)
2782 {
2783     string compatibleFormat;
2784     string formatVersion;
2785     string data;
2786     const ValuesBucket& values = cmd.GetValueBucket();
2787     bool containsCompatibleFormat = GetStringFromValuesBucket(values, COMPATIBLE_FORMAT, compatibleFormat);
2788     bool containsFormatVersion = GetStringFromValuesBucket(values, FORMAT_VERSION, formatVersion);
2789     bool containsData = GetStringFromValuesBucket(values, EDIT_DATA, data);
2790     return containsCompatibleFormat && containsFormatVersion && containsData;
2791 }
2792 
IsCameraEditData(MediaLibraryCommand & cmd)2793 bool MediaLibraryPhotoOperations::IsCameraEditData(MediaLibraryCommand &cmd)
2794 {
2795     string bundleName = cmd.GetBundleName();
2796     return IsContainsData(cmd) && (count(CAMERA_BUNDLE_NAMES.begin(), CAMERA_BUNDLE_NAMES.end(), bundleName) > 0);
2797 }
2798 
ReadEditdataFromFile(const std::string & editDataPath,std::string & editData)2799 int32_t MediaLibraryPhotoOperations::ReadEditdataFromFile(const std::string &editDataPath, std::string &editData)
2800 {
2801     string editDataStr;
2802     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::ReadStrFromFile(editDataPath, editDataStr), E_HAS_FS_ERROR,
2803         "Can not read editdata from %{private}s", editDataPath.c_str());
2804     if (!nlohmann::json::accept(editDataStr)) {
2805         MEDIA_WARN_LOG("Failed to verify the editData format, editData is: %{private}s", editDataStr.c_str());
2806         editData = editDataStr;
2807         return E_OK;
2808     }
2809     nlohmann::json editdataJson = nlohmann::json::parse(editDataStr);
2810     if (editdataJson.contains(EDIT_DATA)) {
2811         editData = editdataJson[EDIT_DATA];
2812     } else {
2813         editData = editDataStr;
2814     }
2815     return E_OK;
2816 }
2817 
SaveEditDataCamera(MediaLibraryCommand & cmd,const std::string & assetPath,std::string & editData)2818 int32_t MediaLibraryPhotoOperations::SaveEditDataCamera(MediaLibraryCommand &cmd, const std::string &assetPath,
2819     std::string &editData)
2820 {
2821     string editDataStr;
2822     string editDataCameraPath = GetEditDataCameraPath(assetPath);
2823     CHECK_AND_RETURN_RET_LOG(!editDataCameraPath.empty(), E_INVALID_VALUES, "Failed to get edit data path");
2824     if (!MediaFileUtils::IsFileExists(editDataCameraPath)) {
2825         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateFile(editDataCameraPath), E_HAS_FS_ERROR,
2826             "Failed to create file %{private}s", editDataCameraPath.c_str());
2827     }
2828     int ret = ParseMediaAssetEditData(cmd, editDataStr);
2829     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::WriteStrToFile(editDataCameraPath, editDataStr), E_HAS_FS_ERROR,
2830         "Failed to write editdata:%{private}s", editDataCameraPath.c_str());
2831     const ValuesBucket& values = cmd.GetValueBucket();
2832     GetStringFromValuesBucket(values, EDIT_DATA, editData);
2833     return ret;
2834 }
2835 
SaveSourceAndEditData(const shared_ptr<FileAsset> & fileAsset,const string & editData)2836 int32_t MediaLibraryPhotoOperations::SaveSourceAndEditData(
2837     const shared_ptr<FileAsset>& fileAsset, const string& editData)
2838 {
2839     CHECK_AND_RETURN_RET_LOG(!editData.empty(), E_INVALID_VALUES, "editData is empty");
2840     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_VALUES, "fileAsset is nullptr");
2841     string assetPath = fileAsset->GetFilePath();
2842     CHECK_AND_RETURN_RET_LOG(!assetPath.empty(), E_INVALID_VALUES, "Failed to get asset path");
2843     string editDataPath = GetEditDataPath(assetPath);
2844     CHECK_AND_RETURN_RET_LOG(!editDataPath.empty(), E_INVALID_VALUES, "Failed to get edit data path");
2845 
2846     if (fileAsset->GetPhotoEditTime() == 0) { // the asset has not been edited before
2847         string editDataDirPath = GetEditDataDirPath(assetPath);
2848         CHECK_AND_RETURN_RET_LOG(!editDataDirPath.empty(), E_INVALID_URI, "Failed to get edit dir path");
2849         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateDirectory(editDataDirPath), E_HAS_FS_ERROR,
2850             "Failed to create dir %{private}s", editDataDirPath.c_str());
2851 
2852         string sourcePath = GetEditDataSourcePath(assetPath);
2853         CHECK_AND_RETURN_RET_LOG(!sourcePath.empty(), E_INVALID_URI, "Failed to get source path");
2854         if (!MediaFileUtils::IsFileExists(sourcePath)) {
2855             CHECK_AND_RETURN_RET_LOG(MediaFileUtils::ModifyAsset(assetPath, sourcePath) == E_SUCCESS, E_HAS_FS_ERROR,
2856                 "Move file failed, srcPath:%{private}s, newPath:%{private}s", assetPath.c_str(), sourcePath.c_str());
2857         }
2858 
2859         if (!MediaFileUtils::IsFileExists(editDataPath)) {
2860             CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateFile(editDataPath), E_HAS_FS_ERROR,
2861                 "Failed to create file %{private}s", editDataPath.c_str());
2862         }
2863     }
2864 
2865     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileExists(editDataPath), E_OK,
2866         "Failed to find editdata:%{private}s", editDataPath.c_str());
2867     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::WriteStrToFile(editDataPath, editData), E_HAS_FS_ERROR,
2868         "Failed to write editdata:%{private}s", editDataPath.c_str());
2869 
2870     return E_OK;
2871 }
2872 
GetFileAsset(MediaLibraryCommand & cmd)2873 std::shared_ptr<FileAsset> MediaLibraryPhotoOperations::GetFileAsset(MediaLibraryCommand& cmd)
2874 {
2875     const ValuesBucket& values = cmd.GetValueBucket();
2876     int32_t id = 0;
2877     GetInt32FromValuesBucket(values, PhotoColumn::MEDIA_ID, id);
2878     vector<string> columns = { PhotoColumn::MEDIA_ID, PhotoColumn::MEDIA_FILE_PATH, PhotoColumn::MEDIA_NAME,
2879         PhotoColumn::PHOTO_SUBTYPE, PhotoColumn::MEDIA_TIME_PENDING, PhotoColumn::MEDIA_DATE_TRASHED };
2880     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(
2881         PhotoColumn::MEDIA_ID, to_string(id), OperationObject::FILESYSTEM_PHOTO, columns);
2882     return fileAsset;
2883 }
2884 
GetPicture(const int32_t & fileId,std::shared_ptr<Media::Picture> & picture,bool isCleanImmediately,std::string & photoId,bool & isHighQualityPicture)2885 int32_t MediaLibraryPhotoOperations::GetPicture(const int32_t &fileId, std::shared_ptr<Media::Picture> &picture,
2886     bool isCleanImmediately, std::string &photoId, bool &isHighQualityPicture)
2887 {
2888     int32_t ret = GetPhotoIdByFileId(fileId, photoId);
2889     if (ret != E_OK || photoId.empty()) {
2890         MEDIA_ERR_LOG("photoId is emply fileId is: %{public}d", fileId);
2891         return E_FILE_EXIST;
2892     }
2893 
2894     MEDIA_INFO_LOG("photoId: %{public}s", photoId.c_str());
2895     auto pictureManagerThread = PictureManagerThread::GetInstance();
2896     if (pictureManagerThread != nullptr) {
2897         picture = pictureManagerThread->GetDataWithImageId(photoId, isHighQualityPicture, isCleanImmediately);
2898     }
2899     CHECK_AND_RETURN_RET_LOG(picture != nullptr, E_FILE_EXIST, "picture is not exists!");
2900     MEDIA_INFO_LOG("photoId: %{public}s, picture use: %{public}d, picture point to addr: %{public}s",
2901         photoId.c_str(), static_cast<int32_t>(picture.use_count()),
2902         std::to_string(reinterpret_cast<long long>(picture.get())).c_str());
2903     return E_OK;
2904 }
2905 
FinishRequestPicture(MediaLibraryCommand & cmd)2906 int32_t MediaLibraryPhotoOperations::FinishRequestPicture(MediaLibraryCommand &cmd)
2907 {
2908     const ValuesBucket& values = cmd.GetValueBucket();
2909     int32_t fileId = 0;
2910     GetInt32FromValuesBucket(values, PhotoColumn::MEDIA_ID, fileId);
2911 
2912     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
2913     predicates.EqualTo(MediaColumn::MEDIA_ID, std::to_string(fileId));
2914     vector<string> columns = { PhotoColumn::PHOTO_ID };
2915     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
2916     CHECK_AND_RETURN_RET_LOG(resultSet->GoToFirstRow() == NativeRdb::E_OK, E_FILE_EXIST, "result set is empty");
2917 
2918     string photoId = GetStringVal(PhotoColumn::PHOTO_ID, resultSet);
2919     resultSet->Close();
2920     if (photoId.empty()) {
2921         MEDIA_ERR_LOG("photoId is emply fileId is: %{public}d", fileId);
2922         return E_FILE_EXIST;
2923     }
2924 
2925     MEDIA_INFO_LOG("photoId: %{public}s", photoId.c_str());
2926     auto pictureManagerThread = PictureManagerThread::GetInstance();
2927     if (pictureManagerThread != nullptr) {
2928         pictureManagerThread->FinishAccessingPicture(photoId);
2929     }
2930     return E_OK;
2931 }
2932 
CloneSingleAsset(MediaLibraryCommand & cmd)2933 int64_t MediaLibraryPhotoOperations::CloneSingleAsset(MediaLibraryCommand &cmd)
2934 {
2935     const ValuesBucket& values = cmd.GetValueBucket();
2936     int fileId = -1;
2937     ValueObject valueObject;
2938     CHECK_AND_RETURN_RET_LOG(values.GetObject(MediaColumn::MEDIA_ID, valueObject), fileId,
2939         "Failed to get media id from values bucket.");
2940     valueObject.GetInt(fileId);
2941     string title;
2942     GetStringFromValuesBucket(values, MediaColumn::MEDIA_TITLE, title);
2943     return MediaLibraryAlbumFusionUtils::CloneSingleAsset(static_cast<int64_t>(fileId), title);
2944 }
2945 
AddFilters(MediaLibraryCommand & cmd)2946 int32_t MediaLibraryPhotoOperations::AddFilters(MediaLibraryCommand& cmd)
2947 {
2948     // moving photo video save and add filters
2949     const ValuesBucket& values = cmd.GetValueBucket();
2950     int32_t id = -1;
2951     CHECK_AND_RETURN_RET_LOG(GetInt32FromValuesBucket(values, PhotoColumn::MEDIA_ID, id),
2952         E_INVALID_VALUES, "Failed to get fileId");
2953 
2954     std::string videoSaveFinishedUri;
2955     if (GetStringFromValuesBucket(values, NOTIFY_VIDEO_SAVE_FINISHED, videoSaveFinishedUri)) {
2956         vector<string> columns = { videoSaveFinishedUri };
2957         ScanMovingPhoto(cmd, columns);
2958 
2959         vector<string> fileAssetColumns = {PhotoColumn::MEDIA_ID, PhotoColumn::PHOTO_DIRTY,
2960             PhotoColumn::MEDIA_FILE_PATH, PhotoColumn::MEDIA_MIME_TYPE, PhotoColumn::MEDIA_TITLE,
2961             PhotoColumn::PHOTO_MEDIA_SUFFIX, PhotoColumn::PHOTO_SUBTYPE, PhotoColumn::PHOTO_EDIT_TIME,
2962             PhotoColumn::PHOTO_ID, PhotoColumn::MEDIA_NAME, PhotoColumn::MOVING_PHOTO_EFFECT_MODE,
2963             PhotoColumn::PHOTO_ORIGINAL_SUBTYPE };
2964         shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(
2965             PhotoColumn::MEDIA_ID, to_string(id), OperationObject::FILESYSTEM_PHOTO, fileAssetColumns);
2966         CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_VALUES,
2967             "Failed to GetFileAssetFromDb, fileId = %{public}d", id);
2968         MultiStagesMovingPhotoCaptureManager::SaveMovingPhotoVideoFinished(fileAsset->GetPhotoId());
2969         return AddFiltersToVideoExecute(fileAsset, true);
2970     }
2971 
2972     if (IsCameraEditData(cmd)) {
2973         shared_ptr<FileAsset> fileAsset = GetFileAsset(cmd);
2974         return AddFiltersExecute(cmd, fileAsset, "");
2975     }
2976     return E_OK;
2977 }
2978 
ForceSavePicture(MediaLibraryCommand & cmd)2979 int32_t MediaLibraryPhotoOperations::ForceSavePicture(MediaLibraryCommand& cmd)
2980 {
2981     MEDIA_DEBUG_LOG("ForceSavePicture");
2982     int fileType = std::atoi(cmd.GetQuerySetParam(IMAGE_FILE_TYPE).c_str());
2983     int fileId = std::atoi(cmd.GetQuerySetParam(PhotoColumn::MEDIA_ID).c_str());
2984     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
2985     predicates.EqualTo(MediaColumn::MEDIA_ID, std::to_string(fileId));
2986     vector<string> columns = { PhotoColumn::PHOTO_IS_TEMP };
2987     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
2988     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr && resultSet->GoToFirstRow() == NativeRdb::E_OK,
2989         E_ERR, "result set is empty");
2990     if (GetInt32Val(PhotoColumn::PHOTO_IS_TEMP, resultSet) == 0) {
2991         return E_OK;
2992     }
2993     resultSet->Close();
2994     string uri = cmd.GetQuerySetParam("uri");
2995     std::shared_ptr<Media::Picture> resultPicture = nullptr;
2996     SavePicture(fileType, fileId, resultPicture);
2997     string path = MediaFileUri::GetPathFromUri(uri, true);
2998     MediaLibraryAssetOperations::ScanFileWithoutAlbumUpdate(path, false, false, true, fileId, resultPicture);
2999     return E_OK;
3000 }
3001 
SavePicture(const int32_t & fileType,const int32_t & fileId,std::shared_ptr<Media::Picture> & resultPicture)3002 int32_t MediaLibraryPhotoOperations::SavePicture(const int32_t &fileType, const int32_t &fileId,
3003     std::shared_ptr<Media::Picture> &resultPicture)
3004 {
3005     MEDIA_INFO_LOG("savePicture fileType is: %{public}d, fileId is: %{public}d", fileType, fileId);
3006     std::shared_ptr<Media::Picture> picture;
3007     std::string photoId;
3008     bool isHighQualityPicture = false;
3009     CHECK_AND_RETURN_RET_LOG(GetPicture(fileId, picture, false, photoId, isHighQualityPicture) == E_OK,
3010         E_FILE_EXIST, "Failed to get picture");
3011 
3012     std::string format = MIME_TYPE_JPEG;
3013     std::string oldFilePath = "";
3014     int32_t updateResult = UpdateExtension(fileId, format, fileType, oldFilePath);
3015     auto fileAsset = GetFileAssetFromDb(PhotoColumn::MEDIA_ID, to_string(fileId),
3016                                         OperationObject::FILESYSTEM_PHOTO, EDITED_COLUMN_VECTOR);
3017     string assetPath = fileAsset->GetFilePath();
3018     CHECK_AND_RETURN_RET_LOG(!assetPath.empty(), E_INVALID_VALUES, "Failed to get asset path");
3019 
3020     FileUtils::DealPicture(format, assetPath, picture);
3021     string editData = "";
3022     string editDataCameraPath = GetEditDataCameraPath(assetPath);
3023     if (ReadEditdataFromFile(editDataCameraPath, editData) == E_OK &&
3024         GetPicture(fileId, picture, false, photoId, isHighQualityPicture) == E_OK) {
3025         MediaFileUtils::CopyFileUtil(assetPath, GetEditDataSourcePath(assetPath));
3026         int32_t ret = MediaChangeEffect::TakeEffectForPicture(picture, editData);
3027         FileUtils::DealPicture(format, assetPath, picture);
3028     }
3029     if (isHighQualityPicture) {
3030         RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
3031         predicates.EqualTo(PhotoColumn::MEDIA_ID, fileId);
3032         ValuesBucket values;
3033         values.Put(PhotoColumn::PHOTO_QUALITY, static_cast<int32_t>(MultiStagesPhotoQuality::FULL));
3034         values.Put(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyType::TYPE_NEW));
3035         int32_t updatedRows = MediaLibraryRdbStore::UpdateWithDateTime(values, predicates);
3036         CHECK_AND_PRINT_LOG(updatedRows >= 0, "update photo quality fail.");
3037     }
3038 
3039     resultPicture = picture;
3040     auto pictureManagerThread = PictureManagerThread::GetInstance();
3041     if (pictureManagerThread != nullptr) {
3042         pictureManagerThread->FinishAccessingPicture(photoId);
3043         pictureManagerThread->DeleteDataWithImageId(lastPhotoId_, LOW_QUALITY_PICTURE);
3044     }
3045     lastPhotoId_ = photoId;
3046     // 删除已经存在的异常后缀的图片
3047     size_t size = -1;
3048     MediaFileUtils::GetFileSize(oldFilePath, size);
3049     if (updateResult == E_OK && oldFilePath != "" && size > 0) {
3050         DeleteAbnormalFile(assetPath, fileId, oldFilePath);
3051     }
3052     return E_OK;
3053 }
3054 
AddFiltersExecute(MediaLibraryCommand & cmd,shared_ptr<FileAsset> & fileAsset,const string & cachePath)3055 int32_t MediaLibraryPhotoOperations::AddFiltersExecute(MediaLibraryCommand& cmd,
3056     shared_ptr<FileAsset>& fileAsset, const string& cachePath)
3057 {
3058     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_VALUES, "fileAsset is nullptr");
3059     int32_t fileId = fileAsset->GetId();
3060     string assetPath = fileAsset->GetFilePath();
3061     CHECK_AND_RETURN_RET_LOG(!assetPath.empty(), E_INVALID_VALUES, "Failed to get asset path");
3062     string editDataDirPath = GetEditDataDirPath(assetPath);
3063     CHECK_AND_RETURN_RET_LOG(!editDataDirPath.empty(), E_INVALID_URI, "Can not get editdara dir path");
3064     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateDirectory(editDataDirPath), E_HAS_FS_ERROR,
3065         "Can not create dir %{private}s", editDataDirPath.c_str());
3066     string sourcePath = GetEditDataSourcePath(assetPath);
3067     CHECK_AND_RETURN_RET_LOG(!sourcePath.empty(), E_INVALID_URI, "Can not get edit source path");
3068 
3069     if (cachePath.empty()) {
3070         // Photo目录照片复制到.editdata目录的source.jpg
3071         MediaFileUtils::CopyFileUtil(assetPath, sourcePath);
3072     } else {
3073         // cache移动到source.jpg
3074         int32_t subtype = fileAsset->GetPhotoSubType();
3075         MoveCacheFile(cmd, subtype, cachePath, sourcePath);
3076     }
3077 
3078     // 保存editdata_camera文件
3079     string editData;
3080     SaveEditDataCamera(cmd, assetPath, editData);
3081     // 生成水印
3082     int32_t ret = AddFiltersToPhoto(sourcePath, assetPath, editData);
3083     if (ret == E_OK) {
3084         ret = HandleNeedSetDisplayName(cmd, fileAsset);
3085         if (ret == E_OK) {
3086             ret = RenameEditDataDirBySetDisplayName(cmd, fileAsset);
3087             MediaLibraryObjectUtils::ScanFileAsync(assetPath, to_string(fileAsset->GetId()), MediaLibraryApi::API_10);
3088         }
3089         if (ret != E_OK) {
3090             DoRevertEdit(fileAsset);
3091         }
3092     }
3093     std::shared_ptr<Media::Picture> picture;
3094     std::string photoId;
3095     bool isHighQualityPicture = false;
3096     CHECK_AND_RETURN_RET(GetPicture(fileId, picture, true, photoId, isHighQualityPicture) != E_OK, E_OK);
3097     return ret;
3098 }
3099 
SaveTempMovingPhotoVideo(const string & assetPath)3100 int32_t SaveTempMovingPhotoVideo(const string &assetPath)
3101 {
3102     string assetTempPath = MediaFileUtils::GetTempMovingPhotoVideoPath(assetPath);
3103     string assetSavePath = MediaFileUtils::GetMovingPhotoVideoPath(assetPath);
3104     if (!MediaFileUtils::IsFileExists(assetSavePath)) {
3105         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::ModifyAsset(assetTempPath, assetSavePath) == E_SUCCESS,
3106             E_HAS_FS_ERROR, "Move video file failed, srcPath:%{private}s, newPath:%{private}s",
3107             assetTempPath.c_str(), assetSavePath.c_str());
3108         return E_OK;
3109     }
3110     MEDIA_ERR_LOG("File exists, assetSavePath: %{public}s.", assetSavePath.c_str());
3111     return E_ERR;
3112 }
3113 
CopyVideoFile(const string & assetPath,bool toSource)3114 int32_t MediaLibraryPhotoOperations::CopyVideoFile(const string& assetPath, bool toSource)
3115 {
3116     string sourceImagePath = PhotoFileUtils::GetEditDataSourcePath(assetPath);
3117     string videoPath = MediaFileUtils::GetMovingPhotoVideoPath(assetPath);
3118     string sourceVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(sourceImagePath);
3119     if (toSource) {
3120         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CopyFileUtil(videoPath, sourceVideoPath), E_HAS_FS_ERROR,
3121             "Copy videoPath to sourceVideoPath, path:%{private}s", videoPath.c_str());
3122     } else {
3123         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CopyFileUtil(sourceVideoPath, videoPath), E_HAS_FS_ERROR,
3124             "Copy sourceVideoPath to videoPath, path:%{private}s", sourceVideoPath.c_str());
3125     }
3126     return E_OK;
3127 }
3128 
AddFiltersToVideoExecute(const shared_ptr<FileAsset> & fileAsset,bool isSaveVideo)3129 int32_t MediaLibraryPhotoOperations::AddFiltersToVideoExecute(const shared_ptr<FileAsset>& fileAsset, bool isSaveVideo)
3130 {
3131     string assetPath = fileAsset->GetFilePath();
3132     string editDataCameraPath = MediaLibraryAssetOperations::GetEditDataCameraPath(assetPath);
3133     if (MediaFileUtils::IsFileExists(editDataCameraPath)) {
3134         string editData;
3135         CHECK_AND_RETURN_RET_LOG(ReadEditdataFromFile(editDataCameraPath, editData) == E_OK, E_HAS_FS_ERROR,
3136             "Failed to read editData, path = %{public}s", editDataCameraPath.c_str());
3137         // erase sticker field
3138         auto index = editData.find(FRAME_STICKER);
3139         if (index != std::string::npos) {
3140             VideoCompositionCallbackImpl::EraseStickerField(editData, index, false);
3141         }
3142         index = editData.find(INPLACE_STICKER);
3143         if (index != std::string::npos) {
3144             VideoCompositionCallbackImpl::EraseStickerField(editData, index, false);
3145         }
3146         index = editData.find(TIMING_STICKER);
3147         if (index != std::string::npos) {
3148             VideoCompositionCallbackImpl::EraseStickerField(editData, index, true);
3149         }
3150         index = editData.find(FESTIVAL_STICKER);
3151         if (index != std::string::npos) {
3152             VideoCompositionCallbackImpl::EraseStickerField(editData, index, false);
3153         }
3154         index = editData.find(FILTERS_FIELD);
3155         if (index == std::string::npos) {
3156             MEDIA_ERR_LOG("Can not find Video filters field.");
3157             return E_ERR;
3158         }
3159         if (editData[index + START_DISTANCE] == FILTERS_END && isSaveVideo) {
3160             MEDIA_INFO_LOG("MovingPhoto video only supports filter now.");
3161             CHECK_AND_RETURN_RET_LOG(SaveTempMovingPhotoVideo(assetPath) == E_OK, E_HAS_FS_ERROR,
3162                 "Failed to save temp movingphoto video, path = %{public}s", assetPath.c_str());
3163             return CopyVideoFile(assetPath, true);
3164         } else if (editData[index + START_DISTANCE] == FILTERS_END && !isSaveVideo) {
3165             return CopyVideoFile(assetPath, false);
3166         }
3167         MEDIA_INFO_LOG("AddFiltersToVideoExecute after EraseStickerField, editData = %{public}s", editData.c_str());
3168         CHECK_AND_RETURN_RET_LOG(SaveSourceVideoFile(fileAsset, assetPath, true) == E_OK, E_HAS_FS_ERROR,
3169             "Failed to save source video, path = %{public}s", assetPath.c_str());
3170         VideoCompositionCallbackImpl::AddCompositionTask(assetPath, editData);
3171         return E_OK;
3172     } else {
3173         return SaveTempMovingPhotoVideo(assetPath);
3174     }
3175 }
3176 
AddFiltersForCloudEnhancementPhoto(int32_t fileId,const string & assetPath,const string & editDataCameraSourcePath,const string & mimeType)3177 int32_t MediaLibraryPhotoOperations::AddFiltersForCloudEnhancementPhoto(int32_t fileId,
3178     const string& assetPath, const string& editDataCameraSourcePath, const string& mimeType)
3179 {
3180     CHECK_AND_RETURN_RET_LOG(!assetPath.empty(), E_INVALID_VALUES, "Failed to get asset path");
3181     string editDataDirPath = GetEditDataDirPath(assetPath);
3182     CHECK_AND_RETURN_RET_LOG(!editDataDirPath.empty(), E_INVALID_URI, "Can not get editdata dir path");
3183     string sourcePath = GetEditDataSourcePath(assetPath);
3184     CHECK_AND_RETURN_RET_LOG(!sourcePath.empty(), E_INVALID_URI, "Can not get edit source path");
3185 
3186     // copy source.jpg
3187     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateDirectory(editDataDirPath), E_HAS_FS_ERROR,
3188         "Can not create dir %{private}s, errno:%{public}d", editDataDirPath.c_str(), errno);
3189     bool copyResult = MediaFileUtils::CopyFileUtil(assetPath, sourcePath);
3190     if (!copyResult) {
3191         MEDIA_ERR_LOG("copy to source.jpg failed. errno=%{public}d, path: %{public}s", errno, assetPath.c_str());
3192     }
3193     string editData;
3194     MediaFileUtils::ReadStrFromFile(editDataCameraSourcePath, editData);
3195     ParseCloudEnhancementEditData(editData);
3196     string editDataCameraDestPath = PhotoFileUtils::GetEditDataCameraPath(assetPath);
3197     copyResult = MediaFileUtils::CopyFileUtil(editDataCameraSourcePath, editDataCameraDestPath);
3198     if (!copyResult) {
3199         MEDIA_ERR_LOG("copy editDataCamera failed. errno=%{public}d, path: %{public}s", errno,
3200             editDataCameraSourcePath.c_str());
3201     }
3202     // normal
3203     return AddFiltersToPhoto(sourcePath, assetPath, editData);
3204 }
3205 
SubmitEditCacheExecute(MediaLibraryCommand & cmd,shared_ptr<FileAsset> & fileAsset,const string & cachePath,bool isWriteGpsAdvanced)3206 int32_t MediaLibraryPhotoOperations::SubmitEditCacheExecute(MediaLibraryCommand& cmd,
3207     shared_ptr<FileAsset>& fileAsset, const string& cachePath, bool isWriteGpsAdvanced)
3208 {
3209     string editData;
3210     int32_t id = fileAsset->GetId();
3211     int32_t errCode = ParseMediaAssetEditData(cmd, editData);
3212     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to parse MediaAssetEditData");
3213     errCode = SaveSourceAndEditData(fileAsset, editData);
3214     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to save source and editData");
3215 
3216     int32_t subtype = fileAsset->GetPhotoSubType();
3217     if (subtype == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
3218         errCode = SubmitEditMovingPhotoExecute(cmd, fileAsset);
3219         CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to SubmitEditMovingPhotoExecute");
3220     }
3221 
3222     string assetPath = fileAsset->GetFilePath();
3223     errCode = MoveCacheFile(cmd, subtype, cachePath, assetPath);
3224     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, E_FILE_OPER_FAIL,
3225         "Failed to move %{private}s to %{private}s, errCode: %{public}d",
3226         cachePath.c_str(), assetPath.c_str(), errCode);
3227 
3228     errCode = UpdateEditTime(id, MediaFileUtils::UTCTimeSeconds());
3229     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to update edit time, fileId:%{public}d", id);
3230 
3231     ResetOcrInfo(id);
3232     if (isWriteGpsAdvanced) {
3233         MultiStagesPhotoCaptureManager::UpdateLocation(cmd.GetValueBucket(), true, assetPath, id);
3234     }
3235     if (HandleNeedSetDisplayName(cmd, fileAsset) != E_OK) {
3236         CHECK_AND_RETURN_RET_LOG(DoRevertEdit(fileAsset) == E_OK, E_FAIL, "Failed to revert when setdisplayname file");
3237         return E_FAIL;
3238     }
3239     // 如果上边成功,则此处资产path和displayname是新的,下边若要用,则要重新获取
3240     if (RenameEditDataDirBySetDisplayName(cmd, fileAsset) != E_OK) {
3241         CHECK_AND_RETURN_RET_LOG(DoRevertEdit(fileAsset) == E_OK, E_FAIL, "Failed to revert when setdisplayname file");
3242         return E_FAIL;
3243     }
3244     ScanFile(fileAsset->GetFilePath(), false, true, true);
3245     MediaLibraryAnalysisAlbumOperations::UpdatePortraitAlbumCoverSatisfied(id);
3246     // delete cloud enhacement task
3247 #ifdef MEDIALIBRARY_FEATURE_CLOUD_ENHANCEMENT
3248     vector<string> fileId;
3249     fileId.emplace_back(to_string(fileAsset->GetId()));
3250     vector<string> photoId;
3251     EnhancementManager::GetInstance().CancelTasksInternal(fileId, photoId, CloudEnhancementAvailableType::EDIT);
3252 #endif
3253     NotifyFormMap(id, fileAsset->GetFilePath(), false);
3254     MediaLibraryVisionOperations::EditCommitOperation(cmd);
3255     MEDIA_INFO_LOG("SubmitEditCacheExecute success, isWriteGpsAdvanced: %{public}d.", isWriteGpsAdvanced);
3256     return E_OK;
3257 }
3258 
SubmitCacheExecute(MediaLibraryCommand & cmd,shared_ptr<FileAsset> & fileAsset,const string & cachePath)3259 int32_t MediaLibraryPhotoOperations::SubmitCacheExecute(MediaLibraryCommand& cmd,
3260     shared_ptr<FileAsset>& fileAsset, const string& cachePath)
3261 {
3262     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_VALUES, "fileAsset is nullptr");
3263     int32_t subtype = fileAsset->GetPhotoSubType();
3264     CHECK_AND_RETURN_RET_LOG(CheckCacheCmd(cmd, subtype, fileAsset->GetDisplayName()),
3265         E_INVALID_VALUES, "Failed to check cache cmd");
3266     CHECK_AND_RETURN_RET_LOG(fileAsset->GetDateTrashed() == 0, E_IS_RECYCLED, "FileAsset is in recycle");
3267 
3268     int64_t pending = fileAsset->GetTimePending();
3269     CHECK_AND_RETURN_RET_LOG(
3270         pending == 0 || pending == UNCREATE_FILE_TIMEPENDING || pending == UNOPEN_FILE_COMPONENT_TIMEPENDING,
3271         E_IS_PENDING_ERROR, "FileAsset is in pending: %{public}ld", static_cast<long>(pending));
3272 
3273     string assetPath = fileAsset->GetFilePath();
3274     CHECK_AND_RETURN_RET_LOG(!assetPath.empty(), E_INVALID_VALUES, "Failed to get asset path");
3275 
3276     int32_t id = fileAsset->GetId();
3277     bool isEdit = (pending == 0);
3278 
3279     std::string val = cmd.GetQuerySetParam(SET_LOCATION_KEY);
3280     bool isWriteGpsAdvanced = val == SET_LOCATION_VALUE;
3281 
3282     if (isEdit) {
3283         CHECK_AND_RETURN_RET(PhotoEditingRecord::GetInstance()->StartCommitEdit(id), E_IS_IN_REVERT);
3284         int32_t errCode = SubmitEditCacheExecute(cmd, fileAsset, cachePath, isWriteGpsAdvanced);
3285         PhotoEditingRecord::GetInstance()->EndCommitEdit(id);
3286         return errCode;
3287     } else if (IsCameraEditData(cmd)) {
3288         AddFiltersExecute(cmd, fileAsset, cachePath);
3289     } else {
3290         int32_t errCode = MoveCacheFile(cmd, subtype, cachePath, assetPath);
3291         CHECK_AND_RETURN_RET_LOG(errCode == E_OK, E_FILE_OPER_FAIL,
3292             "Failed to move %{private}s to %{private}s, errCode: %{public}d",
3293             cachePath.c_str(), assetPath.c_str(), errCode);
3294     }
3295     if (isWriteGpsAdvanced) {
3296         MultiStagesPhotoCaptureManager::UpdateLocation(cmd.GetValueBucket(), true, assetPath, id);
3297     }
3298     if (!IsCameraEditData(cmd) && HandleNeedSetDisplayName(cmd, fileAsset) != E_OK) {
3299         CHECK_AND_RETURN_RET_LOG(DoRevertEdit(fileAsset) == E_OK,
3300             E_FAIL, "HandleNeedSetDisplayName Failed to revert when setdisplayname file");
3301         return E_FAIL;
3302     }
3303     if (RenameEditDataDirBySetDisplayName(cmd, fileAsset) != E_OK) {
3304         CHECK_AND_RETURN_RET_LOG(DoRevertEdit(fileAsset) == E_OK,
3305             E_FAIL, "RenameEditDataDirBySetDisplayName Failed to revert when setdisplayname file");
3306         return E_FAIL;
3307     }
3308     ScanFile(fileAsset->GetFilePath(), false, true, true);
3309     MEDIA_INFO_LOG("SubmitCacheExecute success, isWriteGpsAdvanced: %{public}d.", isWriteGpsAdvanced);
3310     return E_OK;
3311 }
3312 
SaveSourceVideoFile(const shared_ptr<FileAsset> & fileAsset,const string & assetPath,const bool & isTemp)3313 int32_t MediaLibraryPhotoOperations::SaveSourceVideoFile(const shared_ptr<FileAsset>& fileAsset,
3314     const string& assetPath, const bool& isTemp)
3315 {
3316     MEDIA_INFO_LOG("Moving photo SaveSourceVideoFile begin, fileId:%{public}d", fileAsset->GetId());
3317     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_VALUES, "fileAsset is nullptr");
3318     string sourceImagePath = GetEditDataSourcePath(assetPath);
3319     CHECK_AND_RETURN_RET_LOG(!sourceImagePath.empty(), E_INVALID_PATH, "Can not get source image path");
3320     string videoPath = isTemp ? MediaFileUtils::GetTempMovingPhotoVideoPath(assetPath)
3321         : MediaFileUtils::GetMovingPhotoVideoPath(assetPath);
3322     CHECK_AND_RETURN_RET_LOG(!videoPath.empty(), E_INVALID_PATH, "Can not get video path");
3323     string sourceVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(sourceImagePath);
3324     CHECK_AND_RETURN_RET_LOG(!sourceVideoPath.empty(), E_INVALID_PATH, "Can not get source video path");
3325     if (!MediaFileUtils::IsFileExists(sourceVideoPath)) {
3326         CHECK_AND_RETURN_RET_LOG(Move(videoPath, sourceVideoPath) == E_SUCCESS, E_HAS_FS_ERROR,
3327             "Can not move %{private}s to %{private}s", videoPath.c_str(), sourceVideoPath.c_str());
3328     }
3329     return E_OK;
3330 }
3331 
SubmitEditMovingPhotoExecute(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset)3332 int32_t MediaLibraryPhotoOperations::SubmitEditMovingPhotoExecute(MediaLibraryCommand& cmd,
3333     const shared_ptr<FileAsset>& fileAsset)
3334 {
3335     MEDIA_INFO_LOG("Moving photo SubmitEditMovingPhotoExecute begin, fileId:%{public}d", fileAsset->GetId());
3336     string assetPath = fileAsset->GetFilePath();
3337     CHECK_AND_RETURN_RET_LOG(!assetPath.empty(), E_INVALID_VALUES, "Failed to get asset path");
3338     int32_t errCode = E_OK;
3339     if (fileAsset->GetPhotoEditTime() == 0) { // the asset has not been edited before
3340         // Save video file in the photo direvtory to the .editdata directory
3341         errCode = SaveSourceVideoFile(fileAsset, assetPath, false);
3342         CHECK_AND_RETURN_RET_LOG(errCode == E_OK, E_FILE_OPER_FAIL,
3343             "Failed to save %{private}s to sourcePath, errCode: %{public}d", assetPath.c_str(), errCode);
3344     }
3345 
3346     string cacheMovingPhotoVideoName;
3347     GetStringFromValuesBucket(cmd.GetValueBucket(), CACHE_MOVING_PHOTO_VIDEO_NAME, cacheMovingPhotoVideoName);
3348     if (cacheMovingPhotoVideoName.empty()) {
3349         string videoPath = MediaFileUtils::GetMovingPhotoVideoPath(assetPath);
3350         CHECK_AND_RETURN_RET_LOG(!videoPath.empty(), E_INVALID_PATH, "Can not get video path");
3351         if (MediaFileUtils::IsFileExists(videoPath)) {
3352             MEDIA_INFO_LOG("Delete video file in photo directory, file is: %{private}s", videoPath.c_str());
3353             CHECK_AND_RETURN_RET_LOG(MediaFileUtils::DeleteFile(videoPath), E_HAS_FS_ERROR,
3354                 "Failed to delete video file, path:%{private}s", videoPath.c_str());
3355         }
3356         errCode = UpdateMovingPhotoSubtype(fileAsset->GetId(), fileAsset->GetPhotoSubType());
3357         MEDIA_INFO_LOG("Moving photo graffiti editing, which becomes a normal photo, fileId:%{public}d",
3358             fileAsset->GetId());
3359     }
3360     return errCode;
3361 }
3362 
GetMovingPhotoCachePath(MediaLibraryCommand & cmd,const shared_ptr<FileAsset> & fileAsset,string & imageCachePath,string & videoCachePath)3363 int32_t MediaLibraryPhotoOperations::GetMovingPhotoCachePath(MediaLibraryCommand& cmd,
3364     const shared_ptr<FileAsset>& fileAsset, string& imageCachePath, string& videoCachePath)
3365 {
3366     string imageCacheName;
3367     string videoCacheName;
3368     const ValuesBucket& values = cmd.GetValueBucket();
3369     GetStringFromValuesBucket(values, CACHE_FILE_NAME, imageCacheName);
3370     GetStringFromValuesBucket(values, CACHE_MOVING_PHOTO_VIDEO_NAME, videoCacheName);
3371     CHECK_AND_RETURN_RET_LOG(!imageCacheName.empty() || !videoCacheName.empty(),
3372         E_INVALID_VALUES, "Failed to check cache file of moving photo");
3373 
3374     string cacheDir = GetAssetCacheDir();
3375     if (!videoCacheName.empty()) {
3376         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CheckMovingPhotoVideo(cacheDir + "/" + videoCacheName),
3377             E_INVALID_MOVING_PHOTO, "Failed to check cache video of moving photo");
3378     }
3379 
3380     string assetPath = fileAsset->GetPath();
3381     CHECK_AND_RETURN_RET_LOG(!assetPath.empty(), E_INVALID_PATH, "Failed to get image path of moving photo");
3382     string assetVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(assetPath);
3383     CHECK_AND_RETURN_RET_LOG(!assetVideoPath.empty(), E_INVALID_PATH, "Failed to get video path of moving photo");
3384 
3385     if (imageCacheName.empty()) {
3386         imageCacheName = MediaFileUtils::GetTitleFromDisplayName(videoCacheName) + "_image." +
3387                          MediaFileUtils::GetExtensionFromPath(fileAsset->GetDisplayName());
3388         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CopyFileUtil(assetPath, cacheDir + "/" + imageCacheName),
3389             E_HAS_FS_ERROR, "Failed to copy image to cache");
3390     }
3391     if (videoCacheName.empty()) {
3392         videoCacheName = MediaFileUtils::GetTitleFromDisplayName(imageCacheName) + "_video.mp4";
3393         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CopyFileUtil(assetVideoPath, cacheDir + "/" + videoCacheName),
3394             E_HAS_FS_ERROR, "Failed to copy video to cache");
3395     }
3396 
3397     imageCachePath = cacheDir + "/" + imageCacheName;
3398     videoCachePath = cacheDir + "/" + videoCacheName;
3399     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileExists(imageCachePath), E_NO_SUCH_FILE,
3400         "imageCachePath: %{private}s does not exist!", imageCachePath.c_str());
3401     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileExists(videoCachePath), E_NO_SUCH_FILE,
3402         "videoCachePath: %{private}s does not exist!", videoCachePath.c_str());
3403     return E_OK;
3404 }
3405 
ReNameVedioFilePath(const string & assetPath,const string & sourceImagePath,const string & assetVideoPath)3406 int32_t MediaLibraryPhotoOperations::ReNameVedioFilePath(
3407     const string &assetPath, const string &sourceImagePath, const string &assetVideoPath)
3408 {
3409     string editDataDirPath = GetEditDataDirPath(assetPath);
3410     CHECK_AND_RETURN_RET_LOG(!editDataDirPath.empty(), E_INVALID_URI, "Failed to get edit dir path");
3411     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CreateDirectory(editDataDirPath),
3412         E_HAS_FS_ERROR,
3413         "Failed to create dir %{private}s",
3414         editDataDirPath.c_str());
3415 
3416     CHECK_AND_RETURN_RET_LOG(!sourceImagePath.empty(), E_INVALID_PATH, "Cannot get source image path");
3417     string sourceVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(sourceImagePath);
3418     CHECK_AND_RETURN_RET_LOG(!sourceVideoPath.empty(), E_INVALID_PATH, "Cannot get source video path");
3419     if (!MediaFileUtils::IsFileExists(sourceVideoPath)) {
3420         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::ModifyAsset(assetVideoPath, sourceVideoPath) == E_SUCCESS,
3421             E_HAS_FS_ERROR, "Move file failed, srcPath:%{private}s, newPath:%{private}s",
3422             assetVideoPath.c_str(), sourceVideoPath.c_str());
3423     }
3424     if (!MediaFileUtils::IsFileExists(sourceImagePath)) {
3425         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::ModifyAsset(assetPath, sourceImagePath) == E_SUCCESS,
3426             E_HAS_FS_ERROR, "Move file failed, srcPath:%{private}s, newPath:%{private}s",
3427             assetPath.c_str(), sourceImagePath.c_str());
3428     }
3429     return E_SUCCESS;
3430 }
3431 
SubmitEffectModeExecute(MediaLibraryCommand & cmd)3432 int32_t MediaLibraryPhotoOperations::SubmitEffectModeExecute(MediaLibraryCommand& cmd)
3433 {
3434     int32_t id = -1;
3435     int32_t effectMode = -1;
3436     const ValuesBucket& values = cmd.GetValueBucket();
3437     CHECK_AND_RETURN_RET_LOG(GetInt32FromValuesBucket(values, PhotoColumn::MEDIA_ID, id) && id > 0,
3438         E_INVALID_VALUES, "Failed to get file id");
3439     CHECK_AND_RETURN_RET_LOG(GetInt32FromValuesBucket(values, PhotoColumn::MOVING_PHOTO_EFFECT_MODE, effectMode) &&
3440         MediaFileUtils::CheckMovingPhotoEffectMode(effectMode), E_INVALID_VALUES,
3441         "Failed to check effect mode: %{public}d", effectMode);
3442     vector<string> columns = { PhotoColumn::MEDIA_ID, PhotoColumn::MEDIA_FILE_PATH, PhotoColumn::MEDIA_NAME,
3443         PhotoColumn::PHOTO_SUBTYPE, PhotoColumn::MEDIA_TIME_PENDING, PhotoColumn::MEDIA_DATE_TRASHED,
3444         PhotoColumn::PHOTO_EDIT_TIME, PhotoColumn::MEDIA_MIME_TYPE, PhotoColumn::MOVING_PHOTO_EFFECT_MODE,
3445         PhotoColumn::PHOTO_DIRTY, PhotoColumn::MEDIA_TITLE, PhotoColumn::PHOTO_MEDIA_SUFFIX };
3446     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(PhotoColumn::MEDIA_ID, to_string(id),
3447         OperationObject::FILESYSTEM_PHOTO, columns);
3448     int32_t errCode = CheckFileAssetStatus(fileAsset, true);
3449     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to check status of fileAsset, id: %{public}d", id);
3450 
3451     string imageCachePath;
3452     string videoCachePath;
3453     errCode = GetMovingPhotoCachePath(cmd, fileAsset, imageCachePath, videoCachePath);
3454     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to get cache file path of moving photo");
3455 
3456     string assetPath = fileAsset->GetPath();
3457     string assetVideoPath = MediaFileUtils::GetMovingPhotoVideoPath(assetPath);
3458     if (fileAsset->GetPhotoEditTime() == 0) {  // save source moving photo
3459         string sourceImagePath = GetEditDataSourcePath(assetPath);
3460         CHECK_AND_RETURN_RET_LOG(ReNameVedioFilePath(assetPath, sourceImagePath, assetVideoPath) == E_SUCCESS,
3461             E_HAS_FS_ERROR, "Move file failed, srcPath:%{private}s, srcVedioPath:%{private}s, newPath:%{private}s",
3462             assetPath.c_str(), assetVideoPath.c_str(), sourceImagePath.c_str());
3463     }
3464 
3465     CHECK_AND_RETURN_RET_LOG(Move(imageCachePath, assetPath) == E_OK, E_HAS_FS_ERROR, "Failed to move image");
3466     CHECK_AND_RETURN_RET_LOG(Move(videoCachePath, assetVideoPath) == E_OK, E_HAS_FS_ERROR, "Failed to move video");
3467     CHECK_AND_RETURN_RET_LOG(UpdateEffectMode(id, effectMode) == E_OK, errCode, "Failed to update effect mode");
3468     if (HandleNeedSetDisplayName(cmd, fileAsset) != E_OK) {
3469         CHECK_AND_RETURN_RET_LOG(DoRevertEdit(fileAsset) == E_OK, errCode, "Failed to revert when setdisplayname file");
3470         return E_FAIL;
3471     }
3472     if (RenameEditDataDirBySetDisplayName(cmd, fileAsset) != E_OK) {
3473         CHECK_AND_RETURN_RET_LOG(DoRevertEdit(fileAsset) == E_OK, E_FAIL, "Failed to revert when setdisplayname file");
3474         return E_FAIL;
3475     }
3476     ScanFile(fileAsset->GetPath(), true, true, true);
3477     return E_OK;
3478 }
3479 
SubmitCache(MediaLibraryCommand & cmd)3480 int32_t MediaLibraryPhotoOperations::SubmitCache(MediaLibraryCommand& cmd)
3481 {
3482     MediaLibraryTracer tracer;
3483     tracer.Start("MediaLibraryPhotoOperations::SubmitCache");
3484 
3485     if (IsSetEffectMode(cmd)) {
3486         return SubmitEffectModeExecute(cmd);
3487     }
3488 
3489     const ValuesBucket& values = cmd.GetValueBucket();
3490     string fileName;
3491     CHECK_AND_RETURN_RET_LOG(GetStringFromValuesBucket(values, CACHE_FILE_NAME, fileName),
3492         E_INVALID_VALUES, "Failed to get fileName");
3493     string cacheDir = GetAssetCacheDir();
3494     string cachePath = cacheDir + "/" + fileName;
3495     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileExists(cachePath), E_NO_SUCH_FILE,
3496         "cachePath: %{private}s does not exist!", cachePath.c_str());
3497     string movingPhotoVideoName;
3498     if (GetStringFromValuesBucket(values, CACHE_MOVING_PHOTO_VIDEO_NAME, movingPhotoVideoName)) {
3499         CHECK_AND_RETURN_RET_LOG(MediaFileUtils::IsFileExists(cacheDir + "/" + movingPhotoVideoName),
3500             E_NO_SUCH_FILE, "cahce moving video path: %{private}s does not exist!", cachePath.c_str());
3501     }
3502 
3503     int32_t id = 0;
3504     if (!GetInt32FromValuesBucket(values, PhotoColumn::MEDIA_ID, id)) {
3505         string displayName;
3506         CHECK_AND_RETURN_RET_LOG(GetStringFromValuesBucket(values, PhotoColumn::MEDIA_NAME, displayName),
3507             E_INVALID_VALUES, "Failed to get displayName");
3508         CHECK_AND_RETURN_RET_LOG(
3509             MediaFileUtils::GetExtensionFromPath(displayName) == MediaFileUtils::GetExtensionFromPath(fileName),
3510             E_INVALID_VALUES, "displayName mismatches extension of cache file name");
3511         ValuesBucket reservedValues = values;
3512         id = CreateV10(cmd);
3513         CHECK_AND_RETURN_RET_LOG(id > 0, E_FAIL, "Failed to create asset");
3514         cmd.SetValueBucket(reservedValues);
3515     }
3516     vector<string> columns = { PhotoColumn::MEDIA_ID, PhotoColumn::MEDIA_FILE_PATH, PhotoColumn::MEDIA_NAME,
3517         PhotoColumn::PHOTO_SUBTYPE, PhotoColumn::MEDIA_TIME_PENDING, PhotoColumn::MEDIA_DATE_TRASHED,
3518         PhotoColumn::PHOTO_EDIT_TIME, PhotoColumn::PHOTO_DIRTY, PhotoColumn::MEDIA_TITLE,
3519         PhotoColumn::MEDIA_MIME_TYPE, PhotoColumn::PHOTO_MEDIA_SUFFIX, MediaColumn::MEDIA_TYPE,
3520         PhotoColumn::MOVING_PHOTO_EFFECT_MODE, PhotoColumn::PHOTO_ORIGINAL_SUBTYPE };
3521     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(
3522         PhotoColumn::MEDIA_ID, to_string(id), OperationObject::FILESYSTEM_PHOTO, columns);
3523     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_VALUES,
3524         "Failed to getmapmanagerthread:: FileAsset, fileId=%{public}d", id);
3525     int32_t errCode = SubmitCacheExecute(cmd, fileAsset, cachePath);
3526     CHECK_AND_RETURN_RET_LOG(errCode == E_OK, errCode, "Failed to submit cache, fileId=%{public}d", id);
3527     return id;
3528 }
3529 
ProcessMultistagesPhoto(bool isEdited,const std::string & path,const uint8_t * addr,const long bytes,int32_t fileId)3530 int32_t MediaLibraryPhotoOperations::ProcessMultistagesPhoto(bool isEdited, const std::string &path,
3531     const uint8_t *addr, const long bytes, int32_t fileId)
3532 {
3533     MediaLibraryTracer tracer;
3534     tracer.Start("MediaLibraryPhotoOperations::ProcessMultistagesPhoto");
3535     string editDataSourcePath = GetEditDataSourcePath(path);
3536     string editDataCameraPath = GetEditDataCameraPath(path);
3537 
3538     if (isEdited) {
3539         // 图片编辑过了只替换低质量裸图
3540         return FileUtils::SaveImage(editDataSourcePath, (void*)addr, bytes);
3541     } else {
3542         if (!MediaFileUtils::IsFileExists(editDataCameraPath)) {
3543             // 图片没编辑过且没有editdata_camera,只落盘在Photo目录
3544             return FileUtils::SaveImage(path, (void*)addr, bytes);
3545         } else {
3546             // 图片没编辑过且有editdata_camera
3547             MediaLibraryTracer tracer;
3548             tracer.Start("MediaLibraryPhotoOperations::ProcessMultistagesPhoto AddFiltersToPhoto");
3549             // (1) 先替换低质量裸图
3550             int ret = FileUtils::SaveImage(editDataSourcePath, (void*)addr, bytes);
3551             CHECK_AND_RETURN_RET(ret == E_OK, ret);
3552             // (2) 生成高质量水印滤镜图片
3553             string editData;
3554             CHECK_AND_RETURN_RET_LOG(ReadEditdataFromFile(editDataCameraPath, editData) == E_OK, E_HAS_FS_ERROR,
3555                 "Failed to read editdata, path=%{public}s", editDataCameraPath.c_str());
3556             const string HIGH_QUALITY_PHOTO_STATUS = "high";
3557             CHECK_AND_RETURN_RET_LOG(
3558                 AddFiltersToPhoto(editDataSourcePath, path, editData, HIGH_QUALITY_PHOTO_STATUS) == E_OK,
3559                 E_FAIL, "Failed to add filters to photo");
3560             MediaLibraryObjectUtils::ScanFileAsync(path, to_string(fileId), MediaLibraryApi::API_10);
3561             return E_OK;
3562         }
3563     }
3564 }
3565 
ProcessMultistagesPhotoForPicture(bool isEdited,const std::string & path,std::shared_ptr<Media::Picture> & picture,int32_t fileId,const std::string & mime_type,std::shared_ptr<Media::Picture> & resultPicture)3566 int32_t MediaLibraryPhotoOperations::ProcessMultistagesPhotoForPicture(bool isEdited, const std::string &path,
3567     std::shared_ptr<Media::Picture> &picture, int32_t fileId, const std::string &mime_type,
3568     std::shared_ptr<Media::Picture> &resultPicture)
3569 {
3570     MediaLibraryTracer tracer;
3571     tracer.Start("MediaLibraryPhotoOperations::ProcessMultistagesPhoto");
3572     string editDataSourcePath = GetEditDataSourcePath(path);
3573     string editDataCameraPath = GetEditDataCameraPath(path);
3574 
3575     if (isEdited) {
3576         // 图片编辑过了只替换低质量裸图
3577         resultPicture = nullptr;
3578         return FileUtils::SavePicture(editDataSourcePath, picture, mime_type, isEdited);
3579     } else {
3580         if (!MediaFileUtils::IsFileExists(editDataCameraPath)) {
3581             // 图片没编辑过且没有editdata_camera,只落盘在Photo目录
3582             resultPicture = picture;
3583             return FileUtils::SavePicture(path, picture, mime_type, isEdited);
3584         } else {
3585             // 图片没编辑过且有editdata_camera
3586             MediaLibraryTracer tracer;
3587             tracer.Start("MediaLibraryPhotoOperations::ProcessMultistagesPhoto AddFiltersToPhoto");
3588             // (1) 先替换低质量裸图
3589             int ret = FileUtils::SavePicture(editDataSourcePath, picture, mime_type, isEdited);
3590             CHECK_AND_RETURN_RET(ret == E_OK, ret);
3591 
3592             // (2) 生成高质量水印滤镜图片
3593             string editData;
3594             CHECK_AND_RETURN_RET_LOG(ReadEditdataFromFile(editDataCameraPath, editData) == E_OK, E_HAS_FS_ERROR,
3595                 "Failed to read editdata, path=%{public}s", editDataCameraPath.c_str());
3596             CHECK_AND_RETURN_RET_LOG(AddFiltersToPicture(picture, path, editData, mime_type) == E_OK, E_FAIL,
3597                 "Failed to add filters to photo");
3598             resultPicture = picture;
3599             return E_OK;
3600         }
3601     }
3602 }
3603 
AddFiltersToPhoto(const std::string & inputPath,const std::string & outputPath,const std::string & editdata,const std::string & photoStatus)3604 int32_t MediaLibraryPhotoOperations::AddFiltersToPhoto(const std::string &inputPath,
3605     const std::string &outputPath, const std::string &editdata, const std::string &photoStatus)
3606 {
3607     MediaLibraryTracer tracer;
3608     tracer.Start("MediaLibraryPhotoOperations::AddFiltersToPhoto");
3609     MEDIA_INFO_LOG("MultistagesCapture inputPath: %{public}s, outputPath: %{public}s, editdata: %{public}s",
3610         inputPath.c_str(), outputPath.c_str(), editdata.c_str());
3611     std::string info = editdata;
3612     size_t lastSlash = outputPath.rfind('/');
3613     CHECK_AND_RETURN_RET_LOG(lastSlash != string::npos && outputPath.size() > (lastSlash + 1), E_INVALID_VALUES,
3614         "Failed to check outputPath: %{public}s", outputPath.c_str());
3615     string tempOutputPath = outputPath.substr(0, lastSlash) +
3616         "/filters_" + photoStatus + outputPath.substr(lastSlash + 1);
3617     int32_t ret = MediaFileUtils::CreateAsset(tempOutputPath);
3618     CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS || ret == E_FILE_EXIST, E_HAS_FS_ERROR,
3619         "Failed to create temp filters file %{private}s", tempOutputPath.c_str());
3620     tracer.Start("MediaChangeEffect::TakeEffect");
3621     ret = MediaChangeEffect::TakeEffect(inputPath, tempOutputPath, info);
3622     tracer.Finish();
3623     if (ret != E_OK) {
3624         MEDIA_ERR_LOG("MultistagesCapture, TakeEffect error. ret = %{public}d", ret);
3625         return E_ERR;
3626     }
3627 
3628     string editDataPath = GetEditDataPath(outputPath);
3629     if (MediaFileUtils::IsFileExists(editDataPath)) {
3630         MEDIA_INFO_LOG("Editdata path: %{private}s exists, cannot add filters to photo", editDataPath.c_str());
3631         CHECK_AND_PRINT_LOG(MediaFileUtils::DeleteFile(tempOutputPath),
3632             "Failed to delete temp filters file, errno: %{public}d", errno);
3633         return E_OK;
3634     }
3635 
3636     ret = rename(tempOutputPath.c_str(), outputPath.c_str());
3637     if (ret < 0) {
3638         MEDIA_ERR_LOG("Failed to rename temp filters file, ret: %{public}d, errno: %{public}d", ret, errno);
3639         CHECK_AND_PRINT_LOG(MediaFileUtils::DeleteFile(tempOutputPath),
3640             "Failed to delete temp filters file, errno: %{public}d", errno);
3641         return ret;
3642     }
3643     MEDIA_INFO_LOG("MultistagesCapture finish");
3644     return E_OK;
3645 }
3646 
AddFiltersToPicture(std::shared_ptr<Media::Picture> & inPicture,const std::string & outputPath,string & editdata,const std::string & mime_type)3647 int32_t MediaLibraryPhotoOperations::AddFiltersToPicture(std::shared_ptr<Media::Picture> &inPicture,
3648     const std::string &outputPath, string &editdata, const std::string &mime_type)
3649 {
3650     (inPicture != nullptr, E_ERR, "AddFiltersToPicture: picture is null");
3651     MEDIA_INFO_LOG("AddFiltersToPicture outputPath: %{public}s, editdata: %{public}s",
3652         outputPath.c_str(), editdata.c_str());
3653     size_t lastSlash = outputPath.rfind('/');
3654     CHECK_AND_RETURN_RET_LOG(lastSlash != string::npos && outputPath.size() > (lastSlash + 1), E_INVALID_VALUES,
3655         "Failed to check outputPath: %{public}s", outputPath.c_str());
3656     int32_t ret = MediaChangeEffect::TakeEffectForPicture(inPicture, editdata);
3657     FileUtils::DealPicture(mime_type, outputPath, inPicture);
3658     return E_OK;
3659 }
3660 
ProcessMultistagesVideo(bool isEdited,bool isMovingPhoto,const std::string & path)3661 int32_t MediaLibraryPhotoOperations::ProcessMultistagesVideo(bool isEdited, bool isMovingPhoto, const std::string &path)
3662 {
3663     MEDIA_INFO_LOG("ProcessMultistagesVideo path:%{public}s, isEdited: %{public}d, isMovingPhoto: %{public}d",
3664         DfxUtils::GetSafePath(path).c_str(), isEdited, isMovingPhoto);
3665     CHECK_AND_RETURN_RET(!isMovingPhoto, FileUtils::SaveMovingPhotoVideo(path));
3666     return FileUtils::SaveVideo(path, isEdited);
3667 }
3668 
RemoveTempVideo(const std::string & path)3669 int32_t MediaLibraryPhotoOperations::RemoveTempVideo(const std::string &path)
3670 {
3671     MEDIA_INFO_LOG("RemoveTempVideo path: %{public}s", DfxUtils::GetSafePath(path).c_str());
3672     return FileUtils::DeleteTempVideoFile(path);
3673 }
3674 
PhotoEditingRecord()3675 PhotoEditingRecord::PhotoEditingRecord()
3676 {
3677 }
3678 
GetInstance()3679 shared_ptr<PhotoEditingRecord> PhotoEditingRecord::GetInstance()
3680 {
3681     if (instance_ == nullptr) {
3682         lock_guard<mutex> lock(mutex_);
3683         if (instance_ == nullptr) {
3684             instance_ = make_shared<PhotoEditingRecord>();
3685         }
3686     }
3687     return instance_;
3688 }
3689 
StartCommitEdit(int32_t fileId)3690 bool PhotoEditingRecord::StartCommitEdit(int32_t fileId)
3691 {
3692     unique_lock<shared_mutex> lock(addMutex_);
3693     if (revertingPhotoSet_.count(fileId) > 0) {
3694         MEDIA_ERR_LOG("Photo %{public}d is reverting", fileId);
3695         return false;
3696     }
3697     editingPhotoSet_.insert(fileId);
3698     return true;
3699 }
3700 
EndCommitEdit(int32_t fileId)3701 void PhotoEditingRecord::EndCommitEdit(int32_t fileId)
3702 {
3703     unique_lock<shared_mutex> lock(addMutex_);
3704     editingPhotoSet_.erase(fileId);
3705 }
3706 
StartRevert(int32_t fileId)3707 bool PhotoEditingRecord::StartRevert(int32_t fileId)
3708 {
3709     unique_lock<shared_mutex> lock(addMutex_);
3710     if (editingPhotoSet_.count(fileId) > 0) {
3711         MEDIA_ERR_LOG("Photo %{public}d is committing edit", fileId);
3712         return false;
3713     }
3714     revertingPhotoSet_.insert(fileId);
3715     return true;
3716 }
3717 
EndRevert(int32_t fileId)3718 void PhotoEditingRecord::EndRevert(int32_t fileId)
3719 {
3720     unique_lock<shared_mutex> lock(addMutex_);
3721     revertingPhotoSet_.erase(fileId);
3722 }
3723 
IsInRevertOperation(int32_t fileId)3724 bool PhotoEditingRecord::IsInRevertOperation(int32_t fileId)
3725 {
3726     shared_lock<shared_mutex> lock(addMutex_);
3727     return revertingPhotoSet_.count(fileId) > 0;
3728 }
3729 
IsInEditOperation(int32_t fileId)3730 bool PhotoEditingRecord::IsInEditOperation(int32_t fileId)
3731 {
3732     shared_lock<shared_mutex> lock(addMutex_);
3733     if (editingPhotoSet_.count(fileId) > 0 || revertingPhotoSet_.count(fileId) > 0) {
3734         return true;
3735     }
3736     return false;
3737 }
3738 
ConvertPhotoPathToThumbnailDirPath(std::string & path)3739 static bool ConvertPhotoPathToThumbnailDirPath(std::string& path)
3740 {
3741     const std::string photoRelativePath = "/Photo/";
3742     const std::string thumbRelativePath = "/.thumbs/Photo/";
3743     size_t pos = path.find(photoRelativePath);
3744     CHECK_AND_RETURN_RET_LOG(pos != string::npos, false, "source file invalid! path is %{public}s", path.c_str());
3745     path.replace(pos, photoRelativePath.length(), thumbRelativePath);
3746     return true;
3747 }
3748 
StoreThumbnailSize(const string & photoId,const string & photoPath)3749 void MediaLibraryPhotoOperations::StoreThumbnailSize(const string& photoId, const string& photoPath)
3750 {
3751     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
3752     CHECK_AND_RETURN_LOG(rdbStore != nullptr, "Medialibrary rdbStore is nullptr!");
3753 
3754     string thumbnailDir {photoPath};
3755     CHECK_AND_RETURN_LOG(ConvertPhotoPathToThumbnailDirPath(thumbnailDir),
3756         "Failed to get thumbnail dir path from photo path! file id: %{public}s", photoId.c_str());
3757     uint64_t photoThumbnailSize = GetFolderSize(thumbnailDir);
3758     string sql = "INSERT OR REPLACE INTO " + PhotoExtColumn::PHOTOS_EXT_TABLE + " (" +
3759         PhotoExtColumn::PHOTO_ID + ", " + PhotoExtColumn::THUMBNAIL_SIZE +
3760         ") VALUES (" + photoId + ", " + to_string(photoThumbnailSize) + ")";
3761     int32_t ret = rdbStore->ExecuteSql(sql);
3762     CHECK_AND_RETURN_LOG(ret == NativeRdb::E_OK,
3763         "Failed to execute sql, photoId is %{public}s, error code is %{public}d", photoId.c_str(), ret);
3764 }
3765 
HasDroppedThumbnailSize(const string & photoId)3766 bool MediaLibraryPhotoOperations::HasDroppedThumbnailSize(const string& photoId)
3767 {
3768     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
3769     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, false,
3770         "Medialibrary rdbStore is nullptr!");
3771 
3772     string sql = "DELETE FROM " + PhotoExtColumn::PHOTOS_EXT_TABLE +
3773         " WHERE " + PhotoExtColumn::PHOTO_ID + " = " + photoId + ";";
3774     int32_t ret = rdbStore->ExecuteSql(sql);
3775     CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, false,
3776         "Failed to execute sql, photoId is %{public}s, error code is %{public}d", photoId.c_str(), ret);
3777     return true;
3778 }
3779 
ScanMovingPhoto(MediaLibraryCommand & cmd,const vector<string> & columns)3780 shared_ptr<NativeRdb::ResultSet> MediaLibraryPhotoOperations::ScanMovingPhoto(MediaLibraryCommand &cmd,
3781     const vector<string> &columns)
3782 {
3783     if (columns.empty()) {
3784         MEDIA_ERR_LOG("column is empty");
3785         return nullptr;
3786     }
3787     string uri = columns[0]; // 0 in columns predicates uri
3788     string path = MediaFileUri::GetPathFromUri(uri, true);
3789     string fileId = MediaFileUri::GetPhotoId(uri);
3790     MediaLibraryObjectUtils::ScanFileAsync(path, fileId, MediaLibraryApi::API_10, true);
3791     return nullptr;
3792 }
3793 
ScanFileWithoutAlbumUpdate(MediaLibraryCommand & cmd)3794 int32_t MediaLibraryPhotoOperations::ScanFileWithoutAlbumUpdate(MediaLibraryCommand &cmd)
3795 {
3796     if (!PermissionUtils::IsNativeSAApp()) {
3797         MEDIA_DEBUG_LOG("do not have permission");
3798         return E_VIOLATION_PARAMETERS;
3799     }
3800     const ValuesBucket &values = cmd.GetValueBucket();
3801     string uriString;
3802     CHECK_AND_RETURN_RET(GetStringFromValuesBucket(values, MEDIA_DATA_DB_URI, uriString), E_INVALID_VALUES);
3803 
3804     string path = MediaFileUri::GetPathFromUri(uriString, true);
3805     string fileIdStr = MediaFileUri::GetPhotoId(uriString);
3806     int32_t fileId = 0;
3807     if (MediaLibraryDataManagerUtils::IsNumber(fileIdStr)) {
3808         fileId = atoi(fileIdStr.c_str());
3809     }
3810     MediaLibraryAssetOperations::ScanFileWithoutAlbumUpdate(path, false, false, true, fileId);
3811 
3812     return E_OK;
3813 }
3814 
UpdateDirty(int32_t fileId)3815 static void UpdateDirty(int32_t fileId)
3816 {
3817     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
3818     predicates.EqualTo(PhotoColumn::MEDIA_ID, fileId);
3819     predicates.EqualTo(PhotoColumn::PHOTO_QUALITY, static_cast<int32_t>(MultiStagesPhotoQuality::FULL));
3820     predicates.EqualTo(PhotoColumn::PHOTO_IS_TEMP, 0);
3821     predicates.EqualTo(PhotoColumn::PHOTO_DIRTY, -1);
3822     ValuesBucket values;
3823     values.PutInt(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyTypes::TYPE_NEW));
3824     int32_t updateDirtyRows = MediaLibraryRdbStore::UpdateWithDateTime(values, predicates);
3825     MEDIA_INFO_LOG("update dirty to 1, file_id:%{public}d, changedRows:%{public}d", fileId, updateDirtyRows);
3826 }
3827 
DegenerateMovingPhoto(MediaLibraryCommand & cmd)3828 int32_t MediaLibraryPhotoOperations::DegenerateMovingPhoto(MediaLibraryCommand &cmd)
3829 {
3830     vector<string> columns = { PhotoColumn::MEDIA_ID, PhotoColumn::MEDIA_FILE_PATH,
3831         PhotoColumn::MEDIA_NAME, PhotoColumn::PHOTO_SUBTYPE, PhotoColumn::PHOTO_EDIT_TIME };
3832     shared_ptr<FileAsset> fileAsset = GetFileAssetFromDb(*(cmd.GetAbsRdbPredicates()),
3833         OperationObject::FILESYSTEM_PHOTO, columns);
3834     CHECK_AND_RETURN_RET_LOG(fileAsset != nullptr, E_INVALID_VALUES, "failed to query fileAsset");
3835     if (fileAsset->GetPhotoSubType() != static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
3836         MEDIA_INFO_LOG("fileAsset is not moving photo");
3837         return E_OK;
3838     }
3839     if (fileAsset->GetPhotoEditTime() > 0) {
3840         MEDIA_INFO_LOG("moving photo is edited");
3841         return E_OK;
3842     }
3843     string videoPath = MediaFileUtils::GetTempMovingPhotoVideoPath(fileAsset->GetFilePath());
3844     size_t videoSize = 0;
3845     if (MediaFileUtils::GetFileSize(videoPath, videoSize) && videoSize > 0) {
3846         MEDIA_INFO_LOG("no need to degenerate, video size:%{public}d", static_cast<int32_t>(videoSize));
3847         return E_OK;
3848     }
3849 
3850     if (MediaFileUtils::IsFileExists(videoPath)) {
3851         MEDIA_INFO_LOG("delete empty video file, size:%{public}d", static_cast<int32_t>(videoSize));
3852         (void)MediaFileUtils::DeleteFile(videoPath);
3853     }
3854 
3855     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
3856     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "Failed to get rdbStore");
3857     RdbPredicates predicates = RdbUtils::ToPredicates(cmd.GetDataSharePred(), PhotoColumn::PHOTOS_TABLE);
3858     MediaLibraryRdbStore::ReplacePredicatesUriToId(predicates);
3859     ValuesBucket values;
3860     values.Put(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(PhotoSubType::DEFAULT));
3861     int32_t updatedRows = rdbStore->UpdateWithDateTime(values, predicates);
3862     CHECK_AND_RETURN_RET_LOG(updatedRows > 0, updatedRows,
3863         "Failed to update subtype, updatedRows=%{public}d", updatedRows);
3864     UpdateDirty(fileAsset->GetId());
3865 
3866     string extraUri = MediaFileUtils::GetExtraUri(fileAsset->GetDisplayName(), fileAsset->GetFilePath());
3867     auto watch = MediaLibraryNotify::GetInstance();
3868     CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_ERR, "Can not get MediaLibraryNotify Instance");
3869     watch->Notify(
3870         MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(fileAsset->GetId()), extraUri),
3871         NotifyType::NOTIFY_UPDATE);
3872     return updatedRows;
3873 }
3874 
UpdateOwnerAlbumId(MediaLibraryCommand & cmd)3875 int32_t MediaLibraryPhotoOperations::UpdateOwnerAlbumId(MediaLibraryCommand &cmd)
3876 {
3877     const ValuesBucket &values = cmd.GetValueBucket();
3878     int32_t targetAlbumId = 0;
3879     CHECK_AND_RETURN_RET(
3880         GetInt32FromValuesBucket(values, PhotoColumn::PHOTO_OWNER_ALBUM_ID, targetAlbumId), E_HAS_DB_ERROR);
3881     int32_t rowId = UpdateFileInDb(cmd);
3882     CHECK_AND_RETURN_RET_LOG(rowId >= 0, rowId, "Update Photo In database failed, rowId=%{public}d", rowId);
3883 
3884     PhotoAlbumType type;
3885     PhotoAlbumSubType subType;
3886     CHECK_AND_RETURN_RET_LOG(GetAlbumTypeSubTypeById(to_string(targetAlbumId), type, subType) ==
3887         E_SUCCESS, E_INVALID_ARGUMENTS, "invalid album uri");
3888     if (PhotoAlbum::IsUserPhotoAlbum(type, subType)) {
3889         MediaLibraryRdbUtils::UpdateUserAlbumInternal(
3890             MediaLibraryUnistoreManager::GetInstance().GetRdbStore(), { to_string(targetAlbumId) });
3891     }
3892     if (PhotoAlbum::IsSourceAlbum(type, subType)) {
3893         MediaLibraryRdbUtils::UpdateSourceAlbumInternal(
3894             MediaLibraryUnistoreManager::GetInstance().GetRdbStore(), { to_string(targetAlbumId) });
3895     }
3896     auto watch = MediaLibraryNotify::GetInstance();
3897     if (watch != nullptr) {
3898         watch->Notify(PhotoColumn::PHOTO_URI_PREFIX + to_string(rowId),
3899             NotifyType::NOTIFY_ALBUM_ADD_ASSET, targetAlbumId);
3900     }
3901     return rowId;
3902 }
3903 
ProcessCustomRestore(MediaLibraryCommand & cmd)3904 int32_t MediaLibraryPhotoOperations::ProcessCustomRestore(MediaLibraryCommand& cmd)
3905 {
3906     const ValuesBucket& values = cmd.GetValueBucket();
3907     string albumLpath;
3908     string keyPath;
3909     string isDeduplication;
3910     string bundleName;
3911     string appName;
3912     string appId;
3913     CHECK_AND_RETURN_RET_LOG(GetStringFromValuesBucket(values, "albumLpath", albumLpath),
3914         E_INVALID_VALUES, "Failed to get albumLpath: %{public}s", albumLpath.c_str());
3915     CHECK_AND_RETURN_RET_LOG(GetStringFromValuesBucket(values, "keyPath", keyPath),
3916         E_INVALID_VALUES, "Failed to get keyPath: %{public}s", keyPath.c_str());
3917     string dir = CUSTOM_RESTORE_DIR + "/" + keyPath;
3918     CHECK_AND_RETURN_RET_LOG(
3919         MediaFileUtils::IsFileExists(dir), E_NO_SUCH_FILE, "sourceDir: %{public}s does not exist!", dir.c_str());
3920     CHECK_AND_RETURN_RET_LOG(GetStringFromValuesBucket(values, "isDeduplication", isDeduplication),
3921         E_INVALID_VALUES, "Failed to get isDeduplication: %{public}s", isDeduplication.c_str());
3922     CHECK_AND_RETURN_RET_LOG(GetStringFromValuesBucket(values, "bundleName", bundleName),
3923         E_INVALID_VALUES, "Failed to get bundleName: %{public}s", bundleName.c_str());
3924     CHECK_AND_RETURN_RET_LOG(GetStringFromValuesBucket(values, "appName", appName),
3925         E_INVALID_VALUES, "Failed to get appName: %{public}s", appName.c_str());
3926     GetStringFromValuesBucket(values, "appId", appId);
3927 
3928     RestoreTaskInfo restoreTaskInfo = {.albumLpath = albumLpath,
3929         .keyPath = keyPath,
3930         .isDeduplication = isDeduplication == "true",
3931         .bundleName = bundleName,
3932         .packageName = appName,
3933         .appId = appId,
3934         .sourceDir = dir};
3935     PhotoCustomRestoreOperation::GetInstance().AddTask(restoreTaskInfo).Start();
3936     return E_OK;
3937 }
3938 
CancelCustomRestore(MediaLibraryCommand & cmd)3939 int32_t MediaLibraryPhotoOperations::CancelCustomRestore(MediaLibraryCommand& cmd)
3940 {
3941     const ValuesBucket& values = cmd.GetValueBucket();
3942     string keyPath;
3943     CHECK_AND_RETURN_RET_LOG(GetStringFromValuesBucket(values, "keyPath", keyPath),
3944         E_INVALID_VALUES, "Failed to get keyPath: %{public}s", keyPath.c_str());
3945     RestoreTaskInfo restoreTaskInfo = {.keyPath = keyPath};
3946     PhotoCustomRestoreOperation::GetInstance().CancelTask(restoreTaskInfo);
3947     return E_OK;
3948 }
3949 
UpdateSupportedWatermarkType(MediaLibraryCommand & cmd)3950 int32_t MediaLibraryPhotoOperations::UpdateSupportedWatermarkType(MediaLibraryCommand &cmd)
3951 {
3952     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
3953     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "Failed to get rdbStore.");
3954     auto whereClause = cmd.GetAbsRdbPredicates()->GetWhereClause();
3955     auto args = cmd.GetAbsRdbPredicates()->GetWhereArgs();
3956     int32_t updateRows = -1;
3957     int32_t errCode = rdbStore->Update(updateRows, PhotoColumn::PHOTOS_TABLE, cmd.GetValueBucket(), whereClause, args);
3958     CHECK_AND_RETURN_RET_LOG(errCode == NativeRdb::E_OK, E_HAS_DB_ERROR,
3959         "Update subtype field failed. errCode:%{public}d,", errCode);
3960     return updateRows;
3961 }
3962 } // namespace Media
3963 } // namespace OHOS
3964