1 /*
2 * Copyright (C) 2024 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 #include <regex>
16 #include <vector>
17
18 #include "photos_restore.h"
19 #include "backup_const.h"
20 #include "backup_file_utils.h"
21 #include "userfile_manager_types.h"
22 #include "rdb_store.h"
23 #include "result_set_utils.h"
24 #include "media_log.h"
25 #include "moving_photo_file_utils.h"
26 #include "photo_album_dao.h"
27 #include "album_plugin_config.h"
28 #include "backup_file_utils.h"
29 #include "mimetype_utils.h"
30
31 namespace OHOS::Media {
32 static const int32_t CLOUD_ENHANCEMENT_ALBUM = 1;
33 static const int32_t DUAL_ENHANCEMENT_PHOTO_QUALITY = 120;
34 static const int32_t SINGLE_CLOUD_ENHANCEMENT_PHOTO = 120;
35
36 /**
37 * @brief Get the gallery_media to restore to Photos.
38 */
GetGalleryMedia(int32_t minId,int pageSize,bool shouldIncludeSd,bool hasLowQualityImage)39 std::shared_ptr<NativeRdb::ResultSet> PhotosRestore::GetGalleryMedia(
40 int32_t minId, int pageSize, bool shouldIncludeSd, bool hasLowQualityImage)
41 {
42 return this->galleryMediaDao_.GetGalleryMedia(minId, pageSize, shouldIncludeSd, hasLowQualityImage);
43 }
44
45 /**
46 * @brief Get the gallery_media for cloud to restore to Photos.
47 */
GetCloudGalleryMedia(int32_t minId,int pageSize,bool shouldIncludeSd,bool hasLowQualityImage)48 std::shared_ptr<NativeRdb::ResultSet> PhotosRestore::GetCloudGalleryMedia(
49 int32_t minId, int pageSize, bool shouldIncludeSd, bool hasLowQualityImage)
50 {
51 return this->galleryMediaDao_.GetCloudGalleryMedia(minId, pageSize, shouldIncludeSd, hasLowQualityImage);
52 }
53
54 /**
55 * @brief Get the row count of gallery_media.
56 */
GetGalleryMediaCount(bool shouldIncludeSd,bool hasLowQualityImage)57 int32_t PhotosRestore::GetGalleryMediaCount(bool shouldIncludeSd, bool hasLowQualityImage)
58 {
59 return this->galleryMediaDao_.GetGalleryMediaCount(shouldIncludeSd, hasLowQualityImage);
60 }
61
62 /**
63 * @brief Get the row count of cloud_meta.
64 */
GetCloudMetaCount(bool shouldIncludeSd,bool hasLowQualityImage)65 int32_t PhotosRestore::GetCloudMetaCount(bool shouldIncludeSd, bool hasLowQualityImage)
66 {
67 return this->galleryMediaDao_.GetCloudMetaCount(shouldIncludeSd, hasLowQualityImage);
68 }
69
70 /**
71 * @brief Get the PhotoAlbum basic info.
72 */
FindAlbumInfo(const FileInfo & fileInfo)73 PhotoAlbumDao::PhotoAlbumRowData PhotosRestore::FindAlbumInfo(const FileInfo &fileInfo)
74 {
75 std::string lPath = fileInfo.lPath;
76 // Scenario 2, WHEN FileInfo is in hidden album, THEN override lPath to the folder in sourcePath.
77 // Scenario 3, WHEN FileInfo is not belongs to any album, THEN override lPath to the folder in sourcePath.
78 if (fileInfo.lPath.empty() || this->ToLower(fileInfo.lPath) == this->ToLower(GALLERT_HIDDEN_ALBUM)) {
79 lPath = this->photoAlbumDao_.ParseSourcePathToLPath(fileInfo.sourcePath);
80 MEDIA_INFO_LOG("Media_Restore: fix lPath of album.fileInfo.lPath: %{public}s, "
81 "lPathFromSourcePath: %{public}s, lowercase: %{public}s, FileInfo Object: %{public}s",
82 fileInfo.lPath.c_str(),
83 lPath.c_str(),
84 this->ToLower(lPath).c_str(),
85 this->ToString(fileInfo).c_str());
86 }
87 PhotoAlbumDao::PhotoAlbumRowData albumInfo;
88 // Scenario 1, WHEN FileInfo is in /Pictures/Screenshots and Video type, THEN redirect to /Pictures/Screenrecords
89 if (this->ToLower(lPath) == this->ToLower(AlbumPlugin::LPATH_SCREEN_SHOTS) &&
90 fileInfo.fileType == MediaType::MEDIA_TYPE_VIDEO) {
91 albumInfo = this->photoAlbumDao_.BuildAlbumInfoOfRecorders();
92 albumInfo = this->photoAlbumDao_.GetOrCreatePhotoAlbum(albumInfo);
93 MEDIA_INFO_LOG("Media_Restore: screenshots redirect to screenrecords, fileInfo.lPath: %{public}s, "
94 "lPathForScreenshot: %{public}s, Object: %{public}s, albumInfo: %{public}s",
95 fileInfo.lPath.c_str(),
96 lPath.c_str(),
97 this->ToString(fileInfo).c_str(),
98 this->photoAlbumDao_.ToString(albumInfo).c_str());
99 return albumInfo;
100 }
101 albumInfo = this->photoAlbumDao_.BuildAlbumInfoByLPath(lPath);
102 return this->photoAlbumDao_.GetOrCreatePhotoAlbum(albumInfo);
103 }
104
105 /**
106 * @brief Get the PhotoAlbum basic info.
107 */
FindAlbumId(const FileInfo & fileInfo)108 int32_t PhotosRestore::FindAlbumId(const FileInfo &fileInfo)
109 {
110 PhotoAlbumDao::PhotoAlbumRowData albumInfo = this->FindAlbumInfo(fileInfo);
111 CHECK_AND_PRINT_LOG(!albumInfo.lPath.empty(), "Can not find PhotoAlbum. fileInfo.lPath= %{public}s,"
112 " fileInfo.sourcePath= %{public}s", fileInfo.lPath.c_str(), fileInfo.sourcePath.c_str());
113 return albumInfo.albumId;
114 }
115
116 /**
117 * @brief find lPath by FileInfo.
118 */
FindlPath(const FileInfo & fileInfo)119 std::string PhotosRestore::FindlPath(const FileInfo &fileInfo)
120 {
121 PhotoAlbumDao::PhotoAlbumRowData albumInfo = this->FindAlbumInfo(fileInfo);
122 CHECK_AND_PRINT_LOG(!albumInfo.lPath.empty(), "Can not find PhotoAlbum. fileInfo.lPath= %{public}s,"
123 " fileInfo.sourcePath= %{public}s", fileInfo.lPath.c_str(), fileInfo.sourcePath.c_str());
124 return albumInfo.lPath;
125 }
126
127 /**
128 * @brief Find PackageName by FileInfo.
129 */
FindPackageName(const FileInfo & fileInfo)130 std::string PhotosRestore::FindPackageName(const FileInfo &fileInfo)
131 {
132 PhotoAlbumDao::PhotoAlbumRowData albumInfo = this->FindAlbumInfo(fileInfo);
133 CHECK_AND_PRINT_LOG(!albumInfo.lPath.empty(), "Can not find PhotoAlbum. fileInfo.lPath= %{public}s,"
134 " fileInfo.sourcePath= %{public}s", fileInfo.lPath.c_str(), fileInfo.sourcePath.c_str());
135 return albumInfo.albumName;
136 }
137
138 /**
139 * @brief Find BundleName by FileInfo.
140 */
FindBundleName(const FileInfo & fileInfo)141 std::string PhotosRestore::FindBundleName(const FileInfo &fileInfo)
142 {
143 PhotoAlbumDao::PhotoAlbumRowData albumInfo = this->FindAlbumInfo(fileInfo);
144 CHECK_AND_PRINT_LOG(!albumInfo.lPath.empty(), "Can not find PhotoAlbum. fileInfo.lPath= %{public}s,"
145 "fileInfo.sourcePath= %{public}s", fileInfo.lPath.c_str(), fileInfo.sourcePath.c_str());
146 return albumInfo.bundleName;
147 }
148
149 /**
150 * @brief Find BurstKey by FileInfo.
151 */
FindBurstKey(const FileInfo & fileInfo)152 std::string PhotosRestore::FindBurstKey(const FileInfo &fileInfo)
153 {
154 CHECK_AND_RETURN_RET(fileInfo.burstKey.size() <= 0, fileInfo.burstKey);
155 return "";
156 }
157
158 /**
159 * @brief Find Dirty by FileInfo.
160 */
FindDirty(const FileInfo & fileInfo)161 int32_t PhotosRestore::FindDirty(const FileInfo &fileInfo)
162 {
163 return static_cast<int32_t>(DirtyTypes::TYPE_NEW);
164 }
165
166 /**
167 * @brief Find burst_cover_level by FileInfo.
168 */
FindBurstCoverLevel(const FileInfo & fileInfo)169 int32_t PhotosRestore::FindBurstCoverLevel(const FileInfo &fileInfo)
170 {
171 // identify burst photo
172 bool cond = (fileInfo.isBurst == static_cast<int32_t>(BurstCoverLevelType::COVER) ||
173 fileInfo.isBurst == static_cast<int32_t>(BurstCoverLevelType::MEMBER));
174 CHECK_AND_RETURN_RET(!cond, fileInfo.isBurst);
175 return static_cast<int32_t>(BurstCoverLevelType::COVER);
176 }
177
178 /**
179 * @brief Find subtype by FileInfo.
180 */
FindSubtype(const FileInfo & fileInfo)181 int32_t PhotosRestore::FindSubtype(const FileInfo &fileInfo)
182 {
183 CHECK_AND_RETURN_RET(fileInfo.burstKey.size() <= 0, static_cast<int32_t>(PhotoSubType::BURST));
184 CHECK_AND_RETURN_RET(!BackupFileUtils::IsLivePhoto(fileInfo) &&
185 !(fileInfo.subtype == static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)),
186 static_cast<int32_t>(PhotoSubType::MOVING_PHOTO));
187 return static_cast<int32_t>(PhotoSubType::DEFAULT);
188 }
189
190 /**
191 * @brief Find date_trashed by FileInfo.
192 */
FindDateTrashed(const FileInfo & fileInfo)193 int64_t PhotosRestore::FindDateTrashed(const FileInfo &fileInfo)
194 {
195 // prevent Photos marked as deleted when it's in use.
196 CHECK_AND_RETURN_RET(fileInfo.recycleFlag != 0, 0);
197 // LOG INFO for analyser.
198 if (fileInfo.recycledTime != 0) {
199 string fileName = fileInfo.displayName;
200 MEDIA_WARN_LOG("the file :%{public}s is trash.", BackupFileUtils::GarbleFileName(fileName).c_str());
201 }
202 return fileInfo.recycledTime;
203 }
204
205 /**
206 * @brief Get duplicate data in gallery db.
207 */
GetDuplicateData(int32_t duplicateDataCount)208 void PhotosRestore::GetDuplicateData(int32_t duplicateDataCount)
209 {
210 CHECK_AND_RETURN(duplicateDataCount > 0);
211 std::string querySql = this->SQL_GALLERY_MEDIA_QUERY_DUPLICATE_DATA;
212 int rowCount = 0;
213 int offset = 0;
214 int pageSize = 200;
215 do {
216 std::vector<NativeRdb::ValueObject> params = {offset, pageSize};
217 CHECK_AND_BREAK_ERR_LOG(this->galleryRdb_ != nullptr, "Media_Restore: galleryRdb_ is null.");
218 auto resultSet = this->galleryRdb_->QuerySql(querySql, params);
219 CHECK_AND_BREAK_ERR_LOG(resultSet != nullptr, "Query resultSql is null.");
220 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
221 std::string data = GetStringVal(GALLERY_FILE_DATA, resultSet);
222 int32_t count = GetInt32Val(CUSTOM_COUNT, resultSet);
223 this->duplicateDataUsedCountMap_[ToLower(data)] = 0;
224 MEDIA_INFO_LOG("Get duplicate data: %{public}s, count: %{public}d",
225 BackupFileUtils::GarbleFilePath(data, DEFAULT_RESTORE_ID).c_str(),
226 count);
227 }
228 // Check if there are more rows to fetch.
229 resultSet->GetRowCount(rowCount);
230 offset += pageSize;
231 resultSet->Close();
232 } while (rowCount > 0);
233 }
234
235 /**
236 * @brief Check if it is duplicate data in gallery db.
237 */
IsDuplicateData(const std::string & data)238 bool PhotosRestore::IsDuplicateData(const std::string &data)
239 {
240 std::lock_guard<ffrt::mutex> lock(this->duplicateDataUsedCountMutex_);
241 CHECK_AND_RETURN_RET(this->duplicateDataUsedCountMap_.count(ToLower(data)) != 0, false);
242 this->duplicateDataUsedCountMap_[ToLower(data)]++;
243 return this->duplicateDataUsedCountMap_.at(ToLower(data)) > 1;
244 }
245
246 /**
247 * @brief Find PhotoQuality by FileInfo.
248 */
FindPhotoQuality(const FileInfo & fileInfo)249 int32_t PhotosRestore::FindPhotoQuality(const FileInfo &fileInfo)
250 {
251 bool cond = (fileInfo.photoQuality == 1);
252 CHECK_AND_RETURN_RET(!cond, 0);
253 return fileInfo.photoQuality;
254 }
255
256 /**
257 * @brief Find suffix of displayName. include dot, e.g. ".jpg"
258 * @return return the suffix of displayName. "" if not found.
259 */
GetSuffix(const std::string & displayName)260 std::string PhotosRestore::GetSuffix(const std::string &displayName)
261 {
262 size_t dotPos = displayName.rfind('.');
263 /* without dot, e.g. "jpg" */
264 CHECK_AND_RETURN_RET(dotPos == std::string::npos, this->ToLower(displayName.substr(dotPos + 1)));
265 return "";
266 }
267
268 /**
269 * @brief Find media_type by FileInfo.
270 */
FindMediaType(const FileInfo & fileInfo)271 int32_t PhotosRestore::FindMediaType(const FileInfo &fileInfo)
272 {
273 int32_t dualMediaType = fileInfo.fileType;
274 bool cond = (dualMediaType == DUAL_MEDIA_TYPE::IMAGE_TYPE || dualMediaType == DUAL_MEDIA_TYPE::VIDEO_TYPE);
275 CHECK_AND_RETURN_RET(!cond,
276 (dualMediaType == DUAL_MEDIA_TYPE::VIDEO_TYPE ? MediaType::MEDIA_TYPE_VIDEO : MediaType::MEDIA_TYPE_IMAGE));
277 std::string suffix = this->GetSuffix(fileInfo.displayName);
278 MediaType mediaType = MimeTypeUtils::GetMediaTypeFromMimeType(MimeTypeUtils::GetMimeTypeFromExtension(suffix));
279 MEDIA_INFO_LOG("Media_Restore: correct mediaType from %{public}d to %{public}d, displayName: %{public}s",
280 fileInfo.fileType,
281 mediaType,
282 fileInfo.displayName.c_str());
283 return mediaType;
284 }
285
286 /**
287 * @brief Find source_path for the target device by FileInfo.
288 */
FindSourcePath(const FileInfo & fileInfo)289 std::string PhotosRestore::FindSourcePath(const FileInfo &fileInfo)
290 {
291 CHECK_AND_RETURN_RET(fileInfo.sourcePath.empty(), fileInfo.sourcePath);
292 std::string lPath = "/Pictures/其它";
293 if (!fileInfo.lPath.empty()) {
294 lPath = fileInfo.lPath;
295 } else {
296 MEDIA_ERR_LOG("Media_Restore: fileInfo.lPath is empty. Use default lPath: %{public}s", lPath.c_str());
297 }
298 return this->SOURCE_PATH_PREFIX + lPath + "/" + fileInfo.displayName;
299 }
300
301 /**
302 * @brief Find enhancement photo quality for the target device by FileInfo.
303 */
FindStrongAssociation(const FileInfo & fileInfo)304 int32_t PhotosRestore::FindStrongAssociation(const FileInfo &fileInfo)
305 {
306 CHECK_AND_RETURN_RET(fileInfo.photoQuality != DUAL_ENHANCEMENT_PHOTO_QUALITY, CLOUD_ENHANCEMENT_ALBUM);
307 return 0;
308 }
309
310 /**
311 * @brief Find enhancement photo quality for the target device by FileInfo displayName, only for cloud backup restore
312 */
FindStrongAssociationByDisplayName(const FileInfo & fileInfo)313 int32_t PhotosRestore::FindStrongAssociationByDisplayName(const FileInfo &fileInfo)
314 {
315 return IsEndWithEnhanced(fileInfo.displayName) ? CLOUD_ENHANCEMENT_ALBUM : 0;
316 }
317
318 /**
319 * @brief Find cloud enhancement available for the target device by FileInfo.
320 */
FindCeAvailable(const FileInfo & fileInfo)321 int32_t PhotosRestore::FindCeAvailable(const FileInfo &fileInfo)
322 {
323 CHECK_AND_RETURN_RET(fileInfo.photoQuality != DUAL_ENHANCEMENT_PHOTO_QUALITY, SINGLE_CLOUD_ENHANCEMENT_PHOTO);
324 return 0;
325 }
326
327 /**
328 * @brief Find cloud enhancement available for the target device by FileInfo displayName, only for cloud backup restore
329 */
FindCeAvailableByDisplayName(const FileInfo & fileInfo)330 int32_t PhotosRestore::FindCeAvailableByDisplayName(const FileInfo &fileInfo)
331 {
332 return IsEndWithEnhanced(fileInfo.displayName) ? SINGLE_CLOUD_ENHANCEMENT_PHOTO : 0;
333 }
334
335 /**
336 * @brief Find if it is live photo by file format.
337 */
FindIsLivePhoto(const FileInfo & fileInfo)338 bool PhotosRestore::FindIsLivePhoto(const FileInfo &fileInfo)
339 {
340 return MovingPhotoFileUtils::IsLivePhoto(fileInfo.filePath);
341 }
342
IsEndWithEnhanced(const std::string & displayName)343 bool PhotosRestore::IsEndWithEnhanced(const std::string &displayName)
344 {
345 std::regex pattern(R"(.*_enhanced(\.[^.]+)$)");
346 return std::regex_match(displayName, pattern);
347 }
348
GetPhotoAlbumDaoRowData(string & lPath)349 PhotoAlbumDao::PhotoAlbumRowData PhotosRestore::GetPhotoAlbumDaoRowData(string& lPath)
350 {
351 return this->photoAlbumDao_.GetPhotoAlbum(lPath);
352 }
353
GetAlbumIdsFromPhotoAlbumCache()354 std::vector<int32_t> PhotosRestore::GetAlbumIdsFromPhotoAlbumCache()
355 {
356 return this->photoAlbumDao_.GetAlbumIdsFromCache();
357 }
358 } // namespace OHOS::Media