• 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 #define MLOG_TAG "DfxWorker"
16 
17 #include "dfx_worker.h"
18 
19 #include <pthread.h>
20 
21 #include "cloud_media_asset_manager.h"
22 #include "media_file_utils.h"
23 #include "media_log.h"
24 #include "dfx_manager.h"
25 #include "preferences.h"
26 #include "preferences_helper.h"
27 #include "parameters.h"
28 
29 using namespace std;
30 namespace OHOS {
31 namespace Media {
32 shared_ptr<DfxWorker> DfxWorker::dfxWorkerInstance_{nullptr};
33 
GetInstance()34 shared_ptr<DfxWorker> DfxWorker::GetInstance()
35 {
36     if (dfxWorkerInstance_ == nullptr) {
37         dfxWorkerInstance_ = make_shared<DfxWorker>();
38     }
39     return dfxWorkerInstance_;
40 }
41 
DfxWorker()42 DfxWorker::DfxWorker() : isThreadRunning_(false)
43 {
44 }
45 
~DfxWorker()46 DfxWorker::~DfxWorker()
47 {
48     MEDIA_INFO_LOG("DfxWorker deconstructor");
49     isThreadRunning_ = false;
50     workCv_.notify_all();
51     if (delayThread_.joinable()) {
52         delayThread_.join();
53     }
54     dfxWorkerInstance_ = nullptr;
55 }
56 
Init()57 void DfxWorker::Init()
58 {
59     MEDIA_INFO_LOG("init");
60     isThreadRunning_ = true;
61     delayThread_ = thread([this] { this->InitDelayThread(); });
62 }
63 
HandleLoopTask(DfxData * data)64 static void HandleLoopTask(DfxData *data)
65 {
66     MEDIA_DEBUG_LOG("HandleLoopTask");
67     int32_t errCode;
68     shared_ptr<NativePreferences::Preferences> prefs =
69        NativePreferences::PreferencesHelper::GetPreferences(DFX_COMMON_XML, errCode);
70     if (!prefs) {
71         MEDIA_ERR_LOG("get preferences error: %{public}d", errCode);
72         return;
73     }
74     int64_t lastReportTime = prefs->GetLong(LAST_REPORT_TIME, 0);
75     int64_t lastMiddleReportTime = prefs->GetLong(LAST_MIDDLE_REPORT_TIME, 0);
76     DfxManager::GetInstance()->HandleFiveMinuteTask();
77     if (MediaFileUtils::UTCTimeSeconds() - lastMiddleReportTime >= SIX_HOUR) {
78         MEDIA_INFO_LOG("Report Middle Xml");
79         lastMiddleReportTime = DfxManager::GetInstance()->HandleMiddleReport();
80         prefs->PutLong(LAST_MIDDLE_REPORT_TIME, lastMiddleReportTime);
81         prefs->FlushSync();
82     }
83     if (MediaFileUtils::UTCTimeSeconds() - lastReportTime >= ONE_DAY) {
84         MEDIA_INFO_LOG("Report one day Xml");
85         lastReportTime = DfxManager::GetInstance()->HandleOneDayReport();
86         prefs->PutLong(LAST_REPORT_TIME, lastReportTime);
87         prefs->FlushSync();
88     }
89     CloudMediaAssetManager::GetInstance().CheckStorageAndRecoverDownloadTask();
90 }
91 
Prepare()92 void DfxWorker::Prepare()
93 {
94     int32_t errCode;
95     shared_ptr<NativePreferences::Preferences> prefs =
96         NativePreferences::PreferencesHelper::GetPreferences(DFX_COMMON_XML, errCode);
97     if (!prefs) {
98         MEDIA_ERR_LOG("get preferences error: %{public}d", errCode);
99         return;
100     }
101     thumbnailVersion_ = prefs->GetInt(THUMBNAIL_ERROR_VERSION, 0);
102     deleteStatisticVersion_ = prefs->GetInt(DELETE_STATISTIC_VERSION, 0);
103     if (IsThumbnailUpdate()) {
104         thumbnailVersion_ = LATEST_THUMBNAIL_ERROR_VERSION;
105         prefs->PutInt(THUMBNAIL_ERROR_VERSION, LATEST_THUMBNAIL_ERROR_VERSION);
106     }
107     if (IsDeleteStatisticUpdate()) {
108         deleteStatisticVersion_ = LATEST_DELETE_STATISTIC_VERSION;
109         prefs->PutInt(DELETE_STATISTIC_VERSION, LATEST_DELETE_STATISTIC_VERSION);
110     }
111     prefs->FlushSync();
112 }
113 
IsThumbnailUpdate()114 bool DfxWorker::IsThumbnailUpdate()
115 {
116     if (thumbnailVersion_ < LATEST_THUMBNAIL_ERROR_VERSION) {
117         MEDIA_INFO_LOG("update thumbnail version from %{public}d to %{public}d", thumbnailVersion_,
118             LATEST_THUMBNAIL_ERROR_VERSION);
119         int32_t errCode;
120         shared_ptr<NativePreferences::Preferences> prefs =
121             NativePreferences::PreferencesHelper::GetPreferences(THUMBNAIL_ERROR_XML, errCode);
122         if (!prefs) {
123             MEDIA_ERR_LOG("get preferences error: %{public}d", errCode);
124             return false;
125         }
126         prefs->Clear();
127         prefs->FlushSync();
128         return true;
129     }
130     return false;
131 }
132 
IsDeleteStatisticUpdate()133 bool DfxWorker::IsDeleteStatisticUpdate()
134 {
135     if (deleteStatisticVersion_ < LATEST_DELETE_STATISTIC_VERSION) {
136         MEDIA_INFO_LOG("update delete statistic version from %{public}d to %{public}d", deleteStatisticVersion_,
137             LATEST_DELETE_STATISTIC_VERSION);
138         int32_t errCode;
139         shared_ptr<NativePreferences::Preferences> prefs =
140             NativePreferences::PreferencesHelper::GetPreferences(DELETE_BEHAVIOR_XML, errCode);
141         if (!prefs) {
142             MEDIA_ERR_LOG("get preferences error: %{public}d", errCode);
143             return false;
144         }
145         prefs->Clear();
146         prefs->FlushSync();
147         return true;
148     }
149     return false;
150 }
151 
InitDelayThread()152 void DfxWorker::InitDelayThread()
153 {
154     Prepare();
155     bool isStartLoopTask = true;
156     MEDIA_INFO_LOG("InitDelayThread");
157     string name("DfxDelayThread");
158     pthread_setname_np(pthread_self(), name.c_str());
159     while (isThreadRunning_) {
160         if (isStartLoopTask) {
161             HandleLoopTask(nullptr);
162             StartLoopTaskDelay();
163             isStartLoopTask = false;
164         }
165         WaitForTask();
166         if (!isThreadRunning_) {
167             break;
168         }
169         if (IsTaskQueueEmpty()) {
170             continue;
171         }
172         auto now = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
173         auto executeTime = std::chrono::time_point_cast<std::chrono::milliseconds>(GetWaitTime());
174         auto delay = now.time_since_epoch().count() - executeTime.time_since_epoch().count();
175         if (delay < 0) {
176             continue;
177         }
178         shared_ptr<DfxTask> task = GetTask();
179         if (task == nullptr) {
180             continue;
181         }
182         task->executor_(task->data_);
183         if (task->isDelayTask_) {
184             StartLoopTaskDelay();
185         }
186         task = nullptr;
187     }
188 }
189 
StartLoopTaskDelay()190 void DfxWorker::StartLoopTaskDelay()
191 {
192     auto loopTask = make_shared<DfxTask>(HandleLoopTask, nullptr);
193     AddTask(loopTask, FIVE_MINUTE);
194 }
195 
compare(const shared_ptr<DfxTask> & taskOne,const shared_ptr<DfxTask> & taskTwo)196 static bool compare(const shared_ptr<DfxTask> &taskOne, const shared_ptr<DfxTask> &taskTwo)
197 {
198     auto firstTime = std::chrono::time_point_cast<std::chrono::milliseconds>(taskOne->executeTime_);
199     auto secondTime = std::chrono::time_point_cast<std::chrono::milliseconds>(taskTwo->executeTime_);
200     return firstTime.time_since_epoch().count() > secondTime.time_since_epoch().count();
201 }
202 
AddTask(const shared_ptr<DfxTask> & task,int64_t delayTime)203 void DfxWorker::AddTask(const shared_ptr<DfxTask> &task, int64_t delayTime)
204 {
205     lock_guard<mutex> lockGuard(taskLock_);
206     if (delayTime > 0) {
207         task->executeTime_ = std::chrono::system_clock::now() + std::chrono::milliseconds(delayTime);
208         task->isDelayTask_ = true;
209     }
210     taskList_.push_back(task);
211     sort(taskList_.begin(), taskList_.end(), compare);
212     workCv_.notify_one();
213 }
214 
IsTaskQueueEmpty()215 bool DfxWorker::IsTaskQueueEmpty()
216 {
217     lock_guard<mutex> lock_Guard(taskLock_);
218     return taskList_.empty();
219 }
220 
WaitForTask()221 void DfxWorker::WaitForTask()
222 {
223     std::unique_lock<std::mutex> lock(workLock_);
224     if (IsTaskQueueEmpty()) {
225         workCv_.wait(lock,
226             [this]() { return !isThreadRunning_ || !IsTaskQueueEmpty(); });
227     } else {
228         workCv_.wait_until(lock, GetWaitTime(),
229             [this]() { return !isThreadRunning_ || !IsDelayTask(); });
230     }
231 }
232 
GetTask()233 shared_ptr<DfxTask> DfxWorker::GetTask()
234 {
235     lock_guard<mutex> lockGuard(taskLock_);
236     if (taskList_.empty()) {
237         return nullptr;
238     }
239     shared_ptr<DfxTask> task = taskList_.back();
240     taskList_.pop_back();
241     return task;
242 }
243 
244 
IsDelayTask()245 bool DfxWorker::IsDelayTask()
246 {
247     lock_guard<mutex> lockGuard(taskLock_);
248     shared_ptr<DfxTask> task = taskList_.back();
249     return task->isDelayTask_;
250 }
251 
GetWaitTime()252 std::chrono::system_clock::time_point DfxWorker::GetWaitTime()
253 {
254     lock_guard<mutex> lockGuard(taskLock_);
255     shared_ptr<DfxTask> task = taskList_.back();
256     return task->executeTime_;
257 }
258 
End()259 void DfxWorker::End()
260 {
261     isEnd_ = true;
262 }
263 } // namespace Media
264 } // namespace OHOS