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