114cf0368Sopenharmony_ci/*
214cf0368Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
314cf0368Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
414cf0368Sopenharmony_ci * you may not use this file except in compliance with the License.
514cf0368Sopenharmony_ci * You may obtain a copy of the License at
614cf0368Sopenharmony_ci *
714cf0368Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
814cf0368Sopenharmony_ci *
914cf0368Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1014cf0368Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1114cf0368Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1214cf0368Sopenharmony_ci * See the License for the specific language governing permissions and
1314cf0368Sopenharmony_ci * limitations under the License.
1414cf0368Sopenharmony_ci */
1514cf0368Sopenharmony_ci#include "async_obtain_data.h"
1614cf0368Sopenharmony_ci#define LOG_TAG "AsyncObtainData"
1714cf0368Sopenharmony_ci#include <cstdint>
1814cf0368Sopenharmony_ci#include <algorithm>
1914cf0368Sopenharmony_ci#include "unified_types.h"
2014cf0368Sopenharmony_ci#include "logger.h"
2114cf0368Sopenharmony_ci#include "udmf_service_client.h"
2214cf0368Sopenharmony_ci#include "securec.h"
2314cf0368Sopenharmony_ci
2414cf0368Sopenharmony_cinamespace OHOS {
2514cf0368Sopenharmony_cinamespace UDMF {
2614cf0368Sopenharmony_cistatic constexpr size_t MAX_THREADS = 2;
2714cf0368Sopenharmony_cistatic constexpr size_t MIN_THREADS = 0;
2814cf0368Sopenharmony_cistatic constexpr uint32_t MAX_PROGRESS = 100;
2914cf0368Sopenharmony_cistatic constexpr double MAX_PROGRESS_DOUBLE = 100.0;
3014cf0368Sopenharmony_cistatic constexpr double SYNC_COEFF = 0.5;
3114cf0368Sopenharmony_cistatic constexpr double PERM_COEFF = 0.4;
3214cf0368Sopenharmony_ci
3314cf0368Sopenharmony_ciAsyncObtainData::AsyncObtainData() : executor_(MAX_THREADS, MIN_THREADS) {}
3414cf0368Sopenharmony_ci
3514cf0368Sopenharmony_ciStatus AsyncObtainData::InitTask(const QueryOption &query, ObtainDataCallback callback)
3614cf0368Sopenharmony_ci{
3714cf0368Sopenharmony_ci    if (callback == nullptr) {
3814cf0368Sopenharmony_ci        LOG_ERROR(UDMF_CLIENT, "callback invalid");
3914cf0368Sopenharmony_ci        taskStatus_ = ASYNC_FAILURE;
4014cf0368Sopenharmony_ci        return E_INVALID_PARAMETERS;
4114cf0368Sopenharmony_ci    }
4214cf0368Sopenharmony_ci
4314cf0368Sopenharmony_ci    serviceClient_ = UdmfServiceClient::GetInstance();
4414cf0368Sopenharmony_ci    if (serviceClient_ == nullptr) {
4514cf0368Sopenharmony_ci        LOG_ERROR(UDMF_CLIENT, "Service unavailable");
4614cf0368Sopenharmony_ci        taskStatus_ = ASYNC_FAILURE;
4714cf0368Sopenharmony_ci        return E_IPC;
4814cf0368Sopenharmony_ci    }
4914cf0368Sopenharmony_ci
5014cf0368Sopenharmony_ci    initialized_ = true;
5114cf0368Sopenharmony_ci    query_ = query;
5214cf0368Sopenharmony_ci    callback_ = callback;
5314cf0368Sopenharmony_ci    taskStatus_ = ASYNC_RUNNING;
5414cf0368Sopenharmony_ci    processInfo_.syncStatus = ASYNC_RUNNING;
5514cf0368Sopenharmony_ci    return E_OK;
5614cf0368Sopenharmony_ci}
5714cf0368Sopenharmony_ci
5814cf0368Sopenharmony_ciStatus AsyncObtainData::RunTask()
5914cf0368Sopenharmony_ci{
6014cf0368Sopenharmony_ci    LOG_DEBUG(UDMF_CLIENT, "Enter");
6114cf0368Sopenharmony_ci    if (serviceClient_ == nullptr) {
6214cf0368Sopenharmony_ci        LOG_ERROR(UDMF_CLIENT, "failed! service client is nullptr");
6314cf0368Sopenharmony_ci        return E_IPC;
6414cf0368Sopenharmony_ci    }
6514cf0368Sopenharmony_ci    if (!initialized_) {
6614cf0368Sopenharmony_ci        LOG_ERROR(UDMF_CLIENT, "failed! not init");
6714cf0368Sopenharmony_ci        return E_ERROR;
6814cf0368Sopenharmony_ci    }
6914cf0368Sopenharmony_ci    obtainDataTaskId_ = executor_.Execute(std::bind(&AsyncObtainData::ObtainDataTask, this));
7014cf0368Sopenharmony_ci    progressTaskId_ = executor_.Execute(std::bind(&AsyncObtainData::ProgressTask, this));
7114cf0368Sopenharmony_ci
7214cf0368Sopenharmony_ci    return E_OK;
7314cf0368Sopenharmony_ci}
7414cf0368Sopenharmony_ci
7514cf0368Sopenharmony_civoid AsyncObtainData::ObtainDataTask()
7614cf0368Sopenharmony_ci{
7714cf0368Sopenharmony_ci    LOG_DEBUG(UDMF_CLIENT, "Enter");
7814cf0368Sopenharmony_ci    if ((taskStatus_ == ASYNC_RUNNING) && (processInfo_.syncStatus == ASYNC_RUNNING)) {
7914cf0368Sopenharmony_ci        Executor::Duration delay = std::chrono::milliseconds(500);
8014cf0368Sopenharmony_ci        obtainDataTaskId_ = executor_.Schedule(delay, std::bind(&AsyncObtainData::ObtainDataTask, this));
8114cf0368Sopenharmony_ci        return;
8214cf0368Sopenharmony_ci    }
8314cf0368Sopenharmony_ci
8414cf0368Sopenharmony_ci    UnifiedData unifiedData;
8514cf0368Sopenharmony_ci    if (taskStatus_ != ASYNC_FAILURE) {
8614cf0368Sopenharmony_ci        if (serviceClient_ == nullptr) {
8714cf0368Sopenharmony_ci            LOG_ERROR(UDMF_CLIENT, "failed! serviceClient_ is nullptr");
8814cf0368Sopenharmony_ci            return;
8914cf0368Sopenharmony_ci        }
9014cf0368Sopenharmony_ci        int32_t ret = serviceClient_->GetData(query_, unifiedData);
9114cf0368Sopenharmony_ci        if (ret != E_OK) {
9214cf0368Sopenharmony_ci            LOG_ERROR(UDMF_CLIENT, "failed! ret = %{public}d", ret);
9314cf0368Sopenharmony_ci            taskStatus_ = ASYNC_FAILURE;
9414cf0368Sopenharmony_ci        } else {
9514cf0368Sopenharmony_ci            taskStatus_ = ASYNC_SUCCESS;
9614cf0368Sopenharmony_ci        }
9714cf0368Sopenharmony_ci    }
9814cf0368Sopenharmony_ci    InvokeCallback(unifiedData);
9914cf0368Sopenharmony_ci    ClearTask();
10014cf0368Sopenharmony_ci}
10114cf0368Sopenharmony_ci
10214cf0368Sopenharmony_civoid AsyncObtainData::ProgressTask()
10314cf0368Sopenharmony_ci{
10414cf0368Sopenharmony_ci    LOG_DEBUG(UDMF_CLIENT, "Enter");
10514cf0368Sopenharmony_ci    if (serviceClient_ == nullptr) {
10614cf0368Sopenharmony_ci        LOG_ERROR(UDMF_CLIENT, "failed! serviceClient_ is nullptr");
10714cf0368Sopenharmony_ci        return;
10814cf0368Sopenharmony_ci    }
10914cf0368Sopenharmony_ci    AsyncProcessInfo processInfo;
11014cf0368Sopenharmony_ci    int32_t ret = serviceClient_->ObtainAsynProcess(processInfo);
11114cf0368Sopenharmony_ci    if (ret != E_OK) {
11214cf0368Sopenharmony_ci        LOG_ERROR(UDMF_CLIENT, "failed! ret = %{public}d", ret);
11314cf0368Sopenharmony_ci        taskStatus_ = ASYNC_FAILURE;
11414cf0368Sopenharmony_ci        return;
11514cf0368Sopenharmony_ci    }
11614cf0368Sopenharmony_ci
11714cf0368Sopenharmony_ci    UpdateProcessInfo(processInfo);
11814cf0368Sopenharmony_ci
11914cf0368Sopenharmony_ci    UnifiedData unifiedData;
12014cf0368Sopenharmony_ci    InvokeCallback(unifiedData);
12114cf0368Sopenharmony_ci
12214cf0368Sopenharmony_ci    if ((taskStatus_ == ASYNC_RUNNING) &&
12314cf0368Sopenharmony_ci        ((processInfo.syncStatus == ASYNC_RUNNING) || (processInfo.permStatus == ASYNC_RUNNING))) {
12414cf0368Sopenharmony_ci        Executor::Duration delay = std::chrono::milliseconds(500);
12514cf0368Sopenharmony_ci        progressTaskId_ = executor_.Schedule(delay, std::bind(&AsyncObtainData::ProgressTask, this));
12614cf0368Sopenharmony_ci    }
12714cf0368Sopenharmony_ci}
12814cf0368Sopenharmony_ci
12914cf0368Sopenharmony_civoid AsyncObtainData::InvokeCallback(UnifiedData &data)
13014cf0368Sopenharmony_ci{
13114cf0368Sopenharmony_ci    ProgressInfo progress{ "", ASYNC_IDLE, 0 };
13214cf0368Sopenharmony_ci    progress.status = taskStatus_;
13314cf0368Sopenharmony_ci    progress.srcDevName = processInfo_.srcDevName;
13414cf0368Sopenharmony_ci
13514cf0368Sopenharmony_ci    progress.progress = CalProgress();
13614cf0368Sopenharmony_ci    if (progress.progress <= lastProgress_) {
13714cf0368Sopenharmony_ci        progress.progress = lastProgress_;
13814cf0368Sopenharmony_ci    } else {
13914cf0368Sopenharmony_ci        lastProgress_ = progress.progress;
14014cf0368Sopenharmony_ci    }
14114cf0368Sopenharmony_ci    if (callback_ == nullptr) {
14214cf0368Sopenharmony_ci        LOG_ERROR(UDMF_CLIENT, "failed! callback_ is nullptr");
14314cf0368Sopenharmony_ci        return;
14414cf0368Sopenharmony_ci    }
14514cf0368Sopenharmony_ci    callback_(progress, data);
14614cf0368Sopenharmony_ci}
14714cf0368Sopenharmony_ci
14814cf0368Sopenharmony_civoid AsyncObtainData::UpdateProcessInfo(AsyncProcessInfo &info)
14914cf0368Sopenharmony_ci{
15014cf0368Sopenharmony_ci    processInfo_.syncStatus = info.syncStatus;
15114cf0368Sopenharmony_ci    processInfo_.permStatus = info.permStatus;
15214cf0368Sopenharmony_ci    processInfo_.srcDevName = (info.syncStatus == ASYNC_IDLE ? "Local" : info.srcDevName);
15314cf0368Sopenharmony_ci    processInfo_.syncFinished = info.syncFinished;
15414cf0368Sopenharmony_ci    processInfo_.syncTotal = info.syncTotal;
15514cf0368Sopenharmony_ci    processInfo_.syncId = info.syncId;
15614cf0368Sopenharmony_ci    processInfo_.permFnished = info.permFnished;
15714cf0368Sopenharmony_ci    processInfo_.permTotal = info.permTotal;
15814cf0368Sopenharmony_ci
15914cf0368Sopenharmony_ci    if (processInfo_.syncStatus == ASYNC_FAILURE || processInfo_.permStatus == ASYNC_FAILURE) {
16014cf0368Sopenharmony_ci        taskStatus_ = ASYNC_FAILURE;
16114cf0368Sopenharmony_ci    }
16214cf0368Sopenharmony_ci}
16314cf0368Sopenharmony_ci
16414cf0368Sopenharmony_civoid AsyncObtainData::ClearTask()
16514cf0368Sopenharmony_ci{
16614cf0368Sopenharmony_ci    initialized_ = false;
16714cf0368Sopenharmony_ci    taskStatus_ = ASYNC_IDLE;
16814cf0368Sopenharmony_ci    lastProgress_ = 0;
16914cf0368Sopenharmony_ci    progressTaskId_ = ExecutorPool::INVALID_TASK_ID;
17014cf0368Sopenharmony_ci    obtainDataTaskId_ = ExecutorPool::INVALID_TASK_ID;
17114cf0368Sopenharmony_ci    (void)memset_s(&processInfo_, sizeof(processInfo_), 0, sizeof(processInfo_));
17214cf0368Sopenharmony_ci
17314cf0368Sopenharmony_ci    serviceClient_ = UdmfServiceClient::GetInstance();
17414cf0368Sopenharmony_ci    if (serviceClient_ == nullptr) {
17514cf0368Sopenharmony_ci        return;
17614cf0368Sopenharmony_ci    }
17714cf0368Sopenharmony_ci    auto ret = serviceClient_->ClearAsynProcess();
17814cf0368Sopenharmony_ci    if (ret != E_OK) {
17914cf0368Sopenharmony_ci        LOG_ERROR(UDMF_CLIENT, "failed! ret = %{public}d", ret);
18014cf0368Sopenharmony_ci    }
18114cf0368Sopenharmony_ci    serviceClient_ = nullptr;
18214cf0368Sopenharmony_ci}
18314cf0368Sopenharmony_ci
18414cf0368Sopenharmony_ciuint32_t AsyncObtainData::CalProgress()
18514cf0368Sopenharmony_ci{
18614cf0368Sopenharmony_ci    if (taskStatus_ == ASYNC_SUCCESS) {
18714cf0368Sopenharmony_ci        return MAX_PROGRESS;
18814cf0368Sopenharmony_ci    }
18914cf0368Sopenharmony_ci    if ((taskStatus_ == ASYNC_FAILURE) || (processInfo_.syncStatus == ASYNC_FAILURE) ||
19014cf0368Sopenharmony_ci        processInfo_.permStatus == ASYNC_FAILURE) {
19114cf0368Sopenharmony_ci        return lastProgress_;
19214cf0368Sopenharmony_ci    }
19314cf0368Sopenharmony_ci
19414cf0368Sopenharmony_ci    uint32_t syncProgress = CalSyncProgress();
19514cf0368Sopenharmony_ci    uint32_t permProgress = CalPermProgress();
19614cf0368Sopenharmony_ci    double totalProgress = syncProgress * SYNC_COEFF + permProgress * PERM_COEFF;
19714cf0368Sopenharmony_ci    return static_cast<uint32_t>(totalProgress);
19814cf0368Sopenharmony_ci}
19914cf0368Sopenharmony_ci
20014cf0368Sopenharmony_ciuint32_t AsyncObtainData::CalSyncProgress()
20114cf0368Sopenharmony_ci{
20214cf0368Sopenharmony_ci    if (processInfo_.syncStatus == ASYNC_SUCCESS || processInfo_.syncStatus == ASYNC_IDLE) {
20314cf0368Sopenharmony_ci        return MAX_PROGRESS;
20414cf0368Sopenharmony_ci    }
20514cf0368Sopenharmony_ci    if (processInfo_.syncTotal == 0) {
20614cf0368Sopenharmony_ci        return 0;
20714cf0368Sopenharmony_ci    }
20814cf0368Sopenharmony_ci    return std::min(MAX_PROGRESS,
20914cf0368Sopenharmony_ci        static_cast<uint32_t>(processInfo_.syncFinished * MAX_PROGRESS_DOUBLE / processInfo_.syncTotal));
21014cf0368Sopenharmony_ci}
21114cf0368Sopenharmony_ci
21214cf0368Sopenharmony_ciuint32_t AsyncObtainData::CalPermProgress()
21314cf0368Sopenharmony_ci{
21414cf0368Sopenharmony_ci    if (processInfo_.permStatus == ASYNC_SUCCESS) {
21514cf0368Sopenharmony_ci        return MAX_PROGRESS;
21614cf0368Sopenharmony_ci    }
21714cf0368Sopenharmony_ci    if (processInfo_.permTotal == 0) {
21814cf0368Sopenharmony_ci        return 0;
21914cf0368Sopenharmony_ci    }
22014cf0368Sopenharmony_ci    return std::min(MAX_PROGRESS,
22114cf0368Sopenharmony_ci        static_cast<uint32_t>(processInfo_.permFnished * MAX_PROGRESS_DOUBLE / processInfo_.permTotal));
22214cf0368Sopenharmony_ci}
22314cf0368Sopenharmony_ci} // namespace UDMF
22414cf0368Sopenharmony_ci} // namespace OHOS