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