xref: /aosp_15_r20/frameworks/base/libs/hwui/renderthread/ReliableSurface.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker  *
4*d57664e9SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker  *
8*d57664e9SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker  *
10*d57664e9SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker  * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker  */
16*d57664e9SAndroid Build Coastguard Worker 
17*d57664e9SAndroid Build Coastguard Worker #include "ReliableSurface.h"
18*d57664e9SAndroid Build Coastguard Worker 
19*d57664e9SAndroid Build Coastguard Worker #include <log/log_main.h>
20*d57664e9SAndroid Build Coastguard Worker #include <private/android/AHardwareBufferHelpers.h>
21*d57664e9SAndroid Build Coastguard Worker // TODO: this should be including apex instead.
22*d57664e9SAndroid Build Coastguard Worker #include <system/window.h>
23*d57664e9SAndroid Build Coastguard Worker #include <vndk/window.h>
24*d57664e9SAndroid Build Coastguard Worker 
25*d57664e9SAndroid Build Coastguard Worker namespace android::uirenderer::renderthread {
26*d57664e9SAndroid Build Coastguard Worker 
27*d57664e9SAndroid Build Coastguard Worker // TODO: Re-enable after addressing more of the TODO's
28*d57664e9SAndroid Build Coastguard Worker // With this disabled we won't have a good up-front signal that the surface is no longer valid,
29*d57664e9SAndroid Build Coastguard Worker // however we can at least handle that reactively post-draw. There's just not a good mechanism
30*d57664e9SAndroid Build Coastguard Worker // to propagate this error back to the caller
31*d57664e9SAndroid Build Coastguard Worker constexpr bool DISABLE_BUFFER_PREFETCH = true;
32*d57664e9SAndroid Build Coastguard Worker 
ReliableSurface(ANativeWindow * window)33*d57664e9SAndroid Build Coastguard Worker ReliableSurface::ReliableSurface(ANativeWindow* window) : mWindow(window) {
34*d57664e9SAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(!mWindow, "Error, unable to wrap a nullptr");
35*d57664e9SAndroid Build Coastguard Worker     ANativeWindow_acquire(mWindow);
36*d57664e9SAndroid Build Coastguard Worker }
37*d57664e9SAndroid Build Coastguard Worker 
~ReliableSurface()38*d57664e9SAndroid Build Coastguard Worker ReliableSurface::~ReliableSurface() {
39*d57664e9SAndroid Build Coastguard Worker     clearReservedBuffer();
40*d57664e9SAndroid Build Coastguard Worker     // Clear out the interceptors for proper hygiene.
41*d57664e9SAndroid Build Coastguard Worker     // As a concrete example, if the underlying ANativeWindow is associated with
42*d57664e9SAndroid Build Coastguard Worker     // an EGLSurface that is still in use, then if we don't clear out the
43*d57664e9SAndroid Build Coastguard Worker     // interceptors then we walk into undefined behavior.
44*d57664e9SAndroid Build Coastguard Worker     ANativeWindow_setCancelBufferInterceptor(mWindow, nullptr, nullptr);
45*d57664e9SAndroid Build Coastguard Worker     ANativeWindow_setDequeueBufferInterceptor(mWindow, nullptr, nullptr);
46*d57664e9SAndroid Build Coastguard Worker     ANativeWindow_setQueueBufferInterceptor(mWindow, nullptr, nullptr);
47*d57664e9SAndroid Build Coastguard Worker     ANativeWindow_setPerformInterceptor(mWindow, nullptr, nullptr);
48*d57664e9SAndroid Build Coastguard Worker     ANativeWindow_setQueryInterceptor(mWindow, nullptr, nullptr);
49*d57664e9SAndroid Build Coastguard Worker     ANativeWindow_release(mWindow);
50*d57664e9SAndroid Build Coastguard Worker }
51*d57664e9SAndroid Build Coastguard Worker 
init()52*d57664e9SAndroid Build Coastguard Worker void ReliableSurface::init() {
53*d57664e9SAndroid Build Coastguard Worker     int result = ANativeWindow_setCancelBufferInterceptor(mWindow, hook_cancelBuffer, this);
54*d57664e9SAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(result != NO_ERROR, "Failed to set cancelBuffer interceptor: error = %d",
55*d57664e9SAndroid Build Coastguard Worker                         result);
56*d57664e9SAndroid Build Coastguard Worker 
57*d57664e9SAndroid Build Coastguard Worker     result = ANativeWindow_setDequeueBufferInterceptor(mWindow, hook_dequeueBuffer, this);
58*d57664e9SAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(result != NO_ERROR, "Failed to set dequeueBuffer interceptor: error = %d",
59*d57664e9SAndroid Build Coastguard Worker                         result);
60*d57664e9SAndroid Build Coastguard Worker 
61*d57664e9SAndroid Build Coastguard Worker     result = ANativeWindow_setQueueBufferInterceptor(mWindow, hook_queueBuffer, this);
62*d57664e9SAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(result != NO_ERROR, "Failed to set queueBuffer interceptor: error = %d",
63*d57664e9SAndroid Build Coastguard Worker                         result);
64*d57664e9SAndroid Build Coastguard Worker 
65*d57664e9SAndroid Build Coastguard Worker     result = ANativeWindow_setPerformInterceptor(mWindow, hook_perform, this);
66*d57664e9SAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(result != NO_ERROR, "Failed to set perform interceptor: error = %d",
67*d57664e9SAndroid Build Coastguard Worker                         result);
68*d57664e9SAndroid Build Coastguard Worker 
69*d57664e9SAndroid Build Coastguard Worker     result = ANativeWindow_setQueryInterceptor(mWindow, hook_query, this);
70*d57664e9SAndroid Build Coastguard Worker     LOG_ALWAYS_FATAL_IF(result != NO_ERROR, "Failed to set query interceptor: error = %d",
71*d57664e9SAndroid Build Coastguard Worker                         result);
72*d57664e9SAndroid Build Coastguard Worker }
73*d57664e9SAndroid Build Coastguard Worker 
reserveNext()74*d57664e9SAndroid Build Coastguard Worker int ReliableSurface::reserveNext() {
75*d57664e9SAndroid Build Coastguard Worker     if constexpr (DISABLE_BUFFER_PREFETCH) {
76*d57664e9SAndroid Build Coastguard Worker         return OK;
77*d57664e9SAndroid Build Coastguard Worker     }
78*d57664e9SAndroid Build Coastguard Worker     {
79*d57664e9SAndroid Build Coastguard Worker         std::lock_guard _lock{mMutex};
80*d57664e9SAndroid Build Coastguard Worker         if (mReservedBuffer) {
81*d57664e9SAndroid Build Coastguard Worker             ALOGW("reserveNext called but there was already a buffer reserved?");
82*d57664e9SAndroid Build Coastguard Worker             return OK;
83*d57664e9SAndroid Build Coastguard Worker         }
84*d57664e9SAndroid Build Coastguard Worker         if (mBufferQueueState != OK) {
85*d57664e9SAndroid Build Coastguard Worker             return UNKNOWN_ERROR;
86*d57664e9SAndroid Build Coastguard Worker         }
87*d57664e9SAndroid Build Coastguard Worker         if (mHasDequeuedBuffer) {
88*d57664e9SAndroid Build Coastguard Worker             return OK;
89*d57664e9SAndroid Build Coastguard Worker         }
90*d57664e9SAndroid Build Coastguard Worker     }
91*d57664e9SAndroid Build Coastguard Worker 
92*d57664e9SAndroid Build Coastguard Worker     // TODO: Update this to better handle when requested dimensions have changed
93*d57664e9SAndroid Build Coastguard Worker     // Currently the driver does this via query + perform but that's after we've already
94*d57664e9SAndroid Build Coastguard Worker     // reserved a buffer. Should we do that logic instead? Or should we drop
95*d57664e9SAndroid Build Coastguard Worker     // the backing Surface to the ground and go full manual on the IGraphicBufferProducer instead?
96*d57664e9SAndroid Build Coastguard Worker 
97*d57664e9SAndroid Build Coastguard Worker     int fenceFd = -1;
98*d57664e9SAndroid Build Coastguard Worker     ANativeWindowBuffer* buffer = nullptr;
99*d57664e9SAndroid Build Coastguard Worker 
100*d57664e9SAndroid Build Coastguard Worker     // Note that this calls back into our own hooked method.
101*d57664e9SAndroid Build Coastguard Worker     int result = ANativeWindow_dequeueBuffer(mWindow, &buffer, &fenceFd);
102*d57664e9SAndroid Build Coastguard Worker 
103*d57664e9SAndroid Build Coastguard Worker     {
104*d57664e9SAndroid Build Coastguard Worker         std::lock_guard _lock{mMutex};
105*d57664e9SAndroid Build Coastguard Worker         LOG_ALWAYS_FATAL_IF(mReservedBuffer, "race condition in reserveNext");
106*d57664e9SAndroid Build Coastguard Worker         mReservedBuffer = buffer;
107*d57664e9SAndroid Build Coastguard Worker         mReservedFenceFd.reset(fenceFd);
108*d57664e9SAndroid Build Coastguard Worker     }
109*d57664e9SAndroid Build Coastguard Worker 
110*d57664e9SAndroid Build Coastguard Worker     return result;
111*d57664e9SAndroid Build Coastguard Worker }
112*d57664e9SAndroid Build Coastguard Worker 
clearReservedBuffer()113*d57664e9SAndroid Build Coastguard Worker void ReliableSurface::clearReservedBuffer() {
114*d57664e9SAndroid Build Coastguard Worker     ANativeWindowBuffer* buffer = nullptr;
115*d57664e9SAndroid Build Coastguard Worker     int releaseFd = -1;
116*d57664e9SAndroid Build Coastguard Worker     {
117*d57664e9SAndroid Build Coastguard Worker         std::lock_guard _lock{mMutex};
118*d57664e9SAndroid Build Coastguard Worker         if (mReservedBuffer) {
119*d57664e9SAndroid Build Coastguard Worker             ALOGW("Reserved buffer %p was never used", mReservedBuffer);
120*d57664e9SAndroid Build Coastguard Worker             buffer = mReservedBuffer;
121*d57664e9SAndroid Build Coastguard Worker             releaseFd = mReservedFenceFd.release();
122*d57664e9SAndroid Build Coastguard Worker         }
123*d57664e9SAndroid Build Coastguard Worker         mReservedBuffer = nullptr;
124*d57664e9SAndroid Build Coastguard Worker         mReservedFenceFd.reset();
125*d57664e9SAndroid Build Coastguard Worker         mHasDequeuedBuffer = false;
126*d57664e9SAndroid Build Coastguard Worker     }
127*d57664e9SAndroid Build Coastguard Worker     if (buffer) {
128*d57664e9SAndroid Build Coastguard Worker         // Note that clearReservedBuffer may be reentrant here, so
129*d57664e9SAndroid Build Coastguard Worker         // mReservedBuffer must be cleared once we reach here to avoid recursing
130*d57664e9SAndroid Build Coastguard Worker         // forever.
131*d57664e9SAndroid Build Coastguard Worker         ANativeWindow_cancelBuffer(mWindow, buffer, releaseFd);
132*d57664e9SAndroid Build Coastguard Worker     }
133*d57664e9SAndroid Build Coastguard Worker }
134*d57664e9SAndroid Build Coastguard Worker 
isFallbackBuffer(const ANativeWindowBuffer * windowBuffer) const135*d57664e9SAndroid Build Coastguard Worker bool ReliableSurface::isFallbackBuffer(const ANativeWindowBuffer* windowBuffer) const {
136*d57664e9SAndroid Build Coastguard Worker     if (!mScratchBuffer || !windowBuffer) {
137*d57664e9SAndroid Build Coastguard Worker         return false;
138*d57664e9SAndroid Build Coastguard Worker     }
139*d57664e9SAndroid Build Coastguard Worker     ANativeWindowBuffer* scratchBuffer =
140*d57664e9SAndroid Build Coastguard Worker             AHardwareBuffer_to_ANativeWindowBuffer(mScratchBuffer.get());
141*d57664e9SAndroid Build Coastguard Worker     return windowBuffer == scratchBuffer;
142*d57664e9SAndroid Build Coastguard Worker }
143*d57664e9SAndroid Build Coastguard Worker 
acquireFallbackBuffer(int error)144*d57664e9SAndroid Build Coastguard Worker ANativeWindowBuffer* ReliableSurface::acquireFallbackBuffer(int error) {
145*d57664e9SAndroid Build Coastguard Worker     std::lock_guard _lock{mMutex};
146*d57664e9SAndroid Build Coastguard Worker     mBufferQueueState = error;
147*d57664e9SAndroid Build Coastguard Worker 
148*d57664e9SAndroid Build Coastguard Worker     if (mScratchBuffer) {
149*d57664e9SAndroid Build Coastguard Worker         return AHardwareBuffer_to_ANativeWindowBuffer(mScratchBuffer.get());
150*d57664e9SAndroid Build Coastguard Worker     }
151*d57664e9SAndroid Build Coastguard Worker 
152*d57664e9SAndroid Build Coastguard Worker     AHardwareBuffer_Desc desc = AHardwareBuffer_Desc{
153*d57664e9SAndroid Build Coastguard Worker             .width = 1,
154*d57664e9SAndroid Build Coastguard Worker             .height = 1,
155*d57664e9SAndroid Build Coastguard Worker             .layers = 1,
156*d57664e9SAndroid Build Coastguard Worker             .format = mFormat,
157*d57664e9SAndroid Build Coastguard Worker             .usage = mUsage,
158*d57664e9SAndroid Build Coastguard Worker             .rfu0 = 0,
159*d57664e9SAndroid Build Coastguard Worker             .rfu1 = 0,
160*d57664e9SAndroid Build Coastguard Worker     };
161*d57664e9SAndroid Build Coastguard Worker 
162*d57664e9SAndroid Build Coastguard Worker     AHardwareBuffer* newBuffer;
163*d57664e9SAndroid Build Coastguard Worker     int result = AHardwareBuffer_allocate(&desc, &newBuffer);
164*d57664e9SAndroid Build Coastguard Worker 
165*d57664e9SAndroid Build Coastguard Worker     if (result != NO_ERROR) {
166*d57664e9SAndroid Build Coastguard Worker         // Allocate failed, that sucks
167*d57664e9SAndroid Build Coastguard Worker         ALOGW("Failed to allocate scratch buffer, error=%d", result);
168*d57664e9SAndroid Build Coastguard Worker         return nullptr;
169*d57664e9SAndroid Build Coastguard Worker     }
170*d57664e9SAndroid Build Coastguard Worker 
171*d57664e9SAndroid Build Coastguard Worker     mScratchBuffer.reset(newBuffer);
172*d57664e9SAndroid Build Coastguard Worker     return AHardwareBuffer_to_ANativeWindowBuffer(newBuffer);
173*d57664e9SAndroid Build Coastguard Worker }
174*d57664e9SAndroid Build Coastguard Worker 
hook_dequeueBuffer(ANativeWindow * window,ANativeWindow_dequeueBufferFn dequeueBuffer,void * data,ANativeWindowBuffer ** buffer,int * fenceFd)175*d57664e9SAndroid Build Coastguard Worker int ReliableSurface::hook_dequeueBuffer(ANativeWindow* window,
176*d57664e9SAndroid Build Coastguard Worker                                         ANativeWindow_dequeueBufferFn dequeueBuffer, void* data,
177*d57664e9SAndroid Build Coastguard Worker                                         ANativeWindowBuffer** buffer, int* fenceFd) {
178*d57664e9SAndroid Build Coastguard Worker     ReliableSurface* rs = reinterpret_cast<ReliableSurface*>(data);
179*d57664e9SAndroid Build Coastguard Worker     {
180*d57664e9SAndroid Build Coastguard Worker         std::lock_guard _lock{rs->mMutex};
181*d57664e9SAndroid Build Coastguard Worker         if (rs->mReservedBuffer) {
182*d57664e9SAndroid Build Coastguard Worker             *buffer = rs->mReservedBuffer;
183*d57664e9SAndroid Build Coastguard Worker             *fenceFd = rs->mReservedFenceFd.release();
184*d57664e9SAndroid Build Coastguard Worker             rs->mReservedBuffer = nullptr;
185*d57664e9SAndroid Build Coastguard Worker             return OK;
186*d57664e9SAndroid Build Coastguard Worker         }
187*d57664e9SAndroid Build Coastguard Worker     }
188*d57664e9SAndroid Build Coastguard Worker 
189*d57664e9SAndroid Build Coastguard Worker     int result = dequeueBuffer(window, buffer, fenceFd);
190*d57664e9SAndroid Build Coastguard Worker     if (result != OK) {
191*d57664e9SAndroid Build Coastguard Worker         ALOGW("dequeueBuffer failed, error = %d; switching to fallback", result);
192*d57664e9SAndroid Build Coastguard Worker         *buffer = rs->acquireFallbackBuffer(result);
193*d57664e9SAndroid Build Coastguard Worker         *fenceFd = -1;
194*d57664e9SAndroid Build Coastguard Worker         return *buffer ? OK : INVALID_OPERATION;
195*d57664e9SAndroid Build Coastguard Worker     } else {
196*d57664e9SAndroid Build Coastguard Worker         std::lock_guard _lock{rs->mMutex};
197*d57664e9SAndroid Build Coastguard Worker         rs->mHasDequeuedBuffer = true;
198*d57664e9SAndroid Build Coastguard Worker     }
199*d57664e9SAndroid Build Coastguard Worker     return OK;
200*d57664e9SAndroid Build Coastguard Worker }
201*d57664e9SAndroid Build Coastguard Worker 
hook_cancelBuffer(ANativeWindow * window,ANativeWindow_cancelBufferFn cancelBuffer,void * data,ANativeWindowBuffer * buffer,int fenceFd)202*d57664e9SAndroid Build Coastguard Worker int ReliableSurface::hook_cancelBuffer(ANativeWindow* window,
203*d57664e9SAndroid Build Coastguard Worker                                        ANativeWindow_cancelBufferFn cancelBuffer, void* data,
204*d57664e9SAndroid Build Coastguard Worker                                        ANativeWindowBuffer* buffer, int fenceFd) {
205*d57664e9SAndroid Build Coastguard Worker     ReliableSurface* rs = reinterpret_cast<ReliableSurface*>(data);
206*d57664e9SAndroid Build Coastguard Worker     rs->clearReservedBuffer();
207*d57664e9SAndroid Build Coastguard Worker     if (rs->isFallbackBuffer(buffer)) {
208*d57664e9SAndroid Build Coastguard Worker         if (fenceFd > 0) {
209*d57664e9SAndroid Build Coastguard Worker             close(fenceFd);
210*d57664e9SAndroid Build Coastguard Worker         }
211*d57664e9SAndroid Build Coastguard Worker         return OK;
212*d57664e9SAndroid Build Coastguard Worker     }
213*d57664e9SAndroid Build Coastguard Worker     return cancelBuffer(window, buffer, fenceFd);
214*d57664e9SAndroid Build Coastguard Worker }
215*d57664e9SAndroid Build Coastguard Worker 
hook_queueBuffer(ANativeWindow * window,ANativeWindow_queueBufferFn queueBuffer,void * data,ANativeWindowBuffer * buffer,int fenceFd)216*d57664e9SAndroid Build Coastguard Worker int ReliableSurface::hook_queueBuffer(ANativeWindow* window,
217*d57664e9SAndroid Build Coastguard Worker                                       ANativeWindow_queueBufferFn queueBuffer, void* data,
218*d57664e9SAndroid Build Coastguard Worker                                       ANativeWindowBuffer* buffer, int fenceFd) {
219*d57664e9SAndroid Build Coastguard Worker     ReliableSurface* rs = reinterpret_cast<ReliableSurface*>(data);
220*d57664e9SAndroid Build Coastguard Worker     rs->clearReservedBuffer();
221*d57664e9SAndroid Build Coastguard Worker 
222*d57664e9SAndroid Build Coastguard Worker     if (rs->isFallbackBuffer(buffer)) {
223*d57664e9SAndroid Build Coastguard Worker         if (fenceFd > 0) {
224*d57664e9SAndroid Build Coastguard Worker             close(fenceFd);
225*d57664e9SAndroid Build Coastguard Worker         }
226*d57664e9SAndroid Build Coastguard Worker         return OK;
227*d57664e9SAndroid Build Coastguard Worker     }
228*d57664e9SAndroid Build Coastguard Worker 
229*d57664e9SAndroid Build Coastguard Worker     return queueBuffer(window, buffer, fenceFd);
230*d57664e9SAndroid Build Coastguard Worker }
231*d57664e9SAndroid Build Coastguard Worker 
hook_perform(ANativeWindow * window,ANativeWindow_performFn perform,void * data,int operation,va_list args)232*d57664e9SAndroid Build Coastguard Worker int ReliableSurface::hook_perform(ANativeWindow* window, ANativeWindow_performFn perform,
233*d57664e9SAndroid Build Coastguard Worker                                   void* data, int operation, va_list args) {
234*d57664e9SAndroid Build Coastguard Worker     // Drop the reserved buffer if there is one since this (probably) mutated buffer dimensions
235*d57664e9SAndroid Build Coastguard Worker     // TODO: Filter to things that only affect the reserved buffer
236*d57664e9SAndroid Build Coastguard Worker     // TODO: Can we mutate the reserved buffer in some cases?
237*d57664e9SAndroid Build Coastguard Worker     ReliableSurface* rs = reinterpret_cast<ReliableSurface*>(data);
238*d57664e9SAndroid Build Coastguard Worker     rs->clearReservedBuffer();
239*d57664e9SAndroid Build Coastguard Worker 
240*d57664e9SAndroid Build Coastguard Worker     va_list argsCopy;
241*d57664e9SAndroid Build Coastguard Worker     va_copy(argsCopy, args);
242*d57664e9SAndroid Build Coastguard Worker     int result = perform(window, operation, argsCopy);
243*d57664e9SAndroid Build Coastguard Worker 
244*d57664e9SAndroid Build Coastguard Worker     {
245*d57664e9SAndroid Build Coastguard Worker         std::lock_guard _lock{rs->mMutex};
246*d57664e9SAndroid Build Coastguard Worker 
247*d57664e9SAndroid Build Coastguard Worker         switch (operation) {
248*d57664e9SAndroid Build Coastguard Worker             case ANATIVEWINDOW_PERFORM_SET_USAGE:
249*d57664e9SAndroid Build Coastguard Worker                 rs->mUsage = va_arg(args, uint32_t);
250*d57664e9SAndroid Build Coastguard Worker                 break;
251*d57664e9SAndroid Build Coastguard Worker             case ANATIVEWINDOW_PERFORM_SET_USAGE64:
252*d57664e9SAndroid Build Coastguard Worker                 rs->mUsage = va_arg(args, uint64_t);
253*d57664e9SAndroid Build Coastguard Worker                 break;
254*d57664e9SAndroid Build Coastguard Worker             case ANATIVEWINDOW_PERFORM_SET_BUFFERS_GEOMETRY:
255*d57664e9SAndroid Build Coastguard Worker                 /* width */ va_arg(args, uint32_t);
256*d57664e9SAndroid Build Coastguard Worker                 /* height */ va_arg(args, uint32_t);
257*d57664e9SAndroid Build Coastguard Worker                 rs->mFormat = static_cast<AHardwareBuffer_Format>(va_arg(args, int32_t));
258*d57664e9SAndroid Build Coastguard Worker                 break;
259*d57664e9SAndroid Build Coastguard Worker             case ANATIVEWINDOW_PERFORM_SET_BUFFERS_FORMAT:
260*d57664e9SAndroid Build Coastguard Worker                 rs->mFormat = static_cast<AHardwareBuffer_Format>(va_arg(args, int32_t));
261*d57664e9SAndroid Build Coastguard Worker                 break;
262*d57664e9SAndroid Build Coastguard Worker             case NATIVE_WINDOW_SET_BUFFER_COUNT:
263*d57664e9SAndroid Build Coastguard Worker                 size_t bufferCount = va_arg(args, size_t);
264*d57664e9SAndroid Build Coastguard Worker                 if (bufferCount >= rs->mExpectedBufferCount) {
265*d57664e9SAndroid Build Coastguard Worker                     rs->mDidSetExtraBuffers = true;
266*d57664e9SAndroid Build Coastguard Worker                 } else {
267*d57664e9SAndroid Build Coastguard Worker                     ALOGD("HOOK FAILED! Expected %zd got = %zd", rs->mExpectedBufferCount, bufferCount);
268*d57664e9SAndroid Build Coastguard Worker                 }
269*d57664e9SAndroid Build Coastguard Worker                 break;
270*d57664e9SAndroid Build Coastguard Worker         }
271*d57664e9SAndroid Build Coastguard Worker     }
272*d57664e9SAndroid Build Coastguard Worker     return result;
273*d57664e9SAndroid Build Coastguard Worker }
274*d57664e9SAndroid Build Coastguard Worker 
hook_query(const ANativeWindow * window,ANativeWindow_queryFn query,void * data,int what,int * value)275*d57664e9SAndroid Build Coastguard Worker int ReliableSurface::hook_query(const ANativeWindow *window, ANativeWindow_queryFn query,
276*d57664e9SAndroid Build Coastguard Worker         void *data, int what, int *value) {
277*d57664e9SAndroid Build Coastguard Worker     ReliableSurface* rs = reinterpret_cast<ReliableSurface*>(data);
278*d57664e9SAndroid Build Coastguard Worker     int result = query(window, what, value);
279*d57664e9SAndroid Build Coastguard Worker     if (what == ANATIVEWINDOW_QUERY_MIN_UNDEQUEUED_BUFFERS && result == OK) {
280*d57664e9SAndroid Build Coastguard Worker         std::lock_guard _lock{rs->mMutex};
281*d57664e9SAndroid Build Coastguard Worker         rs->mExpectedBufferCount = *value + 2;
282*d57664e9SAndroid Build Coastguard Worker     }
283*d57664e9SAndroid Build Coastguard Worker     return result;
284*d57664e9SAndroid Build Coastguard Worker }
285*d57664e9SAndroid Build Coastguard Worker 
286*d57664e9SAndroid Build Coastguard Worker };  // namespace android::uirenderer::renderthread
287