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