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
25 namespace OHOS::Ace {
26 namespace {
27
28 constexpr uint32_t DELAY_TIME_FOR_IMAGE_DATA_CLEAN = 30000;
29 constexpr char MEMORY_IMAGE_HEAD[] = "memory://";
30
31 } // namespace
32
GenerateClearImageDataCallback(const std::string & name,size_t dataSize)33 std::function<void()> SharedImageManager::GenerateClearImageDataCallback(const std::string& name, size_t dataSize)
34 {
35 auto clearImageDataCallback = [wp = AceType::WeakClaim(this), picName = name, dataSize]() {
36 auto sharedImageManager = wp.Upgrade();
37 if (!sharedImageManager) {
38 return;
39 }
40 {
41 std::lock_guard<std::mutex> lockImageMap(sharedImageManager->sharedImageMapMutex_);
42 sharedImageManager->sharedImageMap_.erase(picName);
43 }
44 {
45 std::lock_guard<std::mutex> lockCancelableCallbackMap_(sharedImageManager->cancelableCallbackMapMutex_);
46 sharedImageManager->cancelableCallbackMap_.erase(picName);
47 }
48 LOGI("Done clean image data for %{private}s, data size is %{public}zu", picName.c_str(), dataSize);
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 if (!taskExecutor_) {
56 LOGE("taskExecutor is null!");
57 return;
58 }
59 std::lock_guard<std::mutex> lockCancelableCallbackMap_(cancelableCallbackMapMutex_);
60 auto& cancelableCallback = cancelableCallbackMap_[name];
61 cancelableCallback.Reset(GenerateClearImageDataCallback(name, dataSize));
62 taskExecutor_->PostDelayedTask(cancelableCallback, TaskExecutor::TaskType::IO, 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 if (!taskExecutor_) {
91 LOGE("taskExecutor is null when try UpdateData");
92 return;
93 }
94 taskExecutor_->PostTask([providerWpSet, name, wp = AceType::WeakClaim(this)] () {
95 auto sharedImageManager = wp.Upgrade();
96 if (!sharedImageManager) {
97 LOGE("sharedImageManager is null when try UpdateData");
98 return;
99 }
100 size_t dataSize = 0;
101 auto sharedImageMap = sharedImageManager->GetSharedImageMap();
102 {
103 std::lock_guard<std::mutex> lockImageMap(sharedImageManager->sharedImageMapMutex_);
104 auto imageDataIter = sharedImageMap.find(name);
105 if (imageDataIter == sharedImageMap.end()) {
106 LOGE("fail to find data of %{public}s in sharedImageMap, stop UpdateData", name.c_str());
107 return;
108 }
109 dataSize = imageDataIter->second.size();
110 for (const auto& providerWp : providerWpSet) {
111 auto provider = providerWp.Upgrade();
112 if (!provider) {
113 LOGE("provider of %{public}s is null when UpdateData, dataSize is %{public}zu",
114 name.c_str(), dataSize);
115 continue;
116 }
117 provider->UpdateData(std::string(MEMORY_IMAGE_HEAD).append(name), imageDataIter->second);
118 }
119 LOGI("done add image data for %{private}s, length of data is %{public}zu", name.c_str(), dataSize);
120 }
121 sharedImageManager->PostDelayedTaskToClearImageData(name, dataSize);
122 }, TaskExecutor::TaskType::UI);
123 }
124
AddPictureNamesToReloadMap(std::string && name)125 void SharedImageManager::AddPictureNamesToReloadMap(std::string&& name)
126 {
127 // add names of memory image to be read from shared memory
128 std::lock_guard<std::mutex> lock(providerMapMutex_);
129 providerMapToReload_.try_emplace(name, std::set<WeakPtr<ImageProviderLoader>>());
130 }
131
132
FindImageInSharedImageMap(const std::string & name,const WeakPtr<ImageProviderLoader> & providerWp)133 bool SharedImageManager::FindImageInSharedImageMap(
134 const std::string& name, const WeakPtr<ImageProviderLoader>& providerWp)
135 {
136 auto loader = providerWp.Upgrade();
137 if (!loader) {
138 LOGE("provider of %{private}s is null", name.c_str());
139 return false;
140 }
141 std::lock_guard<std::mutex> lockImageMap(sharedImageMapMutex_);
142 auto iter = sharedImageMap_.find(name);
143 if (iter == sharedImageMap_.end()) {
144 LOGE("image data of %{private}s does not found in SharedImageMap", name.c_str());
145 return false;
146 }
147 loader->UpdateData(std::string(MEMORY_IMAGE_HEAD).append(name), iter->second);
148 return true;
149 }
150
151 } // namespace OHOS::Ace
152