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