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