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