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