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 "async_obtain_data.h"
16 #define LOG_TAG "AsyncObtainData"
17 #include <cstdint>
18 #include <algorithm>
19 #include "unified_types.h"
20 #include "logger.h"
21 #include "udmf_service_client.h"
22 #include "securec.h"
23
24 namespace OHOS {
25 namespace UDMF {
26 static constexpr size_t MAX_THREADS = 2;
27 static constexpr size_t MIN_THREADS = 0;
28 static constexpr uint32_t MAX_PROGRESS = 100;
29 static constexpr double MAX_PROGRESS_DOUBLE = 100.0;
30 static constexpr double SYNC_COEFF = 0.5;
31 static constexpr double PERM_COEFF = 0.4;
32
AsyncObtainData()33 AsyncObtainData::AsyncObtainData() : executor_(MAX_THREADS, MIN_THREADS) {}
34
InitTask(const QueryOption &query, ObtainDataCallback callback)35 Status AsyncObtainData::InitTask(const QueryOption &query, ObtainDataCallback callback)
36 {
37 if (callback == nullptr) {
38 LOG_ERROR(UDMF_CLIENT, "callback invalid");
39 taskStatus_ = ASYNC_FAILURE;
40 return E_INVALID_PARAMETERS;
41 }
42
43 serviceClient_ = UdmfServiceClient::GetInstance();
44 if (serviceClient_ == nullptr) {
45 LOG_ERROR(UDMF_CLIENT, "Service unavailable");
46 taskStatus_ = ASYNC_FAILURE;
47 return E_IPC;
48 }
49
50 initialized_ = true;
51 query_ = query;
52 callback_ = callback;
53 taskStatus_ = ASYNC_RUNNING;
54 processInfo_.syncStatus = ASYNC_RUNNING;
55 return E_OK;
56 }
57
RunTask()58 Status AsyncObtainData::RunTask()
59 {
60 LOG_DEBUG(UDMF_CLIENT, "Enter");
61 if (serviceClient_ == nullptr) {
62 LOG_ERROR(UDMF_CLIENT, "failed! service client is nullptr");
63 return E_IPC;
64 }
65 if (!initialized_) {
66 LOG_ERROR(UDMF_CLIENT, "failed! not init");
67 return E_ERROR;
68 }
69 obtainDataTaskId_ = executor_.Execute(std::bind(&AsyncObtainData::ObtainDataTask, this));
70 progressTaskId_ = executor_.Execute(std::bind(&AsyncObtainData::ProgressTask, this));
71
72 return E_OK;
73 }
74
ObtainDataTask()75 void AsyncObtainData::ObtainDataTask()
76 {
77 LOG_DEBUG(UDMF_CLIENT, "Enter");
78 if ((taskStatus_ == ASYNC_RUNNING) && (processInfo_.syncStatus == ASYNC_RUNNING)) {
79 Executor::Duration delay = std::chrono::milliseconds(500);
80 obtainDataTaskId_ = executor_.Schedule(delay, std::bind(&AsyncObtainData::ObtainDataTask, this));
81 return;
82 }
83
84 UnifiedData unifiedData;
85 if (taskStatus_ != ASYNC_FAILURE) {
86 if (serviceClient_ == nullptr) {
87 LOG_ERROR(UDMF_CLIENT, "failed! serviceClient_ is nullptr");
88 return;
89 }
90 int32_t ret = serviceClient_->GetData(query_, unifiedData);
91 if (ret != E_OK) {
92 LOG_ERROR(UDMF_CLIENT, "failed! ret = %{public}d", ret);
93 taskStatus_ = ASYNC_FAILURE;
94 } else {
95 taskStatus_ = ASYNC_SUCCESS;
96 }
97 }
98 InvokeCallback(unifiedData);
99 ClearTask();
100 }
101
ProgressTask()102 void AsyncObtainData::ProgressTask()
103 {
104 LOG_DEBUG(UDMF_CLIENT, "Enter");
105 if (serviceClient_ == nullptr) {
106 LOG_ERROR(UDMF_CLIENT, "failed! serviceClient_ is nullptr");
107 return;
108 }
109 AsyncProcessInfo processInfo;
110 int32_t ret = serviceClient_->ObtainAsynProcess(processInfo);
111 if (ret != E_OK) {
112 LOG_ERROR(UDMF_CLIENT, "failed! ret = %{public}d", ret);
113 taskStatus_ = ASYNC_FAILURE;
114 return;
115 }
116
117 UpdateProcessInfo(processInfo);
118
119 UnifiedData unifiedData;
120 InvokeCallback(unifiedData);
121
122 if ((taskStatus_ == ASYNC_RUNNING) &&
123 ((processInfo.syncStatus == ASYNC_RUNNING) || (processInfo.permStatus == ASYNC_RUNNING))) {
124 Executor::Duration delay = std::chrono::milliseconds(500);
125 progressTaskId_ = executor_.Schedule(delay, std::bind(&AsyncObtainData::ProgressTask, this));
126 }
127 }
128
InvokeCallback(UnifiedData &data)129 void AsyncObtainData::InvokeCallback(UnifiedData &data)
130 {
131 ProgressInfo progress{ "", ASYNC_IDLE, 0 };
132 progress.status = taskStatus_;
133 progress.srcDevName = processInfo_.srcDevName;
134
135 progress.progress = CalProgress();
136 if (progress.progress <= lastProgress_) {
137 progress.progress = lastProgress_;
138 } else {
139 lastProgress_ = progress.progress;
140 }
141 if (callback_ == nullptr) {
142 LOG_ERROR(UDMF_CLIENT, "failed! callback_ is nullptr");
143 return;
144 }
145 callback_(progress, data);
146 }
147
UpdateProcessInfo(AsyncProcessInfo &info)148 void AsyncObtainData::UpdateProcessInfo(AsyncProcessInfo &info)
149 {
150 processInfo_.syncStatus = info.syncStatus;
151 processInfo_.permStatus = info.permStatus;
152 processInfo_.srcDevName = (info.syncStatus == ASYNC_IDLE ? "Local" : info.srcDevName);
153 processInfo_.syncFinished = info.syncFinished;
154 processInfo_.syncTotal = info.syncTotal;
155 processInfo_.syncId = info.syncId;
156 processInfo_.permFnished = info.permFnished;
157 processInfo_.permTotal = info.permTotal;
158
159 if (processInfo_.syncStatus == ASYNC_FAILURE || processInfo_.permStatus == ASYNC_FAILURE) {
160 taskStatus_ = ASYNC_FAILURE;
161 }
162 }
163
ClearTask()164 void AsyncObtainData::ClearTask()
165 {
166 initialized_ = false;
167 taskStatus_ = ASYNC_IDLE;
168 lastProgress_ = 0;
169 progressTaskId_ = ExecutorPool::INVALID_TASK_ID;
170 obtainDataTaskId_ = ExecutorPool::INVALID_TASK_ID;
171 (void)memset_s(&processInfo_, sizeof(processInfo_), 0, sizeof(processInfo_));
172
173 serviceClient_ = UdmfServiceClient::GetInstance();
174 if (serviceClient_ == nullptr) {
175 return;
176 }
177 auto ret = serviceClient_->ClearAsynProcess();
178 if (ret != E_OK) {
179 LOG_ERROR(UDMF_CLIENT, "failed! ret = %{public}d", ret);
180 }
181 serviceClient_ = nullptr;
182 }
183
CalProgress()184 uint32_t AsyncObtainData::CalProgress()
185 {
186 if (taskStatus_ == ASYNC_SUCCESS) {
187 return MAX_PROGRESS;
188 }
189 if ((taskStatus_ == ASYNC_FAILURE) || (processInfo_.syncStatus == ASYNC_FAILURE) ||
190 processInfo_.permStatus == ASYNC_FAILURE) {
191 return lastProgress_;
192 }
193
194 uint32_t syncProgress = CalSyncProgress();
195 uint32_t permProgress = CalPermProgress();
196 double totalProgress = syncProgress * SYNC_COEFF + permProgress * PERM_COEFF;
197 return static_cast<uint32_t>(totalProgress);
198 }
199
CalSyncProgress()200 uint32_t AsyncObtainData::CalSyncProgress()
201 {
202 if (processInfo_.syncStatus == ASYNC_SUCCESS || processInfo_.syncStatus == ASYNC_IDLE) {
203 return MAX_PROGRESS;
204 }
205 if (processInfo_.syncTotal == 0) {
206 return 0;
207 }
208 return std::min(MAX_PROGRESS,
209 static_cast<uint32_t>(processInfo_.syncFinished * MAX_PROGRESS_DOUBLE / processInfo_.syncTotal));
210 }
211
CalPermProgress()212 uint32_t AsyncObtainData::CalPermProgress()
213 {
214 if (processInfo_.permStatus == ASYNC_SUCCESS) {
215 return MAX_PROGRESS;
216 }
217 if (processInfo_.permTotal == 0) {
218 return 0;
219 }
220 return std::min(MAX_PROGRESS,
221 static_cast<uint32_t>(processInfo_.permFnished * MAX_PROGRESS_DOUBLE / processInfo_.permTotal));
222 }
223 } // namespace UDMF
224 } // namespace OHOS