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 };
50 return clearImageDataCallback;
51 }
52
PostDelayedTaskToClearImageData(const std::string & name,size_t dataSize)53 void SharedImageManager::PostDelayedTaskToClearImageData(const std::string& name, size_t dataSize)
54 {
55 auto taskExecutor = taskExecutor_.Upgrade();
56 CHECK_NULL_VOID(taskExecutor);
57 std::lock_guard<std::mutex> lockCancelableCallbackMap_(cancelableCallbackMapMutex_);
58 auto& cancelableCallback = cancelableCallbackMap_[name];
59 cancelableCallback.Reset(GenerateClearImageDataCallback(name, dataSize));
60 auto bkTask = [wp = taskExecutor_, cancelableCallback]() {
61 auto taskExecutor = wp.Upgrade();
62 CHECK_NULL_VOID(taskExecutor);
63 taskExecutor->PostTask(cancelableCallback, TaskExecutor::TaskType::BACKGROUND);
64 };
65 taskExecutor->PostDelayedTask(bkTask, TaskExecutor::TaskType::UI, DELAY_TIME_FOR_IMAGE_DATA_CLEAN);
66 }
67
AddSharedImage(const std::string & name,SharedImage && sharedImage)68 void SharedImageManager::AddSharedImage(const std::string& name, SharedImage&& sharedImage)
69 {
70 std::set<WeakPtr<ImageProviderLoader>> providerWpSet = std::set<WeakPtr<ImageProviderLoader>>();
71 // step1: lock provider map to search for record of current picture name
72 std::scoped_lock lock(providerMapMutex_, sharedImageMapMutex_);
73 auto providersToNotify = providerMapToReload_.find(name);
74 if (providersToNotify != providerMapToReload_.end()) {
75 for (const auto& providerWp : providersToNotify->second) {
76 auto provider = providerWp.Upgrade();
77 if (!provider) {
78 continue;
79 }
80 providerWpSet.emplace(provider);
81 }
82 providerMapToReload_.erase(providersToNotify);
83 }
84 // step2: lock image map to add shared image and notify [LazyMemoryImageProvider]s to update data and reload
85 // update image data when the name can be found in map
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 }
92 auto taskExecutor = taskExecutor_.Upgrade();
93 CHECK_NULL_VOID(taskExecutor);
94 taskExecutor->PostTask(
95 [providerWpSet, name, wp = AceType::WeakClaim(this)]() {
96 auto sharedImageManager = wp.Upgrade();
97 CHECK_NULL_VOID(sharedImageManager);
98 size_t dataSize = 0;
99 auto sharedImageMap = sharedImageManager->GetSharedImageMap();
100 {
101 std::lock_guard<std::mutex> lockImageMap(sharedImageManager->sharedImageMapMutex_);
102 auto imageDataIter = sharedImageMap.find(name);
103 if (imageDataIter == sharedImageMap.end()) {
104 LOGW("fail to find data of %{public}s in sharedImageMap, stop UpdateData", name.c_str());
105 return;
106 }
107 dataSize = imageDataIter->second.size();
108 for (const auto& providerWp : providerWpSet) {
109 auto provider = providerWp.Upgrade();
110 if (!provider) {
111 continue;
112 }
113 provider->UpdateData(std::string(MEMORY_IMAGE_HEAD).append(name), imageDataIter->second);
114 }
115 }
116 sharedImageManager->PostDelayedTaskToClearImageData(name, dataSize);
117 },
118 TaskExecutor::TaskType::UI);
119 }
120
AddPictureNamesToReloadMap(std::string && name)121 void SharedImageManager::AddPictureNamesToReloadMap(std::string&& name)
122 {
123 // add names of memory image to be read from shared memory
124 std::lock_guard<std::mutex> lock(providerMapMutex_);
125 providerMapToReload_.try_emplace(name, std::set<WeakPtr<ImageProviderLoader>>());
126 }
127
FindImageInSharedImageMap(const std::string & name,const WeakPtr<ImageProviderLoader> & providerWp)128 bool SharedImageManager::FindImageInSharedImageMap(
129 const std::string& name, const WeakPtr<ImageProviderLoader>& providerWp)
130 {
131 auto loader = providerWp.Upgrade();
132 if (!loader) {
133 return false;
134 }
135 std::lock_guard<std::mutex> lockImageMap(sharedImageMapMutex_);
136 auto iter = sharedImageMap_.find(name);
137 if (iter == sharedImageMap_.end()) {
138 LOGW("image data of %{private}s does not found in SharedImageMap", name.c_str());
139 return false;
140 }
141 loader->UpdateData(std::string(MEMORY_IMAGE_HEAD).append(name), iter->second);
142 return true;
143 }
144
RegisterLoader(const std::string & name,const WeakPtr<ImageProviderLoader> & providerWp)145 bool SharedImageManager::RegisterLoader(const std::string& name, const WeakPtr<ImageProviderLoader>& providerWp)
146 {
147 std::lock_guard<std::mutex> lockProviderMap(providerMapMutex_);
148 bool resourceInMap = (providerMapToReload_.find(name) != providerMapToReload_.end());
149 providerMapToReload_[name].emplace(providerWp);
150 return resourceInMap;
151 }
152
Remove(const std::string & name)153 bool SharedImageManager::Remove(const std::string& name)
154 {
155 int res = static_cast<int>(sharedImageMap_.erase(name));
156 return (res != 0);
157 }
158 } // namespace OHOS::Ace
159