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