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