diff options
author | 2023-02-23 17:55:07 -0500 | |
---|---|---|
committer | 2023-02-28 09:48:10 -0500 | |
commit | 42fcb0dd358baf425754d4229828506877ebe8b9 (patch) | |
tree | 13fab1b1232929c4b1de84362479a7d22395bdf6 | |
parent | b304b2f1177251c5deb904306ba5ad820e1c119d (diff) |
Fix implementation of ANW_read/write parcel
Bug: 268427650
Test: atest android.graphics.cts.ANativeWindowTest
Change-Id: I19d7390998edbad960fe8812ec1d57e5a725b4e6
-rw-r--r-- | libs/gui/view/Surface.cpp | 52 | ||||
-rw-r--r-- | libs/nativewindow/ANativeWindow.cpp | 84 |
2 files changed, 96 insertions, 40 deletions
diff --git a/libs/gui/view/Surface.cpp b/libs/gui/view/Surface.cpp index 1bfe4624f1..198908d334 100644 --- a/libs/gui/view/Surface.cpp +++ b/libs/gui/view/Surface.cpp @@ -16,17 +16,59 @@ #define LOG_TAG "Surface" -#include <gui/view/Surface.h> - +#include <android/binder_libbinder.h> +#include <android/binder_parcel.h> +#include <android/native_window.h> #include <binder/Parcel.h> - -#include <utils/Log.h> - #include <gui/IGraphicBufferProducer.h> +#include <gui/Surface.h> +#include <gui/view/Surface.h> +#include <system/window.h> +#include <utils/Log.h> namespace android { namespace view { +// Since this is a parcelable utility and we want to keep the wire format stable, only build this +// when building the system libgui to detect any issues loading the wrong libgui from +// libnativewindow + +#if (!defined(__ANDROID_APEX__) && !defined(__ANDROID_VNDK__)) + +extern "C" status_t android_view_Surface_writeToParcel(ANativeWindow* _Nonnull window, + Parcel* _Nonnull parcel) { + int value; + int err = (*window->query)(window, NATIVE_WINDOW_CONCRETE_TYPE, &value); + if (err != OK || value != NATIVE_WINDOW_SURFACE) { + ALOGE("Error: ANativeWindow is not backed by Surface"); + return STATUS_BAD_VALUE; + } + // Use a android::view::Surface to parcelize the window + android::view::Surface shimSurface; + shimSurface.graphicBufferProducer = android::Surface::getIGraphicBufferProducer(window); + shimSurface.surfaceControlHandle = android::Surface::getSurfaceControlHandle(window); + return shimSurface.writeToParcel(parcel); +} + +extern "C" status_t android_view_Surface_readFromParcel( + const Parcel* _Nonnull parcel, ANativeWindow* _Nullable* _Nonnull outWindow) { + // Use a android::view::Surface to unparcel the window + android::view::Surface shimSurface; + status_t ret = shimSurface.readFromParcel(parcel); + if (ret != OK) { + ALOGE("%s: Error: Failed to create android::view::Surface from AParcel", __FUNCTION__); + return STATUS_BAD_VALUE; + } + auto surface = sp<android::Surface>::make(shimSurface.graphicBufferProducer, false, + shimSurface.surfaceControlHandle); + ANativeWindow* anw = surface.get(); + ANativeWindow_acquire(anw); + *outWindow = anw; + return STATUS_OK; +} + +#endif + status_t Surface::writeToParcel(Parcel* parcel) const { return writeToParcel(parcel, false); } diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp index b7b2926c73..5306529fcb 100644 --- a/libs/nativewindow/ANativeWindow.cpp +++ b/libs/nativewindow/ANativeWindow.cpp @@ -24,14 +24,49 @@ #include <private/android/AHardwareBufferHelpers.h> +#include <android/binder_libbinder.h> +#include <dlfcn.h> #include <log/log.h> #include <ui/GraphicBuffer.h> -#include <gui/Surface.h> -#include <gui/view/Surface.h> -#include <android/binder_libbinder.h> using namespace android; +#if defined(__ANDROID_APEX__) || defined(__ANDROID_VNDK__) +#error libnativewindow can only be built for system +#endif + +using android_view_Surface_writeToParcel = status_t (*)(ANativeWindow* _Nonnull window, + Parcel* _Nonnull parcel); + +using android_view_Surface_readFromParcel = + status_t (*)(const Parcel* _Nonnull parcel, ANativeWindow* _Nullable* _Nonnull outWindow); + +struct SurfaceParcelables { + android_view_Surface_writeToParcel write = nullptr; + android_view_Surface_readFromParcel read = nullptr; +}; + +const SurfaceParcelables* getSurfaceParcelFunctions() { + static SurfaceParcelables funcs = []() -> SurfaceParcelables { + SurfaceParcelables ret; + void* dl = dlopen("libgui.so", RTLD_NOW); + LOG_ALWAYS_FATAL_IF(!dl, "Failed to find libgui.so"); + ret.write = + (android_view_Surface_writeToParcel)dlsym(dl, "android_view_Surface_writeToParcel"); + LOG_ALWAYS_FATAL_IF(!ret.write, + "libgui.so missing android_view_Surface_writeToParcel; " + "loaded wrong libgui?"); + ret.read = + (android_view_Surface_readFromParcel)dlsym(dl, + "android_view_Surface_readFromParcel"); + LOG_ALWAYS_FATAL_IF(!ret.read, + "libgui.so missing android_view_Surface_readFromParcel; " + "loaded wrong libgui?"); + return ret; + }(); + return &funcs; +} + static int32_t query(ANativeWindow* window, int what) { int value; int res = window->query(window, what, &value); @@ -64,13 +99,6 @@ static bool isDataSpaceValid(ANativeWindow* window, int32_t dataSpace) { return false; } } -static sp<IGraphicBufferProducer> IGraphicBufferProducer_from_ANativeWindow(ANativeWindow* window) { - return Surface::getIGraphicBufferProducer(window); -} - -static sp<IBinder> SurfaceControlHandle_from_ANativeWindow(ANativeWindow* window) { - return Surface::getSurfaceControlHandle(window); -} /************************************************************************************************** * NDK @@ -355,38 +383,24 @@ int ANativeWindow_setAutoPrerotation(ANativeWindow* window, bool autoPrerotation binder_status_t ANativeWindow_readFromParcel( const AParcel* _Nonnull parcel, ANativeWindow* _Nullable* _Nonnull outWindow) { - const Parcel* nativeParcel = AParcel_viewPlatformParcel(parcel); - - // Use a android::view::Surface to unparcel the window - std::shared_ptr<android::view::Surface> shimSurface = std::shared_ptr<android::view::Surface>(); - status_t ret = shimSurface->readFromParcel(nativeParcel); - if (ret != OK) { - ALOGE("%s: Error: Failed to create android::view::Surface from AParcel", __FUNCTION__); - return STATUS_BAD_VALUE; + auto funcs = getSurfaceParcelFunctions(); + if (funcs->read == nullptr) { + ALOGE("Failed to load Surface_readFromParcel implementation"); + return STATUS_FAILED_TRANSACTION; } - sp<Surface> surface = sp<Surface>::make( - shimSurface->graphicBufferProducer, false, shimSurface->surfaceControlHandle); - ANativeWindow* anw = surface.get(); - ANativeWindow_acquire(anw); - *outWindow = anw; - return STATUS_OK; + const Parcel* nativeParcel = AParcel_viewPlatformParcel(parcel); + return funcs->read(nativeParcel, outWindow); } binder_status_t ANativeWindow_writeToParcel( ANativeWindow* _Nonnull window, AParcel* _Nonnull parcel) { - int value; - int err = (*window->query)(window, NATIVE_WINDOW_CONCRETE_TYPE, &value); - if (err != OK || value != NATIVE_WINDOW_SURFACE) { - ALOGE("Error: ANativeWindow is not backed by Surface"); - return STATUS_BAD_VALUE; + auto funcs = getSurfaceParcelFunctions(); + if (funcs->write == nullptr) { + ALOGE("Failed to load Surface_writeToParcel implementation"); + return STATUS_FAILED_TRANSACTION; } - // Use a android::view::Surface to parcelize the window - std::shared_ptr<android::view::Surface> shimSurface = std::shared_ptr<android::view::Surface>(); - shimSurface->graphicBufferProducer = IGraphicBufferProducer_from_ANativeWindow(window); - shimSurface->surfaceControlHandle = SurfaceControlHandle_from_ANativeWindow(window); - Parcel* nativeParcel = AParcel_viewPlatformParcel(parcel); - return shimSurface->writeToParcel(nativeParcel); + return funcs->write(window, nativeParcel); } /************************************************************************************************** |