• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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