1 /*
2 * Copyright (C) 2025 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 CLONE_RESTORE_HIGHLIGHT_H
17 #define CLONE_RESTORE_HIGHLIGHT_H
18
19 #include <sstream>
20 #include <string>
21
22 #include "backup_const.h"
23 #include "backup_database_utils.h"
24 #include "media_log.h"
25 #include "nlohmann/json.hpp"
26 #include "rdb_store.h"
27 #include "safe_map.h"
28
29 namespace OHOS::Media {
30 class CloneRestoreHighlight {
31 public:
32 struct InitInfo {
33 int32_t sceneCode{-1};
34 std::string taskId;
35 std::shared_ptr<NativeRdb::RdbStore> mediaLibraryRdb;
36 std::shared_ptr<NativeRdb::RdbStore> mediaRdb;
37 std::string backupRestoreDir;
38 std::unordered_map<int32_t, PhotoInfo> photoInfoMap;
39 };
40
41 void Init(const InitInfo &info);
42 void Restore();
43 void ReportCloneRestoreHighlightTask();
44 int32_t GetNewHighlightAlbumId(int32_t oldId);
45 int32_t GetNewHighlightPhotoId(int32_t oldId);
46 std::string GetNewHighlightPhotoUri(int32_t oldId);
47 bool IsCloneHighlight();
48 std::string GetDefaultPlayInfo();
49 void UpdateHighlightStatus(const std::vector<int32_t> &highlightIds);
50 void UpdateRestoreTimeCost(int64_t timeCost);
51
52 template<typename T>
53 static void PutIfPresent(NativeRdb::ValuesBucket &values, const std::string &columnName,
54 const std::optional<T> &optionalValue);
55
56 template<typename T>
57 static void PutIfInIntersection(NativeRdb::ValuesBucket &values, const std::string &columnName,
58 const std::optional<T> &optionalValue, const std::unordered_set<std::string> &intersection);
59
60 template<typename T>
61 static void GetIfInIntersection(const std::string &columnName, std::optional<T> &optionalValue,
62 const std::unordered_set<std::string> &intersection, std::shared_ptr<NativeRdb::ResultSet> resultSet);
63
64 private:
65 struct AnalysisAlbumInfo {
66 std::optional<int32_t> albumIdOld;
67 std::optional<int32_t> albumIdNew;
68 std::optional<int32_t> albumType;
69 std::optional<int32_t> albumSubtype;
70 std::optional<std::string> albumName;
71 std::optional<std::string> oldCoverUri;
72 std::string coverUri = "";
73 std::optional<int64_t> dateModified;
74
75 std::optional<int32_t> rank;
76 std::optional<std::string> tagId;
77 std::optional<int32_t> userOperation;
78 std::optional<std::string> groupTag;
79 std::optional<int32_t> userDisplayLevel;
80 std::optional<int32_t> isMe;
81 std::optional<int32_t> isRemoved;
82 std::optional<int32_t> renameOperation;
83 std::optional<int32_t> isLocal;
84 std::optional<int32_t> isCoverSatisfied;
85 std::optional<std::string> relationship;
86
87 std::optional<int32_t> highlightIdOld;
88 std::optional<int32_t> highlightIdNew;
89
ToStringAnalysisAlbumInfo90 std::string ToString() const
91 {
92 std::stringstream outputStr;
93 outputStr << "HighlightAlbumInfo[" << "albumIdOld: ";
94 if (albumIdOld.has_value()) { outputStr << albumIdOld.value(); }
95 outputStr << ", albumIdNew: ";
96 if (albumIdNew.has_value()) { outputStr << albumIdNew.value(); }
97 outputStr << ", albumName: ";
98 if (albumName.has_value()) { outputStr << albumName.value(); }
99 outputStr << ", oldCoverUri: ";
100 if (oldCoverUri.has_value()) { outputStr << oldCoverUri.value(); }
101 outputStr << ", highlightIdNew: ";
102 if (highlightIdNew.has_value()) { outputStr << highlightIdNew.value(); }
103 outputStr << ", coverUri: " << coverUri << "]";
104 return outputStr.str();
105 }
106 };
107
108 struct HighlightAlbumInfo {
109 std::optional<int32_t> highlightIdOld;
110 std::optional<int32_t> highlightIdNew;
111 std::optional<int32_t> albumIdOld;
112 std::optional<int32_t> aiAlbumIdOld;
113 std::optional<int32_t> albumIdNew;
114 std::optional<int32_t> aiAlbumIdNew;
115 std::optional<std::string> subTitle;
116 std::optional<std::string> clusterType;
117 std::optional<std::string> clusterSubType;
118 std::optional<std::string> clusterCondition;
119 std::optional<int64_t> minDateAdded;
120 std::optional<int64_t> maxDateAdded;
121 std::optional<int64_t> generateTime;
122 std::optional<int32_t> highlightVersion;
123 std::optional<std::string> remarks;
124 std::optional<int32_t> highlightStatus;
125
126 std::optional<int32_t> insertPicCount;
127 std::optional<int32_t> removePicCount;
128 std::optional<int32_t> shareScreenshotCount;
129 std::optional<int32_t> shareCoverCount;
130 std::optional<int32_t> renameCount;
131 std::optional<int32_t> changeCoverCount;
132 std::optional<int32_t> renderViewedTimes;
133 std::optional<int64_t> renderViewedDuration;
134 std::optional<int32_t> artLayoutViewedTimes;
135 std::optional<int64_t> artLayoutViewedDuration;
136 std::optional<int32_t> musicEditCount;
137 std::optional<int32_t> filterEditCount;
138 std::optional<int32_t> isMuted;
139 std::optional<int32_t> isFavorite;
140 std::optional<std::string> theme;
141 std::optional<int64_t> pinTime;
142 std::optional<int32_t> useSubtitle;
143 std::optional<std::string> highlightLocation;
144
ToStringHighlightAlbumInfo145 std::string ToString() const
146 {
147 std::stringstream outputStr;
148 outputStr << "HighlightAlbumInfo[" << "albumIdNew: ";
149 if (albumIdNew.has_value()) { outputStr << albumIdNew.value(); }
150 outputStr << ", aiAlbumIdNew: ";
151 if (aiAlbumIdNew.has_value()) { outputStr << aiAlbumIdNew.value(); }
152 outputStr << ", subTitle: ";
153 if (subTitle.has_value()) { outputStr << subTitle.value(); }
154 outputStr << ", clusterType: ";
155 if (clusterType.has_value()) { outputStr << clusterType.value(); }
156 outputStr << ", clusterSubType: ";
157 if (clusterSubType.has_value()) { outputStr << clusterSubType.value(); }
158 outputStr << ", clusterCondition: ";
159 if (clusterCondition.has_value()) { outputStr << clusterCondition.value(); }
160 outputStr << ", highlightStatus: ";
161 if (highlightStatus.has_value()) { outputStr << highlightStatus.value(); }
162 outputStr << "]";
163 return outputStr.str();
164 }
165 };
166
167 struct HighlightCoverInfo {
168 std::optional<int32_t> highlightIdNew;
169 std::optional<std::string> ratio;
170 std::optional<std::string> background;
171 std::optional<std::string> foreground;
172 std::optional<std::string> wordart;
173 std::optional<int32_t> isCovered;
174 std::optional<std::string> color;
175 std::optional<int32_t> radius;
176 std::optional<double> saturation;
177 std::optional<double> brightness;
178 std::optional<int32_t> backgroundColorType;
179 std::optional<int32_t> shadowLevel;
180 std::optional<double> scaleX;
181 std::optional<double> scaleY;
182 std::optional<double> rectWidth;
183 std::optional<double> rectHeight;
184 std::optional<double> bgrScaleX;
185 std::optional<double> bgrScaleY;
186 std::optional<double> bgrRectWidth;
187 std::optional<double> bgrRectHeight;
188 std::optional<int32_t> layoutIndex;
189 std::optional<int32_t> coverAlgoVer;
190 std::optional<int32_t> coverServiceVer;
191
192 std::optional<int32_t> status;
193
ToStringHighlightCoverInfo194 std::string ToString() const
195 {
196 std::stringstream outputStr;
197 outputStr << "HighlightCoverInfo[" << "highlightIdNew: ";
198 if (highlightIdNew.has_value()) { outputStr << highlightIdNew.value(); }
199 outputStr << ", ratio: ";
200 if (ratio.has_value()) { outputStr << ratio.value(); }
201 outputStr << "]";
202 return outputStr.str();
203 }
204 };
205
206 struct HighlightPlayInfo {
207 std::optional<int32_t> highlightIdNew;
208 std::optional<int32_t> playId;
209 std::optional<std::string> music;
210 std::optional<int32_t> filter;
211 std::optional<std::string> pInfo;
212 std::optional<int32_t> isChosen;
213 std::optional<int32_t> pInfoVer;
214 std::optional<std::string> hAlgoVer;
215 std::optional<std::string> cameraAlgoVer;
216 std::optional<std::string> transAlgoVer;
217 std::optional<std::string> playServiceVer;
218 std::optional<int32_t> status;
219
ToStringHighlightPlayInfo220 std::string ToString() const
221 {
222 std::stringstream outputStr;
223 outputStr << "HighlightPlayInfo[" << "highlightIdNew: ";
224 if (highlightIdNew.has_value()) { outputStr << highlightIdNew.value(); }
225 outputStr << ", playId: ";
226 if (playId.has_value()) { outputStr << playId.value(); }
227 outputStr << "]";
228 return outputStr.str();
229 }
230 };
231
232 void Preprocess();
233 void RestoreAlbums();
234 void RestoreMaps();
235 int32_t GetTotalNumberOfMaps();
236 void RestoreMapsBatch();
237 void UpdateAlbums();
238
239 void GetAnalysisAlbumInfos();
240 void GetAnalysisRowInfo(AnalysisAlbumInfo &info, std::shared_ptr<NativeRdb::ResultSet> resultSet);
241 void UpdateAlbumCoverUri(AnalysisAlbumInfo &info);
242 void InsertIntoAnalysisAlbum();
243 void GetAnalysisInsertValue(NativeRdb::ValuesBucket &value, const AnalysisAlbumInfo &info);
244 void UpdateHighlightStatusMap(int32_t highlightStatus, int32_t highlightId,
245 std::unordered_map<int32_t, std::vector<NativeRdb::ValueObject>> &highlightStatusMap);
246 void UpdateHighlightStatusInDatabase(
247 const std::unordered_map<int32_t, std::vector<NativeRdb::ValueObject>> &highlightStatusMap);
248 int32_t GetMaxAlbumId(const std::string &tableName, const std::string &idName);
249 void UpdateMapInsertValues(std::vector<NativeRdb::ValuesBucket> &values);
250 void UpdateMapInsertValuesByAlbumId(std::vector<NativeRdb::ValuesBucket> &values,
251 std::shared_ptr<NativeRdb::ResultSet> resultSet);
252 void InsertAnalysisPhotoMap(std::vector<NativeRdb::ValuesBucket> &values);
253 int32_t BatchInsertWithRetry(const std::string &tableName, const std::vector<NativeRdb::ValuesBucket> &values,
254 int64_t &rowNum);
255 NativeRdb::ValuesBucket GetMapInsertValue(int32_t albumId, int32_t fileId, std::optional<int32_t> &order);
256 void GetHighlightAlbumInfos();
257 void GetHighlightNewAlbumId(HighlightAlbumInfo &info);
258 void GetHighlightRowInfo(HighlightAlbumInfo &info, std::shared_ptr<NativeRdb::ResultSet> resultSet);
259 void InsertIntoHighlightAlbum();
260 void GetHighlightInsertValue(NativeRdb::ValuesBucket &value, const HighlightAlbumInfo &info);
261 void PutTempHighlightStatus(NativeRdb::ValuesBucket &value, const HighlightAlbumInfo &info);
262 void MoveHighlightCovers();
263 void MoveHighlightWordart(const AnalysisAlbumInfo &info, const std::string &srcDir);
264 void MoveHighlightGround(const AnalysisAlbumInfo &info, const std::string &srcDir);
265 int32_t MoveHighlightMusic(const std::string &srcDir, const std::string &dstDir);
266 void GetHighlightCoverInfos();
267 void GetCoverRowInfo(HighlightCoverInfo &info, std::shared_ptr<NativeRdb::ResultSet> resultSet);
268 void GetCoverGroundSourceInfo(HighlightCoverInfo &info, std::shared_ptr<NativeRdb::ResultSet> resultSet);
269 void InsertIntoHighlightCoverInfo();
270 void GetCoverInsertValue(NativeRdb::ValuesBucket &value, const HighlightCoverInfo &info);
271 void GetHighlightPlayInfos();
272 void GetPlayRowInfo(HighlightPlayInfo &info, std::shared_ptr<NativeRdb::ResultSet> resultSet);
273 void InsertIntoHighlightPlayInfo();
274 void GetPlayInsertValue(NativeRdb::ValuesBucket &value, const HighlightPlayInfo &info);
275 std::unordered_set<std::string> GetCommonColumns(const std::string &tableName);
276 void ReportRestoreTaskOfTotal();
277 void ReportRestoreTaskOfAlbumStats();
278 void ReportRestoreTaskOfAlbumInfo();
279 bool IsMapColumnOrderExist();
280 void HighlightDeduplicate(const HighlightAlbumInfo &info);
281 std::vector<NativeRdb::ValueObject> GetHighlightDuplicateIds(const HighlightAlbumInfo &info,
282 std::string &duplicateAlbumName, std::unordered_set<int32_t> &duplicateAnalysisAlbumIdSet);
283 void UpdateHighlightDuplicateRows(const std::vector<NativeRdb::ValueObject> &changeIds,
284 const std::string &duplicateAlbumName);
285 void DeleteAnalysisDuplicateRows(const std::unordered_set<int32_t> &duplicateAnalysisAlbumIdSet,
286 const std::string &duplicateAlbumName);
287
288 private:
289 int32_t sceneCode_{-1};
290 std::string taskId_;
291 std::string coverPath_;
292 std::string musicDir_;
293 std::string garblePath_;
294 // old media_liabrary.db
295 std::shared_ptr<NativeRdb::RdbStore> mediaRdb_;
296 // new media_liabrary.db
297 std::shared_ptr<NativeRdb::RdbStore> mediaLibraryRdb_;
298 std::unordered_map<int32_t, PhotoInfo> photoInfoMap_;
299 std::unordered_map<std::string, std::unordered_set<std::string>> intersectionMap_;
300
301 std::vector<AnalysisAlbumInfo> analysisInfos_;
302 std::vector<HighlightAlbumInfo> highlightInfos_;
303 std::vector<HighlightCoverInfo> coverInfos_;
304 std::vector<HighlightPlayInfo> playInfos_;
305
306 std::mutex counterMutex_;
307 std::unordered_map<std::string, int32_t> albumPhotoCounter_;
308 bool isMapOrder_{false};
309 bool isCloneHighlight_{false};
310 bool isHighlightDirExist_{false};
311 int32_t maxIdOfAlbum_{0};
312 int32_t maxIdOfHighlight_{0};
313 int32_t lastIdOfMap_{0};
314 int64_t albumSuccessCnt_{0};
315 int64_t albumDuplicateCnt_{0};
316 int64_t albumFailedCnt_{0};
317 int64_t highlightSuccessCnt_{0};
318 int64_t highlightDuplicateCnt_{0};
319 int64_t highlightFailedCnt_{0};
320 int64_t mapSuccessCnt_{0};
321 int64_t mapFailedCnt_{0};
322 int64_t coverInfoSuccessCnt_{0};
323 int64_t coverInfoFailedCnt_{0};
324 int64_t playInfoSuccessCnt_{0};
325 int64_t playInfoFailedCnt_{0};
326 int64_t restoreTimeCost_{0};
327 };
328
329 template<typename T>
PutIfPresent(NativeRdb::ValuesBucket & values,const std::string & columnName,const std::optional<T> & optionalValue)330 void CloneRestoreHighlight::PutIfPresent(NativeRdb::ValuesBucket& values, const std::string& columnName,
331 const std::optional<T>& optionalValue)
332 {
333 if (optionalValue.has_value()) {
334 if constexpr (std::is_same_v<std::decay_t<T>, int32_t>) {
335 values.PutInt(columnName, optionalValue.value());
336 } else if constexpr (std::is_same_v<std::decay_t<T>, int64_t>) {
337 values.PutLong(columnName, optionalValue.value());
338 } else if constexpr (std::is_same_v<std::decay_t<T>, std::string>) {
339 values.PutString(columnName, optionalValue.value());
340 } else if constexpr (std::is_same_v<std::decay_t<T>, double>) {
341 values.PutDouble(columnName, optionalValue.value());
342 }
343 }
344 }
345
346 template<typename T>
PutIfInIntersection(NativeRdb::ValuesBucket & values,const std::string & columnName,const std::optional<T> & optionalValue,const std::unordered_set<std::string> & intersection)347 void CloneRestoreHighlight::PutIfInIntersection(NativeRdb::ValuesBucket& values, const std::string& columnName,
348 const std::optional<T>& optionalValue, const std::unordered_set<std::string> &intersection)
349 {
350 if (intersection.count(columnName) > 0) {
351 PutIfPresent<T>(values, columnName, optionalValue);
352 return;
353 }
354 }
355
356 template<typename T>
GetIfInIntersection(const std::string & columnName,std::optional<T> & optionalValue,const std::unordered_set<std::string> & intersection,std::shared_ptr<NativeRdb::ResultSet> resultSet)357 void CloneRestoreHighlight::GetIfInIntersection(const std::string &columnName, std::optional<T> &optionalValue,
358 const std::unordered_set<std::string> &intersection, std::shared_ptr<NativeRdb::ResultSet> resultSet)
359 {
360 if (intersection.count(columnName) > 0) {
361 optionalValue = BackupDatabaseUtils::GetOptionalValue<T>(resultSet, columnName);
362 return;
363 }
364 }
365 } // namespace OHOS::Media
366 #endif // CLONE_RESTORE_HIGHLIGHT_H