1 /*
2 * Copyright (c) 2025 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 #define MLOG_TAG "Media_Cloud_Service"
17
18 #include "cloud_media_download_service.h"
19
20 #include "cover_position_parser.h"
21 #include "directory_ex.h"
22 #include "parameters.h"
23 #include "media_log.h"
24 #include "media_file_utils.h"
25 #include "moving_photo_file_utils.h"
26 #include "cloud_media_file_utils.h"
27 #include "cloud_media_attachment_utils.h"
28 #include "cloud_media_sync_utils.h"
29 #include "cloud_sync_notify_handler.h"
30 #include "thumbnail_const.h"
31 #include "thumbnail_service.h"
32 #include "cloud_media_asset_manager.h"
33 #include "cloud_media_asset_types.h"
34 #include "cloud_media_dfx_service.h"
35 #include "cloud_media_scan_service.h"
36 #include "dfx_const.h"
37 #include "media_gallery_sync_notify.h"
38
39 namespace OHOS::Media::CloudSync {
40 using ChangeType = AAFwk::ChangeInfo::ChangeType;
GetDownloadThmNum(const int32_t type,int32_t & totalNum)41 int32_t CloudMediaDownloadService::GetDownloadThmNum(const int32_t type, int32_t &totalNum)
42 {
43 return this->dao_.GetDownloadThmNum(type, totalNum);
44 }
45
GetDownloadThms(const DownloadThumbnailQueryDto & queryDto,std::vector<PhotosDto> & photosDtos)46 int32_t CloudMediaDownloadService::GetDownloadThms(
47 const DownloadThumbnailQueryDto &queryDto, std::vector<PhotosDto> &photosDtos)
48 {
49 std::vector<PhotosPo> photosPos;
50 int32_t ret = this->dao_.GetDownloadThms(queryDto, photosPos);
51 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "GetDownloadThms failed, ret:%{public}d", ret);
52 photosDtos = this->processor_.GetPhotosDto(photosPos);
53 return ret;
54 }
55
GetDownloadThmsByUri(const std::vector<int32_t> & fileIds,const int32_t type)56 std::vector<PhotosDto> CloudMediaDownloadService::GetDownloadThmsByUri(
57 const std::vector<int32_t> &fileIds, const int32_t type)
58 {
59 MEDIA_INFO_LOG("enter CloudMediaDownloadService::GetDownloadThmsByUri type:%{public}d", type);
60 std::vector<PhotosDto> photosDtoVec;
61 std::vector<PhotosPo> photosPos;
62 int32_t ret = this->dao_.GetDownloadAsset(fileIds, photosPos);
63 CHECK_AND_RETURN_RET_LOG(ret == E_OK, photosDtoVec, "GetDownloadAsset failed, ret:%{public}d", ret);
64 std::vector<DownloadAssetData> downloadAssetDataVec;
65 this->processor_.GetDownloadAssetData(photosPos, downloadAssetDataVec);
66 MEDIA_INFO_LOG("GetDownloadThmsByUri size of downloadAssetDataVec: %{public}zu", downloadAssetDataVec.size());
67 CHECK_AND_RETURN_RET_LOG(
68 !downloadAssetDataVec.empty(), photosDtoVec, "GetDownloadThmsByUri Failed to get downloadAssetDataVec.");
69 for (const auto &downloadAssetData : downloadAssetDataVec) {
70 std::string filePath;
71 std::string fileName;
72 CHECK_AND_RETURN_RET_LOG(
73 CloudMediaFileUtils::GetParentPathAndFilename(downloadAssetData.path, filePath, fileName),
74 photosDtoVec,
75 "GetDownloadThmsByUri failed to GetParentPathAndFilename");
76 PhotosDto photosDto;
77 photosDto.fileId = downloadAssetData.fileId;
78 photosDto.cloudId = downloadAssetData.cloudId;
79 photosDto.data = filePath;
80 photosDto.mediaType = downloadAssetData.mediaType;
81 photosDto.size = downloadAssetData.fileSize;
82 photosDto.path = downloadAssetData.path;
83 photosDto.modifiedTime = downloadAssetData.editTime;
84 photosDto.fileName = fileName;
85 photosDto.originalCloudId = downloadAssetData.originalCloudId;
86 int32_t retThm = E_OK;
87 int32_t retLcd = E_OK;
88 if (static_cast<uint32_t>(type) & TYPE_THM_MASK) {
89 retThm = CloudMediaAttachmentUtils::GetThumbnail("thumbnail", downloadAssetData, photosDto);
90 CHECK_AND_PRINT_LOG(retThm == E_OK, "GetDownloadThmsByUri GetAttachment thm fail");
91 }
92 if (static_cast<uint32_t>(type) & TYPE_LCD_MASK) {
93 retLcd = CloudMediaAttachmentUtils::GetLcdThumbnail("lcd", downloadAssetData, photosDto);
94 CHECK_AND_PRINT_LOG(retLcd == E_OK, "GetDownloadThmsByUri GetAttachment lcd fail");
95 }
96 if ((retThm != E_OK) && (retLcd != E_OK)) {
97 continue;
98 }
99 MEDIA_DEBUG_LOG("GetDownloadThmsByUri Photo: %{public}s", photosDto.ToString().c_str());
100 photosDtoVec.push_back(photosDto);
101 }
102 return photosDtoVec;
103 }
104
OnDownloadThm(const std::vector<std::string> & thmVector,std::vector<MediaOperateResultDto> & result)105 int32_t CloudMediaDownloadService::OnDownloadThm(
106 const std::vector<std::string> &thmVector, std::vector<MediaOperateResultDto> &result)
107 {
108 CHECK_AND_RETURN_RET_LOG(!thmVector.empty(), E_OK, "thmVector is empty");
109 MEDIA_INFO_LOG("size of thmVector is %{public}zu", thmVector.size());
110 int32_t ret = this->dao_.UpdateDownloadThm(thmVector);
111 CHECK_AND_PRINT_LOG(ret == E_OK, "Failed to UpdateDownloadThms.");
112 if (ret == E_OK && !thmVector.empty()) {
113 CloudMediaDfxService::UpdateAttachmentStat(INDEX_THUMB_SUCCESS, thmVector.size());
114 }
115 /* 通知
116 DataSyncNotifier::GetInstance().TryNotify(PHOTO_URI_PREFIX, ChangeType::INSERT, "");
117 DataSyncNotifier::GetInstance().FinalNotify();
118 */
119 MediaGallerySyncNotify::GetInstance().TryNotify(PhotoColumn::PHOTO_CLOUD_URI_PREFIX, ChangeType::INSERT, "");
120 MediaGallerySyncNotify::GetInstance().FinalNotify();
121 for (auto &thm : thmVector) { // collect results
122 MediaOperateResultDto mediaResult;
123 mediaResult.cloudId = thm;
124 mediaResult.errorCode = ret;
125 result.emplace_back(mediaResult);
126 }
127 return ret;
128 }
129
OnDownloadLcd(const std::vector<std::string> & lcdVector,std::vector<MediaOperateResultDto> & result)130 int32_t CloudMediaDownloadService::OnDownloadLcd(
131 const std::vector<std::string> &lcdVector, std::vector<MediaOperateResultDto> &result)
132 {
133 CHECK_AND_RETURN_RET_LOG(!lcdVector.empty(), E_OK, "lcdVector is empty");
134 MEDIA_INFO_LOG("size of lcdVector is %{public}zu", lcdVector.size());
135 int32_t ret = this->dao_.UpdateDownloadLcd(lcdVector);
136 CHECK_AND_PRINT_LOG(ret == E_OK, "Failed to UpdateDownloadLcd.");
137 if (ret == E_OK && !lcdVector.empty()) {
138 CloudMediaDfxService::UpdateAttachmentStat(INDEX_LCD_SUCCESS, lcdVector.size());
139 }
140 for (auto &thm : lcdVector) { // collect results
141 MediaOperateResultDto mediaResult;
142 mediaResult.cloudId = thm;
143 mediaResult.errorCode = ret;
144 result.emplace_back(mediaResult);
145 }
146 return ret;
147 }
148
OnDownloadThmAndLcd(const std::vector<std::string> & bothVector,std::vector<MediaOperateResultDto> & result)149 int32_t CloudMediaDownloadService::OnDownloadThmAndLcd(
150 const std::vector<std::string> &bothVector, std::vector<MediaOperateResultDto> &result)
151 {
152 CHECK_AND_RETURN_RET_LOG(!bothVector.empty(), E_OK, "bothVector is empty");
153 MEDIA_INFO_LOG("size of bothVector is %{public}zu", bothVector.size());
154 int32_t ret = this->dao_.UpdateDownloadThmAndLcd(bothVector);
155 CHECK_AND_PRINT_LOG(ret == E_OK, "Failed to UpdateDownloadThmAndLcd.");
156 if (ret == E_OK && !bothVector.empty()) {
157 CloudMediaDfxService::UpdateAttachmentStat(INDEX_THUMB_SUCCESS, bothVector.size());
158 CloudMediaDfxService::UpdateAttachmentStat(INDEX_LCD_SUCCESS, bothVector.size());
159 }
160 for (auto &thm : bothVector) { // collect results
161 MediaOperateResultDto mediaResult;
162 mediaResult.cloudId = thm;
163 mediaResult.errorCode = ret;
164 result.emplace_back(mediaResult);
165 }
166 return ret;
167 }
168
NotifyDownloadLcd(const std::vector<std::string> & cloudIds)169 void CloudMediaDownloadService::NotifyDownloadLcd(const std::vector<std::string> &cloudIds)
170 {
171 std::vector<std::string> fileIds;
172 this->dao_.GetFileIdFromCloudId(cloudIds, fileIds);
173 MEDIA_INFO_LOG("size of fileIds is %{public}zu", fileIds.size());
174 for (auto &fileId : fileIds) {
175 std::string uri = PhotoColumn::PHOTO_CLOUD_URI_PREFIX + fileId;
176 MediaGallerySyncNotify::GetInstance().TryNotify(uri, ChangeType::INSERT, "");
177 }
178 MediaGallerySyncNotify::GetInstance().FinalNotify();
179 }
180
IsCloudInsertTaskPriorityHigh()181 bool CloudMediaDownloadService::IsCloudInsertTaskPriorityHigh()
182 {
183 int32_t cloudSyncStatus = static_cast<int32_t>(system::GetParameter(CLOUDSYNC_STATUS_KEY, "0").at(0) - '0');
184 MEDIA_INFO_LOG("cloudSyncStatus: %{public}d", cloudSyncStatus);
185 return cloudSyncStatus == CloudSyncStatus::FIRST_FIVE_HUNDRED ||
186 cloudSyncStatus == CloudSyncStatus::INCREMENT_DOWNLOAD;
187 }
188
OnDownloadThms(const std::unordered_map<std::string,int32_t> & downloadThumbnailMap,std::vector<MediaOperateResultDto> & result)189 int32_t CloudMediaDownloadService::OnDownloadThms(
190 const std::unordered_map<std::string, int32_t> &downloadThumbnailMap, std::vector<MediaOperateResultDto> &result)
191 {
192 MEDIA_INFO_LOG("enter CloudMediaDownloadService::OnDownloadThms");
193 std::vector<std::string> thmVector;
194 std::vector<std::string> lcdVector;
195 std::vector<std::string> bothVector;
196 std::vector<std::string> astcVector;
197 MEDIA_INFO_LOG("size of downloadThumbnailMap is %{public}zu", downloadThumbnailMap.size());
198 for (auto &pair : downloadThumbnailMap) {
199 //(key,value) => key : cloudId, value : 001-> thm, 010 -> lcd, 011 -> thm and lcd, 100 -> astc(端云不会下载astc)
200 if (pair.second == TYPE_THM) {
201 thmVector.emplace_back(pair.first);
202 } else if (pair.second == TYPE_LCD) {
203 lcdVector.emplace_back(pair.first);
204 } else if (pair.second == TYPE_THM_AND_LCD) {
205 bothVector.emplace_back(pair.first);
206 }
207 }
208
209 int32_t ret = E_ERR;
210 ret = this->OnDownloadThm(thmVector, result);
211 ret = this->OnDownloadLcd(lcdVector, result);
212 if (ret == E_OK) {
213 astcVector.insert(astcVector.end(), lcdVector.begin(), lcdVector.end());
214 }
215 ret = this->OnDownloadThmAndLcd(bothVector, result);
216 if (ret == E_OK) {
217 astcVector.insert(astcVector.end(), bothVector.begin(), bothVector.end());
218 }
219 MEDIA_INFO_LOG("size of astcVector is %{public}zu", astcVector.size());
220 this->NotifyDownloadLcd(astcVector);
221 return E_OK;
222 }
223
GetDownloadAsset(const std::vector<int32_t> & fileIds)224 std::vector<PhotosDto> CloudMediaDownloadService::GetDownloadAsset(const std::vector<int32_t> &fileIds)
225 {
226 MEDIA_INFO_LOG("enter CloudMediaDownloadService::GetDownloadAsset");
227 std::vector<PhotosDto> photosDtoVec;
228 std::vector<PhotosPo> photosPos;
229 int32_t ret = this->dao_.GetDownloadAsset(fileIds, photosPos);
230 CHECK_AND_RETURN_RET_LOG(ret == E_OK, photosDtoVec, "GetDownloadAsset failed, ret:%{public}d", ret);
231 std::vector<DownloadAssetData> downloadAssetDataVec;
232 this->processor_.GetDownloadAssetData(photosPos, downloadAssetDataVec);
233 MEDIA_INFO_LOG("GetDownloadAsset size of downloadAssetDataVec: %{public}zu", downloadAssetDataVec.size());
234 CHECK_AND_RETURN_RET_LOG(
235 !downloadAssetDataVec.empty(), photosDtoVec, "GetDownloadAsset Failed to get downloadAssetDataVec.");
236 for (const auto &downloadAssetData : downloadAssetDataVec) {
237 std::string filePath;
238 std::string fileName;
239 CHECK_AND_RETURN_RET_LOG(
240 CloudMediaFileUtils::GetParentPathAndFilename(downloadAssetData.path, filePath, fileName),
241 photosDtoVec,
242 "GetDownloadAsset failed to GetParentPathAndFilename");
243 PhotosDto photosDto;
244 photosDto.fileId = downloadAssetData.fileId;
245 photosDto.cloudId = downloadAssetData.cloudId;
246 photosDto.data = filePath;
247 photosDto.mediaType = downloadAssetData.mediaType;
248 photosDto.size = downloadAssetData.fileSize;
249 photosDto.path = downloadAssetData.path;
250 photosDto.modifiedTime = downloadAssetData.editTime;
251 photosDto.fileName = fileName;
252 photosDto.originalCloudId = downloadAssetData.originalCloudId;
253
254 CHECK_AND_RETURN_RET_LOG(
255 CloudMediaAttachmentUtils::GetAttachment("content", downloadAssetData, photosDto) == E_OK,
256 photosDtoVec,
257 "failed to GetAttachment");
258 MEDIA_DEBUG_LOG("GetDownloadAsset Photo: %{public}s", photosDto.ToString().c_str());
259
260 photosDtoVec.push_back(photosDto);
261 }
262 return photosDtoVec;
263 }
264
GetOnDownloadAssetData(PhotosPo & photosPo)265 OnDownloadAssetData CloudMediaDownloadService::GetOnDownloadAssetData(PhotosPo &photosPo)
266 {
267 OnDownloadAssetData assetData;
268 assetData.err = E_OK;
269 assetData.errorMsg = "";
270 bool isMovingPhoto = CloudMediaSyncUtils::IsMovingPhoto(photosPo);
271 bool isGraffiti = CloudMediaSyncUtils::IsGraffiti(photosPo);
272 bool isLivePhoto = CloudMediaSyncUtils::IsLivePhoto(photosPo);
273 bool isInvalidCover = photosPo.coverPosition.value_or(0) == 0 && photosPo.isRectificationCover.value_or(0) == 0;
274 MEDIA_INFO_LOG("GetOnDownloadAssetData %{public}d,%{public}d,%{public}d", isMovingPhoto, isGraffiti, isLivePhoto);
275 assetData.fixFileType = isMovingPhoto && !isGraffiti && !isLivePhoto;
276 assetData.needSliceContent = (isMovingPhoto && !isGraffiti) && isLivePhoto;
277 assetData.needParseCover = isMovingPhoto && isInvalidCover;
278 assetData.needSliceRaw = isMovingPhoto;
279 assetData.path = photosPo.data.value_or("");
280 assetData.localPath = CloudMediaSyncUtils::GetLocalPath(assetData.path);
281 assetData.dateModified = photosPo.dateModified.value_or(0);
282 std::string extraUri = MediaFileUtils::GetExtraUri(photosPo.displayName.value_or(""), photosPo.data.value_or(""));
283 assetData.fileUri = MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX,
284 std::to_string(photosPo.fileId.value_or(0)), extraUri);
285 assetData.needScanShootingMode = (photosPo.shootingModeTag.has_value() && photosPo.shootingModeTag->empty()) ||
286 (photosPo.frontCamera.has_value() && photosPo.frontCamera->empty());
287 assetData.mediaType = photosPo.mediaType.value_or(0);
288 assetData.exifRotate = CloudMediaSyncUtils::GetExifRotate(assetData.mediaType, assetData.localPath);
289 return assetData;
290 }
291
UnlinkAsset(OnDownloadAssetData & assetData)292 void CloudMediaDownloadService::UnlinkAsset(OnDownloadAssetData &assetData)
293 {
294 int32_t ret = unlink(assetData.localPath.c_str());
295 CHECK_AND_RETURN_LOG(
296 ret != E_OK, "unlink %{public}s succeeded", MediaFileUtils::DesensitizePath(assetData.localPath).c_str());
297 assetData.err = errno; // err always -1, use errno.
298 assetData.errorMsg = "unlink failed";
299 MEDIA_WARN_LOG("unlink %{public}s failed", MediaFileUtils::DesensitizePath(assetData.localPath).c_str());
300 }
301
ResetAssetModifyTime(OnDownloadAssetData & assetData)302 void CloudMediaDownloadService::ResetAssetModifyTime(OnDownloadAssetData &assetData)
303 {
304 int32_t ret = access(assetData.localPath.c_str(), F_OK); // 0 mean file exist.
305 CHECK_AND_RETURN_LOG(
306 ret == E_OK, "file not exist %{public}s", MediaFileUtils::DesensitizePath(assetData.localPath).c_str());
307 int32_t err = CloudMediaSyncUtils::UpdateModifyTime(assetData.localPath, assetData.dateModified);
308 CHECK_AND_RETURN_INFO_LOG(err != E_OK,
309 "UpdateModifyTime %{public}s succeeded",
310 MediaFileUtils::DesensitizePath(assetData.localPath).c_str());
311 assetData.err = err;
312 assetData.errorMsg = "Update ModifyTime failed";
313 MEDIA_WARN_LOG("DownloadAsset UpdateModifyTime %{public}s failed",
314 MediaFileUtils::DesensitizePath(assetData.localPath).c_str());
315 }
316
SliceAssetFile(const std::string & originalFile,const std::string & path,const std::string & videoPath,const std::string & extraDataPath)317 int32_t CloudMediaDownloadService::SliceAssetFile(const std::string &originalFile, const std::string &path,
318 const std::string &videoPath, const std::string &extraDataPath)
319 {
320 MEDIA_INFO_LOG("SliceAssetFile");
321 if (access(originalFile.c_str(), F_OK) != F_OK) {
322 MEDIA_ERR_LOG("SliceAssetFile Not exist %{public}s", originalFile.c_str());
323 return E_PATH;
324 }
325 std::string temp = originalFile + ".slicetemp";
326 if (rename(originalFile.c_str(), temp.c_str()) == 0) {
327 MEDIA_INFO_LOG("SliceAssetFile originalFile:%{public}s, path:%{public}s, videoPath:%{public}s, "
328 "extraDataPath:%{public}s, temp:%{public}s",
329 originalFile.c_str(),
330 path.c_str(),
331 videoPath.c_str(),
332 extraDataPath.c_str(),
333 temp.c_str());
334 if (MovingPhotoFileUtils::ConvertToMovingPhoto(temp, path, videoPath, extraDataPath) != 0) {
335 MEDIA_INFO_LOG("SliceAssetFile convert to moving photo fail %{public}s", originalFile.c_str());
336 if (unlink(temp.c_str()) != 0) {
337 MEDIA_WARN_LOG("SliceAssetFile convert failed delete temp");
338 }
339 return E_PATH;
340 }
341 if (unlink(temp.c_str()) != 0) {
342 MEDIA_WARN_LOG("SliceAssetFile convert success delete temp");
343 }
344 } else {
345 MEDIA_ERR_LOG("SliceAssetFile rename failed path:%{public}s, to temp:%{public}s", path.c_str(), temp.c_str());
346 return E_PATH;
347 }
348 return E_OK;
349 }
350
SliceAsset(const OnDownloadAssetData & assetData,const PhotosPo & photo)351 int32_t CloudMediaDownloadService::SliceAsset(const OnDownloadAssetData &assetData, const PhotosPo &photo)
352 {
353 if (assetData.needSliceRaw) {
354 std::string rawFilePath = PhotoFileUtils::GetEditDataSourcePath(assetData.path);
355 bool isLivePhoto = MovingPhotoFileUtils::IsLivePhoto(rawFilePath);
356 if (isLivePhoto) {
357 std::string sourceImage = CloudMediaSyncUtils::GetSourceMovingPhotoImagePath(assetData.path);
358 std::string sourceVideo = CloudMediaSyncUtils::GetSourceMovingPhotoVideoPath(assetData.path);
359 int32_t ret = SliceAssetFile(rawFilePath, sourceImage, sourceVideo, "");
360 CHECK_AND_PRINT_LOG(ret == E_OK,
361 "SliceRawFile Failed. rawFilePath: %{public}s, sourceImage: %{public}s, sourceVideo: %{public}s",
362 rawFilePath.c_str(), sourceImage.c_str(), sourceVideo.c_str());
363 } else {
364 MEDIA_WARN_LOG("OnDownloadAsset need slice raw, but file is not live photo");
365 }
366 }
367 if (assetData.needSliceContent) {
368 bool isGraffiti = CloudMediaSyncUtils::IsGraffiti(photo);
369 std::string videoPath = CloudMediaSyncUtils::GetMovingPhotoVideoPath(assetData.path);
370 std::string extraDir = CloudMediaSyncUtils::GetMovingPhotoExtraDataDir(assetData.path);
371 std::string extraDataPath = isGraffiti ? "" : CloudMediaSyncUtils::GetMovingPhotoExtraDataPath(assetData.path);
372 if (!ForceCreateDirectory(extraDir)) {
373 MEDIA_ERR_LOG("HandleAssetFile %{public}s error %{public}d", extraDir.c_str(), errno);
374 return E_PATH;
375 }
376 int32_t ret = SliceAssetFile(assetData.localPath, assetData.localPath, videoPath, extraDataPath);
377 if (ret == E_OK && assetData.needParseCover) {
378 MEDIA_DEBUG_LOG("cover position is invalid, parse cover position from file");
379 CoverPositionParser::GetInstance().AddTask(assetData.path, assetData.fileUri);
380 }
381 return ret;
382 }
383 MEDIA_INFO_LOG("SliceAsset, assetData: %{public}s", assetData.ToString().c_str());
384 return E_OK;
385 }
386
OnDownloadAsset(const std::vector<std::string> & cloudIds,std::vector<MediaOperateResultDto> & result)387 int32_t CloudMediaDownloadService::OnDownloadAsset(
388 const std::vector<std::string> &cloudIds, std::vector<MediaOperateResultDto> &result)
389 {
390 MEDIA_INFO_LOG("enter CloudMediaDownloadService::OnDownloadAsset, %{public}zu", cloudIds.size());
391 // get downloadAssetDataVec
392 std::vector<PhotosPo> photosPoVec;
393 int32_t ret = this->dao_.QueryDownloadAssetByCloudIds(cloudIds, photosPoVec);
394 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "QueryDownloadAssetByCloudIds failed, ret:%{public}d", ret);
395 // Requirement: If any asset is not in the database, return error. Caller should check the result.
396 CHECK_AND_RETURN_RET_LOG(photosPoVec.size() == cloudIds.size(),
397 E_CLOUDSYNC_INVAL_ARG,
398 "QueryDownloadAssetByCloudIds failed, cloudIds size:%{public}zu, photosPoVec size:%{public}zu",
399 cloudIds.size(),
400 photosPoVec.size());
401 // Update
402 OnDownloadAssetData assetData;
403 for (auto &photosPo : photosPoVec) {
404 assetData = this->GetOnDownloadAssetData(photosPo);
405 MEDIA_DEBUG_LOG(
406 "OnDownloadAsset %{public}s, %{public}s", photosPo.ToString().c_str(), assetData.ToString().c_str());
407 HandlePhoto(photosPo, assetData);
408 // record result
409 MediaOperateResultDto mediaResult;
410 mediaResult.cloudId = photosPo.cloudId.value_or("");
411 mediaResult.errorCode = assetData.err;
412 mediaResult.errorMsg = assetData.errorMsg;
413 result.emplace_back(mediaResult);
414 }
415 return E_OK;
416 }
417
HandlePhoto(const ORM::PhotosPo & photo,OnDownloadAssetData & assetData)418 void CloudMediaDownloadService::HandlePhoto(const ORM::PhotosPo &photo, OnDownloadAssetData &assetData)
419 {
420 int32_t ret = SliceAsset(assetData, photo);
421 if (ret != E_OK) {
422 MEDIA_INFO_LOG(
423 "HandlePhoto Failed to Slice %{public}s", MediaFileUtils::DesensitizePath(assetData.localPath).c_str());
424 assetData.errorMsg = "Slice Moving File Failed";
425 assetData.err = ret;
426 return;
427 }
428 CloudMediaScanService::ScanResult scanResult;
429 if (assetData.needScanShootingMode) {
430 CloudMediaScanService().ScanShootingMode(assetData.path, scanResult);
431 }
432 ret = this->dao_.UpdateDownloadAsset(assetData.fixFileType, assetData.path, scanResult);
433 if (scanResult.scanSuccess) {
434 CloudMediaScanService().UpdateAndNotifyShootingModeAlbumIfNeeded(scanResult);
435 }
436
437 if (ret != E_OK) {
438 MEDIA_INFO_LOG(
439 "Failed to Handle HandlePhoto %{public}s", MediaFileUtils::DesensitizePath(assetData.localPath).c_str());
440 assetData.errorMsg = "UpdateDownloadAsset failed";
441 assetData.err = ret;
442 this->UnlinkAsset(assetData);
443 return;
444 } else if (assetData.dateModified > 0 && (assetData.needSliceContent || assetData.needSliceRaw)) {
445 this->ResetAssetModifyTime(assetData);
446 }
447
448 ret = FixDownloadAssetExifRotate(photo, assetData);
449 if (ret != E_OK) {
450 MEDIA_INFO_LOG("HandlePhoto Failed to fix exif rotate %{public}s",
451 MediaFileUtils::DesensitizePath(assetData.localPath).c_str());
452 assetData.errorMsg = "Fix Exif Rotate Failed";
453 assetData.err = ret;
454 return;
455 }
456 }
457
FixDownloadAssetExifRotate(const ORM::PhotosPo & photo,OnDownloadAssetData & assetData)458 int32_t CloudMediaDownloadService::FixDownloadAssetExifRotate(
459 const ORM::PhotosPo &photo, OnDownloadAssetData &assetData)
460 {
461 CHECK_AND_RETURN_RET(assetData.exifRotate != photo.exifRotate.value_or(0), E_OK);
462
463 int32_t oldExifRotate = photo.exifRotate.value_or(0);
464 int32_t newExifRotate = assetData.exifRotate;
465 int32_t fileId = photo.fileId.value_or(0);
466 string fileIdStr = std::to_string(fileId);
467 string dateTaken = std::to_string(photo.dateTaken.value_or(0));
468 string path = assetData.path;
469 MEDIA_INFO_LOG("Need FixDownloadAssetExifRotate, id:%{public}d, mediaType:%{public}d, oldExifRotate:%{public}d, "
470 "newExifRotate:%{public}d", fileId, assetData.mediaType, oldExifRotate, newExifRotate);
471 if (CloudMediaSyncUtils::CanUpdateExifRotateOnly(assetData.mediaType, oldExifRotate, newExifRotate)) {
472 return this->dao_.UpdateDownloadAssetExifRotateFix(
473 fileId, assetData.exifRotate, DirtyTypes::TYPE_MDIRTY, false);
474 }
475
476 DirtyTypes dirtyType;
477 if (assetData.mediaType == static_cast<int32_t>(MediaType::MEDIA_TYPE_IMAGE)) {
478 dirtyType = DirtyTypes::TYPE_MDIRTY;
479 } else {
480 dirtyType = DirtyTypes::TYPE_FDIRTY;
481 }
482 int32_t ret = this->dao_.UpdateDownloadAssetExifRotateFix(fileId, assetData.exifRotate, dirtyType, true);
483 CHECK_AND_RETURN_RET(ret == E_OK, ret);
484
485 auto thumbnailService = ThumbnailService::GetInstance();
486 thumbnailService->DeleteThumbnailDirAndAstc(fileIdStr, PhotoColumn::PHOTOS_TABLE, path, dateTaken);
487 return thumbnailService->FixThumbnailExifRotateAfterDownloadAsset(fileIdStr);
488 }
489 } // namespace OHOS::Media::CloudSync