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