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 24namespace OHOS { 25namespace UDMF { 26static constexpr size_t MAX_THREADS = 2; 27static constexpr size_t MIN_THREADS = 0; 28static constexpr uint32_t MAX_PROGRESS = 100; 29static constexpr double MAX_PROGRESS_DOUBLE = 100.0; 30static constexpr double SYNC_COEFF = 0.5; 31static constexpr double PERM_COEFF = 0.4; 32 33AsyncObtainData::AsyncObtainData() : executor_(MAX_THREADS, MIN_THREADS) {} 34 35Status 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 58Status 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 75void 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 102void 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 129void 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 148void 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 164void 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 184uint32_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 200uint32_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 212uint32_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