1 /*
2 * Copyright (c) 2021 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 "base/resource/shared_image_manager.h"
17
18 #include "base/utils/utils.h"
19
20 namespace OHOS::Ace {
21 namespace {
22
23 constexpr uint32_t DELAY_TIME_FOR_IMAGE_DATA_CLEAN = 30000;
24 constexpr char MEMORY_IMAGE_HEAD[] = "memory://";
25
26 constexpr uint32_t MAX_SIZE_FOR_EACH_IMAGE = 2000000;
27 constexpr uint32_t MAX_NUM_OF_IMAGE = 5;
28
29 } // namespace
30
GenerateClearImageDataCallback(const std::string& name, size_t dataSize)31 std::function<void()> SharedImageManager::GenerateClearImageDataCallback(const std::string& name, size_t dataSize)
32 {
33 auto clearImageDataCallback = [wp = AceType::WeakClaim(this), picName = name, dataSize]() {
34 auto sharedImageManager = wp.Upgrade();
35 if (!sharedImageManager) {
36 return;
37 }
38 {
39 std::lock_guard<std::mutex> lockImageMap(sharedImageManager->sharedImageMapMutex_);
40 sharedImageManager->sharedImageMap_.erase(picName);
41 }
42 {
43 std::lock_guard<std::mutex> lockCancelableCallbackMap_(sharedImageManager->cancelableCallbackMapMutex_);
44 sharedImageManager->cancelableCallbackMap_.erase(picName);
45 }
46 };
47 return clearImageDataCallback;
48 }
49
PostDelayedTaskToClearImageData(const std::string& name, size_t dataSize)50 void SharedImageManager::PostDelayedTaskToClearImageData(const std::string& name, size_t dataSize)
51 {
52 auto taskExecutor = taskExecutor_.Upgrade();
53 CHECK_NULL_VOID(taskExecutor);
54 std::lock_guard<std::mutex> lockCancelableCallbackMap_(cancelableCallbackMapMutex_);
55 auto& cancelableCallback = cancelableCallbackMap_[name];
56 cancelableCallback.Reset(GenerateClearImageDataCallback(name, dataSize));
57 auto bkTask = [wp = taskExecutor_, cancelableCallback]() {
58 auto taskExecutor = wp.Upgrade();
59 CHECK_NULL_VOID(taskExecutor);
60 taskExecutor->PostTask(
61 cancelableCallback, TaskExecutor::TaskType::BACKGROUND, "ArkUIImageClearSharedImageData");
62 };
63 taskExecutor->PostDelayedTask(
64 bkTask, TaskExecutor::TaskType::UI, DELAY_TIME_FOR_IMAGE_DATA_CLEAN, "ArkUIImageClearSharedImageData");
65 }
66
AddSharedImage(const std::string& name, SharedImage&& sharedImage)67 void SharedImageManager::AddSharedImage(const std::string& name, SharedImage&& sharedImage)
68 {
69 std::set<WeakPtr<ImageProviderLoader>> providerWpSet = std::set<WeakPtr<ImageProviderLoader>>();
70 // step1: lock provider map to search for record of current picture name
71 std::scoped_lock lock(providerMapMutex_, sharedImageMapMutex_);
72 auto providersToNotify = providerMapToReload_.find(name);
73 if (providersToNotify != providerMapToReload_.end()) {
74 for (const auto& providerWp : providersToNotify->second) {
75 auto provider = providerWp.Upgrade();
76 if (!provider) {
77 continue;
78 }
79 providerWpSet.emplace(provider);
80 }
81 providerMapToReload_.erase(providersToNotify);
82 }
83 // step2: lock image map to add shared image and notify [LazyMemoryImageProvider]s to update data and reload
84 // update image data when the name can be found in map
85 bool isClear = UpdateImageMap(name, sharedImage);
86 auto taskExecutor = taskExecutor_.Upgrade();
87 CHECK_NULL_VOID(taskExecutor);
88 taskExecutor->PostTask(
89 [isClear, providerWpSet, name, wp = AceType::WeakClaim(this)]() {
90 auto sharedImageManager = wp.Upgrade();
91 CHECK_NULL_VOID(sharedImageManager);
92 size_t dataSize = 0;
93 {
94 std::lock_guard<std::mutex> lockImageMap(sharedImageManager->sharedImageMapMutex_);
95 auto sharedImageMap = sharedImageManager->GetSharedImageMap();
96 auto imageDataIter = sharedImageMap.find(name);
97 if (imageDataIter == sharedImageMap.end()) {
98 LOGW("fail to find data of %{public}s in sharedImageMap, stop UpdateData", name.c_str());
99 return;
100 }
101 dataSize = imageDataIter->second.size();
102 for (const auto& providerWp : providerWpSet) {
103 auto provider = providerWp.Upgrade();
104 if (!provider) {
105 continue;
106 }
107 provider->UpdateData(std::string(MEMORY_IMAGE_HEAD).append(name), imageDataIter->second);
108 }
109 }
110 if (isClear) {
111 sharedImageManager->PostDelayedTaskToClearImageData(name, dataSize);
112 }
113 },
114 TaskExecutor::TaskType::UI, "ArkUIImageAddSharedImageData");
115 }
116
UpdateImageMap(const std::string& name, const SharedImage& sharedImage)117 bool SharedImageManager::UpdateImageMap(const std::string& name, const SharedImage& sharedImage)
118 {
119 bool isClear = false;
120 auto iter = sharedImageMap_.find(name);
121 if (iter != sharedImageMap_.end()) {
122 iter->second = sharedImage;
123 } else {
124 sharedImageMap_.emplace(name, sharedImage);
125 if (sharedImageMap_.size() > MAX_NUM_OF_IMAGE) {
126 isClear = true;
127 }
128 }
129 if (sharedImage.size() > MAX_SIZE_FOR_EACH_IMAGE) {
130 isClear = true;
131 }
132 return isClear;
133 }
134
AddPictureNamesToReloadMap(std::string&& name)135 void SharedImageManager::AddPictureNamesToReloadMap(std::string&& name)
136 {
137 // add names of memory image to be read from shared memory
138 std::lock_guard<std::mutex> lock(providerMapMutex_);
139 providerMapToReload_.try_emplace(name, std::set<WeakPtr<ImageProviderLoader>>());
140 }
141
FindImageInSharedImageMap( const std::string& name, const WeakPtr<ImageProviderLoader>& providerWp)142 bool SharedImageManager::FindImageInSharedImageMap(
143 const std::string& name, const WeakPtr<ImageProviderLoader>& providerWp)
144 {
145 auto loader = providerWp.Upgrade();
146 if (!loader) {
147 return false;
148 }
149 std::lock_guard<std::mutex> lockImageMap(sharedImageMapMutex_);
150 auto iter = sharedImageMap_.find(name);
151 if (iter == sharedImageMap_.end()) {
152 LOGW("image data of %{private}s does not found in SharedImageMap", name.c_str());
153 return false;
154 }
155 loader->UpdateData(std::string(MEMORY_IMAGE_HEAD).append(name), iter->second);
156 return true;
157 }
158
RegisterLoader(const std::string& name, const WeakPtr<ImageProviderLoader>& providerWp)159 bool SharedImageManager::RegisterLoader(const std::string& name, const WeakPtr<ImageProviderLoader>& providerWp)
160 {
161 std::lock_guard<std::mutex> lockProviderMap(providerMapMutex_);
162 bool resourceInMap = (providerMapToReload_.find(name) != providerMapToReload_.end());
163 providerMapToReload_[name].emplace(providerWp);
164 return resourceInMap;
165 }
166
Remove(const std::string& name)167 bool SharedImageManager::Remove(const std::string& name)
168 {
169 int res = static_cast<int>(sharedImageMap_.erase(name));
170 return (res != 0);
171 }
172 } // namespace OHOS::Ace
173