Add hook for intercepting query
Bug: 143555869
Test: verified no kgsl maps in RenderThread
Change-Id: Ifac5869cd6b29570286f8fd2aa641701f77fde94
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index f911e70..2bf8ff7 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -57,7 +57,8 @@
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;
+ op == NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR ||
+ op == NATIVE_WINDOW_SET_QUERY_INTERCEPTOR;
}
} // namespace
@@ -501,6 +502,19 @@
int Surface::hook_query(const ANativeWindow* window, int what, int* value) {
const Surface* c = getSelf(window);
+ {
+ std::shared_lock<std::shared_mutex> lock(c->mInterceptorMutex);
+ if (c->mQueryInterceptor != nullptr) {
+ auto interceptor = c->mQueryInterceptor;
+ auto data = c->mQueryInterceptorData;
+ return interceptor(window, Surface::queryInternal, data, what, value);
+ }
+ }
+ return c->query(what, value);
+}
+
+int Surface::queryInternal(const ANativeWindow* window, int what, int* value) {
+ const Surface* c = getSelf(window);
return c->query(what, value);
}
@@ -1177,6 +1191,9 @@
case NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR:
res = dispatchAddQueueInterceptor(args);
break;
+ case NATIVE_WINDOW_SET_QUERY_INTERCEPTOR:
+ res = dispatchAddQueryInterceptor(args);
+ break;
case NATIVE_WINDOW_ALLOCATE_BUFFERS:
allocateBuffers();
res = NO_ERROR;
@@ -1457,6 +1474,15 @@
return NO_ERROR;
}
+int Surface::dispatchAddQueryInterceptor(va_list args) {
+ ANativeWindow_queryInterceptor interceptor = va_arg(args, ANativeWindow_queryInterceptor);
+ void* data = va_arg(args, void*);
+ std::lock_guard<std::shared_mutex> lock(mInterceptorMutex);
+ mQueryInterceptor = interceptor;
+ mQueryInterceptorData = data;
+ return NO_ERROR;
+}
+
int Surface::dispatchGetLastQueuedBuffer(va_list args) {
AHardwareBuffer** buffer = va_arg(args, AHardwareBuffer**);
int* fence = va_arg(args, int*);
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 917c0d4..49c83da 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -209,6 +209,7 @@
int* fenceFd);
static int performInternal(ANativeWindow* window, int operation, va_list args);
static int queueBufferInternal(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd);
+ static int queryInternal(const ANativeWindow* window, int what, int* value);
static int hook_cancelBuffer_DEPRECATED(ANativeWindow* window,
ANativeWindowBuffer* buffer);
@@ -261,6 +262,7 @@
int dispatchAddDequeueInterceptor(va_list args);
int dispatchAddPerformInterceptor(va_list args);
int dispatchAddQueueInterceptor(va_list args);
+ int dispatchAddQueryInterceptor(va_list args);
int dispatchGetLastQueuedBuffer(va_list args);
bool transformToDisplayInverse();
@@ -468,7 +470,7 @@
mutable Mutex mMutex;
// mInterceptorMutex is the mutex guarding interceptors.
- std::shared_mutex mInterceptorMutex;
+ mutable std::shared_mutex mInterceptorMutex;
ANativeWindow_cancelBufferInterceptor mCancelInterceptor = nullptr;
void* mCancelInterceptorData = nullptr;
@@ -478,6 +480,8 @@
void* mPerformInterceptorData = nullptr;
ANativeWindow_queueBufferInterceptor mQueueInterceptor = nullptr;
void* mQueueInterceptorData = nullptr;
+ ANativeWindow_queryInterceptor mQueryInterceptor = nullptr;
+ void* mQueryInterceptorData = nullptr;
// must be used from the lock/unlock thread
sp<GraphicBuffer> mLockedBuffer;
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 869ca9e..b78fc5d 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -254,6 +254,7 @@
NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR = 44, /* private */
NATIVE_WINDOW_ALLOCATE_BUFFERS = 45, /* private */
NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER = 46, /* private */
+ NATIVE_WINDOW_SET_QUERY_INTERCEPTOR = 47, /* private */
// clang-format on
};
@@ -1062,4 +1063,38 @@
return value;
}
+/**
+ * Prototype of the function that an ANativeWindow implementation would call
+ * when ANativeWindow_query is called.
+ */
+typedef int (*ANativeWindow_queryFn)(const ANativeWindow* window, int what, int* value);
+
+/**
+ * Prototype of the function that intercepts an invocation of
+ * ANativeWindow_queryFn, 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_queryFn if it were to be called.
+ */
+typedef int (*ANativeWindow_queryInterceptor)(const ANativeWindow* window,
+ ANativeWindow_queryFn perform, void* data,
+ int what, int* value);
+
+/**
+ * Registers an interceptor for ANativeWindow_query. Instead of calling
+ * the underlying query function, instead the provided interceptor is
+ * called, which may optionally call the underlying query 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.
+ */
+static inline int ANativeWindow_setQueryInterceptor(ANativeWindow* window,
+ ANativeWindow_queryInterceptor interceptor,
+ void* data) {
+ return window->perform(window, NATIVE_WINDOW_SET_QUERY_INTERCEPTOR, interceptor, data);
+}
+
__END_DECLS