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