• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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