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 #define MLOG_TAG "DfxManager"
16 
17 #include "dfx_manager.h"
18 
19 #include "dfx_cloud_manager.h"
20 #include "dfx_utils.h"
21 #include "media_file_utils.h"
22 #include "media_log.h"
23 #include "userfile_manager_types.h"
24 #include "medialibrary_bundle_manager.h"
25 #include "dfx_database_utils.h"
26 #include "vision_aesthetics_score_column.h"
27 #include "parameters.h"
28 #include "preferences.h"
29 #include "preferences_helper.h"
30 #include "hi_audit.h"
31 #include "medialibrary_errno.h"
32 
33 using namespace std;
34 
35 namespace OHOS {
36 namespace Media {
37 
38 shared_ptr<DfxManager> DfxManager::dfxManagerInstance_{nullptr};
39 mutex DfxManager::instanceLock_;
40 
41 struct QueryParams {
42     MediaType mediaType;
43     PhotoPositionType positionType;
44 };
45 
GetInstance()46 shared_ptr<DfxManager> DfxManager::GetInstance()
47 {
48     lock_guard<mutex> lockGuard(instanceLock_);
49     if (dfxManagerInstance_ == nullptr) {
50         dfxManagerInstance_ = make_shared<DfxManager>();
51         if (dfxManagerInstance_ != nullptr) {
52             dfxManagerInstance_->Init();
53         }
54     }
55     return dfxManagerInstance_;
56 }
57 
DfxManager()58 DfxManager::DfxManager() : isInitSuccess_(false)
59 {
60 }
61 
~DfxManager()62 DfxManager::~DfxManager()
63 {
64 }
65 
Init()66 void DfxManager::Init()
67 {
68     MEDIA_INFO_LOG("Init DfxManager");
69     dfxCollector_ = make_shared<DfxCollector>();
70     dfxAnalyzer_ = make_shared<DfxAnalyzer>();
71     dfxReporter_ = make_shared<DfxReporter>();
72     dfxWorker_ = DfxWorker::GetInstance();
73     dfxWorker_->Init();
74     isInitSuccess_ = true;
75 }
76 
HandleTimeOutOperation(std::string & bundleName,int32_t type,int32_t object,int32_t time)77 void DfxManager::HandleTimeOutOperation(std::string &bundleName, int32_t type, int32_t object, int32_t time)
78 {
79     if (!isInitSuccess_) {
80         MEDIA_WARN_LOG("DfxManager not init");
81         return;
82     }
83     dfxReporter_->ReportTimeOutOperation(bundleName, type, object, time);
84 }
85 
HandleHighMemoryThumbnail(std::string & path,int32_t mediaType,int32_t width,int32_t height)86 int32_t DfxManager::HandleHighMemoryThumbnail(std::string &path, int32_t mediaType, int32_t width,
87     int32_t height)
88 {
89     if (!isInitSuccess_) {
90         MEDIA_WARN_LOG("DfxManager not init");
91         return NOT_INIT;
92     }
93     string suffix = MediaFileUtils::GetExtensionFromPath(path);
94     if (mediaType == MEDIA_TYPE_IMAGE) {
95         return dfxReporter_->ReportHighMemoryImageThumbnail(path, suffix, width, height);
96     } else {
97         return dfxReporter_->ReportHighMemoryVideoThumbnail(path, suffix, width, height);
98     }
99 }
100 
HandleThumbnailError(const std::string & path,int32_t method,int32_t errorCode)101 void DfxManager::HandleThumbnailError(const std::string &path, int32_t method, int32_t errorCode)
102 {
103     string safePath = DfxUtils::GetSafePath(path);
104     MEDIA_ERR_LOG("Failed to %{public}d, path: %{public}s, err: %{public}d", method, safePath.c_str(), errorCode);
105     if (!isInitSuccess_) {
106         MEDIA_WARN_LOG("DfxManager not init");
107         return;
108     }
109     dfxCollector_->CollectThumbnailError(safePath, method, errorCode);
110 }
111 
HandleThumbnailGeneration(const ThumbnailData::GenerateStats & stats)112 void DfxManager::HandleThumbnailGeneration(const ThumbnailData::GenerateStats &stats)
113 {
114     if (!isInitSuccess_) {
115         MEDIA_WARN_LOG("DfxManager not init");
116         return;
117     }
118     dfxReporter_->ReportThumbnailGeneration(stats);
119 }
120 
HandleCommonBehavior(string bundleName,int32_t type)121 void DfxManager::HandleCommonBehavior(string bundleName, int32_t type)
122 {
123     if (!isInitSuccess_) {
124         MEDIA_WARN_LOG("DfxManager not init");
125         return;
126     }
127     dfxCollector_->AddCommonBahavior(bundleName, type);
128 }
129 
LogDelete(DfxData * data)130 static void LogDelete(DfxData *data)
131 {
132     if (data == nullptr) {
133         return;
134     }
135     auto *taskData = static_cast<DeleteBehaviorTask *>(data);
136     string id = taskData->id_;
137     int32_t type = taskData->type_;
138     int32_t size = taskData->size_;
139     std::shared_ptr<DfxReporter> dfxReporter = taskData->dfxReporter_;
140     MEDIA_INFO_LOG("id: %{public}s, type: %{public}d, size: %{public}d", id.c_str(), type, size);
141 
142     OHOS::Media::AuditLog auditLog;
143     auditLog.isUserBehavior = true;
144     auditLog.cause = "USER BEHAVIOR";
145     auditLog.operationType = "DELETE";
146     auditLog.operationScenario = "io";
147     auditLog.operationCount = 1,
148     auditLog.operationStatus = "running";
149     auditLog.extend = "OK",
150     auditLog.id = id;
151     auditLog.type = type;
152     auditLog.size = size;
153     OHOS::Media::HiAudit::GetInstance().Write(auditLog);
154 
155     std::vector<std::string> uris = taskData->uris_;
156     if (!uris.empty()) {
157         for (auto& uri: uris) {
158             string::size_type pos = uri.find_last_of('/');
159             if (pos == string::npos) {
160                 continue;
161             }
162             string halfUri = uri.substr(0, pos);
163             string::size_type pathPos = halfUri.find_last_of('/');
164             if (pathPos == string::npos) {
165                 continue;
166             }
167             dfxReporter->ReportDeleteBehavior(id, type, halfUri.substr(pathPos + 1));
168         }
169     }
170 }
171 
HandleNoPermmison(int32_t type,int32_t object,int32_t error)172 void DfxManager::HandleNoPermmison(int32_t type, int32_t object, int32_t error)
173 {
174     MEDIA_INFO_LOG("permission deny: {%{public}d, %{public}d, %{public}d}", type, object, error);
175 }
176 
HandleDeleteBehavior(int32_t type,int32_t size,std::vector<std::string> & uris,string bundleName)177 void DfxManager::HandleDeleteBehavior(int32_t type, int32_t size, std::vector<std::string> &uris, string bundleName)
178 {
179     if (bundleName == "") {
180         bundleName = MediaLibraryBundleManager::GetInstance()->GetClientBundleName();
181     }
182     dfxCollector_->CollectDeleteBehavior(bundleName, type, size);
183     if (dfxWorker_ == nullptr) {
184         MEDIA_ERR_LOG("Can not get dfxWork_");
185         return;
186     }
187     string id = bundleName == "" ? to_string(IPCSkeleton::GetCallingUid()) : bundleName;
188     auto *taskData = new (nothrow) DeleteBehaviorTask(id, type, size, uris, dfxReporter_);
189     if (taskData == nullptr) {
190         MEDIA_ERR_LOG("Failed to new taskData");
191         return;
192     }
193     auto deleteBehaviorTask = make_shared<DfxTask>(LogDelete, taskData);
194     if (deleteBehaviorTask == nullptr) {
195         MEDIA_ERR_LOG("Failed to create async task for deleteBehaviorTask.");
196         return;
197     }
198     dfxWorker_->AddTask(deleteBehaviorTask);
199 }
200 
HandlePhotoInfo(std::shared_ptr<DfxReporter> & dfxReporter)201 static void HandlePhotoInfo(std::shared_ptr<DfxReporter>& dfxReporter)
202 {
203     const std::vector<QueryParams> queryParamsList = {
204         {MediaType::MEDIA_TYPE_IMAGE, PhotoPositionType::LOCAL},
205         {MediaType::MEDIA_TYPE_VIDEO, PhotoPositionType::LOCAL},
206         {MediaType::MEDIA_TYPE_IMAGE, PhotoPositionType::CLOUD},
207         {MediaType::MEDIA_TYPE_VIDEO, PhotoPositionType::CLOUD},
208         {MediaType::MEDIA_TYPE_IMAGE, PhotoPositionType::LOCAL_AND_CLOUD},
209         {MediaType::MEDIA_TYPE_VIDEO, PhotoPositionType::LOCAL_AND_CLOUD}
210     };
211 
212     PhotoStatistics stats = {};
213     int32_t* countPtrs[] = {
214         &stats.localImageCount,
215         &stats.localVideoCount,
216         &stats.cloudImageCount,
217         &stats.cloudVideoCount,
218         &stats.sharedImageCount,
219         &stats.sharedVideoCount
220     };
221 
222     for (size_t i = 0; i < queryParamsList.size(); i++) {
223         const auto& params = queryParamsList[i];
224         *countPtrs[i] = DfxDatabaseUtils::QueryFromPhotos(params.mediaType, static_cast<int32_t>(params.positionType));
225     }
226 
227     MEDIA_INFO_LOG("localImageCount: %{public}d, localVideoCount: %{public}d, "
228                    "cloudImageCount: %{public}d, cloudVideoCount: %{public}d, "
229                    "sharedImageCount: %{public}d, sharedVideoCount: %{public}d",
230                    stats.localImageCount, stats.localVideoCount,
231                    stats.cloudImageCount, stats.cloudVideoCount,
232                    stats.sharedImageCount, stats.sharedVideoCount);
233 
234     dfxReporter->ReportPhotoInfo(stats);
235 }
236 
HandleAlbumInfoBySubtype(std::shared_ptr<DfxReporter> & dfxReporter,int32_t albumSubType)237 static void HandleAlbumInfoBySubtype(std::shared_ptr<DfxReporter> &dfxReporter, int32_t albumSubType)
238 {
239     AlbumInfo albumInfo = DfxDatabaseUtils::QueryAlbumInfoBySubtype(albumSubType);
240     string albumName = ALBUM_MAP.at(albumSubType);
241     MEDIA_INFO_LOG("album %{public}s: {count:%{public}d, imageCount:%{public}d, videoCount:%{public}d, \
242         isLocal:%{public}d}", albumName.c_str(), albumInfo.count, albumInfo.imageCount, albumInfo.videoCount,
243         albumInfo.isLocal);
244     dfxReporter->ReportAlbumInfo(albumName.c_str(), albumInfo.imageCount, albumInfo.videoCount, albumInfo.isLocal);
245 }
246 
HandleAlbumInfo(std::shared_ptr<DfxReporter> & dfxReporter)247 static void HandleAlbumInfo(std::shared_ptr<DfxReporter> &dfxReporter)
248 {
249     HandleAlbumInfoBySubtype(dfxReporter, static_cast<int32_t>(PhotoAlbumSubType::IMAGE));
250     HandleAlbumInfoBySubtype(dfxReporter, static_cast<int32_t>(PhotoAlbumSubType::VIDEO));
251     HandleAlbumInfoBySubtype(dfxReporter, static_cast<int32_t>(PhotoAlbumSubType::FAVORITE));
252     HandleAlbumInfoBySubtype(dfxReporter, static_cast<int32_t>(PhotoAlbumSubType::HIDDEN));
253     HandleAlbumInfoBySubtype(dfxReporter, static_cast<int32_t>(PhotoAlbumSubType::TRASH));
254 }
255 
HandleDirtyCloudPhoto(std::shared_ptr<DfxReporter> & dfxReporter)256 static void HandleDirtyCloudPhoto(std::shared_ptr<DfxReporter> &dfxReporter)
257 {
258     vector<PhotoInfo> photoInfoList = DfxDatabaseUtils::QueryDirtyCloudPhoto();
259     if (photoInfoList.empty()) {
260         return;
261     }
262     for (auto& photoInfo: photoInfoList) {
263         dfxReporter->ReportDirtyCloudPhoto(photoInfo.data, photoInfo.dirty, photoInfo.cloudVersion);
264     }
265 }
266 
HandleLocalVersion(std::shared_ptr<DfxReporter> & dfxReporter)267 static void HandleLocalVersion(std::shared_ptr<DfxReporter> &dfxReporter)
268 {
269     int32_t dbVersion = DfxDatabaseUtils::QueryDbVersion();
270     dfxReporter->ReportCommonVersion(dbVersion);
271     int32_t aestheticsVersion = DfxDatabaseUtils::QueryAnalysisVersion("tab_analysis_aesthetics_score",
272         "aesthetics_version");
273     dfxReporter->ReportAnalysisVersion("aesthetics_score", aestheticsVersion);
274     int32_t compositionVersion = DfxDatabaseUtils::QueryAnalysisVersion("tab_analysis_composition",
275         "composition_version");
276     dfxReporter->ReportAnalysisVersion("composition", compositionVersion);
277     int32_t headVersion = DfxDatabaseUtils::QueryAnalysisVersion("tab_analysis_head", "head_version");
278     dfxReporter->ReportAnalysisVersion("head", headVersion);
279     int32_t imageFaceVersion = DfxDatabaseUtils::QueryAnalysisVersion("tab_analysis_image_face", "features_version");
280     dfxReporter->ReportAnalysisVersion("image_face", imageFaceVersion);
281     int32_t labelVersion = DfxDatabaseUtils::QueryAnalysisVersion("tab_analysis_label", "label_version");
282     dfxReporter->ReportAnalysisVersion("label", labelVersion);
283     int32_t objectVersion = DfxDatabaseUtils::QueryAnalysisVersion("tab_analysis_object", "object_version");
284     dfxReporter->ReportAnalysisVersion("object", objectVersion);
285     int32_t ocrVersion = DfxDatabaseUtils::QueryAnalysisVersion("tab_analysis_ocr", "ocr_version");
286     dfxReporter->ReportAnalysisVersion("ocr", ocrVersion);
287     int32_t poseVersion = DfxDatabaseUtils::QueryAnalysisVersion("tab_analysis_pose", "pose_version");
288     dfxReporter->ReportAnalysisVersion("pose", poseVersion);
289     int32_t recommendationVersion = DfxDatabaseUtils::QueryAnalysisVersion("tab_analysis_recommendation",
290         "recommendation_version");
291     dfxReporter->ReportAnalysisVersion("recommendation", recommendationVersion);
292     int32_t saliencyDetectVersion = DfxDatabaseUtils::QueryAnalysisVersion("tab_analysis_saliency_detect",
293         "saliency_version");
294     dfxReporter->ReportAnalysisVersion("saliency_detect", saliencyDetectVersion);
295     int32_t segmentationVersion = DfxDatabaseUtils::QueryAnalysisVersion("tab_analysis_segmentation",
296         "segmentation_version");
297     dfxReporter->ReportAnalysisVersion("segmentation", segmentationVersion);
298     int32_t videoLabelVersion = DfxDatabaseUtils::QueryAnalysisVersion("tab_analysis_video_label", "algo_version");
299     dfxReporter->ReportAnalysisVersion("video_label", videoLabelVersion);
300 }
301 
HandleStatistic(DfxData * data)302 static void HandleStatistic(DfxData *data)
303 {
304     if (data == nullptr) {
305         return;
306     }
307     auto *taskData = static_cast<StatisticData *>(data);
308     std::shared_ptr<DfxReporter> dfxReporter = taskData->dfxReporter_;
309     HandlePhotoInfo(dfxReporter);
310     HandleAlbumInfo(dfxReporter);
311     HandleDirtyCloudPhoto(dfxReporter);
312     HandleLocalVersion(dfxReporter);
313 }
314 
HandleHalfDayMissions()315 void DfxManager::HandleHalfDayMissions()
316 {
317     if (!isInitSuccess_) {
318         MEDIA_WARN_LOG("DfxManager not init");
319         return;
320     }
321     int32_t errCode;
322     shared_ptr<NativePreferences::Preferences> prefs =
323         NativePreferences::PreferencesHelper::GetPreferences(DFX_COMMON_XML, errCode);
324     if (!prefs) {
325         MEDIA_ERR_LOG("get preferences error: %{public}d", errCode);
326         return;
327     }
328     int64_t lastReportTime = prefs->GetLong(LAST_HALF_DAY_REPORT_TIME, 0);
329     if (MediaFileUtils::UTCTimeSeconds() - lastReportTime > HALF_DAY && dfxWorker_ != nullptr) {
330         MEDIA_INFO_LOG("start handle statistic behavior");
331         auto *taskData = new (nothrow) StatisticData(dfxReporter_);
332         if (taskData == nullptr) {
333             MEDIA_ERR_LOG("Failed to alloc async data for Handle Half Day Missions!");
334             return;
335         }
336         auto statisticTask = make_shared<DfxTask>(HandleStatistic, taskData);
337         if (statisticTask == nullptr) {
338             MEDIA_ERR_LOG("Failed to create statistic task.");
339             return;
340         }
341         dfxWorker_->AddTask(statisticTask);
342         int64_t time = MediaFileUtils::UTCTimeSeconds();
343         prefs->PutLong(LAST_HALF_DAY_REPORT_TIME, time);
344         prefs->FlushSync();
345     }
346 }
347 
IsDirectoryExist(const string & dirName)348 void DfxManager::IsDirectoryExist(const string& dirName)
349 {
350     struct stat statInfo {};
351     if (stat(dirName.c_str(), &statInfo) == E_SUCCESS) {
352         if (statInfo.st_mode & S_IFDIR) {
353             return;
354         }
355         MEDIA_ERR_LOG("Not Is DIR, errno is %{public}d", errno);
356         return;
357     }
358     MEDIA_ERR_LOG("Directory Not Exist, errno is %{public}d", errno);
359     return;
360 }
361 
CheckStatus()362 void DfxManager::CheckStatus()
363 {
364     const std::string CLOUD_FILE_PATH = "/storage/cloud/files";
365     IsDirectoryExist(CLOUD_FILE_PATH);
366 }
367 
HandleFiveMinuteTask()368 void DfxManager::HandleFiveMinuteTask()
369 {
370     if (!isInitSuccess_) {
371         MEDIA_WARN_LOG("DfxManager not init");
372         return;
373     }
374     std::unordered_map<string, CommonBehavior> commonBehavior = dfxCollector_->GetCommonBehavior();
375     dfxAnalyzer_->FlushCommonBehavior(commonBehavior);
376     HandleDeleteBehaviors();
377     std::unordered_map<std::string, ThumbnailErrorInfo> result = dfxCollector_->GetThumbnailError();
378     dfxAnalyzer_->FlushThumbnail(result);
379     AdaptationToMovingPhotoInfo adaptationInfo = dfxCollector_->GetAdaptationToMovingPhotoInfo();
380     dfxAnalyzer_->FlushAdaptationToMovingPhoto(adaptationInfo);
381     CheckStatus();
382 }
383 
HandleDeleteBehaviors()384 void DfxManager::HandleDeleteBehaviors()
385 {
386     std::unordered_map<string, int32_t> deleteAssetToTrash =
387         dfxCollector_->GetDeleteBehavior(DfxType::TRASH_PHOTO);
388     dfxAnalyzer_->FlushDeleteBehavior(deleteAssetToTrash, DfxType::TRASH_PHOTO);
389     std::unordered_map<string, int32_t> deleteAssetFromDisk =
390         dfxCollector_->GetDeleteBehavior(DfxType::ALBUM_DELETE_ASSETS);
391     dfxAnalyzer_->FlushDeleteBehavior(deleteAssetToTrash, DfxType::ALBUM_DELETE_ASSETS);
392     std::unordered_map<string, int32_t> removeAssets =
393         dfxCollector_->GetDeleteBehavior(DfxType::ALBUM_REMOVE_PHOTOS);
394     dfxAnalyzer_->FlushDeleteBehavior(removeAssets, DfxType::ALBUM_REMOVE_PHOTOS);
395 }
396 
HandleMiddleReport()397 int64_t DfxManager::HandleMiddleReport()
398 {
399     if (!isInitSuccess_) {
400         MEDIA_WARN_LOG("DfxManager not init");
401         return MediaFileUtils::UTCTimeSeconds();
402     }
403     dfxReporter_->ReportCommonBehavior();
404     dfxReporter_->ReportDeleteStatistic();
405     return MediaFileUtils::UTCTimeSeconds();
406 }
407 
HandleOneDayReport()408 int64_t DfxManager::HandleOneDayReport()
409 {
410     if (!isInitSuccess_) {
411         MEDIA_WARN_LOG("DfxManager not init");
412         return MediaFileUtils::UTCTimeSeconds();
413     }
414     dfxReporter_->ReportThumbnailError();
415     dfxReporter_->ReportAdaptationToMovingPhoto();
416     dfxReporter_->ReportPhotoRecordInfo();
417     return MediaFileUtils::UTCTimeSeconds();
418 }
419 
HandleAdaptationToMovingPhoto(const string & appName,bool adapted)420 void DfxManager::HandleAdaptationToMovingPhoto(const string &appName, bool adapted)
421 {
422     if (!isInitSuccess_) {
423         MEDIA_WARN_LOG("DfxManager not init");
424         return;
425     }
426     dfxCollector_->CollectAdaptationToMovingPhotoInfo(appName, adapted);
427 }
428 
IsReported()429 bool IsReported()
430 {
431     int32_t errCode;
432     shared_ptr<NativePreferences::Preferences> prefs =
433         NativePreferences::PreferencesHelper::GetPreferences(DFX_COMMON_XML, errCode);
434     if (!prefs) {
435         MEDIA_ERR_LOG("get dfx common preferences error: %{public}d", errCode);
436         return false;
437     }
438     return prefs->GetBool(IS_REPORTED, false);
439 }
440 
SetReported(bool isReported)441 void SetReported(bool isReported)
442 {
443     int32_t errCode;
444     shared_ptr<NativePreferences::Preferences> prefs =
445         NativePreferences::PreferencesHelper::GetPreferences(DFX_COMMON_XML, errCode);
446     if (!prefs) {
447         MEDIA_ERR_LOG("get dfx common preferences error: %{public}d", errCode);
448         return;
449     }
450     prefs->PutBool(IS_REPORTED, isReported);
451 }
452 
~CloudSyncDfxManager()453 CloudSyncDfxManager::~CloudSyncDfxManager()
454 {
455     ShutDownTimer();
456 }
457 
GetInstance()458 CloudSyncDfxManager& CloudSyncDfxManager::GetInstance()
459 {
460     static CloudSyncDfxManager cloudSyncDfxManager;
461     return cloudSyncDfxManager;
462 }
463 
GetCloudSyncStatus()464 CloudSyncStatus GetCloudSyncStatus()
465 {
466     return static_cast<CloudSyncStatus>(system::GetParameter(CLOUDSYNC_STATUS_KEY, "0").at(0) - '0');
467 }
468 
CloudSyncDfxManager()469 CloudSyncDfxManager::CloudSyncDfxManager()
470 {
471     InitSyncState();
472     uint16_t newState = static_cast<uint16_t>(syncState_);
473     stateProcessFuncs_[newState].Process(*this);
474 }
475 
InitSyncState()476 void CloudSyncDfxManager::InitSyncState()
477 {
478     CloudSyncStatus cloudSyncStatus = GetCloudSyncStatus();
479     switch (cloudSyncStatus) {
480         case CloudSyncStatus::BEGIN:
481         case CloudSyncStatus::SYNC_SWITCHED_OFF:
482             syncState_ = SyncState::INIT_STATE;
483             return;
484         case CloudSyncStatus::FIRST_FIVE_HUNDRED:
485         case CloudSyncStatus::TOTAL_DOWNLOAD:
486             syncState_ = SyncState::START_STATE;
487             return;
488         case CloudSyncStatus::TOTAL_DOWNLOAD_FINISH:
489             syncState_ = SyncState::END_STATE;
490             return;
491         default:
492             return;
493     }
494 }
495 
StateSwitch(CloudSyncDfxManager & manager)496 bool InitState::StateSwitch(CloudSyncDfxManager& manager)
497 {
498     CloudSyncStatus cloudSyncStatus = GetCloudSyncStatus();
499     switch (cloudSyncStatus) {
500         case CloudSyncStatus::FIRST_FIVE_HUNDRED:
501         case CloudSyncStatus::TOTAL_DOWNLOAD:
502             manager.syncState_ = SyncState::START_STATE;
503             return true;
504         case CloudSyncStatus::TOTAL_DOWNLOAD_FINISH:
505             manager.syncState_ = SyncState::END_STATE;
506             MEDIA_INFO_LOG("CloudSyncDfxManager new status:%{public}hu", manager.syncState_);
507             return true;
508         default:
509             return false;
510     }
511 }
512 
Process(CloudSyncDfxManager & manager)513 void InitState::Process(CloudSyncDfxManager& manager)
514 {
515     MEDIA_INFO_LOG("CloudSyncDfxManager new status:%{public}hu", manager.syncState_);
516     manager.ResetStartTime();
517     manager.ShutDownTimer();
518     SetReported(false);
519 }
520 
RunDfx()521 void CloudSyncDfxManager::RunDfx()
522 {
523     uint16_t oldState = static_cast<uint16_t>(syncState_);
524     if (stateProcessFuncs_[oldState].StateSwitch(*this)) {
525         uint16_t newState = static_cast<uint16_t>(syncState_);
526         stateProcessFuncs_[newState].Process(*this);
527     }
528 }
529 
StateSwitch(CloudSyncDfxManager & manager)530 bool StartState::StateSwitch(CloudSyncDfxManager& manager)
531 {
532     CloudSyncStatus cloudSyncStatus = GetCloudSyncStatus();
533     switch (cloudSyncStatus) {
534         case CloudSyncStatus::BEGIN:
535         case CloudSyncStatus::SYNC_SWITCHED_OFF:
536             manager.syncState_ = SyncState::INIT_STATE;
537             return true;
538         case CloudSyncStatus::TOTAL_DOWNLOAD_FINISH:
539             manager.syncState_ = SyncState::END_STATE;
540             MEDIA_INFO_LOG("CloudSyncDfxManager new status:%{public}hu", manager.syncState_);
541             return true;
542         default:
543             return false;
544     }
545 }
546 
Process(CloudSyncDfxManager & manager)547 void StartState::Process(CloudSyncDfxManager& manager)
548 {
549     MEDIA_INFO_LOG("CloudSyncDfxManager new status:%{public}hu", manager.syncState_);
550     manager.SetStartTime();
551     manager.StartTimer();
552     SetReported(false);
553 }
554 
StateSwitch(CloudSyncDfxManager & manager)555 bool EndState::StateSwitch(CloudSyncDfxManager& manager)
556 {
557     CloudSyncStatus cloudSyncStatus = GetCloudSyncStatus();
558     switch (cloudSyncStatus) {
559         case CloudSyncStatus::BEGIN:
560         case CloudSyncStatus::SYNC_SWITCHED_OFF:
561             manager.syncState_ = SyncState::INIT_STATE;
562             return true;
563         case CloudSyncStatus::TOTAL_DOWNLOAD_FINISH:
564             return true;
565         default:
566             return false;
567     }
568 }
569 
Process(CloudSyncDfxManager & manager)570 void EndState::Process(CloudSyncDfxManager& manager)
571 {
572     std::unique_lock<std::mutex> lock(manager.endStateMutex_);
573     if (IsReported()) {
574         manager.ShutDownTimer();
575         return;
576     }
577     manager.SetStartTime();
578     manager.StartTimer();
579     int32_t downloadedThumb = 0;
580     int32_t generatedThumb = 0;
581     if (!DfxDatabaseUtils::QueryDownloadedAndGeneratedThumb(downloadedThumb, generatedThumb)) {
582         if (downloadedThumb != generatedThumb) {
583             return;
584         }
585         int32_t totalDownload = 0;
586         DfxDatabaseUtils::QueryTotalCloudThumb(totalDownload);
587         if (totalDownload != downloadedThumb) {
588             return;
589         }
590         SetReported(true);
591         manager.ShutDownTimer();
592         DfxReporter::ReportCloudSyncThumbGenerationStatus(downloadedThumb, generatedThumb, totalDownload);
593     }
594 }
595 
StartTimer()596 void CloudSyncDfxManager::StartTimer()
597 {
598     std::unique_lock<std::mutex> lock(timerMutex_);
599     if (timerId_ != 0) {
600         return;
601     }
602     if (timer_.Setup() != ERR_OK) {
603         MEDIA_INFO_LOG("CloudSync Dfx Set Timer Failed");
604         return;
605     }
606     Utils::Timer::TimerCallback timerCallback = [this]() {
607         if (IsReported()) {
608             return;
609         }
610         int32_t generatedThumb = 0;
611         int32_t downloadedThumb = 0;
612         if (!DfxDatabaseUtils::QueryDownloadedAndGeneratedThumb(downloadedThumb, generatedThumb)) {
613             int32_t totalDownload = 0;
614             DfxDatabaseUtils::QueryTotalCloudThumb(totalDownload);
615             if (downloadedThumb == generatedThumb && totalDownload == generatedThumb) {
616                 MEDIA_INFO_LOG("CloudSyncDfxManager Dfx report Thumb generation status, "
617                     "download: %{public}d, generate: %{public}d", downloadedThumb, generatedThumb);
618                 SetReported(true);
619             }
620             DfxReporter::ReportCloudSyncThumbGenerationStatus(downloadedThumb, generatedThumb, totalDownload);
621         }
622     };
623     timerId_ = timer_.Register(timerCallback, SIX_HOUR * TO_MILLION, false);
624     MEDIA_INFO_LOG("CloudSyncDfxManager StartTimer id:%{public}d", timerId_);
625 }
626 
ShutDownTimer()627 void CloudSyncDfxManager::ShutDownTimer()
628 {
629     std::unique_lock<std::mutex> lock(timerMutex_);
630     if (timerId_ == 0) {
631         return;
632     }
633     MEDIA_INFO_LOG("CloudSyncDfxManager ShutDownTimer id:%{public}d", timerId_);
634     timer_.Unregister(timerId_);
635     timerId_ = 0;
636     timer_.Shutdown();
637 }
638 
ResetStartTime()639 void CloudSyncDfxManager::ResetStartTime()
640 {
641     int32_t errCode;
642     shared_ptr<NativePreferences::Preferences> prefs =
643         NativePreferences::PreferencesHelper::GetPreferences(DFX_COMMON_XML, errCode);
644     if (!prefs) {
645         MEDIA_ERR_LOG("get dfx common preferences error: %{public}d", errCode);
646         return;
647     }
648     prefs->PutLong(CLOUD_SYNC_START_TIME, 0);
649     prefs->FlushSync();
650 }
651 
SetStartTime()652 void CloudSyncDfxManager::SetStartTime()
653 {
654     int32_t errCode;
655     shared_ptr<NativePreferences::Preferences> prefs =
656         NativePreferences::PreferencesHelper::GetPreferences(DFX_COMMON_XML, errCode);
657     if (!prefs) {
658         MEDIA_ERR_LOG("get dfx common preferences error: %{public}d", errCode);
659         return;
660     }
661     int64_t time = prefs->GetLong(CLOUD_SYNC_START_TIME, 0);
662     // if startTime exists, no need to reset startTime
663     if (time != 0) {
664         return;
665     }
666     time = MediaFileUtils::UTCTimeSeconds();
667     prefs->PutLong(CLOUD_SYNC_START_TIME, time);
668     prefs->FlushSync();
669 }
670 
671 } // namespace Media
672 } // namespace OHOS