• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 size_t MAX_SIZE_FOR_TOTAL_IMAGE = 10000000;
27 
28 } // namespace
29 
GenerateClearImageDataCallback(const std::string & name,size_t dataSize)30 std::function<void()> SharedImageManager::GenerateClearImageDataCallback(const std::string& name, size_t dataSize)
31 {
32     auto clearImageDataCallback = [wp = AceType::WeakClaim(this), picName = name, dataSize]() {
33         auto sharedImageManager = wp.Upgrade();
34         if (!sharedImageManager) {
35             return;
36         }
37         {
38             std::lock_guard<std::mutex> lockImageMap(sharedImageManager->sharedImageMapMutex_);
39             sharedImageManager->sharedImageMap_.erase(picName);
40         }
41         {
42             std::lock_guard<std::mutex> lockCancelableCallbackMap_(sharedImageManager->cancelableCallbackMapMutex_);
43             std::lock_guard<std::mutex> lockImageMap(sharedImageManager->sharedImageMapMutex_);
44             LOGW("clear image cache name: %{public}s", picName.c_str());
45             sharedImageManager->sharedImageTotalSize_ -= dataSize;
46             sharedImageManager->cancelableCallbackMap_.erase(picName);
47         }
48     };
49     return clearImageDataCallback;
50 }
51 
PostDelayedTaskToClearImageData(const std::string & name,size_t dataSize)52 void SharedImageManager::PostDelayedTaskToClearImageData(const std::string& name, size_t dataSize)
53 {
54     auto taskExecutor = taskExecutor_.Upgrade();
55     CHECK_NULL_VOID(taskExecutor);
56     std::lock_guard<std::mutex> lockCancelableCallbackMap_(cancelableCallbackMapMutex_);
57     auto& cancelableCallback = cancelableCallbackMap_[name];
58     cancelableCallback.Reset(GenerateClearImageDataCallback(name, dataSize));
59     auto bkTask = [wp = taskExecutor_, cancelableCallback]() {
60         auto taskExecutor = wp.Upgrade();
61         CHECK_NULL_VOID(taskExecutor);
62         taskExecutor->PostTask(
63             cancelableCallback, TaskExecutor::TaskType::BACKGROUND, "ArkUIImageClearSharedImageData");
64     };
65     taskExecutor->PostDelayedTask(
66         bkTask, TaskExecutor::TaskType::UI, DELAY_TIME_FOR_IMAGE_DATA_CLEAN, "ArkUIImageClearSharedImageData");
67 }
68 
AddSharedImage(const std::string & name,SharedImage && sharedImage)69 void SharedImageManager::AddSharedImage(const std::string& name, SharedImage&& sharedImage)
70 {
71         std::set<WeakPtr<ImageProviderLoader>> providerWpSet = std::set<WeakPtr<ImageProviderLoader>>();
72         // step1: lock provider map to search for record of current picture name
73         std::scoped_lock lock(providerMapMutex_, sharedImageMapMutex_);
74         auto providersToNotify = providerMapToReload_.find(name);
75         if (providersToNotify != providerMapToReload_.end()) {
76             for (const auto& providerWp : providersToNotify->second) {
77                 auto provider = providerWp.Upgrade();
78                 if (!provider) {
79                     continue;
80                 }
81                 providerWpSet.emplace(provider);
82             }
83             providerMapToReload_.erase(providersToNotify);
84         }
85         // step2: lock image map to add shared image and notify [LazyMemoryImageProvider]s to update data and reload
86         // update image data when the name can be found in map
87         bool isClear = UpdateImageMap(name, sharedImage);
88         auto taskExecutor = taskExecutor_.Upgrade();
89         CHECK_NULL_VOID(taskExecutor);
90         taskExecutor->PostTask(
91             [isClear, providerWpSet, name, wp = AceType::WeakClaim(this)]() {
92                 auto sharedImageManager = wp.Upgrade();
93                 CHECK_NULL_VOID(sharedImageManager);
94                 size_t dataSize = 0;
95                 {
96                     std::lock_guard<std::mutex> lockImageMap(sharedImageManager->sharedImageMapMutex_);
97                     auto sharedImageMap = sharedImageManager->GetSharedImageMap();
98                     auto imageDataIter = sharedImageMap.find(name);
99                     if (imageDataIter == sharedImageMap.end()) {
100                         LOGW("fail to find data of %{public}s in sharedImageMap, stop UpdateData", name.c_str());
101                         return;
102                     }
103                     dataSize = imageDataIter->second.size();
104                     for (const auto& providerWp : providerWpSet) {
105                         auto provider = providerWp.Upgrade();
106                         if (!provider) {
107                             continue;
108                         }
109                         provider->UpdateData(std::string(MEMORY_IMAGE_HEAD).append(name), imageDataIter->second);
110                     }
111                 }
112                 if (isClear) {
113                     sharedImageManager->PostDelayedTaskToClearImageData(name, dataSize);
114                 }
115             },
116             TaskExecutor::TaskType::UI, "ArkUIImageAddSharedImageData");
117 }
118 
UpdateImageMap(const std::string & name,const SharedImage & sharedImage)119 bool SharedImageManager::UpdateImageMap(const std::string& name, const SharedImage& sharedImage)
120 {
121     bool isClear = false;
122     auto iter = sharedImageMap_.find(name);
123     if (iter != sharedImageMap_.end()) {
124         sharedImageTotalSize_ -= iter->second.size();
125         sharedImageTotalSize_ += sharedImage.size();
126         iter->second = sharedImage;
127     } else {
128         sharedImageTotalSize_ += sharedImage.size();
129         sharedImageMap_.emplace(name, sharedImage);
130         if (static_cast<int>(sharedImageMap_.size()) > sharedImageCacheThreshold_) {
131             LOGW("will clear %{public}s cache, sharedImageMap_ size %{public}d max cache: %{public}d",
132                 name.c_str(), static_cast<int>(sharedImageMap_.size()), sharedImageCacheThreshold_);
133             isClear = true;
134         }
135     }
136     if (sharedImageTotalSize_ > MAX_SIZE_FOR_TOTAL_IMAGE) {
137         LOGW("will clear %{public}s cache, sharedImageTotalSize_ size %{public}d",
138             name.c_str(), static_cast<int32_t>(sharedImageTotalSize_));
139         isClear = true;
140     }
141     return isClear;
142 }
143 
AddPictureNamesToReloadMap(std::string && name)144 void SharedImageManager::AddPictureNamesToReloadMap(std::string&& name)
145 {
146     // add names of memory image to be read from shared memory
147     std::lock_guard<std::mutex> lock(providerMapMutex_);
148     providerMapToReload_.try_emplace(name, std::set<WeakPtr<ImageProviderLoader>>());
149 }
150 
FindImageInSharedImageMap(const std::string & name,const WeakPtr<ImageProviderLoader> & providerWp)151 bool SharedImageManager::FindImageInSharedImageMap(
152     const std::string& name, const WeakPtr<ImageProviderLoader>& providerWp)
153 {
154     LOGD("find image %{public}s in SharedImageMap", name.c_str());
155     auto loader = providerWp.Upgrade();
156     if (!loader) {
157         LOGW("image %{public}s loader nullptr", name.c_str());
158         return false;
159     }
160     std::lock_guard<std::mutex> lockImageMap(sharedImageMapMutex_);
161     auto iter = sharedImageMap_.find(name);
162     if (iter == sharedImageMap_.end()) {
163         LOGW("image data of %{private}s does not found in SharedImageMap", name.c_str());
164         return false;
165     }
166     loader->UpdateData(std::string(MEMORY_IMAGE_HEAD).append(name), iter->second);
167     return true;
168 }
169 
RegisterLoader(const std::string & name,const WeakPtr<ImageProviderLoader> & providerWp)170 bool SharedImageManager::RegisterLoader(const std::string& name, const WeakPtr<ImageProviderLoader>& providerWp)
171 {
172     std::lock_guard<std::mutex> lockProviderMap(providerMapMutex_);
173     bool resourceInMap = (providerMapToReload_.find(name) != providerMapToReload_.end());
174     providerMapToReload_[name].emplace(providerWp);
175     return resourceInMap;
176 }
177 
Remove(const std::string & name)178 bool SharedImageManager::Remove(const std::string& name)
179 {
180     std::lock_guard<std::mutex> lockImageMap(sharedImageMapMutex_);
181     auto iter = sharedImageMap_.find(name);
182     if (iter == sharedImageMap_.end()) {
183         LOGW("Remove failed: image data of %{private}s does not found in SharedImageMap", name.c_str());
184         return false;
185     }
186     sharedImageTotalSize_ -= iter->second.size();
187     LOGW("clear image cache name: %{public}s", name.c_str());
188     int res = static_cast<int>(sharedImageMap_.erase(name));
189     return (res != 0);
190 }
191 } // namespace OHOS::Ace
192