1 /*
2 * Copyright (c) 2023 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 "purgeable_pixelmap_builder.h"
17
18 #include "hitrace_meter.h"
19 #include "hilog/log.h"
20 #include "media_errors.h"
21 #include "parameters.h"
22 #include "purgeable_ashmem.h"
23 #include "purgeable_mem_base.h"
24 #include "purgeable_mem_builder.h"
25 #include "purgeable_resource_manager.h"
26
27 #ifndef _WIN32
28 #include "securec.h"
29 #else
30 #include "memory.h"
31 #endif
32
33 namespace OHOS {
34 namespace PurgeableBuilder {
35 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0xD001799, "PurgeablePixelMapBuilder" };
36 constexpr int THRESHOLD_HEIGHT = 256;
37 constexpr int THRESHOLD_WIDGHT = 256;
38 const std::string SYSTEM_PARAM_PURGEABLE_ENABLE = "persist.resourceschedule.memmgr.purgeable.enable";
39 const std::string SYSTEM_PARAM_PIXELMAP_THRESHOLD_HEIGHT = "persist.memmgr.purgeable.pixelmap.threshold.height";
40 const std::string SYSTEM_PARAM_PIXELMAP_THRESHOLD_WIDGHT = "persist.memmgr.purgeable.pixelmap.threshold.widght";
41
PurgeablePixelMapBuilder(uint32_t index,std::unique_ptr<ImageSource> & imageSource,DecodeOptions opts)42 PurgeablePixelMapBuilder::PurgeablePixelMapBuilder(uint32_t index, std::unique_ptr<ImageSource> &imageSource,
43 DecodeOptions opts)
44 : index_(index), opts_(opts), imageSource_(move(imageSource)) {}
45
Build(void * data,size_t size)46 bool PurgeablePixelMapBuilder::Build(void *data, size_t size)
47 {
48 HiviewDFX::HiLog::Debug(LABEL, "purgeableMem build in.");
49 uint32_t errorCode;
50 if (imageSource_ == nullptr) {
51 return false;
52 }
53
54 StartTrace(HITRACE_TAG_ZIMAGE, "OHOS::PurgeableBuilder::PixelMapPurgeableMemBuilder::Build");
55 std::unique_ptr<PixelMap> pixelMap = imageSource_->CreatePixelMap(index_, opts_, errorCode);
56 if (pixelMap == nullptr || data == nullptr) {
57 FinishTrace(HITRACE_TAG_ZIMAGE);
58 return false;
59 }
60
61 StartTrace(HITRACE_TAG_ZIMAGE, ("OHOS::PurgeableBuilder::PixelMapPurgeableMemBuilder::CopyData " +
62 std::to_string(size)));
63 if (memcpy_s((char *)data, size, (char *)pixelMap->GetPixels(), size)) {
64 FinishTrace(HITRACE_TAG_ZIMAGE);
65 return false;
66 }
67
68 DoRebuildSuccessCallback();
69
70 FinishTrace(HITRACE_TAG_ZIMAGE); // memcpy_s trace
71 FinishTrace(HITRACE_TAG_ZIMAGE); // PixelMapPurgeableMemBuilder::Build trace
72
73 return true;
74 }
75
GetSysForPurgeable()76 bool GetSysForPurgeable()
77 {
78 return system::GetBoolParameter(SYSTEM_PARAM_PURGEABLE_ENABLE, false);
79 }
80
SetBuilderToBePurgeable(PixelMap * pixelMap,std::unique_ptr<PurgeableMem::PurgeableMemBuilder> & builder)81 void SetBuilderToBePurgeable(PixelMap *pixelMap,
82 std::unique_ptr<PurgeableMem::PurgeableMemBuilder> &builder)
83 {
84 HiviewDFX::HiLog::Debug(LABEL, "set builder for purgeable pixelmap. allocatorType = %{public}d.",
85 pixelMap->GetAllocatorType());
86 StartTrace(HITRACE_TAG_ZIMAGE, "OHOS::PurgeableBuilder::SetBuilderToBePurgeable");
87 if (pixelMap == nullptr) {
88 FinishTrace(HITRACE_TAG_ZIMAGE);
89 return;
90 }
91
92 if (builder == nullptr) {
93 FinishTrace(HITRACE_TAG_ZIMAGE);
94 return;
95 }
96
97 if (pixelMap->GetAllocatorType() == AllocatorType::SHARE_MEM_ALLOC) {
98 std::shared_ptr<OHOS::PurgeableMem::PurgeableAshMem> tmpPtr =
99 std::make_shared<OHOS::PurgeableMem::PurgeableAshMem>(std::move(builder));
100 bool isChanged = tmpPtr->ChangeAshmemData(pixelMap->GetCapacity(),
101 *(static_cast<int *>(pixelMap->GetFd())), pixelMap->GetWritablePixels());
102 if (isChanged) {
103 pixelMap->SetPurgeableMemPtr(tmpPtr);
104 pixelMap->GetPurgeableMemPtr()->BeginReadWithDataLock();
105 } else {
106 HiviewDFX::HiLog::Error(LABEL, "ChangeAshmemData fail.");
107 }
108 }
109
110 FinishTrace(HITRACE_TAG_ZIMAGE);
111 }
112
RemoveFromPurgeableResourceMgr(PixelMap * pixelMap)113 void RemoveFromPurgeableResourceMgr(PixelMap *pixelMap)
114 {
115 StartTrace(HITRACE_TAG_ZIMAGE, "OHOS::PurgeableBuilder::RemoveFromPurgeableResourceMgr");
116 HiviewDFX::HiLog::Debug(LABEL, "remove pixelmap from PurgeableResourceMgr.");
117
118 if (pixelMap == nullptr) {
119 FinishTrace(HITRACE_TAG_ZIMAGE);
120 return;
121 }
122
123 if (pixelMap->IsPurgeable()) {
124 PurgeableMem::PurgeableResourceManager::GetInstance().RemoveResource(pixelMap->GetPurgeableMemPtr());
125 }
126
127 FinishTrace(HITRACE_TAG_ZIMAGE);
128 }
129
AddToPurgeableResourceMgr(PixelMap * pixelMap)130 void AddToPurgeableResourceMgr(PixelMap *pixelMap)
131 {
132 StartTrace(HITRACE_TAG_ZIMAGE, "OHOS::PurgeableBuilder::AddToPurgeableResourceMgr");
133 HiviewDFX::HiLog::Debug(LABEL, "add pixelmap purgeablemem ptr to PurgeableResourceMgr");
134
135 if (pixelMap == nullptr) {
136 FinishTrace(HITRACE_TAG_ZIMAGE);
137 return;
138 }
139
140 if (pixelMap->IsPurgeable()) {
141 PurgeableMem::PurgeableResourceManager::GetInstance().AddResource(pixelMap->GetPurgeableMemPtr());
142 }
143
144 FinishTrace(HITRACE_TAG_ZIMAGE);
145 }
146
IfCanBePurgeable(DecodeOptions & decodeOpts)147 bool IfCanBePurgeable(DecodeOptions &decodeOpts)
148 {
149 int thresholdHeight = system::GetIntParameter(SYSTEM_PARAM_PIXELMAP_THRESHOLD_HEIGHT, THRESHOLD_HEIGHT);
150 int thresholdWidght = system::GetIntParameter(SYSTEM_PARAM_PIXELMAP_THRESHOLD_WIDGHT, THRESHOLD_WIDGHT);
151 Size size = decodeOpts.desiredSize;
152
153 if (size.height > thresholdHeight || size.width > thresholdWidght) {
154 return false;
155 }
156 return true;
157 }
158
MakePixelMapToBePurgeable(std::unique_ptr<PixelMap> & pixelMap,std::unique_ptr<ImageSource> & backupImgSrc4Rebuild,DecodeOptions & decodeOpts)159 bool MakePixelMapToBePurgeable(std::unique_ptr<PixelMap> &pixelMap, std::unique_ptr<ImageSource> &backupImgSrc4Rebuild,
160 DecodeOptions &decodeOpts)
161 {
162 return MakePixelMapToBePurgeableBySrc(pixelMap.get(), backupImgSrc4Rebuild, decodeOpts);
163 }
164
MakePixelMapToBePurgeable(std::unique_ptr<PixelMap> & pixelMap,const int fd,const SourceOptions & opts,DecodeOptions & decodeOpts)165 bool MakePixelMapToBePurgeable(std::unique_ptr<PixelMap> &pixelMap, const int fd,
166 const SourceOptions &opts, DecodeOptions &decodeOpts)
167 {
168 return MakePixelMapToBePurgeableByFd(pixelMap.get(), fd, opts, decodeOpts);
169 }
170
MakePixelMapToBePurgeableByFd(PixelMap * pixelMap,const int fd,const SourceOptions & opts,DecodeOptions & decodeOpts)171 bool MakePixelMapToBePurgeableByFd(PixelMap *pixelMap, const int fd, const SourceOptions &opts,
172 DecodeOptions &decodeOpts)
173 {
174 uint32_t errorCode = 0;
175 std::unique_ptr<ImageSource> backupImgSrc = ImageSource::CreateImageSource(fd, opts, errorCode);
176 if (errorCode != Media::SUCCESS) {
177 return false;
178 }
179 return MakePixelMapToBePurgeableBySrc(pixelMap, backupImgSrc, decodeOpts);
180 }
181
MakePixelMapToBePurgeableBySrc(PixelMap * pixelMap,std::unique_ptr<ImageSource> & backupImgSrc4Rebuild,DecodeOptions & decodeOpts)182 bool MakePixelMapToBePurgeableBySrc(PixelMap *pixelMap,
183 std::unique_ptr<ImageSource> &backupImgSrc4Rebuild, DecodeOptions &decodeOpts)
184 {
185 StartTrace(HITRACE_TAG_ZIMAGE, "OHOS::PurgeableBuilder::MakePixelMapToBePurgeable");
186 HiviewDFX::HiLog::Debug(LABEL, "MakePixelMapToBePurgeable in.");
187
188 if (!GetSysForPurgeable()) {
189 FinishTrace(HITRACE_TAG_ZIMAGE);
190 return false;
191 }
192
193 if (!IfCanBePurgeable(decodeOpts)) {
194 FinishTrace(HITRACE_TAG_ZIMAGE);
195 return false;
196 }
197
198 if (pixelMap == nullptr || backupImgSrc4Rebuild == nullptr) {
199 HiviewDFX::HiLog::Error(LABEL, "PixelMap or backupImgSrc4Rebuild is null.");
200 FinishTrace(HITRACE_TAG_ZIMAGE);
201 return false;
202 }
203
204 if (pixelMap->IsPurgeable()) {
205 HiviewDFX::HiLog::Error(LABEL, "PixelMap is already purgeable.");
206 FinishTrace(HITRACE_TAG_ZIMAGE);
207 return false;
208 }
209
210 std::unique_ptr<PurgeableMem::PurgeableMemBuilder> purgeableMemBuilder =
211 std::make_unique<PurgeablePixelMapBuilder>(0, backupImgSrc4Rebuild, decodeOpts);
212 SetBuilderToBePurgeable(pixelMap, purgeableMemBuilder);
213
214 if (pixelMap->IsPurgeable()) {
215 AddToPurgeableResourceMgr(pixelMap);
216 }
217
218 FinishTrace(HITRACE_TAG_ZIMAGE);
219 return true;
220 }
221 } // namespace PurgeableBuilder
222 } // namespace OHOS