Loading libs/gui/Surface.cpp +126 −7 Original line number Original line Diff line number Diff line Loading @@ -50,6 +50,17 @@ namespace android { using ui::ColorMode; using ui::ColorMode; using ui::Dataspace; 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) Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp) : mGraphicBufferProducer(bufferProducer), : mGraphicBufferProducer(bufferProducer), mCrop(Rect::EMPTY_RECT), mCrop(Rect::EMPTY_RECT), Loading Loading @@ -366,18 +377,58 @@ int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) { int Surface::hook_dequeueBuffer(ANativeWindow* window, int Surface::hook_dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd) { ANativeWindowBuffer** buffer, int* fenceFd) { Surface* c = getSelf(window); 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); return c->dequeueBuffer(buffer, fenceFd); } } int Surface::hook_cancelBuffer(ANativeWindow* window, int Surface::hook_cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) { ANativeWindowBuffer* buffer, int fenceFd) { Surface* c = getSelf(window); 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); return c->cancelBuffer(buffer, fenceFd); } } int Surface::hook_queueBuffer(ANativeWindow* window, int Surface::hook_queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) { ANativeWindowBuffer* buffer, int fenceFd) { Surface* c = getSelf(window); 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); return c->queueBuffer(buffer, fenceFd); } } Loading Loading @@ -420,20 +471,37 @@ int Surface::hook_queueBuffer_DEPRECATED(ANativeWindow* window, return c->queueBuffer(buffer, -1); 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, ...) { int Surface::hook_perform(ANativeWindow* window, int operation, ...) { va_list args; va_list args; va_start(args, operation); va_start(args, operation); Surface* c = getSelf(window); 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); va_end(args); return result; 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) { int Surface::setSwapInterval(int interval) { ATRACE_CALL(); ATRACE_CALL(); Loading Loading @@ -1096,6 +1164,18 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_SET_FRAME_RATE: case NATIVE_WINDOW_SET_FRAME_RATE: res = dispatchSetFrameRate(args); res = dispatchSetFrameRate(args); break; 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: default: res = NAME_NOT_FOUND; res = NAME_NOT_FOUND; break; break; Loading Loading @@ -1329,6 +1409,45 @@ int Surface::dispatchSetFrameRate(va_list args) { return setFrameRate(frameRate); 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() { bool Surface::transformToDisplayInverse() { return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) == return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) == NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; Loading libs/gui/include/gui/Surface.h +25 −3 Original line number Original line Diff line number Diff line Loading @@ -21,16 +21,15 @@ #include <gui/HdrMetadata.h> #include <gui/HdrMetadata.h> #include <gui/IGraphicBufferProducer.h> #include <gui/IGraphicBufferProducer.h> #include <gui/IProducerListener.h> #include <gui/IProducerListener.h> #include <system/window.h> #include <ui/ANativeObjectBase.h> #include <ui/ANativeObjectBase.h> #include <ui/GraphicTypes.h> #include <ui/GraphicTypes.h> #include <ui/Region.h> #include <ui/Region.h> #include <utils/Condition.h> #include <utils/Condition.h> #include <utils/Mutex.h> #include <utils/Mutex.h> #include <utils/RefBase.h> #include <utils/RefBase.h> #include <system/window.h> #include <shared_mutex> namespace android { namespace android { Loading Loading @@ -205,6 +204,13 @@ private: ANativeWindowBuffer* buffer, int fenceFd); ANativeWindowBuffer* buffer, int fenceFd); static int hook_setSwapInterval(ANativeWindow* window, int interval); static int hook_setSwapInterval(ANativeWindow* window, int interval); static int cancelBufferInternal(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd); static int dequeueBufferInternal(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd); static int performInternal(ANativeWindow* window, int operation, va_list args); static int queueBufferInternal(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd); static int hook_cancelBuffer_DEPRECATED(ANativeWindow* window, static int hook_cancelBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer* buffer); ANativeWindowBuffer* buffer); static int hook_dequeueBuffer_DEPRECATED(ANativeWindow* window, static int hook_dequeueBuffer_DEPRECATED(ANativeWindow* window, Loading Loading @@ -252,6 +258,10 @@ private: int dispatchGetLastDequeueDuration(va_list args); int dispatchGetLastDequeueDuration(va_list args); int dispatchGetLastQueueDuration(va_list args); int dispatchGetLastQueueDuration(va_list args); int dispatchSetFrameRate(va_list args); int dispatchSetFrameRate(va_list args); int dispatchAddCancelInterceptor(va_list args); int dispatchAddDequeueInterceptor(va_list args); int dispatchAddPerformInterceptor(va_list args); int dispatchAddQueueInterceptor(va_list args); bool transformToDisplayInverse(); bool transformToDisplayInverse(); protected: protected: Loading Loading @@ -457,6 +467,18 @@ protected: // member variables are accessed. // member variables are accessed. mutable Mutex mMutex; mutable Mutex mMutex; // mInterceptorMutex is the mutex guarding interceptors. std::shared_mutex mInterceptorMutex; ANativeWindow_cancelBufferInterceptor mCancelInterceptor = nullptr; void* mCancelInterceptorData = nullptr; ANativeWindow_dequeueBufferInterceptor mDequeueInterceptor = nullptr; void* mDequeueInterceptorData = nullptr; ANativeWindow_performInterceptor mPerformInterceptor = nullptr; void* mPerformInterceptorData = nullptr; ANativeWindow_queueBufferInterceptor mQueueInterceptor = nullptr; void* mQueueInterceptorData = nullptr; // must be used from the lock/unlock thread // must be used from the lock/unlock thread sp<GraphicBuffer> mLockedBuffer; sp<GraphicBuffer> mLockedBuffer; sp<GraphicBuffer> mPostedBuffer; sp<GraphicBuffer> mPostedBuffer; Loading libs/nativewindow/ANativeWindow.cpp +23 −0 Original line number Original line Diff line number Diff line Loading @@ -304,3 +304,26 @@ int64_t ANativeWindow_getLastDequeueStartTime(ANativeWindow* window) { int ANativeWindow_setDequeueTimeout(ANativeWindow* window, int64_t timeout) { int ANativeWindow_setDequeueTimeout(ANativeWindow* window, int64_t timeout) { return window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT, timeout); return window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT, timeout); } } int ANativeWindow_setCancelBufferInterceptor(ANativeWindow* window, ANativeWindow_cancelBufferInterceptor interceptor, void* data) { return window->perform(window, NATIVE_WINDOW_SET_CANCEL_INTERCEPTOR, interceptor, data); } int ANativeWindow_setDequeueBufferInterceptor(ANativeWindow* window, ANativeWindow_dequeueBufferInterceptor interceptor, void* data) { return window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_INTERCEPTOR, interceptor, data); } int ANativeWindow_setPerformInterceptor(ANativeWindow* window, ANativeWindow_performInterceptor interceptor, void* data) { return window->perform(window, NATIVE_WINDOW_SET_PERFORM_INTERCEPTOR, interceptor, data); } int ANativeWindow_setQueueBufferInterceptor(ANativeWindow* window, ANativeWindow_queueBufferInterceptor interceptor, void* data) { return window->perform(window, NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR, interceptor, data); } libs/nativewindow/include/apex/window.h +147 −0 Original line number Original line Diff line number Diff line Loading @@ -17,12 +17,159 @@ #pragma once #pragma once #include <nativebase/nativebase.h> #include <nativebase/nativebase.h> #include <stdarg.h> // apex is a superset of the NDK // apex is a superset of the NDK #include <android/native_window.h> #include <android/native_window.h> __BEGIN_DECLS __BEGIN_DECLS /* * perform bits that can be used with ANativeWindow_perform() * * This is only to support the intercepting methods below - these should notbe * used directly otherwise. */ enum ANativeWindowPerform { // clang-format off ANATIVEWINDOW_PERFORM_SET_USAGE = 0, ANATIVEWINDOW_PERFORM_SET_BUFFERS_GEOMETRY = 5, ANATIVEWINDOW_PERFORM_SET_BUFFERS_FORMAT = 9, ANATIVEWINDOW_PERFORM_SET_USAGE64 = 30, // clang-format on }; /** * Prototype of the function that an ANativeWindow implementation would call * when ANativeWindow_cancelBuffer is called. */ typedef int (*ANativeWindow_cancelBufferFn)(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd); /** * Prototype of the function that intercepts an invocation of * ANativeWindow_cancelBufferFn, along with a data pointer that's passed by the * caller who set the interceptor, as well as arguments that would be * passed to ANativeWindow_cancelBufferFn if it were to be called. */ typedef int (*ANativeWindow_cancelBufferInterceptor)(ANativeWindow* window, ANativeWindow_cancelBufferFn cancelBuffer, void* data, ANativeWindowBuffer* buffer, int fenceFd); /** * Prototype of the function that an ANativeWindow implementation would call * when ANativeWindow_dequeueBuffer is called. */ typedef int (*ANativeWindow_dequeueBufferFn)(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd); /** * Prototype of the function that intercepts an invocation of * ANativeWindow_dequeueBufferFn, along with a data pointer that's passed by the * caller who set the interceptor, as well as arguments that would be * passed to ANativeWindow_dequeueBufferFn if it were to be called. */ typedef int (*ANativeWindow_dequeueBufferInterceptor)(ANativeWindow* window, ANativeWindow_dequeueBufferFn dequeueBuffer, void* data, ANativeWindowBuffer** buffer, int* fenceFd); /** * Prototype of the function that an ANativeWindow implementation would call * when ANativeWindow_perform is called. */ typedef int (*ANativeWindow_performFn)(ANativeWindow* window, int operation, va_list args); /** * Prototype of the function that intercepts an invocation of * ANativeWindow_performFn, along with a data pointer that's passed by the * caller who set the interceptor, as well as arguments that would be * passed to ANativeWindow_performFn if it were to be called. */ typedef int (*ANativeWindow_performInterceptor)(ANativeWindow* window, ANativeWindow_performFn perform, void* data, int operation, va_list args); /** * Prototype of the function that an ANativeWindow implementation would call * when ANativeWindow_queueBuffer is called. */ typedef int (*ANativeWindow_queueBufferFn)(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd); /** * Prototype of the function that intercepts an invocation of * ANativeWindow_queueBufferFn, along with a data pointer that's passed by the * caller who set the interceptor, as well as arguments that would be * passed to ANativeWindow_queueBufferFn if it were to be called. */ typedef int (*ANativeWindow_queueBufferInterceptor)(ANativeWindow* window, ANativeWindow_queueBufferFn queueBuffer, void* data, ANativeWindowBuffer* buffer, int fenceFd); /** * Registers an interceptor for ANativeWindow_cancelBuffer. Instead of calling * the underlying cancelBuffer function, instead the provided interceptor is * called, which may optionally call the underlying cancelBuffer function. An * optional data pointer is also provided to side-channel additional arguments. * * Note that usage of this should only be used for specialized use-cases by * either the system partition or to Mainline modules. This should never be * exposed to NDK or LL-NDK. * * Returns NO_ERROR on success, -errno if registration failed. */ int ANativeWindow_setCancelBufferInterceptor(ANativeWindow* window, ANativeWindow_cancelBufferInterceptor interceptor, void* data); /** * Registers an interceptor for ANativeWindow_dequeueBuffer. Instead of calling * the underlying dequeueBuffer function, instead the provided interceptor is * called, which may optionally call the underlying dequeueBuffer function. An * optional data pointer is also provided to side-channel additional arguments. * * Note that usage of this should only be used for specialized use-cases by * either the system partition or to Mainline modules. This should never be * exposed to NDK or LL-NDK. * * Returns NO_ERROR on success, -errno if registration failed. */ int ANativeWindow_setDequeueBufferInterceptor(ANativeWindow* window, ANativeWindow_dequeueBufferInterceptor interceptor, void* data); /** * Registers an interceptor for ANativeWindow_perform. Instead of calling * the underlying perform function, instead the provided interceptor is * called, which may optionally call the underlying perform function. An * optional data pointer is also provided to side-channel additional arguments. * * Note that usage of this should only be used for specialized use-cases by * either the system partition or to Mainline modules. This should never be * exposed to NDK or LL-NDK. * * Returns NO_ERROR on success, -errno if registration failed. */ int ANativeWindow_setPerformInterceptor(ANativeWindow* window, ANativeWindow_performInterceptor interceptor, void* data); /** * Registers an interceptor for ANativeWindow_queueBuffer. Instead of calling * the underlying queueBuffer function, instead the provided interceptor is * called, which may optionally call the underlying queueBuffer function. An * optional data pointer is also provided to side-channel additional arguments. * * Note that usage of this should only be used for specialized use-cases by * either the system partition or to Mainline modules. This should never be * exposed to NDK or LL-NDK. * * Returns NO_ERROR on success, -errno if registration failed. */ int ANativeWindow_setQueueBufferInterceptor(ANativeWindow* window, ANativeWindow_queueBufferInterceptor interceptor, void* data); /** /** * Retrieves how long it took for the last time a buffer was dequeued. * Retrieves how long it took for the last time a buffer was dequeued. * * Loading libs/nativewindow/include/system/window.h +8 −4 Original line number Original line Diff line number Diff line Loading @@ -207,16 +207,16 @@ enum { */ */ enum { enum { // clang-format off // clang-format off NATIVE_WINDOW_SET_USAGE = 0, /* deprecated */ NATIVE_WINDOW_SET_USAGE = ANATIVEWINDOW_PERFORM_SET_USAGE, /* deprecated */ NATIVE_WINDOW_CONNECT = 1, /* deprecated */ NATIVE_WINDOW_CONNECT = 1, /* deprecated */ NATIVE_WINDOW_DISCONNECT = 2, /* deprecated */ NATIVE_WINDOW_DISCONNECT = 2, /* deprecated */ NATIVE_WINDOW_SET_CROP = 3, /* private */ NATIVE_WINDOW_SET_CROP = 3, /* private */ NATIVE_WINDOW_SET_BUFFER_COUNT = 4, NATIVE_WINDOW_SET_BUFFER_COUNT = 4, NATIVE_WINDOW_SET_BUFFERS_GEOMETRY = 5, /* deprecated */ NATIVE_WINDOW_SET_BUFFERS_GEOMETRY = ANATIVEWINDOW_PERFORM_SET_BUFFERS_GEOMETRY, /* deprecated */ NATIVE_WINDOW_SET_BUFFERS_TRANSFORM = 6, NATIVE_WINDOW_SET_BUFFERS_TRANSFORM = 6, NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP = 7, NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP = 7, NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS = 8, NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS = 8, NATIVE_WINDOW_SET_BUFFERS_FORMAT = 9, NATIVE_WINDOW_SET_BUFFERS_FORMAT = ANATIVEWINDOW_PERFORM_SET_BUFFERS_FORMAT, NATIVE_WINDOW_SET_SCALING_MODE = 10, /* private */ NATIVE_WINDOW_SET_SCALING_MODE = 10, /* private */ NATIVE_WINDOW_LOCK = 11, /* private */ NATIVE_WINDOW_LOCK = 11, /* private */ NATIVE_WINDOW_UNLOCK_AND_POST = 12, /* private */ NATIVE_WINDOW_UNLOCK_AND_POST = 12, /* private */ Loading @@ -237,7 +237,7 @@ enum { NATIVE_WINDOW_GET_FRAME_TIMESTAMPS = 27, NATIVE_WINDOW_GET_FRAME_TIMESTAMPS = 27, NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT = 28, NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT = 28, NATIVE_WINDOW_GET_HDR_SUPPORT = 29, NATIVE_WINDOW_GET_HDR_SUPPORT = 29, NATIVE_WINDOW_SET_USAGE64 = 30, NATIVE_WINDOW_SET_USAGE64 = ANATIVEWINDOW_PERFORM_SET_USAGE64, NATIVE_WINDOW_GET_CONSUMER_USAGE64 = 31, NATIVE_WINDOW_GET_CONSUMER_USAGE64 = 31, NATIVE_WINDOW_SET_BUFFERS_SMPTE2086_METADATA = 32, NATIVE_WINDOW_SET_BUFFERS_SMPTE2086_METADATA = 32, NATIVE_WINDOW_SET_BUFFERS_CTA861_3_METADATA = 33, NATIVE_WINDOW_SET_BUFFERS_CTA861_3_METADATA = 33, Loading @@ -248,6 +248,10 @@ enum { NATIVE_WINDOW_GET_LAST_DEQUEUE_DURATION = 38, /* private */ NATIVE_WINDOW_GET_LAST_DEQUEUE_DURATION = 38, /* private */ NATIVE_WINDOW_GET_LAST_QUEUE_DURATION = 39, /* private */ NATIVE_WINDOW_GET_LAST_QUEUE_DURATION = 39, /* private */ NATIVE_WINDOW_SET_FRAME_RATE = 40, NATIVE_WINDOW_SET_FRAME_RATE = 40, NATIVE_WINDOW_SET_CANCEL_INTERCEPTOR = 41, /* private */ NATIVE_WINDOW_SET_DEQUEUE_INTERCEPTOR = 42, /* private */ NATIVE_WINDOW_SET_PERFORM_INTERCEPTOR = 43, /* private */ NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR = 44, /* private */ // clang-format on // clang-format on }; }; Loading Loading
libs/gui/Surface.cpp +126 −7 Original line number Original line Diff line number Diff line Loading @@ -50,6 +50,17 @@ namespace android { using ui::ColorMode; using ui::ColorMode; using ui::Dataspace; 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) Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp) : mGraphicBufferProducer(bufferProducer), : mGraphicBufferProducer(bufferProducer), mCrop(Rect::EMPTY_RECT), mCrop(Rect::EMPTY_RECT), Loading Loading @@ -366,18 +377,58 @@ int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) { int Surface::hook_dequeueBuffer(ANativeWindow* window, int Surface::hook_dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd) { ANativeWindowBuffer** buffer, int* fenceFd) { Surface* c = getSelf(window); 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); return c->dequeueBuffer(buffer, fenceFd); } } int Surface::hook_cancelBuffer(ANativeWindow* window, int Surface::hook_cancelBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) { ANativeWindowBuffer* buffer, int fenceFd) { Surface* c = getSelf(window); 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); return c->cancelBuffer(buffer, fenceFd); } } int Surface::hook_queueBuffer(ANativeWindow* window, int Surface::hook_queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd) { ANativeWindowBuffer* buffer, int fenceFd) { Surface* c = getSelf(window); 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); return c->queueBuffer(buffer, fenceFd); } } Loading Loading @@ -420,20 +471,37 @@ int Surface::hook_queueBuffer_DEPRECATED(ANativeWindow* window, return c->queueBuffer(buffer, -1); 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, ...) { int Surface::hook_perform(ANativeWindow* window, int operation, ...) { va_list args; va_list args; va_start(args, operation); va_start(args, operation); Surface* c = getSelf(window); 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); va_end(args); return result; 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) { int Surface::setSwapInterval(int interval) { ATRACE_CALL(); ATRACE_CALL(); Loading Loading @@ -1096,6 +1164,18 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_SET_FRAME_RATE: case NATIVE_WINDOW_SET_FRAME_RATE: res = dispatchSetFrameRate(args); res = dispatchSetFrameRate(args); break; 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: default: res = NAME_NOT_FOUND; res = NAME_NOT_FOUND; break; break; Loading Loading @@ -1329,6 +1409,45 @@ int Surface::dispatchSetFrameRate(va_list args) { return setFrameRate(frameRate); 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() { bool Surface::transformToDisplayInverse() { return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) == return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) == NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; Loading
libs/gui/include/gui/Surface.h +25 −3 Original line number Original line Diff line number Diff line Loading @@ -21,16 +21,15 @@ #include <gui/HdrMetadata.h> #include <gui/HdrMetadata.h> #include <gui/IGraphicBufferProducer.h> #include <gui/IGraphicBufferProducer.h> #include <gui/IProducerListener.h> #include <gui/IProducerListener.h> #include <system/window.h> #include <ui/ANativeObjectBase.h> #include <ui/ANativeObjectBase.h> #include <ui/GraphicTypes.h> #include <ui/GraphicTypes.h> #include <ui/Region.h> #include <ui/Region.h> #include <utils/Condition.h> #include <utils/Condition.h> #include <utils/Mutex.h> #include <utils/Mutex.h> #include <utils/RefBase.h> #include <utils/RefBase.h> #include <system/window.h> #include <shared_mutex> namespace android { namespace android { Loading Loading @@ -205,6 +204,13 @@ private: ANativeWindowBuffer* buffer, int fenceFd); ANativeWindowBuffer* buffer, int fenceFd); static int hook_setSwapInterval(ANativeWindow* window, int interval); static int hook_setSwapInterval(ANativeWindow* window, int interval); static int cancelBufferInternal(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd); static int dequeueBufferInternal(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd); static int performInternal(ANativeWindow* window, int operation, va_list args); static int queueBufferInternal(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd); static int hook_cancelBuffer_DEPRECATED(ANativeWindow* window, static int hook_cancelBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer* buffer); ANativeWindowBuffer* buffer); static int hook_dequeueBuffer_DEPRECATED(ANativeWindow* window, static int hook_dequeueBuffer_DEPRECATED(ANativeWindow* window, Loading Loading @@ -252,6 +258,10 @@ private: int dispatchGetLastDequeueDuration(va_list args); int dispatchGetLastDequeueDuration(va_list args); int dispatchGetLastQueueDuration(va_list args); int dispatchGetLastQueueDuration(va_list args); int dispatchSetFrameRate(va_list args); int dispatchSetFrameRate(va_list args); int dispatchAddCancelInterceptor(va_list args); int dispatchAddDequeueInterceptor(va_list args); int dispatchAddPerformInterceptor(va_list args); int dispatchAddQueueInterceptor(va_list args); bool transformToDisplayInverse(); bool transformToDisplayInverse(); protected: protected: Loading Loading @@ -457,6 +467,18 @@ protected: // member variables are accessed. // member variables are accessed. mutable Mutex mMutex; mutable Mutex mMutex; // mInterceptorMutex is the mutex guarding interceptors. std::shared_mutex mInterceptorMutex; ANativeWindow_cancelBufferInterceptor mCancelInterceptor = nullptr; void* mCancelInterceptorData = nullptr; ANativeWindow_dequeueBufferInterceptor mDequeueInterceptor = nullptr; void* mDequeueInterceptorData = nullptr; ANativeWindow_performInterceptor mPerformInterceptor = nullptr; void* mPerformInterceptorData = nullptr; ANativeWindow_queueBufferInterceptor mQueueInterceptor = nullptr; void* mQueueInterceptorData = nullptr; // must be used from the lock/unlock thread // must be used from the lock/unlock thread sp<GraphicBuffer> mLockedBuffer; sp<GraphicBuffer> mLockedBuffer; sp<GraphicBuffer> mPostedBuffer; sp<GraphicBuffer> mPostedBuffer; Loading
libs/nativewindow/ANativeWindow.cpp +23 −0 Original line number Original line Diff line number Diff line Loading @@ -304,3 +304,26 @@ int64_t ANativeWindow_getLastDequeueStartTime(ANativeWindow* window) { int ANativeWindow_setDequeueTimeout(ANativeWindow* window, int64_t timeout) { int ANativeWindow_setDequeueTimeout(ANativeWindow* window, int64_t timeout) { return window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT, timeout); return window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT, timeout); } } int ANativeWindow_setCancelBufferInterceptor(ANativeWindow* window, ANativeWindow_cancelBufferInterceptor interceptor, void* data) { return window->perform(window, NATIVE_WINDOW_SET_CANCEL_INTERCEPTOR, interceptor, data); } int ANativeWindow_setDequeueBufferInterceptor(ANativeWindow* window, ANativeWindow_dequeueBufferInterceptor interceptor, void* data) { return window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_INTERCEPTOR, interceptor, data); } int ANativeWindow_setPerformInterceptor(ANativeWindow* window, ANativeWindow_performInterceptor interceptor, void* data) { return window->perform(window, NATIVE_WINDOW_SET_PERFORM_INTERCEPTOR, interceptor, data); } int ANativeWindow_setQueueBufferInterceptor(ANativeWindow* window, ANativeWindow_queueBufferInterceptor interceptor, void* data) { return window->perform(window, NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR, interceptor, data); }
libs/nativewindow/include/apex/window.h +147 −0 Original line number Original line Diff line number Diff line Loading @@ -17,12 +17,159 @@ #pragma once #pragma once #include <nativebase/nativebase.h> #include <nativebase/nativebase.h> #include <stdarg.h> // apex is a superset of the NDK // apex is a superset of the NDK #include <android/native_window.h> #include <android/native_window.h> __BEGIN_DECLS __BEGIN_DECLS /* * perform bits that can be used with ANativeWindow_perform() * * This is only to support the intercepting methods below - these should notbe * used directly otherwise. */ enum ANativeWindowPerform { // clang-format off ANATIVEWINDOW_PERFORM_SET_USAGE = 0, ANATIVEWINDOW_PERFORM_SET_BUFFERS_GEOMETRY = 5, ANATIVEWINDOW_PERFORM_SET_BUFFERS_FORMAT = 9, ANATIVEWINDOW_PERFORM_SET_USAGE64 = 30, // clang-format on }; /** * Prototype of the function that an ANativeWindow implementation would call * when ANativeWindow_cancelBuffer is called. */ typedef int (*ANativeWindow_cancelBufferFn)(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd); /** * Prototype of the function that intercepts an invocation of * ANativeWindow_cancelBufferFn, along with a data pointer that's passed by the * caller who set the interceptor, as well as arguments that would be * passed to ANativeWindow_cancelBufferFn if it were to be called. */ typedef int (*ANativeWindow_cancelBufferInterceptor)(ANativeWindow* window, ANativeWindow_cancelBufferFn cancelBuffer, void* data, ANativeWindowBuffer* buffer, int fenceFd); /** * Prototype of the function that an ANativeWindow implementation would call * when ANativeWindow_dequeueBuffer is called. */ typedef int (*ANativeWindow_dequeueBufferFn)(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd); /** * Prototype of the function that intercepts an invocation of * ANativeWindow_dequeueBufferFn, along with a data pointer that's passed by the * caller who set the interceptor, as well as arguments that would be * passed to ANativeWindow_dequeueBufferFn if it were to be called. */ typedef int (*ANativeWindow_dequeueBufferInterceptor)(ANativeWindow* window, ANativeWindow_dequeueBufferFn dequeueBuffer, void* data, ANativeWindowBuffer** buffer, int* fenceFd); /** * Prototype of the function that an ANativeWindow implementation would call * when ANativeWindow_perform is called. */ typedef int (*ANativeWindow_performFn)(ANativeWindow* window, int operation, va_list args); /** * Prototype of the function that intercepts an invocation of * ANativeWindow_performFn, along with a data pointer that's passed by the * caller who set the interceptor, as well as arguments that would be * passed to ANativeWindow_performFn if it were to be called. */ typedef int (*ANativeWindow_performInterceptor)(ANativeWindow* window, ANativeWindow_performFn perform, void* data, int operation, va_list args); /** * Prototype of the function that an ANativeWindow implementation would call * when ANativeWindow_queueBuffer is called. */ typedef int (*ANativeWindow_queueBufferFn)(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd); /** * Prototype of the function that intercepts an invocation of * ANativeWindow_queueBufferFn, along with a data pointer that's passed by the * caller who set the interceptor, as well as arguments that would be * passed to ANativeWindow_queueBufferFn if it were to be called. */ typedef int (*ANativeWindow_queueBufferInterceptor)(ANativeWindow* window, ANativeWindow_queueBufferFn queueBuffer, void* data, ANativeWindowBuffer* buffer, int fenceFd); /** * Registers an interceptor for ANativeWindow_cancelBuffer. Instead of calling * the underlying cancelBuffer function, instead the provided interceptor is * called, which may optionally call the underlying cancelBuffer function. An * optional data pointer is also provided to side-channel additional arguments. * * Note that usage of this should only be used for specialized use-cases by * either the system partition or to Mainline modules. This should never be * exposed to NDK or LL-NDK. * * Returns NO_ERROR on success, -errno if registration failed. */ int ANativeWindow_setCancelBufferInterceptor(ANativeWindow* window, ANativeWindow_cancelBufferInterceptor interceptor, void* data); /** * Registers an interceptor for ANativeWindow_dequeueBuffer. Instead of calling * the underlying dequeueBuffer function, instead the provided interceptor is * called, which may optionally call the underlying dequeueBuffer function. An * optional data pointer is also provided to side-channel additional arguments. * * Note that usage of this should only be used for specialized use-cases by * either the system partition or to Mainline modules. This should never be * exposed to NDK or LL-NDK. * * Returns NO_ERROR on success, -errno if registration failed. */ int ANativeWindow_setDequeueBufferInterceptor(ANativeWindow* window, ANativeWindow_dequeueBufferInterceptor interceptor, void* data); /** * Registers an interceptor for ANativeWindow_perform. Instead of calling * the underlying perform function, instead the provided interceptor is * called, which may optionally call the underlying perform function. An * optional data pointer is also provided to side-channel additional arguments. * * Note that usage of this should only be used for specialized use-cases by * either the system partition or to Mainline modules. This should never be * exposed to NDK or LL-NDK. * * Returns NO_ERROR on success, -errno if registration failed. */ int ANativeWindow_setPerformInterceptor(ANativeWindow* window, ANativeWindow_performInterceptor interceptor, void* data); /** * Registers an interceptor for ANativeWindow_queueBuffer. Instead of calling * the underlying queueBuffer function, instead the provided interceptor is * called, which may optionally call the underlying queueBuffer function. An * optional data pointer is also provided to side-channel additional arguments. * * Note that usage of this should only be used for specialized use-cases by * either the system partition or to Mainline modules. This should never be * exposed to NDK or LL-NDK. * * Returns NO_ERROR on success, -errno if registration failed. */ int ANativeWindow_setQueueBufferInterceptor(ANativeWindow* window, ANativeWindow_queueBufferInterceptor interceptor, void* data); /** /** * Retrieves how long it took for the last time a buffer was dequeued. * Retrieves how long it took for the last time a buffer was dequeued. * * Loading
libs/nativewindow/include/system/window.h +8 −4 Original line number Original line Diff line number Diff line Loading @@ -207,16 +207,16 @@ enum { */ */ enum { enum { // clang-format off // clang-format off NATIVE_WINDOW_SET_USAGE = 0, /* deprecated */ NATIVE_WINDOW_SET_USAGE = ANATIVEWINDOW_PERFORM_SET_USAGE, /* deprecated */ NATIVE_WINDOW_CONNECT = 1, /* deprecated */ NATIVE_WINDOW_CONNECT = 1, /* deprecated */ NATIVE_WINDOW_DISCONNECT = 2, /* deprecated */ NATIVE_WINDOW_DISCONNECT = 2, /* deprecated */ NATIVE_WINDOW_SET_CROP = 3, /* private */ NATIVE_WINDOW_SET_CROP = 3, /* private */ NATIVE_WINDOW_SET_BUFFER_COUNT = 4, NATIVE_WINDOW_SET_BUFFER_COUNT = 4, NATIVE_WINDOW_SET_BUFFERS_GEOMETRY = 5, /* deprecated */ NATIVE_WINDOW_SET_BUFFERS_GEOMETRY = ANATIVEWINDOW_PERFORM_SET_BUFFERS_GEOMETRY, /* deprecated */ NATIVE_WINDOW_SET_BUFFERS_TRANSFORM = 6, NATIVE_WINDOW_SET_BUFFERS_TRANSFORM = 6, NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP = 7, NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP = 7, NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS = 8, NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS = 8, NATIVE_WINDOW_SET_BUFFERS_FORMAT = 9, NATIVE_WINDOW_SET_BUFFERS_FORMAT = ANATIVEWINDOW_PERFORM_SET_BUFFERS_FORMAT, NATIVE_WINDOW_SET_SCALING_MODE = 10, /* private */ NATIVE_WINDOW_SET_SCALING_MODE = 10, /* private */ NATIVE_WINDOW_LOCK = 11, /* private */ NATIVE_WINDOW_LOCK = 11, /* private */ NATIVE_WINDOW_UNLOCK_AND_POST = 12, /* private */ NATIVE_WINDOW_UNLOCK_AND_POST = 12, /* private */ Loading @@ -237,7 +237,7 @@ enum { NATIVE_WINDOW_GET_FRAME_TIMESTAMPS = 27, NATIVE_WINDOW_GET_FRAME_TIMESTAMPS = 27, NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT = 28, NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT = 28, NATIVE_WINDOW_GET_HDR_SUPPORT = 29, NATIVE_WINDOW_GET_HDR_SUPPORT = 29, NATIVE_WINDOW_SET_USAGE64 = 30, NATIVE_WINDOW_SET_USAGE64 = ANATIVEWINDOW_PERFORM_SET_USAGE64, NATIVE_WINDOW_GET_CONSUMER_USAGE64 = 31, NATIVE_WINDOW_GET_CONSUMER_USAGE64 = 31, NATIVE_WINDOW_SET_BUFFERS_SMPTE2086_METADATA = 32, NATIVE_WINDOW_SET_BUFFERS_SMPTE2086_METADATA = 32, NATIVE_WINDOW_SET_BUFFERS_CTA861_3_METADATA = 33, NATIVE_WINDOW_SET_BUFFERS_CTA861_3_METADATA = 33, Loading @@ -248,6 +248,10 @@ enum { NATIVE_WINDOW_GET_LAST_DEQUEUE_DURATION = 38, /* private */ NATIVE_WINDOW_GET_LAST_DEQUEUE_DURATION = 38, /* private */ NATIVE_WINDOW_GET_LAST_QUEUE_DURATION = 39, /* private */ NATIVE_WINDOW_GET_LAST_QUEUE_DURATION = 39, /* private */ NATIVE_WINDOW_SET_FRAME_RATE = 40, NATIVE_WINDOW_SET_FRAME_RATE = 40, NATIVE_WINDOW_SET_CANCEL_INTERCEPTOR = 41, /* private */ NATIVE_WINDOW_SET_DEQUEUE_INTERCEPTOR = 42, /* private */ NATIVE_WINDOW_SET_PERFORM_INTERCEPTOR = 43, /* private */ NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR = 44, /* private */ // clang-format on // clang-format on }; }; Loading