• 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 <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