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 = false;
86 auto iter = sharedImageMap_.find(name);
87 if (iter != sharedImageMap_.end()) {
88 iter->second = std::move(sharedImage);
89 } else {
90 sharedImageMap_.emplace(name, std::move(sharedImage));
91 if (sharedImageMap_.size() > MAX_NUM_OF_IMAGE) {
92 isClear = true;
93 }
94 }
95 if (sharedImage.size() > MAX_SIZE_FOR_EACH_IMAGE) {
96 isClear = true;
97 }
98 auto taskExecutor = taskExecutor_.Upgrade();
99 CHECK_NULL_VOID(taskExecutor);
100 taskExecutor->PostTask(
101 [isClear, providerWpSet, name, wp = AceType::WeakClaim(this)]() {
102 auto sharedImageManager = wp.Upgrade();
103 CHECK_NULL_VOID(sharedImageManager);
104 size_t dataSize = 0;
105 {
106 std::lock_guard<std::mutex> lockImageMap(sharedImageManager->sharedImageMapMutex_);
107 auto sharedImageMap = sharedImageManager->GetSharedImageMap();
108 auto imageDataIter = sharedImageMap.find(name);
109 if (imageDataIter == sharedImageMap.end()) {
110 LOGW("fail to find data of %{public}s in sharedImageMap, stop UpdateData", name.c_str());
111 return;
112 }
113 dataSize = imageDataIter->second.size();
114 for (const auto& providerWp : providerWpSet) {
115 auto provider = providerWp.Upgrade();
116 if (!provider) {
117 continue;
118 }
119 provider->UpdateData(std::string(MEMORY_IMAGE_HEAD).append(name), imageDataIter->second);
120 }
121 }
122 if (isClear) {
123 sharedImageManager->PostDelayedTaskToClearImageData(name, dataSize);
124 }
125 },
126 TaskExecutor::TaskType::UI, "ArkUIImageAddSharedImageData");
127 }
128
AddPictureNamesToReloadMap(std::string && name)129 void SharedImageManager::AddPictureNamesToReloadMap(std::string&& name)
130 {
131 // add names of memory image to be read from shared memory
132 std::lock_guard<std::mutex> lock(providerMapMutex_);
133 providerMapToReload_.try_emplace(name, std::set<WeakPtr<ImageProviderLoader>>());
134 }
135
FindImageInSharedImageMap(const std::string & name,const WeakPtr<ImageProviderLoader> & providerWp)136 bool SharedImageManager::FindImageInSharedImageMap(
137 const std::string& name, const WeakPtr<ImageProviderLoader>& providerWp)
138 {
139 auto loader = providerWp.Upgrade();
140 if (!loader) {
141 return false;
142 }
143 std::lock_guard<std::mutex> lockImageMap(sharedImageMapMutex_);
144 auto iter = sharedImageMap_.find(name);
145 if (iter == sharedImageMap_.end()) {
146 LOGW("image data of %{private}s does not found in SharedImageMap", name.c_str());
147 return false;
148 }
149 loader->UpdateData(std::string(MEMORY_IMAGE_HEAD).append(name), iter->second);
150 return true;
151 }
152
RegisterLoader(const std::string & name,const WeakPtr<ImageProviderLoader> & providerWp)153 bool SharedImageManager::RegisterLoader(const std::string& name, const WeakPtr<ImageProviderLoader>& providerWp)
154 {
155 std::lock_guard<std::mutex> lockProviderMap(providerMapMutex_);
156 bool resourceInMap = (providerMapToReload_.find(name) != providerMapToReload_.end());
157 providerMapToReload_[name].emplace(providerWp);
158 return resourceInMap;
159 }
160
Remove(const std::string & name)161 bool SharedImageManager::Remove(const std::string& name)
162 {
163 int res = static_cast<int>(sharedImageMap_.erase(name));
164 return (res != 0);
165 }
166 } // namespace OHOS::Ace
167