1 /*
2 * Copyright (c) 2024 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 "surfaceconcurrent_fuzzer.h"
17
18 #include <securec.h>
19 #include <atomic>
20
21 #include "data_generate.h"
22 #include "iconsumer_surface.h"
23 #include "producer_surface_delegator.h"
24 #include "surface.h"
25 #include "surface_buffer.h"
26 #include "surface_buffer_impl.h"
27 #include <iostream>
28
29 using namespace g_fuzzCommon;
30 namespace OHOS {
31 static constexpr const uint32_t QUESIZE_RANGE = 10;
32 static constexpr const uint32_t QUESIZE_MIN = 3;
33 static constexpr const uint32_t BUFFERR_ROTATION_TIMES = 500;
34 static constexpr const uint32_t BUFFERR_ROTATION_INTERVAL_MICRO_SECOND = 10;
35 static constexpr const uint32_t CONCURRENCY_FUNCTION_TIMES = 500;
36 static constexpr const uint32_t CONCURRENCY_FUNCTION_INTERVAL_MICRO_SECOND = 50;
37 static constexpr const uint32_t ATTACHBUFFER_RETRY_TIMES = 10;
38 BufferRequestConfig requestConfigTmp = {
39 .width = 0x100,
40 .height = 0x100,
41 .strideAlignment = 0x8,
42 .format = GRAPHIC_PIXEL_FMT_RGBA_8888,
43 .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
44 .timeout = 1000,
45 };
46 int g_releaseFence = -1;
47 BufferFlushConfig flushConfig = {
48 .damage = {
49 .w = 0x100,
50 .h = 0x100,
51 },
52 };
53 std::atomic<bool> g_isCleanCacheFinish = false;
54 std::atomic<bool> g_isGoBackGroundFinish = false;
55
producerBufferFunc(sptr<Surface> pSurface)56 void producerBufferFunc(sptr<Surface> pSurface)
57 {
58 for (uint32_t i = 0; i < BUFFERR_ROTATION_TIMES; i++) {
59 usleep(BUFFERR_ROTATION_INTERVAL_MICRO_SECOND);
60 sptr<SurfaceBuffer> requestBuffer = nullptr;
61 pSurface->RequestBuffer(requestBuffer, g_releaseFence, requestConfigTmp);
62 usleep(BUFFERR_ROTATION_INTERVAL_MICRO_SECOND);
63 pSurface->FlushBuffer(requestBuffer, -1, flushConfig);
64 }
65 std::cout<< pSurface->GetName() <<"prudecer finish"<<std::endl;
66 };
67
consumerBufferFunc(sptr<IConsumerSurface> cSurface)68 void consumerBufferFunc(sptr<IConsumerSurface> cSurface)
69 {
70 int32_t flushFence;
71 int64_t timestamp;
72 OHOS::Rect damage;
73 GSError ret;
74 for (uint32_t i = 0; i < BUFFERR_ROTATION_TIMES; i++) {
75 sptr<SurfaceBuffer> acquireBuffer;
76 usleep(BUFFERR_ROTATION_INTERVAL_MICRO_SECOND);
77 ret = cSurface->AcquireBuffer(acquireBuffer, flushFence, timestamp, damage);
78 usleep(BUFFERR_ROTATION_INTERVAL_MICRO_SECOND);
79 cSurface->ReleaseBuffer(acquireBuffer, -1);
80 }
81 std::cout<< cSurface->GetName() <<" consumerFunc finish"<<std::endl;
82 }
83
cleanCacheFunc(sptr<Surface> pSurface)84 void cleanCacheFunc(sptr<Surface> pSurface)
85 {
86 for (uint32_t i = 0; i < CONCURRENCY_FUNCTION_TIMES; i++) {
87 usleep(CONCURRENCY_FUNCTION_INTERVAL_MICRO_SECOND);
88 pSurface->CleanCache(true);
89 }
90 std::cout<< pSurface->GetName() <<" cleanCacheFunc finish"<<std::endl;
91 };
92
producerGoBackGroundFunc(sptr<Surface> pSurface)93 void producerGoBackGroundFunc(sptr<Surface> pSurface)
94 {
95 for (uint32_t i = 0; i < CONCURRENCY_FUNCTION_TIMES; i++) {
96 usleep(CONCURRENCY_FUNCTION_INTERVAL_MICRO_SECOND);
97 pSurface->GoBackground();
98 }
99 std::cout<< pSurface->GetName() <<" producerGoBackGroundFunc finish"<<std::endl;
100 };
101
consumerAttachFunc(sptr<IConsumerSurface> cSurface,sptr<SurfaceBuffer> buffer)102 void consumerAttachFunc(sptr<IConsumerSurface> cSurface, sptr<SurfaceBuffer> buffer)
103 {
104 uint32_t ret = 1;
105 uint32_t count = ATTACHBUFFER_RETRY_TIMES;
106 while (ret != GSERROR_OK && count-- > 0) {
107 usleep(CONCURRENCY_FUNCTION_INTERVAL_MICRO_SECOND);
108 ret = cSurface->AttachBufferToQueue(buffer);
109 std::cout<< cSurface->GetName() <<"Comsumer call AttachBufferToQueue result: "<< ret <<std::endl;
110 ret = cSurface->ReleaseBuffer(buffer, -1);
111 }
112 };
113
producerAttachFunc(sptr<Surface> pSurface,sptr<SurfaceBuffer> buffer)114 void producerAttachFunc(sptr<Surface> pSurface, sptr<SurfaceBuffer> buffer)
115 {
116 uint32_t ret = 1;
117 uint32_t count = ATTACHBUFFER_RETRY_TIMES;
118 while (ret != GSERROR_OK && count-- > 0) {
119 usleep(CONCURRENCY_FUNCTION_INTERVAL_MICRO_SECOND);
120 ret = pSurface->AttachBufferToQueue(buffer);
121 std::cout<< pSurface->GetName() <<" producer call AttachBufferToQueue result: "<< ret <<std::endl;
122 ret = pSurface->FlushBuffer(buffer, -1, flushConfig);
123 }
124 };
125
126 /*
127 * CaseDescription: 1. preSetup: create two surface(surfaceA and surfaceB)
128 * 2. operation: While surfaceA and surfaceB are rotating the buffer, the producer of surfaceA detaches
129 * the buffer to surfaceB, and the producers of surfaceA and surfaceB perform cleanCache and
130 * GoBackground operations.
131 * Concurrent interface:
132 * 1、RequestBuffer
133 * 2、FlushBuffer
134 * 3、AcquireBuffer
135 * 4、ReleaseBuffer
136 * 5、CleanCahce (producer)
137 * 6、GoBackGround (producer)
138 * 7、AttachBufferToQueue
139 * 8、DetachBufferFromQueue (producer)
140 * 3. result: buffer detach from surfaceA attach to surfaceB success multiple times without crash.
141 */
BufferRotationConcurrentWithAttachBufferAndDetachBufferAndCleanCacheAndGoBackground()142 void BufferRotationConcurrentWithAttachBufferAndDetachBufferAndCleanCacheAndGoBackground()
143 {
144 std::cout<<"start"<<std::endl;
145 // create surface A
146 std::string name = GetStringFromData(STR_LEN);
147 sptr<IConsumerSurface> cSurfaceA = IConsumerSurface::Create(name);
148 sptr<IBufferConsumerListener> consumerListener = new BufferConsumerListener();
149 cSurfaceA->RegisterConsumerListener(consumerListener);
150 sptr<IBufferProducer> producerClient = cSurfaceA->GetProducer();
151 sptr<Surface> pSurfaceA = Surface::CreateSurfaceAsProducer(producerClient);
152
153 // create surface B
154 sptr<IConsumerSurface> cSurfaceB = IConsumerSurface::Create("SurfaceB");
155 sptr<IBufferConsumerListener> consumerListenerB = new BufferConsumerListener();
156 cSurfaceB->RegisterConsumerListener(consumerListenerB);
157 sptr<IBufferProducer> producerClientB = cSurfaceB->GetProducer();
158 sptr<Surface> pSurfaceB = Surface::CreateSurfaceAsProducer(producerClientB);
159
160 //init
161 uint32_t queueSize = GetData<uint32_t>();
162 queueSize = queueSize % QUESIZE_RANGE + QUESIZE_MIN;
163 pSurfaceA->SetQueueSize(queueSize);
164 pSurfaceB->SetQueueSize(queueSize);
165 std::cout<<"Queue size: "<< queueSize <<std::endl;
166
167 //create concurrent thread
168 g_isCleanCacheFinish= false;
169 g_isGoBackGroundFinish = false;
170 std::thread consumerThread(consumerBufferFunc, cSurfaceA);
171 std::thread consumerThreadB(consumerBufferFunc, cSurfaceB);
172 std::thread cleanCacheThread(cleanCacheFunc, pSurfaceA);
173 std::thread cleanCacheThreadB(cleanCacheFunc, pSurfaceB);
174 std::thread goBackgroundThread(producerGoBackGroundFunc, pSurfaceA);
175 std::thread goBackgroundThreadB(producerGoBackGroundFunc, pSurfaceB);
176 std::thread producerThreadB(producerBufferFunc, pSurfaceB);
177
178 std::vector<std::thread> attachThreadList;
179 uint32_t detachBufferTrigger = GetData<uint32_t>();
180 detachBufferTrigger = (detachBufferTrigger % QUESIZE_RANGE) + 1;
181 std::cout<<"detachBuffer Trigger: "<< detachBufferTrigger <<std::endl;
182 for (uint32_t i = 0; i < CONCURRENCY_FUNCTION_TIMES; i++) {
183 usleep(BUFFERR_ROTATION_INTERVAL_MICRO_SECOND);
184 sptr<SurfaceBuffer> requestBuffer = nullptr;
185 auto ret = pSurfaceA->RequestBuffer(requestBuffer, g_releaseFence, requestConfigTmp);
186 uint32_t count = 0;
187 if (detachBufferTrigger == 0) {
188 detachBufferTrigger++;
189 }
190 if (ret == GSERROR_OK && count++ % detachBufferTrigger == 0
191 && (!g_isCleanCacheFinish|| !g_isGoBackGroundFinish)) {
192 usleep(BUFFERR_ROTATION_INTERVAL_MICRO_SECOND);
193 ret = pSurfaceA->DetachBufferFromQueue(requestBuffer);
194 if (ret != GSERROR_OK) {
195 usleep(BUFFERR_ROTATION_INTERVAL_MICRO_SECOND);
196 pSurfaceA->FlushBuffer(requestBuffer, -1, flushConfig);
197 }
198 bool surfaceBIsProducer = GetData<bool>();
199 if (surfaceBIsProducer) {
200 std::thread attachThread(consumerAttachFunc, cSurfaceB, requestBuffer);
201 attachThreadList.push_back(std::move(attachThread));
202 } else {
203 std::thread attachThread(producerAttachFunc, pSurfaceB, requestBuffer);
204 attachThreadList.push_back(std::move(attachThread));
205 }
206 continue;
207 }
208 usleep(BUFFERR_ROTATION_INTERVAL_MICRO_SECOND);
209 pSurfaceA->FlushBuffer(requestBuffer, -1, flushConfig);
210 }
211
212 // wait concurrent thread finish
213 std::cout<< pSurfaceA->GetName() <<"prudecer finish"<<std::endl;
214 for (auto& attachThread : attachThreadList) {
215 if (attachThread.joinable()) {
216 attachThread.join();
217 }
218 }
219 consumerThread.join();
220 cleanCacheThread.join();
221 goBackgroundThread.join();
222 consumerThreadB.join();
223 cleanCacheThreadB.join();
224 goBackgroundThreadB.join();
225 producerThreadB.join();
226 pSurfaceA = nullptr;
227 producerClient = nullptr;
228 cSurfaceA = nullptr;
229 pSurfaceB = nullptr;
230 producerClientB = nullptr;
231 cSurfaceB = nullptr;
232 std::cout<<"end"<<std::endl;
233 }
234
DoSomethingInterestingWithMyAPI(const uint8_t * data,size_t size)235 bool DoSomethingInterestingWithMyAPI(const uint8_t* data, size_t size)
236 {
237 if (data == nullptr) {
238 return false;
239 }
240 BufferRotationConcurrentWithAttachBufferAndDetachBufferAndCleanCacheAndGoBackground();
241 return true;
242 }
243 } // namespace OHOS
244
245 /* Fuzzer entry point */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)246 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
247 {
248 /* Run your code on data */
249 OHOS::DoSomethingInterestingWithMyAPI(data, size);
250 return 0;
251 }
252
253