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/log/log.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 } // namespace
27
GenerateClearImageDataCallback(const std::string & name,size_t dataSize)28 std::function<void()> SharedImageManager::GenerateClearImageDataCallback(const std::string& name, size_t dataSize)
29 {
30 auto clearImageDataCallback = [wp = AceType::WeakClaim(this), picName = name, dataSize]() {
31 auto sharedImageManager = wp.Upgrade();
32 if (!sharedImageManager) {
33 return;
34 }
35 {
36 std::lock_guard<std::mutex> lockImageMap(sharedImageManager->sharedImageMapMutex_);
37 sharedImageManager->sharedImageMap_.erase(picName);
38 }
39 {
40 std::lock_guard<std::mutex> lockCancelableCallbackMap_(sharedImageManager->cancelableCallbackMapMutex_);
41 sharedImageManager->cancelableCallbackMap_.erase(picName);
42 }
43 LOGI("Done clean image data for %{private}s, data size is %{public}zu", picName.c_str(), dataSize);
44 };
45 return clearImageDataCallback;
46 }
47
PostDelayedTaskToClearImageData(const std::string & name,size_t dataSize)48 void SharedImageManager::PostDelayedTaskToClearImageData(const std::string& name, size_t dataSize)
49 {
50 if (!taskExecutor_) {
51 LOGE("taskExecutor is null!");
52 return;
53 }
54 std::lock_guard<std::mutex> lockCancelableCallbackMap_(cancelableCallbackMapMutex_);
55 auto& cancelableCallback = cancelableCallbackMap_[name];
56 cancelableCallback.Reset(GenerateClearImageDataCallback(name, dataSize));
57 taskExecutor_->PostDelayedTask(cancelableCallback, TaskExecutor::TaskType::IO, DELAY_TIME_FOR_IMAGE_DATA_CLEAN);
58 }
59
AddSharedImage(const std::string & name,SharedImage && sharedImage)60 void SharedImageManager::AddSharedImage(const std::string& name, SharedImage&& sharedImage)
61 {
62 size_t dataSize = 0;
63 {
64 std::set<RefPtr<ImageProviderLoader>> providerSet = std::set<RefPtr<ImageProviderLoader>>();
65 // step1: lock provider map to search for record of current picture name
66 std::scoped_lock lock(providerMapMutex_, sharedImageMapMutex_);
67 auto providersToNotify = providerMapToReload_.find(name);
68 if (providersToNotify != providerMapToReload_.end()) {
69 for (const auto& providerWp : providersToNotify->second) {
70 auto provider = providerWp.Upgrade();
71 if (!provider) {
72 LOGE("provider of %{private}s is null, data size is %{public}zu", name.c_str(), sharedImage.size());
73 continue;
74 }
75 providerSet.emplace(provider);
76 }
77 providerMapToReload_.erase(providersToNotify);
78 }
79 // step2: lock image map to add shared image and notify [LazyMemoryImageProvider]s to update data and reload
80 // update image data when the name can be found in map
81 auto result = sharedImageMap_.try_emplace(name, std::move(sharedImage));
82 if (!result.second) {
83 result.first->second = std::move(sharedImage);
84 }
85 for (const auto& provider : providerSet) {
86 provider->UpdateData(std::string(MEMORY_IMAGE_HEAD).append(name), result.first->second);
87 }
88 dataSize = result.first->second.size();
89 LOGI("done add image data for %{private}s, length of data is %{public}zu", name.c_str(), dataSize);
90 }
91 PostDelayedTaskToClearImageData(name, dataSize);
92 }
93
AddPictureNamesToReloadMap(std::string && name)94 void SharedImageManager::AddPictureNamesToReloadMap(std::string&& name)
95 {
96 // add names of memory image to be read from shared memory
97 std::lock_guard<std::mutex> lock(providerMapMutex_);
98 providerMapToReload_.try_emplace(name, std::set<WeakPtr<ImageProviderLoader>>());
99 }
100
AddProviderToReloadMap(const std::string & name,const WeakPtr<ImageProviderLoader> & loaderWp)101 bool SharedImageManager::AddProviderToReloadMap(
102 const std::string& name, const WeakPtr<ImageProviderLoader>& loaderWp)
103 {
104 std::lock_guard<std::mutex> lock(providerMapMutex_);
105 auto providerMapIter = providerMapToReload_.find(name);
106 if (providerMapIter != providerMapToReload_.end()) {
107 providerMapIter->second.emplace(loaderWp);
108 return true;
109 }
110 return false;
111 }
112
FindImageInSharedImageMap(const std::string & name,const WeakPtr<ImageProviderLoader> & providerWp)113 bool SharedImageManager::FindImageInSharedImageMap(
114 const std::string& name, const WeakPtr<ImageProviderLoader>& providerWp)
115 {
116 auto loader = providerWp.Upgrade();
117 if (!loader) {
118 LOGE("provider of %{private}s is null", name.c_str());
119 return false;
120 }
121 std::lock_guard<std::mutex> lockImageMap(sharedImageMapMutex_);
122 auto iter = sharedImageMap_.find(name);
123 if (iter == sharedImageMap_.end()) {
124 LOGE("image data of %{private}s does not found in SharedImageMap", name.c_str());
125 return false;
126 }
127 loader->UpdateData(std::string(MEMORY_IMAGE_HEAD).append(name), iter->second);
128 return true;
129 }
130
131 } // namespace OHOS::Ace
132