diff options
Diffstat (limited to 'libs/gui/Surface.cpp')
-rw-r--r-- | libs/gui/Surface.cpp | 133 |
1 files changed, 126 insertions, 7 deletions
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index d5cf11d305..e7880ebc39 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -50,6 +50,17 @@ namespace android { using ui::ColorMode; using ui::Dataspace; +namespace { + +bool isInterceptorRegistrationOp(int op) { + return op == NATIVE_WINDOW_SET_CANCEL_INTERCEPTOR || + op == NATIVE_WINDOW_SET_DEQUEUE_INTERCEPTOR || + op == NATIVE_WINDOW_SET_PERFORM_INTERCEPTOR || + op == NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR; +} + +} // namespace + Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp) : mGraphicBufferProducer(bufferProducer), mCrop(Rect::EMPTY_RECT), @@ -366,18 +377,58 @@ int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) { int Surface::hook_dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd) { Surface* c = getSelf(window); + { + std::shared_lock<std::shared_mutex> lock(c->mInterceptorMutex); + if (c->mDequeueInterceptor != nullptr) { + auto interceptor = c->mDequeueInterceptor; + auto data = c->mDequeueInterceptorData; + return interceptor(window, Surface::dequeueBufferInternal, data, buffer, fenceFd); + } + } + return c->dequeueBuffer(buffer, fenceFd); +} + +int Surface::dequeueBufferInternal(ANativeWindow* window, ANativeWindowBuffer** buffer, + int* fenceFd) { + Surface* c = getSelf(window); return c->dequeueBuffer(buffer, fenceFd); } int Surface::hook_cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) { Surface* c = getSelf(window); + { + std::shared_lock<std::shared_mutex> lock(c->mInterceptorMutex); + if (c->mCancelInterceptor != nullptr) { + auto interceptor = c->mCancelInterceptor; + auto data = c->mCancelInterceptorData; + return interceptor(window, Surface::cancelBufferInternal, data, buffer, fenceFd); + } + } + return c->cancelBuffer(buffer, fenceFd); +} + +int Surface::cancelBufferInternal(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) { + Surface* c = getSelf(window); return c->cancelBuffer(buffer, fenceFd); } int Surface::hook_queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) { Surface* c = getSelf(window); + { + std::shared_lock<std::shared_mutex> lock(c->mInterceptorMutex); + if (c->mQueueInterceptor != nullptr) { + auto interceptor = c->mQueueInterceptor; + auto data = c->mQueueInterceptorData; + return interceptor(window, Surface::queueBufferInternal, data, buffer, fenceFd); + } + } + return c->queueBuffer(buffer, fenceFd); +} + +int Surface::queueBufferInternal(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) { + Surface* c = getSelf(window); return c->queueBuffer(buffer, fenceFd); } @@ -420,21 +471,38 @@ int Surface::hook_queueBuffer_DEPRECATED(ANativeWindow* window, return c->queueBuffer(buffer, -1); } -int Surface::hook_query(const ANativeWindow* window, - int what, int* value) { - const Surface* c = getSelf(window); - return c->query(what, value); -} - int Surface::hook_perform(ANativeWindow* window, int operation, ...) { va_list args; va_start(args, operation); Surface* c = getSelf(window); - int result = c->perform(operation, args); + int result; + // Don't acquire shared ownership of the interceptor mutex if we're going to + // do interceptor registration, as otherwise we'll deadlock on acquiring + // exclusive ownership. + if (!isInterceptorRegistrationOp(operation)) { + std::shared_lock<std::shared_mutex> lock(c->mInterceptorMutex); + if (c->mPerformInterceptor != nullptr) { + result = c->mPerformInterceptor(window, Surface::performInternal, + c->mPerformInterceptorData, operation, args); + va_end(args); + return result; + } + } + result = c->perform(operation, args); va_end(args); return result; } +int Surface::performInternal(ANativeWindow* window, int operation, va_list args) { + Surface* c = getSelf(window); + return c->perform(operation, args); +} + +int Surface::hook_query(const ANativeWindow* window, int what, int* value) { + const Surface* c = getSelf(window); + return c->query(what, value); +} + int Surface::setSwapInterval(int interval) { ATRACE_CALL(); // EGL specification states: @@ -1096,6 +1164,18 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_SET_FRAME_RATE: res = dispatchSetFrameRate(args); break; + case NATIVE_WINDOW_SET_CANCEL_INTERCEPTOR: + res = dispatchAddCancelInterceptor(args); + break; + case NATIVE_WINDOW_SET_DEQUEUE_INTERCEPTOR: + res = dispatchAddDequeueInterceptor(args); + break; + case NATIVE_WINDOW_SET_PERFORM_INTERCEPTOR: + res = dispatchAddPerformInterceptor(args); + break; + case NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR: + res = dispatchAddQueueInterceptor(args); + break; default: res = NAME_NOT_FOUND; break; @@ -1329,6 +1409,45 @@ int Surface::dispatchSetFrameRate(va_list args) { return setFrameRate(frameRate); } +int Surface::dispatchAddCancelInterceptor(va_list args) { + ANativeWindow_cancelBufferInterceptor interceptor = + va_arg(args, ANativeWindow_cancelBufferInterceptor); + void* data = va_arg(args, void*); + std::lock_guard<std::shared_mutex> lock(mInterceptorMutex); + mCancelInterceptor = interceptor; + mCancelInterceptorData = data; + return NO_ERROR; +} + +int Surface::dispatchAddDequeueInterceptor(va_list args) { + ANativeWindow_dequeueBufferInterceptor interceptor = + va_arg(args, ANativeWindow_dequeueBufferInterceptor); + void* data = va_arg(args, void*); + std::lock_guard<std::shared_mutex> lock(mInterceptorMutex); + mDequeueInterceptor = interceptor; + mDequeueInterceptorData = data; + return NO_ERROR; +} + +int Surface::dispatchAddPerformInterceptor(va_list args) { + ANativeWindow_performInterceptor interceptor = va_arg(args, ANativeWindow_performInterceptor); + void* data = va_arg(args, void*); + std::lock_guard<std::shared_mutex> lock(mInterceptorMutex); + mPerformInterceptor = interceptor; + mPerformInterceptorData = data; + return NO_ERROR; +} + +int Surface::dispatchAddQueueInterceptor(va_list args) { + ANativeWindow_queueBufferInterceptor interceptor = + va_arg(args, ANativeWindow_queueBufferInterceptor); + void* data = va_arg(args, void*); + std::lock_guard<std::shared_mutex> lock(mInterceptorMutex); + mQueueInterceptor = interceptor; + mQueueInterceptorData = data; + return NO_ERROR; +} + bool Surface::transformToDisplayInverse() { return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) == NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; |