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