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