1 /*
2  * Copyright (C) 2023 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 
16 #ifndef OHOS_MEDIA_CLONE_RESTORE_H
17 #define OHOS_MEDIA_CLONE_RESTORE_H
18 
19 #include <optional>
20 #include <type_traits>
21 #include <set>
22 #include <sstream>
23 #include <algorithm>
24 #include <iterator>
25 #include <vector>
26 
27 #include "base_restore.h"
28 #include "backup_const.h"
29 #include "medialibrary_rdb_utils.h"
30 #include "medialibrary_errno.h"
31 #include "medialibrary_kvstore_manager.h"
32 #include "backup_database_utils.h"
33 #include "photo_album_clone.h"
34 #include "photos_clone.h"
35 
36 namespace OHOS {
37 namespace Media {
38 class CloneRestore : public BaseRestore {
39 public:
40     CloneRestore();
41     virtual ~CloneRestore() = default;
42     // upgradePath is useless now
43     void StartRestore(const std::string &backupRestorePath, const std::string &upgradePath) override;
44     int32_t Init(const std::string &backupRestoreDir, const std::string &upgradeFilePath, bool isUpgrade) override;
45     NativeRdb::ValuesBucket GetInsertValue(const FileInfo &fileInfo, const std::string &newPath,
46         int32_t sourceType) override;
47     std::string GetBackupInfo() override;
48     void StartBackup() override;
49     using CoverUriInfo = std::pair<std::string, std::pair<std::string, int32_t>>;
50 
51 private:
52     void RestorePhoto(void) override;
53     void HandleRestData(void) override;
54     std::vector<FileInfo> QueryFileInfos(int32_t offset, int32_t isRelatedToPhotoMap = 0);
55     bool ParseResultSet(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, FileInfo &info,
56         std::string dbName = "") override;
57     bool ParseResultSetForAudio(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, FileInfo &info) override;
58     void AnalyzeSource() override;
59     void RestoreAlbum(void);
60     void RestoreAudio(void) override;
61     void NotifyAlbum() override;
62     int InsertPhoto(std::vector<FileInfo> &fileInfos);
63     std::vector<NativeRdb::ValuesBucket> GetInsertValues(int32_t sceneCode, std::vector<FileInfo> &fileInfos,
64         int32_t sourceType);
65     std::vector<NativeRdb::ValuesBucket> GetInsertValues(std::vector<AnalysisAlbumTbl> &analysisAlbumTbl);
66     int32_t MoveAsset(FileInfo &fileInfo);
67     bool IsFilePathExist(const std::string &filePath) const;
68     int32_t QueryTotalNumber(const std::string &tableName);
69     std::vector<AlbumInfo> QueryAlbumInfos(const std::string &tableName, int32_t offset);
70     bool ParseAlbumResultSet(const std::string &tableName, const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
71         AlbumInfo &albumInfo);
72     bool PrepareCommonColumnInfoMap(const std::string &tableName,
73         const std::unordered_map<std::string, std::string> &srcColumnInfoMap,
74         const std::unordered_map<std::string, std::string> &dstColumnInfoMap);
75     bool HasSameColumn(const std::unordered_map<std::string, std::string> &columnInfoMap, const std::string &columnName,
76         const std::string &columnType);
77     void GetValFromResultSet(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
78         std::unordered_map<std::string, std::variant<int32_t, int64_t, double, std::string>> &valMap,
79         const std::string &columnName, const std::string &columnType);
80     void PrepareCommonColumnVal(NativeRdb::ValuesBucket &values, const std::string &columnName,
81         const std::variant<int32_t, int64_t, double, std::string> &columnVal,
82         const std::unordered_map<std::string, std::string> &commonColumnInfoMap) const;
83     void GetQueryWhereClause(const std::string &tableName,
84         const std::unordered_map<std::string, std::string> &columnInfoMap);
85     void BatchQueryPhoto(std::vector<FileInfo> &fileInfos);
86     void BatchNotifyPhoto(const std::vector<FileInfo> &fileInfos);
87     void InsertAlbum(std::vector<AlbumInfo> &albumInfos, const std::string &tableName);
88     std::vector<NativeRdb::ValuesBucket> GetInsertValues(std::vector<AlbumInfo> &albumInfos,
89         const std::string &tableName);
90     bool HasSameAlbum(const AlbumInfo &albumInfo, const std::string &tableName);
91     void BatchQueryAlbum(std::vector<AlbumInfo> &albumInfos, const std::string &tableName);
92     void BatchInsertMap(const std::vector<FileInfo> &fileInfos, int64_t &totalRowNum);
93     NativeRdb::ValuesBucket GetInsertValue(const MapInfo &mapInfo) const;
94     NativeRdb::ValuesBucket GetInsertValue(const AlbumInfo &albumInfo, const std::string &tableName) const;
95     void CheckTableColumnStatus(std::shared_ptr<NativeRdb::RdbStore> rdbStore,
96         const std::vector<std::vector<std::string>> &cloneTableList);
97     bool HasColumns(const std::unordered_map<std::string, std::string> &columnInfoMap,
98         const std::unordered_set<std::string> &columnSet);
99     bool HasColumn(const std::unordered_map<std::string, std::string> &columnInfoMap, const std::string &columnName);
100     void GetAlbumExtraQueryWhereClause(const std::string &tableName);
101     bool IsReadyForRestore(const std::string &tableName);
102     void UpdateAlbumToNotifySet(const std::string &tableName, const std::unordered_set<int32_t> &albumSet);
103     void PrepareEditTimeVal(NativeRdb::ValuesBucket &values, int64_t editTime, const FileInfo &fileInfo,
104         const std::unordered_map<std::string, std::string> &commonColumnInfoMap) const;
105     void RestoreGallery();
106     bool PrepareCloudPath(const std::string &tableName, FileInfo &fileInfo);
107     void RestoreMusic();
108     std::vector<FileInfo> QueryFileInfos(const std::string &tableName, int32_t offset);
109     bool ParseResultSet(const std::string &tableName, const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
110         FileInfo &fileInfo);
111     void InsertAudio(std::vector<FileInfo> &fileInfos);
112     int32_t QueryTotalNumberByMediaType(std::shared_ptr<NativeRdb::RdbStore> rdbStore, const std::string &tableName,
113         MediaType mediaType);
114     std::string GetBackupInfoByCount(int32_t photoCount, int32_t videoCount, int32_t audioCount);
115     void MoveMigrateFile(std::vector<FileInfo> &fileInfos, int64_t &fileMoveCount, int64_t &videoFileMoveCount);
116     void RestorePhotoBatch(int32_t offset, int32_t isRelatedToPhotoMap = 0);
117     void RestoreAudioBatch(int32_t offset);
118     void InsertPhotoRelated(std::vector<FileInfo> &fileInfos);
119     void SetFileIdReference(const std::vector<FileInfo> &fileInfos, std::string &selection,
120         std::unordered_map<int32_t, int32_t> &fileIdMap);
121     int32_t QueryMapTotalNumber(const std::string &baseQuerySql);
122     std::vector<MapInfo> QueryMapInfos(const std::string &tableName, const std::string &baseQuerySql, int32_t offset,
123         const std::unordered_map<int32_t, int32_t> &fileIdMap, const std::unordered_map<int32_t, int32_t> &albumIdMap);
124     int64_t InsertMapByTable(const std::string &tableName, const std::vector<MapInfo> &mapInfos,
125         std::unordered_set<int32_t> &albumSet);
126     std::vector<NativeRdb::ValuesBucket> GetInsertValues(const std::vector<MapInfo> &mapInfos);
127     std::string GetQueryWhereClauseByTable(const std::string &tableName);
128     void SetSpecialAttributes(const std::string &tableName, const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
129         FileInfo &fileInfo);
130     bool IsSameFileForClone(const std::string &tableName, FileInfo &fileInfo);
131     int32_t MovePicture(FileInfo &fileInfo);
132     int32_t MoveMovingPhotoVideo(FileInfo &fileInfo);
133     NativeRdb::ValuesBucket GetInsertValue(const AnalysisAlbumTbl &portraitAlbumInfo);
134     int32_t InsertPortraitAlbumByTable(std::vector<AnalysisAlbumTbl> &analysisAlbumTbl);
135     void InsertPortraitAlbum(std::vector<AnalysisAlbumTbl> &analysisAlbumTbl);
136     void ParsePortraitAlbumResultSet(const std::shared_ptr<NativeRdb::ResultSet> &resultSet,
137         AnalysisAlbumTbl &analysisAlbumTbl);
138     std::vector<AnalysisAlbumTbl> QueryPortraitAlbumTbl(int32_t offset,
139         const std::vector<std::string>& commonColumns);
140     void RestoreFromGalleryPortraitAlbum();
141     int32_t QueryPortraitAlbumTotalNumber(std::shared_ptr<NativeRdb::RdbStore> rdbPtr, std::string query);
142     std::unordered_map<std::string, std::string> CreateImgFaceColumnFieldMap();
143     void ParseImageFaceResultSet(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, ImageFaceTbl &imageFaceTbl);
144     void ParseFaceTagResultSet(const std::shared_ptr<NativeRdb::ResultSet> &resultSet, FaceTagTbl &faceTagTbl);
145     NativeRdb::ValuesBucket CreateValuesBucketFromImageFaceTbl(const ImageFaceTbl& imageFaceTbl);
146     void BatchInsertImageFaces(const std::vector<ImageFaceTbl>& imageFaceTbls);
147     std::vector<ImageFaceTbl> ProcessImageFaceTbls(const std::vector<ImageFaceTbl>& imageFaceTbls,
148         const std::vector<FileIdPair>& fileIdPairs);
149     std::vector<ImageFaceTbl> QueryImageFaceTbl(int32_t offset, std::string &fileIdClause,
150         const std::vector<std::string>& commonColumns);
151     std::vector<PortraitAlbumDfx> QueryAllPortraitAlbum(int32_t& offset, int32_t& rowCount);
152     void RecordOldPortraitAlbumDfx();
153     std::unordered_set<std::string> QueryAllPortraitAlbum();
154     void LogPortraitCloneDfx();
155     void RestoreImageFaceInfo(std::vector<FileInfo> &fileInfos);
156     NativeRdb::ValuesBucket CreateValuesBucketFromFaceTagTbl(const FaceTagTbl& faceTagTbl);
157     void BatchInsertFaceTags(const std::vector<FaceTagTbl>& faceTagTbls);
158     void DeleteExistingFaceTagData(const std::string& inClause);
159     std::vector<FaceTagTbl> QueryFaceTagTbl(int32_t offset, std::vector<std::string> &commonColumns);
160     void RestorePortraitClusteringInfo();
161     void ReportPortraitCloneStat(int32_t sceneCode);
162     void AppendExtraWhereClause(std::string& whereClause, const std::string& tableName);
163     void GenNewCoverUris(const std::vector<CoverUriInfo>& coverUriInfo,
164         std::vector<FileInfo> &fileInfos);
165     bool GetFileInfoByFileId(int32_t fileId, const std::vector<FileInfo>& fileInfos, FileInfo& outFileInfo);
166     std::string GenCoverUriUpdateSql(const std::unordered_map<std::string, std::pair<std::string, int32_t>>&
167         tagIdToCoverInfo, const std::unordered_map<std::string, int32_t>& oldToNewFileId,
168         const std::vector<FileInfo>& fileInfos, std::vector<std::string>& tagIds);
169     std::string ProcessUriAndGenNew(const std::string& tagId, const std::string& oldCoverUri,
170         const std::unordered_map<std::string, int32_t>& oldToNewFileId, const std::vector<FileInfo>& fileInfos);
171     int32_t MoveThumbnail(FileInfo &fileInfo);
172     int32_t MoveThumbnailDir(FileInfo &fileInfo);
173     int32_t MoveAstc(FileInfo &fileInfo);
174     void InitThumbnailStatus();
175     bool InitAllKvStore();
176     void CloseAllKvStore();
177     bool BackupKvStore();
178     void GetThumbnailInsertValue(const FileInfo &fileInfo, NativeRdb::ValuesBucket &values);
179     int32_t GetNoNeedMigrateCount() override;
180 
181     template<typename T>
182     static void PutIfPresent(NativeRdb::ValuesBucket& values, const std::string& columnName,
183         const std::optional<T>& optionalValue);
184 
185     template<typename T>
186     void PutWithDefault(NativeRdb::ValuesBucket& values, const std::string& columnName,
187         const std::optional<T>& optionalValue, const T& defaultValue);
188     int32_t MoveEditedData(FileInfo &fileInfo);
189 
190 private:
191     std::atomic<uint64_t> migrateDatabaseAlbumNumber_{0};
192     std::atomic<uint64_t> migrateDatabaseMapNumber_{0};
193     std::shared_ptr<NativeRdb::RdbStore> mediaRdb_;
194     std::string filePath_;
195     std::string dbPath_;
196     std::unordered_map<std::string, bool> tableColumnStatusMap_;
197     std::unordered_map<std::string, std::string> tableQueryWhereClauseMap_;
198     std::unordered_map<std::string, std::string> tableExtraQueryWhereClauseMap_;
199     std::unordered_map<std::string, std::unordered_map<int32_t, int32_t>> tableAlbumIdMap_;
200     std::unordered_map<std::string, std::unordered_map<std::string, std::string>> tableCommonColumnInfoMap_;
201     std::unordered_set<std::string> albumToNotifySet_;
202     std::string garbagePath_;
203     std::vector<CoverUriInfo> coverUriInfo_;
204     std::vector<PortraitAlbumDfx> portraitAlbumDfx_;
205     PhotoAlbumClone photoAlbumClone_;
206     PhotosClone photosClone_;
207     static constexpr int32_t INVALID_COVER_SATISFIED_STATUS = -1;
208     bool hasCloneThumbnailDir_{false};
209     bool isInitKvstoreSuccess_{false};
210     std::shared_ptr<MediaLibraryKvStore> oldMonthKvStorePtr_ = nullptr;
211     std::shared_ptr<MediaLibraryKvStore> oldYearKvStorePtr_ = nullptr;
212     std::shared_ptr<MediaLibraryKvStore> newMonthKvStorePtr_ = nullptr;
213     std::shared_ptr<MediaLibraryKvStore> newYearKvStorePtr_ = nullptr;
214     std::vector<int> photosFailedOffsets;
215 };
216 
217 template<typename T>
PutIfPresent(NativeRdb::ValuesBucket & values,const std::string & columnName,const std::optional<T> & optionalValue)218 void CloneRestore::PutIfPresent(NativeRdb::ValuesBucket& values, const std::string& columnName,
219     const std::optional<T>& optionalValue)
220 {
221     if (optionalValue.has_value()) {
222         if constexpr (std::is_same_v<std::decay_t<T>, int32_t>) {
223             values.PutInt(columnName, optionalValue.value());
224         } else if constexpr (std::is_same_v<std::decay_t<T>, int64_t>) {
225             values.PutLong(columnName, optionalValue.value());
226         } else if constexpr (std::is_same_v<std::decay_t<T>, std::string>) {
227             values.PutString(columnName, optionalValue.value());
228         } else if constexpr (std::is_same_v<std::decay_t<T>, double>) {
229             values.PutDouble(columnName, optionalValue.value());
230         }
231     }
232 }
233 
234 template<typename T>
PutWithDefault(NativeRdb::ValuesBucket & values,const std::string & columnName,const std::optional<T> & optionalValue,const T & defaultValue)235 void CloneRestore::PutWithDefault(NativeRdb::ValuesBucket& values, const std::string& columnName,
236     const std::optional<T>& optionalValue, const T& defaultValue)
237 {
238     if (optionalValue.has_value()) {
239         PutIfPresent(values, columnName, optionalValue);
240     } else {
241         PutIfPresent(values, columnName, std::optional<T>(defaultValue));
242     }
243 }
244 } // namespace Media
245 } // namespace OHOS
246 
247 #endif  // OHOS_MEDIA_CLONE_RESTORE_H
248