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_Dao"
17
18 #include "cloud_media_download_dao.h"
19
20 #include <string>
21 #include <utime.h>
22 #include <vector>
23
24 #include "medialibrary_unistore_manager.h"
25 #include "result_set_reader.h"
26 #include "photos_po_writer.h"
27 #include "media_column.h"
28 #include "cloud_media_operation_code.h"
29 #include "cloud_media_dao_utils.h"
30 #include "cloud_media_sync_utils.h"
31 #include "moving_photo_file_utils.h"
32 #include "accurate_common_data.h"
33 #include "asset_accurate_refresh.h"
34 #include "album_accurate_refresh.h"
35
36 namespace OHOS::Media::CloudSync {
GetDownloadThmsConditions(const int32_t type)37 NativeRdb::AbsRdbPredicates CloudMediaDownloadDao::GetDownloadThmsConditions(const int32_t type)
38 {
39 NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(PhotoColumn::PHOTOS_TABLE);
40 predicates.EqualTo(PhotoColumn::PHOTO_SYNC_STATUS, static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE));
41 predicates.EqualTo(PhotoColumn::PHOTO_CLEAN_FLAG, static_cast<int32_t>(CleanType::TYPE_NOT_CLEAN));
42 predicates.NotEqualTo(PhotoColumn::PHOTO_POSITION, static_cast<int32_t>(CloudFilePosition::POSITION_LOCAL))
43 ->And()
44 ->BeginWrap();
45 ThmLcdState state;
46 if (type != static_cast<int32_t>(ThmLcdState::THM) && type != static_cast<int32_t>(ThmLcdState::THMLCD) &&
47 type != static_cast<int32_t>(ThmLcdState::LCD)) {
48 state = ThmLcdState::THMLCD;
49 } else {
50 state = static_cast<ThmLcdState>(type);
51 }
52 predicates.EqualTo(PhotoColumn::PHOTO_THUMB_STATUS, static_cast<int32_t>(ThumbState::TO_DOWNLOAD));
53 predicates.Or()->EqualTo(PhotoColumn::PHOTO_THUMB_STATUS, static_cast<int32_t>(ThumbState::THM_TO_DOWNLOAD));
54 if (state == ThmLcdState::LCD || state == ThmLcdState::THMLCD) {
55 predicates.Or()->EqualTo(PhotoColumn::PHOTO_THUMB_STATUS, static_cast<int32_t>(ThumbState::LCD_TO_DOWNLOAD));
56 }
57 predicates.EndWrap();
58 return predicates;
59 }
60
GetDownloadThmNum(const int32_t type,int32_t & totalNum)61 int32_t CloudMediaDownloadDao::GetDownloadThmNum(const int32_t type, int32_t &totalNum)
62 {
63 MEDIA_INFO_LOG("GetDownloadThmNum begin %{public}d", type);
64 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
65 CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_RDB_STORE_NULL, "Query Thumbs to Download Failed to get rdbStore.");
66 NativeRdb::AbsRdbPredicates predicates = this->GetDownloadThmsConditions(type);
67 std::shared_ptr<NativeRdb::ResultSet> resultSet = rdbStore->Query(predicates, {"COUNT(1) AS count"});
68 if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
69 MEDIA_ERR_LOG("get nullptr Query Thumbs to Download");
70 return E_RDB;
71 }
72 totalNum = GetInt32Val("count", resultSet);
73 resultSet->Close();
74 MEDIA_INFO_LOG("QueryThumbsToDownload end %{public}d", totalNum);
75 return E_OK;
76 }
77
GetDownloadThms(const DownloadThumbnailQueryDto & queryDto,std::vector<PhotosPo> & photos)78 int32_t CloudMediaDownloadDao::GetDownloadThms(const DownloadThumbnailQueryDto &queryDto, std::vector<PhotosPo> &photos)
79 {
80 MEDIA_INFO_LOG("QueryThumbsToDownload begin %{public}s", queryDto.ToString().c_str());
81 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
82 CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "Query Thumbs to Download Failed to get rdbStore.");
83 NativeRdb::AbsRdbPredicates predicates = this->GetDownloadThmsConditions(queryDto.type);
84 if (queryDto.isDownloadDisplayFirst) {
85 predicates.EqualTo(MediaColumn::MEDIA_DATE_TRASHED, 0); // NOT_IN_TRASH
86 predicates.EqualTo(MediaColumn::MEDIA_TIME_PENDING, 0); // NOT_IN_PENDING
87 predicates.EqualTo(MediaColumn::MEDIA_HIDDEN, 0); // NOT_HIDDEN
88 predicates.EqualTo(PhotoColumn::PHOTO_IS_TEMP, 0); // NOT_TEMP_FILE
89 predicates.EqualTo(PhotoColumn::PHOTO_BURST_COVER_LEVEL, 1); // IS_BURST_COVER
90 }
91 predicates.Limit(queryDto.offset, queryDto.size);
92 predicates.OrderByDesc(PhotoColumn::MEDIA_DATE_TAKEN);
93
94 std::shared_ptr<NativeRdb::ResultSet> resultSet = rdbStore->Query(predicates, this->DOWNLOAD_THUMBNAIL_COLUMNS);
95 int32_t ret = ResultSetReader<PhotosPoWriter, PhotosPo>(resultSet).ReadRecords(photos);
96 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "Query Thumbs to Download Failed to read records, ret: %{public}d", ret);
97 MEDIA_INFO_LOG("GetDownloadThms, photos size: %{public}zu", photos.size());
98 return E_OK;
99 }
100
GetDownloadAsset(const std::vector<int32_t> & fileIds,std::vector<PhotosPo> & photos)101 int32_t CloudMediaDownloadDao::GetDownloadAsset(const std::vector<int32_t> &fileIds, std::vector<PhotosPo> &photos)
102 {
103 MEDIA_INFO_LOG("enter GetDownloadAsset");
104 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
105 CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "GetDownloadAsset Failed to get rdbStore.");
106 NativeRdb::AbsRdbPredicates queryPredicates = NativeRdb::AbsRdbPredicates(PhotoColumn::PHOTOS_TABLE);
107 queryPredicates.In(PhotoColumn::MEDIA_ID, CloudMediaDaoUtils::GetStringVector(fileIds))
108 ->And()
109 ->EqualTo(PhotoColumn::PHOTO_SYNC_STATUS, static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE))
110 ->And()
111 ->EqualTo(PhotoColumn::PHOTO_CLEAN_FLAG, static_cast<int32_t>(CleanType::TYPE_NOT_CLEAN));
112 auto resultSet = rdbStore->Query(queryPredicates, this->COLUMNS_DOWNLOAD_ASSET_QUERY_BY_FILE_ID);
113 int32_t ret = ResultSetReader<PhotosPoWriter, PhotosPo>(resultSet).ReadRecords(photos);
114 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "GetDownloadAsset Failed to query, ret: %{public}d", ret);
115 return ret;
116 }
117
UpdateDownloadThm(const std::vector<std::string> & cloudIds)118 int32_t CloudMediaDownloadDao::UpdateDownloadThm(const std::vector<std::string> &cloudIds)
119 {
120 MEDIA_INFO_LOG("enter UpdateDownloadThm");
121 CHECK_AND_RETURN_RET_LOG(!cloudIds.empty(), E_OK, "UpdateDownloadThm cloudIds is empty.");
122 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
123 CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_RDB_STORE_NULL, "Failed to get rdbStore.");
124 CHECK_AND_PRINT_LOG(cloudIds.size() <= BATCH_LIMIT_SIZE,
125 "UpdateDownloadThm cloudIds size: %{public}zu, limit: %{public}d",
126 cloudIds.size(),
127 BATCH_LIMIT_SIZE);
128 std::string sql = "\
129 UPDATE Photos \
130 SET sync_status = 0, \
131 thumb_status = thumb_status & ? \
132 WHERE cloud_id IN ({0});";
133 std::vector<std::string> params = {CloudMediaDaoUtils::ToStringWithCommaAndQuote(cloudIds)};
134 std::string execSql = CloudMediaDaoUtils::FillParams(sql, params);
135 std::vector<NativeRdb::ValueObject> bindArgs = {static_cast<int32_t>(~THM_TO_DOWNLOAD_MASK)};
136 int32_t ret = rdbStore->ExecuteSql(execSql, bindArgs);
137 CHECK_AND_RETURN_RET_LOG(ret == E_OK, E_ERR, "Failed to UpdateDownloadThm.");
138 return ret;
139 }
140
UpdateDownloadLcd(const std::vector<std::string> & cloudIds)141 int32_t CloudMediaDownloadDao::UpdateDownloadLcd(const std::vector<std::string> &cloudIds)
142 {
143 MEDIA_INFO_LOG("enter UpdateDownloadLcd");
144 CHECK_AND_RETURN_RET_LOG(!cloudIds.empty(), E_OK, "UpdateDownloadLcd cloudIds is empty.");
145 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
146 CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_RDB_STORE_NULL, "Failed to get rdbStore.");
147 CHECK_AND_PRINT_LOG(cloudIds.size() <= BATCH_LIMIT_SIZE,
148 "UpdateDownloadLcd cloudIds size: %{public}zu, limit: %{public}d",
149 cloudIds.size(),
150 BATCH_LIMIT_SIZE);
151 std::string sql = "\
152 UPDATE Photos \
153 SET thumb_status = thumb_status & ? \
154 WHERE cloud_id IN ({0});";
155 std::vector<std::string> params = {CloudMediaDaoUtils::ToStringWithCommaAndQuote(cloudIds)};
156 std::string execSql = CloudMediaDaoUtils::FillParams(sql, params);
157 std::vector<NativeRdb::ValueObject> bindArgs = {static_cast<int32_t>(~LCD_TO_DOWNLOAD_MASK)};
158 int32_t ret = rdbStore->ExecuteSql(execSql, bindArgs);
159 CHECK_AND_RETURN_RET_LOG(ret == E_OK, E_ERR, "Failed to UpdateDownloadLcd.");
160 return ret;
161 }
162
UpdateDownloadThmAndLcd(const std::vector<std::string> & cloudIds)163 int32_t CloudMediaDownloadDao::UpdateDownloadThmAndLcd(const std::vector<std::string> &cloudIds)
164 {
165 MEDIA_INFO_LOG("enter UpdateDownloadThmAndLcd");
166 CHECK_AND_RETURN_RET_LOG(!cloudIds.empty(), E_OK, "UpdateDownloadThmAndLcd cloudIds is empty.");
167 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
168 CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_RDB_STORE_NULL, "Failed to get rdbStore.");
169 NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(PhotoColumn::PHOTOS_TABLE);
170 predicates.In(PhotoColumn::PHOTO_CLOUD_ID, cloudIds);
171 NativeRdb::ValuesBucket values;
172 values.PutInt(PhotoColumn::PHOTO_SYNC_STATUS, static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE));
173 values.PutInt(PhotoColumn::PHOTO_THUMB_STATUS, static_cast<int32_t>(ThumbState::DOWNLOADED));
174 int32_t changedRows = DEFAULT_VALUE;
175 int32_t ret = rdbStore->Update(changedRows, values, predicates);
176 CHECK_AND_RETURN_RET_LOG(ret == E_OK, E_ERR, "Failed to UpdateDownloadThmAndLcd.");
177 CHECK_AND_PRINT_LOG(changedRows > 0, "Check updateRows: %{public}d.", changedRows);
178 MEDIA_INFO_LOG("UpdateDownloadThmAndLcd, changedRows: %{public}d.", changedRows);
179 return ret;
180 }
181
GetFileIdFromCloudId(const std::vector<std::string> & cloudIds,std::vector<std::string> & fileIds)182 int32_t CloudMediaDownloadDao::GetFileIdFromCloudId(
183 const std::vector<std::string> &cloudIds, std::vector<std::string> &fileIds)
184 {
185 MEDIA_INFO_LOG("enter GetFileIdFromCloudId, cloudIds size: %{public}zu", cloudIds.size());
186 CHECK_AND_RETURN_RET_LOG(cloudIds.size() > 0, E_OK, "GetFileIdFromCloudId cloudIds is empty.");
187 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
188 CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_RDB_STORE_NULL, "Failed to get rdbStore.");
189 NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(PhotoColumn::PHOTOS_TABLE);
190 predicates.In(PhotoColumn::PHOTO_CLOUD_ID, cloudIds);
191 std::vector<std::string> columns = {MediaColumn::MEDIA_ID};
192 auto resultSet = rdbStore->Query(predicates, columns);
193 std::vector<PhotosPo> photos;
194 int32_t ret = ResultSetReader<PhotosPoWriter, PhotosPo>(resultSet).ReadRecords(photos);
195 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "GetFileIdFromCloudId Failed to query, ret: %{public}d", ret);
196 for (auto photo : photos) {
197 if (!photo.fileId.has_value()) {
198 continue;
199 }
200 fileIds.emplace_back(std::to_string(photo.fileId.value_or(0)));
201 }
202 return ret;
203 }
204
QueryDownloadAssetByCloudIds(const std::vector<std::string> & cloudIds,std::vector<PhotosPo> & result)205 int32_t CloudMediaDownloadDao::QueryDownloadAssetByCloudIds(
206 const std::vector<std::string> &cloudIds, std::vector<PhotosPo> &result)
207 {
208 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
209 CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_RDB_STORE_NULL, "Failed to get rdbStore.");
210 NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(PhotoColumn::PHOTOS_TABLE);
211 predicates.In(PhotoColumn::PHOTO_CLOUD_ID, cloudIds);
212 predicates.NotEqualTo(PhotoColumn::PHOTO_DIRTY, static_cast<int32_t>(DirtyType::TYPE_DELETED));
213 auto resultSet = rdbStore->Query(predicates, this->COLUMNS_DOWNLOAD_ASSET_QUERY_BY_CLOUD_ID);
214 int32_t ret = ResultSetReader<PhotosPoWriter, PhotosPo>(resultSet).ReadRecords(result);
215 CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "Failed to query, ret: %{public}d", ret);
216 MEDIA_INFO_LOG("QueryDownloadAssetByCloudId, rowCount: %{public}d", static_cast<int32_t>(result.size()));
217 return E_OK;
218 }
219
UpdateDownloadAsset(const bool fixFileType,const std::string & path,const CloudMediaScanService::ScanResult & scanResult)220 int32_t CloudMediaDownloadDao::UpdateDownloadAsset(const bool fixFileType, const std::string &path,
221 const CloudMediaScanService::ScanResult& scanResult)
222 {
223 MEDIA_INFO_LOG("enter UpdateDownloadAsset %{public}d, %{public}s",
224 fixFileType, path.c_str());
225 std::shared_ptr<AccurateRefresh::AssetAccurateRefresh> photoRefresh =
226 std::make_shared<AccurateRefresh::AssetAccurateRefresh>();
227 CHECK_AND_RETURN_RET_LOG(photoRefresh != nullptr, E_RDB_STORE_NULL, "UpdateDownloadAsset Failed to get rdbStore.");
228 NativeRdb::AbsRdbPredicates predicates = NativeRdb::AbsRdbPredicates(PhotoColumn::PHOTOS_TABLE);
229 predicates.EqualTo(MediaColumn::MEDIA_FILE_PATH, path);
230 NativeRdb::ValuesBucket values;
231 values.PutInt(PhotoColumn::PHOTO_POSITION, static_cast<int32_t>(PhotoPositionType::LOCAL_AND_CLOUD));
232 if (fixFileType) {
233 MEDIA_INFO_LOG("UpdateDownloadAsset file is not real moving photo, need fix subtype");
234 values.PutInt(PhotoColumn::PHOTO_SUBTYPE, static_cast<int32_t>(PhotoSubType::DEFAULT));
235 }
236 if (scanResult.scanSuccess) {
237 values.PutString(PhotoColumn::PHOTO_SHOOTING_MODE, scanResult.shootingMode);
238 values.PutString(PhotoColumn::PHOTO_SHOOTING_MODE_TAG, scanResult.shootingModeTag);
239 values.PutString(PhotoColumn::PHOTO_FRONT_CAMERA, scanResult.frontCamera);
240 }
241 int32_t changedRows = -1;
242 int32_t ret = photoRefresh->Update(changedRows, values, predicates);
243 CHECK_AND_RETURN_RET_LOG(ret == AccurateRefresh::ACCURATE_REFRESH_RET_OK,
244 E_ERR,
245 "UpdateDownloadAsset Failed to Update, ret: %{public}d.",
246 ret);
247 CHECK_AND_PRINT_LOG(changedRows > 0, "UpdateDownloadAsset changedRows: %{public}d.", changedRows);
248 photoRefresh->RefreshAlbumNoDateModified(static_cast<NotifyAlbumType>(NotifyAlbumType::SYS_ALBUM |
249 NotifyAlbumType::USER_ALBUM | NotifyAlbumType::SOURCE_ALBUM));
250 photoRefresh->Notify();
251 return ret;
252 }
253
UpdateDownloadAssetExifRotateFix(const int32_t fileId,const int32_t exifRotate,const DirtyTypes dirtyType,bool needRegenerateThumbnail)254 int32_t CloudMediaDownloadDao::UpdateDownloadAssetExifRotateFix(const int32_t fileId,
255 const int32_t exifRotate, const DirtyTypes dirtyType, bool needRegenerateThumbnail)
256 {
257 CHECK_AND_RETURN_RET_LOG(dirtyType == DirtyTypes::TYPE_MDIRTY || dirtyType == DirtyTypes::TYPE_FDIRTY,
258 E_ERR, "Not support update this dirtype:%{public}d", dirtyType);
259 std::shared_ptr<AccurateRefresh::AssetAccurateRefresh> photoRefresh =
260 std::make_shared<AccurateRefresh::AssetAccurateRefresh>();
261 CHECK_AND_RETURN_RET_LOG(photoRefresh != nullptr, E_RDB_STORE_NULL,
262 "UpdateDownloadAssetExifRotateFix Failed to get rdbStore.");
263
264 std::vector<NativeRdb::ValueObject> bindArgs = {
265 exifRotate, std::to_string(static_cast<int32_t>(dirtyType)), fileId,
266 };
267 int32_t ret = 0;
268 if (needRegenerateThumbnail) {
269 ret = photoRefresh->ExecuteSql(this->SQL_FIX_EXIF_ROTATE_WITH_REGENERATE_THUMBNAIL,
270 bindArgs, AccurateRefresh::RdbOperation::RDB_OPERATION_UPDATE);
271 } else {
272 ret = photoRefresh->ExecuteSql(this->SQL_FIX_EXIF_ROTATE_WITHOUT_REGENERATE_THUMBNAIL,
273 bindArgs, AccurateRefresh::RdbOperation::RDB_OPERATION_UPDATE);
274 }
275
276 CHECK_AND_RETURN_RET_LOG(ret == AccurateRefresh::ACCURATE_REFRESH_RET_OK,
277 E_ERR,
278 "UpdateDownloadAssetExifRotateFix Failed to Update, ret: %{public}d.",
279 ret);
280 photoRefresh->Notify();
281 return E_OK;
282 }
283 } // namespace OHOS::Media::CloudSync