1 /*
2 * Copyright (c) 2025 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
16 #include "download_callback_middle_ani.h"
17 #include "dfs_error.h"
18 #include "multi_download_progress_ani.h"
19 #include "utils_log.h"
20
21 namespace OHOS::FileManagement::CloudSync {
22 constexpr int32_t ANI_SCOPE_SIZE = 16;
RemoveDownloadInfo(int64_t downloadId)23 void CloudDlCallbackMiddleAni::RemoveDownloadInfo(int64_t downloadId)
24 {
25 std::lock_guard<std::mutex> lock(downloadInfoMtx_);
26 downloadInfos_.erase(downloadId);
27 }
28
GetDownloadInfo(const DownloadProgressObj & progress)29 std::shared_ptr<DlProgressAni> CloudDlCallbackMiddleAni::GetDownloadInfo(const DownloadProgressObj &progress)
30 {
31 std::shared_ptr<DlProgressAni> originProgress = nullptr;
32 {
33 std::lock_guard<std::mutex> lock(downloadInfoMtx_);
34 auto it = downloadInfos_.find(progress.downloadId);
35 if (it == downloadInfos_.end()) {
36 return nullptr;
37 }
38 originProgress = it->second;
39 }
40
41 // Copy a new object to return the callback to avoid affecting the download progress.
42 std::shared_ptr<DlProgressAni> resProgress = originProgress->CreateNewObject();
43 originProgress->Update(progress);
44 resProgress->Update(progress);
45 return resProgress;
46 }
47
GetDownloadIdsByUri(const std::string & uri)48 std::vector<int64_t> CloudDlCallbackMiddleAni::GetDownloadIdsByUri(const std::string &uri)
49 {
50 std::vector<int64_t> ids;
51 std::lock_guard<std::mutex> lock(downloadInfoMtx_);
52 for (const auto &[id, progress] : downloadInfos_) {
53 if (progress->GetUri() == uri) {
54 ids.push_back(id);
55 }
56 }
57 return ids;
58 }
59
OnDownloadProcess(const DownloadProgressObj & progress)60 void CloudDlCallbackMiddleAni::OnDownloadProcess(const DownloadProgressObj &progress)
61 {
62 auto fileCacheInfo = GetDownloadInfo(progress);
63 if (fileCacheInfo == nullptr) {
64 LOGE("Failed to callback, no such taskId: %{public}lld", static_cast<long long>(progress.downloadId));
65 return;
66 }
67 std::shared_ptr<CloudDlCallbackMiddleAni> callbackImpl = shared_from_this();
68 auto task = [fileCacheInfo, callbackImpl]() mutable {
69 if (fileCacheInfo == nullptr || callbackImpl == nullptr) {
70 LOGE("Failed to callback, is callbackImpl null: %{public}d", (callbackImpl == nullptr));
71 return;
72 }
73 LOGI("CloudDlCallbackMiddleAni OnDownloadProcess for JS");
74 ani_env *tmpEnv = callbackImpl->GetEnv();
75 if (tmpEnv == nullptr) {
76 LOGE("Failed to get env from vm");
77 return;
78 }
79 ani_size nr_refs = ANI_SCOPE_SIZE;
80 ani_status ret = tmpEnv->CreateLocalScope(nr_refs);
81 if (ret != ANI_OK) {
82 LOGE("crete local scope failed. ret = %{public}d", ret);
83 return;
84 }
85 ani_object pg = fileCacheInfo->ConvertToObject(tmpEnv);
86 callbackImpl->OnJsCallback(tmpEnv, pg, 1);
87 ret = tmpEnv->DestroyLocalScope();
88 if (ret != ANI_OK) {
89 LOGE("failed to DestroyLocalScope. ret = %{public}d", ret);
90 }
91 if (fileCacheInfo->IsNeedClean()) {
92 callbackImpl->RemoveDownloadInfo(fileCacheInfo->GetTaskId());
93 }
94 callbackImpl->DetachEnv();
95 };
96 if (!ANIUtils::SendEventToMainThread(task)) {
97 LOGE("failed to send event");
98 }
99 }
100 } // namespace OHOS::FileManagement::CloudSync