• 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 "photos_clone.h"
16 
17 #include <uuid.h>
18 #include <numeric>
19 
20 #include "rdb_store.h"
21 #include "result_set_utils.h"
22 #include "photo_album_dao.h"
23 #include "backup_const.h"
24 #include "media_log.h"
25 #include "album_plugin_config.h"
26 #include "userfile_manager_types.h"
27 
28 namespace OHOS::Media {
ToString(const FileInfo & fileInfo)29 std::string PhotosClone::ToString(const FileInfo &fileInfo)
30 {
31     return "FileInfo[ fileId: " + std::to_string(fileInfo.fileIdOld) + ", displayName: " + fileInfo.displayName +
32            ", bundleName: " + fileInfo.bundleName + ", lPath: " + fileInfo.lPath +
33            ", size: " + std::to_string(fileInfo.fileSize) + ", fileType: " + std::to_string(fileInfo.fileType) + " ]";
34 }
35 
ToLower(const std::string & str)36 std::string PhotosClone::ToLower(const std::string &str)
37 {
38     std::string lowerStr;
39     std::transform(
40         str.begin(), str.end(), std::back_inserter(lowerStr), [](unsigned char c) { return std::tolower(c); });
41     return lowerStr;
42 }
43 
44 /**
45  * @brief Get Row Count of Photos in Album.
46  */
GetPhotosRowCountInPhotoMap()47 int32_t PhotosClone::GetPhotosRowCountInPhotoMap()
48 {
49     std::string querySql = this->SQL_PHOTOS_TABLE_COUNT_IN_PHOTO_MAP;
50     if (this->mediaLibraryOriginalRdb_ == nullptr) {
51         MEDIA_ERR_LOG("Media_Restore: mediaLibraryOriginalRdb_ is null.");
52         return 0;
53     }
54     auto resultSet = this->mediaLibraryOriginalRdb_->QuerySql(querySql);
55     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
56         return 0;
57     }
58     return GetInt32Val("count", resultSet);
59 }
60 
61 /**
62  * @brief Get Row Count of Photos not in Album.
63  */
GetPhotosRowCountNotInPhotoMap()64 int32_t PhotosClone::GetPhotosRowCountNotInPhotoMap()
65 {
66     std::string querySql = this->SQL_PHOTOS_TABLE_COUNT_NOT_IN_PHOTO_MAP;
67     if (this->mediaLibraryOriginalRdb_ == nullptr) {
68         MEDIA_ERR_LOG("Media_Restore: mediaLibraryOriginalRdb_ is null.");
69         return 0;
70     }
71     auto resultSet = this->mediaLibraryOriginalRdb_->QuerySql(querySql);
72     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
73         return 0;
74     }
75     return GetInt32Val("count", resultSet);
76 }
77 
78 /**
79  * @brief Query the Photos Info, which is in PhotoAlbum, from the Original MediaLibrary Database.
80  */
GetPhotosInPhotoMap(int32_t offset,int32_t pageSize)81 std::shared_ptr<NativeRdb::ResultSet> PhotosClone::GetPhotosInPhotoMap(int32_t offset, int32_t pageSize)
82 {
83     std::vector<NativeRdb::ValueObject> bindArgs = {offset, pageSize};
84     if (this->mediaLibraryOriginalRdb_ == nullptr) {
85         MEDIA_ERR_LOG("Media_Restore: mediaLibraryOriginalRdb_ is null.");
86         return nullptr;
87     }
88     return this->mediaLibraryOriginalRdb_->QuerySql(this->SQL_PHOTOS_TABLE_QUERY_IN_PHOTO_MAP, bindArgs);
89 }
90 
91 /**
92  * @brief Query the Photos Info, which is not in PhotoAlbum, from the Original MediaLibrary Database.
93  */
GetPhotosNotInPhotoMap(int32_t offset,int32_t pageSize)94 std::shared_ptr<NativeRdb::ResultSet> PhotosClone::GetPhotosNotInPhotoMap(int32_t offset, int32_t pageSize)
95 {
96     std::vector<NativeRdb::ValueObject> bindArgs = {offset, pageSize};
97     if (this->mediaLibraryOriginalRdb_ == nullptr) {
98         MEDIA_ERR_LOG("Media_Restore: mediaLibraryOriginalRdb_ is null.");
99         return nullptr;
100     }
101     return this->mediaLibraryOriginalRdb_->QuerySql(this->SQL_PHOTOS_TABLE_QUERY_NOT_IN_PHOTO_MAP, bindArgs);
102 }
103 /**
104  * @note If the lPath is empty, return '/Pictures/其它' string.
105  *      If the lPath is '/Pictures/ScreenShots', return '/Pictures/ScreenShots' string.
106  *      Otherwise, return the lPath of the FileInfo.
107  */
FindAlbumInfo(const FileInfo & fileInfo)108 PhotoAlbumDao::PhotoAlbumRowData PhotosClone::FindAlbumInfo(const FileInfo &fileInfo)
109 {
110     PhotoAlbumDao::PhotoAlbumRowData albumInfo;
111     if (fileInfo.lPath.empty()) {
112         MEDIA_ERR_LOG("Media_Restore: lPath is empty, Object: %{public}s", this->ToString(fileInfo).c_str());
113         return albumInfo;
114     }
115     if (this->ToLower(fileInfo.lPath) == this->ToLower(AlbumPlugin::LPATH_SCREEN_SHOTS) &&
116         fileInfo.fileType == MediaType::MEDIA_TYPE_VIDEO) {
117         albumInfo = this->photoAlbumDao_.BuildAlbumInfoOfRecorders();
118         albumInfo = this->photoAlbumDao_.GetOrCreatePhotoAlbum(albumInfo);
119         MEDIA_INFO_LOG(
120             "Media_Restore: screenshots redirect to screenrecords, Object: %{public}s, albumInfo: %{public}s",
121             this->ToString(fileInfo).c_str(),
122             this->photoAlbumDao_.ToString(albumInfo).c_str());
123         return albumInfo;
124     }
125     albumInfo = this->photoAlbumDao_.GetPhotoAlbum(fileInfo.lPath);
126     if (albumInfo.lPath.empty()) {
127         MEDIA_ERR_LOG("Media_Restore: albumInfo is empty, albumInfo: %{public}s, Object: %{public}s",
128             this->photoAlbumDao_.ToString(albumInfo).c_str(),
129             this->ToString(fileInfo).c_str());
130     }
131     return albumInfo;
132 }
133 
134 /**
135  * @brief Find the lPath of the PhotoAlbum related to Photos from target database.
136  */
FindlPath(const FileInfo & fileInfo)137 std::string PhotosClone::FindlPath(const FileInfo &fileInfo)
138 {
139     PhotoAlbumDao::PhotoAlbumRowData albumInfo = this->FindAlbumInfo(fileInfo);
140     return albumInfo.lPath;
141 }
142 
143 /**
144  * @brief Find the albumId of the PhotoAlbum related to Photos from target database.
145  */
FindAlbumId(const FileInfo & fileInfo)146 int32_t PhotosClone::FindAlbumId(const FileInfo &fileInfo)
147 {
148     PhotoAlbumDao::PhotoAlbumRowData albumInfo = this->FindAlbumInfo(fileInfo);
149     return albumInfo.albumId;
150 }
151 
152 /**
153  * @brief Find the packageName of the PhotoAlbum related to Photos from target database.
154  */
FindPackageName(const FileInfo & fileInfo)155 std::string PhotosClone::FindPackageName(const FileInfo &fileInfo)
156 {
157     PhotoAlbumDao::PhotoAlbumRowData albumInfo = this->FindAlbumInfo(fileInfo);
158     // Only provide the package name of the SOURCE album.
159     if (albumInfo.albumType != static_cast<int32_t>(PhotoAlbumType::SOURCE) ||
160         albumInfo.albumSubType != static_cast<int32_t>(PhotoAlbumSubType::SOURCE_GENERIC)) {
161         return "";
162     }
163     return albumInfo.albumName;
164 }
165 
166 /**
167  * @brief Find the bundleName of the PhotoAlbum related to Photos from target database.
168  */
FindBundleName(const FileInfo & fileInfo)169 std::string PhotosClone::FindBundleName(const FileInfo &fileInfo)
170 {
171     PhotoAlbumDao::PhotoAlbumRowData albumInfo = this->FindAlbumInfo(fileInfo);
172     // Only provide the bundle name of the SOURCE album.
173     if (albumInfo.albumType != static_cast<int32_t>(PhotoAlbumType::SOURCE) ||
174         albumInfo.albumSubType != static_cast<int32_t>(PhotoAlbumSubType::SOURCE_GENERIC)) {
175         return "";
176     }
177     return albumInfo.bundleName;
178 }
179 
FindDuplicateBurstKey()180 std::vector<PhotosDao::PhotosRowData> PhotosClone::FindDuplicateBurstKey()
181 {
182     std::vector<PhotosDao::PhotosRowData> result;
183     std::string querySql = this->SQL_PHOTOS_TABLE_BURST_KEY_DUPLICATE_QUERY;
184     int rowCount = 0;
185     int offset = 0;
186     int pageSize = 200;
187     do {
188         std::vector<NativeRdb::ValueObject> bindArgs = {offset, pageSize};
189         if (this->mediaLibraryOriginalRdb_ == nullptr) {
190             MEDIA_ERR_LOG("Media_Restore: mediaLibraryOriginalRdb_ is null.");
191             break;
192         }
193         auto resultSet = this->mediaLibraryTargetRdb_->QuerySql(querySql, bindArgs);
194         if (resultSet == nullptr) {
195             MEDIA_ERR_LOG("Query resultSql is null.");
196             break;
197         }
198         while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
199             PhotosDao::PhotosRowData info;
200             info.burstKey = GetStringVal("burst_key", resultSet);
201             info.ownerAlbumId = GetInt32Val("owner_album_id", resultSet);
202             result.emplace_back(info);
203         }
204         // Check if there are more rows to fetch.
205         resultSet->GetRowCount(rowCount);
206         offset += pageSize;
207     } while (rowCount > 0);
208     return result;
209 }
210 
FindPhotoQuality(const FileInfo & fileInfo)211 int32_t PhotosClone::FindPhotoQuality(const FileInfo &fileInfo)
212 {
213     if (fileInfo.photoQuality == 1 && fileInfo.fileType == MediaType::MEDIA_TYPE_VIDEO) {
214         return 0;
215     }
216     return fileInfo.photoQuality;
217 }
218 
ToString(const std::vector<NativeRdb::ValueObject> & values)219 std::string PhotosClone::ToString(const std::vector<NativeRdb::ValueObject> &values)
220 {
221     std::vector<std::string> result;
222     for (auto &value : values) {
223         std::string str;
224         value.GetString(str);
225         result.emplace_back(str + ", ");
226     }
227     return std::accumulate(result.begin(), result.end(), std::string());
228 }
229 
230 /**
231  * @brief generate a uuid
232  *
233  * @return std::string uuid with 32 characters
234  */
GenerateUuid()235 std::string PhotosClone::GenerateUuid()
236 {
237     uuid_t uuid;
238     uuid_generate(uuid);
239     char str[UUID_STR_LENGTH] = {};
240     uuid_unparse(uuid, str);
241     return str;
242 }
243 
244 /**
245  * @brief Fix Duplicate burst_key in Photos, which is used in different PhotoAlbum.
246  */
FixDuplicateBurstKeyInDifferentAlbum(std::atomic<uint64_t> & totalNumber)247 int32_t PhotosClone::FixDuplicateBurstKeyInDifferentAlbum(std::atomic<uint64_t> &totalNumber)
248 {
249     std::vector<PhotosDao::PhotosRowData> duplicateBurstKeyList = this->FindDuplicateBurstKey();
250     totalNumber += static_cast<uint64_t>(duplicateBurstKeyList.size());
251     MEDIA_INFO_LOG("onProcess Update otherTotalNumber_: %{public}lld", (long long)totalNumber);
252     std::string executeSql = this->SQL_PHOTOS_TABLE_BURST_KEY_UPDATE;
253     for (auto &info : duplicateBurstKeyList) {
254         std::string burstKeyNew = this->GenerateUuid();
255         std::vector<NativeRdb::ValueObject> bindArgs = {burstKeyNew, info.ownerAlbumId, info.burstKey};
256         MEDIA_INFO_LOG("Media_Restore: executeSql = %{public}s, bindArgs=%{public}s",
257             executeSql.c_str(),
258             this->ToString(bindArgs).c_str());
259         if (this->mediaLibraryOriginalRdb_ == nullptr) {
260             MEDIA_ERR_LOG("Media_Restore: mediaLibraryOriginalRdb_ is null.");
261             break;
262         }
263         int32_t ret = this->mediaLibraryTargetRdb_->ExecuteSql(executeSql, bindArgs);
264         if (ret != NativeRdb::E_OK) {
265             MEDIA_ERR_LOG("Media_Restore: FixDuplicateBurstKeyInDifferentAlbum failed,"
266                           " ret=%{public}d, sql=%{public}s, bindArgs=%{public}s",
267                 ret,
268                 executeSql.c_str(),
269                 this->ToString(bindArgs).c_str());
270         }
271     }
272     return 0;
273 }
274 }  // namespace OHOS::Media